Compare commits

...
699 Commits
Author SHA1 Message Date
ptitSeb 8153391dd7 Some slight adjustment to DynablocAge and steam/heroic settings 2023-07-09 10:37:18 +02:00
ptitSeb 2420f9ffdd Added a comment on why code is disabled 2023-07-08 18:41:21 +02:00
ptitSeb b9fd1c6213 Made aging more aggressive for steamwebhelper and heroic 2023-07-08 18:41:21 +02:00
ptitSeb b5e6f92547 Fixed test if aged dynablock is ok to delete 2023-07-08 18:41:21 +02:00
ptitSeb d2c391406e [RV64] Another fix for the build 2023-07-08 18:41:21 +02:00
ptitSeb db1df82696 [RV64] Tis should fix the build 2023-07-08 18:41:21 +02:00
ptitSeb 67380e2c00 Implemented age of dynablock, with enter/exit counter 2023-07-08 18:41:21 +02:00
ptitSeb b956b29f66 Free jmptable when possible 2023-07-08 18:41:20 +02:00
ptitSeb ca9bc13619 Better wrapping for __libc_stack_end symbol 2023-07-08 18:01:51 +02:00
ptitSeb 3f573711aa Fixed non dynarec build 2023-07-08 17:44:49 +02:00
ptitSeb 55306b1d3d Fixed an issue with Alternate address and PltResolver 2023-07-08 17:36:54 +02:00
ptitSeb ab2d68ef45 Simplyfied internal jmpbuf handling 2023-07-08 17:21:49 +02:00
ptitSeb b7a2d59a61 Some more small improvments to BOX64_MALLOC_HACK=2 2023-07-08 15:10:28 +02:00
ptitSeb 25c8453353 More work on BOX64_MALLOC_HACK=2 2023-07-08 14:54:37 +02:00
ptitSeb aa39a923ed Improved BOX64_MALLOC_HACK=2 and the glAleternate mecanism (help steam & heroic and other libcef based software) 2023-07-08 14:26:07 +02:00
ptitSeb 57b7729ea7 But sigaction debug message back to LOG_DEBUG level 2023-07-06 16:13:02 +02:00
ptitSeb 0e750a7d0d Added __isoc99_swscanf wrapped function to libc for real this time (for #424) 2023-07-05 18:32:34 +02:00
ptitSeb 5cd583f944 Added __iso99_swscanf wrapped function to libc (for #424) 2023-07-05 16:24:14 +02:00
ptitSeb c7a93758cb Added some more libxft wrapped function (for #424) 2023-07-05 16:21:00 +02:00
Alexandre Julliard a450806dd2 A few Push/Pop fixes and cleanups (#878)
* Use 32-bit push/pop for PUSHAD/POPAD.

* Always specify the Push/Pop size explicitly.

* Make the Push/Pop functions inline.
2023-07-03 21:54:37 +02:00
ptitSeb cf6048419b Added 2 wrapped function for libxft (for #424) 2023-07-02 20:35:05 +02:00
ptitSeb cd6487ab94 Fixed signature for wrapped vkGetPhysicalDeviceQueueFamilyProperties2 function 2023-07-02 19:07:44 +02:00
ptitSeb 157a9cc651 Better wrapping for libz and liblzma 2023-07-02 14:05:22 +02:00
ptitSeb 509157a8b0 Go back to using regular malloc/free for Dynarec temporary allocation when building a block 2023-06-30 15:24:08 +02:00
ptitSeb aa8b8184b3 Small improvement to Signal Handling, and put back trace of Syscall/Sigaction to DEBUG level 2023-06-30 15:23:37 +02:00
Alexandre Julliard 1f65d3add7 [DYNAREC] Fix push rsp instruction (#875)
* [DYNAREC] Add one more missing void to a function prototype.

* [DYNAREC] Add a missing return in arm64_print().

* [DYNAREC] Use an intermediate register for PUSH RSP.

To avoid undefined behavior, similar to POP RSP.
2023-06-28 17:50:14 +02:00
Yang Liu 3b97724717 [32BITS][RV64_DYNAREC] Hanlding of STll struct in FILD/FISTP (#868)
* [32BITS][RV64_DYNAREC] Hanlding of STll struct in FILD/FISTP

* Fixed 0F B3 BTR
2023-06-27 15:18:44 +02:00
ptitSeb 144db5f07f Reworked a bit privileged instruction ([32BITS] too)(ARM64_DYNAREC] too) 2023-06-27 13:53:52 +02:00
ptitSeb dc0ab611c4 Added handling of INT 0x29 (__fastfail) 2023-06-26 18:43:52 +02:00
ptitSeb 5ddc93cf0d [32BITS][ARM64_DYNAREC] Added 66 60/61 opcodes (for #865) 2023-06-26 17:46:33 +02:00
ptitSeb ad5328e6c7 [32BITS] Added 66 60/61 opcodes (for #865) 2023-06-26 17:45:56 +02:00
Yang Liu 7e514ce4bd [DYNAREC_RV64] Fixed A0 MOV AL,Ob (#866)
* [DYNAREC_RV64] Fixed A0 MOV AL,Ob

* Fixed rv64_move32
2023-06-26 08:36:11 +02:00
Yang Liu 42dc36ad5a [32BTIS][DYNAREC_RV64] Added support for 32bits (#861)
* [32BTIS][DYNAREC_RV64] Added support for 32bits

* Fixed 32bit INC/DEC

* Fixed a typo

* Some more fixes

* Fixed geted_32

* POP -> POP1, PUSH -> PUSH1
2023-06-25 20:32:24 +02:00
ptitSeb 7689d0d568 [32BITS][ARM64_DYNAREC] Added 06/07 opcodes 2023-06-25 20:16:50 +02:00
ptitSeb f37265235e [32BITS] Fixed 1E/1F opcodes and added 06/07 opcodes 2023-06-25 20:16:17 +02:00
ptitSeb f83b192d70 [ARM64_DYNAREC] Fixed issue with the newly introduced I64 optim for x87 regs (fixes sound issue of #465) 2023-06-25 18:59:32 +02:00
ptitSeb 910420af07 [ARM64_DYNAREC] Fixed 8C opcode and added 66 8C opcode 2023-06-25 18:24:27 +02:00
ptitSeb 8f719b7fed [ARM64_DYNAREC] Added (F2/F3) 66 A7 opcode 2023-06-25 18:17:09 +02:00
ptitSeb 0272446f2b [32BITS][ARM64_DYNAREC] Hanlding of STll struct in FILD/FISTP 64bits (for #870) 2023-06-25 18:12:48 +02:00
ptitSeb 735d7ab1b4 [ARM64_DYNAREC] Improved handling of FILD/FISTP i64 sequence, important fo 32bits process (for #860) 2023-06-25 16:58:43 +02:00
ptitSeb 3c9b556ca8 [32BITS][ARM64_DYNAREC] Added 82 opcodes 2023-06-25 15:25:06 +02:00
ptitSeb 4e2ccf13cb [32BITS] Added 82 opcodes 2023-06-25 15:24:59 +02:00
ptitSeb 8d0a7d322e [32BITS][ARM64_DYNAREC] Added 1E/1F opcodes 2023-06-25 15:20:37 +02:00
ptitSeb 3880b7811b [32BITS] Added 1E/1F opcodes 2023-06-25 15:20:18 +02:00
ptitSeb 2604bb078c [32BITS][ARM64_DYNAREC] Added (faked) 6D opcode 2023-06-25 15:12:42 +02:00
ptitSeb 8670d622da [32BITS] Added 6C..6F opcodes 2023-06-25 15:12:22 +02:00
ptitSeb 1ca1c37a9c [32BITS][ARM64_DYNAREC] Added (faked) EF opcode 2023-06-25 15:00:21 +02:00
ptitSeb 7e7db57369 [32BITS][ARM64_DYNAREC] Added (F2/F3) 66 AD opcode 2023-06-25 14:54:45 +02:00
ptitSeb deb6fe8d7a [32BITS][ARM64_DYNAREC] Added 64 8F opcode 2023-06-25 14:50:02 +02:00
ptitSeb 1e20ed7099 [DYNAREC] Small improvment on instruction size array memory allocation 2023-06-25 14:41:57 +02:00
ptitSeb 40d94c84e0 [32BITS][ARM64_DYNAREC] Added (F2/F3) 66 AF opcode 2023-06-25 14:41:16 +02:00
ptitSeb bfc9af16a1 Comment fix on 66 AF opcode name 2023-06-25 14:40:39 +02:00
Alexandre Julliard 770cba7e2b A few cosmetic fixes (#858)
* [DYNAREC] Don't include pthread.h in C files.

It's already included from box64context.h.

Since there's no pthread.h on Win32, including it only once avoids
having to add ifdefs everywhere.

* [DYNAREC] Remove some duplicate definitions of the GETG helper macros.

* Declare void functions with an explicit void.

To avoid 'function declaration is not a prototype' warnings when using
-Wstrict-prototypes.

* Avoid including bridge_private.h in files that don't need it.

* Avoid defining ZYDIS_RUNTIME_ADDRESS_NONE.

It's not used, and conflicts with the original Zydis headers.
2023-06-24 18:20:24 +02:00
ptitSeb 8aa98d3f53 Faked libvdpau and added 2 wrapped symbols to libva and steam can stream games again 2023-06-24 17:34:57 +02:00
ptitSeb 4219af78f4 Try to improve custom memory allocator 2023-06-24 17:08:28 +02:00
ptitSeb 0352f2e6f0 [ARM64_DYNAREC] Fix potential issue on FF /5 opcode 2023-06-24 15:00:07 +02:00
ptitSeb 9ea02922ee [32BITS] Added 66/61 opcodes ([ARM64_DYNAREC] too) 2023-06-24 14:49:28 +02:00
ptitSeb 816cbc74f4 [ARM64_DYNAREC] Fixed a nasty issue with Double Push / Double Pop optimisation ([32BITS] too) 2023-06-24 14:25:58 +02:00
ptitSeb e8cd8ca8c0 [ARM64_DYNAREC] Added 67 66 89 opcode 2023-06-24 13:43:36 +02:00
ptitSeb 179015a050 [ARM64_DYNAREC] Added 67 63 opcode 2023-06-24 13:40:11 +02:00
ptitSeb d34428d249 [ARM64_DYNAREC] Added 67 0F B6/B7 opcodes 2023-06-24 13:36:34 +02:00
ptitSeb 974df6190e [32BITS][ARM64_DYNAREC] Added 66 40..4F opcodes 2023-06-24 13:30:19 +02:00
ptitSeb 294a18e680 [32BITS][ARM64_DYNAREC] Added 66 0F prefixed opcodes 2023-06-24 13:26:23 +02:00
ptitSeb 47edda2c1b [32BITS][ARM64_DYNAREC] Added 66 64 prefixed opcodes 2023-06-24 13:20:19 +02:00
ptitSeb ebe758f741 [32BITS][ARM64_DYNAREC] Added 66 F0 prefixed opcodes 2023-06-24 13:18:51 +02:00
ptitSeb 2f42eb02d4 [32BITS][ARM64_DYNAREC] Added 66 prefixed opcodes 2023-06-24 13:18:10 +02:00
ptitSeb 08e4823917 [32BITS][ARM64_DYNAREC] Added F0 prefixed opcode (except 66 prefix) 2023-06-24 13:06:56 +02:00
ptitSeb d67615c976 [32BITS][ARM64_DYNAREC] Added 64 A1/A3 opcode 2023-06-24 13:03:00 +02:00
ptitSeb 2ca9b70c84 [32BITS][ARM64_DYNAREC] Added some dynarec support for 32bits code (no-prefix + 0F/64/F20F/F30F prefixed opcodes) 2023-06-24 12:52:18 +02:00
Yang Liu bd8e532353 [32BITS][DYNAREC] Added basic 32 bits RV64 support (#856)
* [32BITS][DYNAREC] Added basic 32 bits RV64 support

* break!
2023-06-24 12:45:00 +02:00
Yang Liu 4f69f090e6 [DYNAREC_RV64] Fixed a typo (#855) 2023-06-24 10:36:50 +02:00
Yang Liu 0077fbe916 [DYNAREC_RV64] Small optim to FLAGS_ADJUST_TO11 (#854) 2023-06-24 08:14:10 +02:00
ptitSeb b263d1a049 [32BITS] Added 66 40..4F opcodes 2023-06-23 21:00:56 +02:00
ptitSeb bb3c647f49 [32BITS][DYNAREC] Preparing work for 32bits dynarec 2023-06-23 21:00:56 +02:00
Yang Liu c9b7180bb3 [WRAPPER] Added more symbols for nss3 (#853) 2023-06-23 20:37:41 +02:00
Yang Liu aca28bcb79 [INTERP] Added more opcodes (#852) 2023-06-23 19:52:28 +02:00
Alexandre Julliard 410447b340 [32BITS] Use 32-bit types to compute 32-bit addresses. (#851)
The base address needs to wrap around at 32 bits before being
converted to a pointer.
2023-06-23 15:24:22 +02:00
ptitSeb 6b0a1d286a [32BITS][DYNAREC] Preparing Dynarec to handle 32bits code 2023-06-22 16:33:33 +02:00
ptitSeb e78cd0d623 [32BITS] Separate RUn67 32bits from 64bits version, as they are too differents 2023-06-22 15:06:12 +02:00
Yang Liu 6eb72b71b1 [WRAPPER] Added more gtk functions (#849)
* [WRAPPER] Added more gtk functions

* Fixed some gtk wrappers
2023-06-21 18:22:40 +02:00
Yang Liu 0cef7f27ea [WRAPPER] Added more symbols for openssl wrapper (#847)
* Added more symbols for openssl

* Added more symbols for openssl
2023-06-19 20:47:37 +02:00
ptitSeb 9698844cc3 [32BITS] Various small fixes in 32bits interpreter 2023-06-18 19:01:22 +02:00
ptitSeb 9ca5e13d7f [TRACE] Improve trace for 32bits part 2023-06-18 16:36:11 +02:00
ptitSeb e1825e0ff2 [32BITS] Some work on signal handling from 32bits code (not enough yet) 2023-06-18 16:35:53 +02:00
ptitSeb a55fc58e24 [32BITS] Fix potential 32bits 67 prefixed opcodes 2023-06-18 14:50:24 +02:00
ptitSeb 8e2889c2b5 Added 67 0F B6 opcode 2023-06-18 14:49:11 +02:00
ptitSeb 95d21e61e4 Added 64 8F opcode 2023-06-18 14:35:10 +02:00
ptitSeb ed09b87953 Added 67 63 opcode 2023-06-18 14:28:15 +02:00
ptitSeb 8c3fbe26ad [32BITS] Fixed some issue reading rex in 32bits mode 2023-06-18 14:24:44 +02:00
ptitSeb af2699ec21 Added 67 66 89 opcode 2023-06-18 14:24:17 +02:00
ptitSeb 17364dc445 [32BITS] Fixed an issue with 66 A1/A3 opcodes 2023-06-18 14:19:16 +02:00
ptitSeb 59dd97cb72 Added some support for 32bits code (doesn't seems enough for wow64 yet) 2023-06-18 10:52:28 +02:00
ptitSeb a0a98419f0 [TRACE] Fixed 32bits trace and dump 2023-06-17 14:17:22 +02:00
ptitSeb 1b47fd952c Added ability to trace and dump 32bits code 2023-06-17 12:08:43 +02:00
ptitSeb bf9e5b8e6e Added support for creating 32bits selector (no 32bits execution yet) 2023-06-17 11:32:56 +02:00
Jank9525 7e282c9027 Reduce duplication of compile instructions (#837)
* Reduce duplication of compile instructions

* Update COMPILE.md
2023-06-14 09:24:26 +02:00
Yang Liu e0dc494e71 [WRAPPER] Rework on libharfbuzz wrapper (#836)
* Rework of libharfbuzz, part 1

* Rework of libharfbuzz, part 2

* Rework of libharfbuzz, part 3

* Rework of libharfbuzz, part 4

* Rework of libharfbuzz, part 5

* Fixed typo

* Fixed typo

* Rework of libharfbuzz, part 6

* Rework of libharfbuzz, part 7

* Done
2023-06-13 19:25:30 +02:00
澪 4110956dda ryanfortner's package now have a different name (#834) 2023-06-12 13:14:10 +02:00
ptitSeb d0acd59adc Added 0F EA/EE opcodes ([ARM64_DYNAREC] too) (for #829) 2023-06-10 15:19:21 +02:00
ptitSeb 8ad6ffc93d Handle chained sigaction (for #829) 2023-06-10 15:03:30 +02:00
ptitSeb 56d0926bdf made my_dlsym protected by static mutex (help #829) 2023-06-10 15:02:55 +02:00
ptitSeb 8d99e12723 Added libsound.so wrpping (same as libasound.so.2) 2023-06-10 15:01:38 +02:00
ptitSeb 8ee8301bd0 Added a bunch of wrapped function to libssl.so.3, libcrytpo.so.3 and icu (for #829) 2023-06-10 11:43:14 +02:00
ptitSeb 1d584fead4 Fixed an issue in wrapped execv 2023-06-10 09:28:38 +02:00
Yang Liu cc56ebbb35 [WRAPPER] Added more libicu wrapped functions (for #829) (#831) 2023-06-09 18:47:51 +02:00
ptitSeb 56b87146e7 Added more libicu wrapped function (for #829) 2023-06-09 14:40:51 +02:00
ptitSeb a5b9cdf90f Improve logs a bit 2023-06-09 11:11:52 +02:00
ptitSeb 6cd3d0d977 Added some icu wrapped function (for #829) 2023-06-09 11:11:16 +02:00
Yang Liu 361de53d86 [DYNAREC_RV64] Added more opcodes (#828)
* [RV64_DYNAREC] Added 64 0F 11 opcodes

* Added F2 0F F0 LDDQU opcode

* Added F3 0F 12 MOVSLDUP opcode

* Added 66 0F 38 DB AESIMC opcode

* Added F3 0F 53 RCPSS

* Added F5 CMC opcode

* Added 9F LAHF opcode

* Added 66 0F 38 10 PBLENDVB opcode

* Fixed typo

* Fxied typo

* Fixed review
2023-06-08 13:35:15 +02:00
Yang Liu 4021f6d8c3 [INTERPRETER] Added 66 0F 38 37 PCMPGTQ opcode (#827) 2023-06-08 09:05:55 +02:00
Yang Liu 2949e5cd8d [WRAPPER] Added some more libc wrappers (#826) 2023-06-08 08:27:00 +02:00
ptitSeb c8f3921c3d [VULKAN] Added one more extension 2023-06-06 14:23:45 +02:00
Yang Liu 5254834d43 [DYNAREC_RV64] Fixed 9x SETcc opcodes (#824) 2023-06-06 12:38:51 +02:00
Yang Liu 2b0ceaf417 [DYNAREC] Fixed call_c issues (#823)
* [DYNAREC] Fixed call_c issues and small optims to DIV opcode

* [DYNAREC] Do not test RDTSC

* Revert changes to DIV
2023-06-06 12:27:08 +02:00
Yang Liu a688abddc1 [DYNAREC] Fixed native_fprem (#822) 2023-06-06 09:59:36 +02:00
Yang Liu 648678ba7d [ARM64_DYNAREC] Fixed PUSH rsp when double pushing (#821) 2023-06-05 08:20:50 +02:00
ptitSeb f4c8c29510 [ELF_LOAD] Also use SONAME of loaded elf to match loaded libs (helps #805) 2023-06-04 12:01:58 +02:00
ptitSeb 87be9fd1ad [DYNAREC] Lair of the Clockwork God need FASTROUND to 0 (help #805) 2023-06-04 11:13:31 +02:00
Yang Liu 7cbb2bf435 [RV64_DYNAREC] Small optim on GETGX/GETGM helper macros (#817) 2023-06-03 12:01:08 +02:00
ptitSeb 4f1cefec30 Added some more setup for Project Zomboid (should help #112) 2023-06-02 17:42:21 +02:00
xctan 5e19c8f142 [RV64_DYNAREC] Added more opcodes for ICEY (#816)
* [RV64_DYNAREC] Added 66 AF SCASW opcode

* [RV64_DYNAREC] Added DD /7 FNSTSW opcode

* [RV64_DYNAREC] Added {D0,D2} /0 ROL opcode

* [RV64_DYNAREC] Added {D0,D2} /{4,6} SHL opcode
2023-06-02 08:19:45 +02:00
xctan a6737720f4 [RV64_DYNAREC] Added F0 80 /1 LOCK OR opcode for ICEY (#815) 2023-06-01 17:44:18 +02:00
ptitSeb e028a67f4f Do not try to preserve high memory (unless BOX64_RESERVE_HIGH=1 is used), as currently, it seems buggy and making more harm then good 2023-05-31 20:13:41 +02:00
ptitSeb c5e8aaff4a [DYNAREC] Addeddetection of libjvm (and an option to disable it) to apply conservative settings when loaded (should help #813) and probably other java based games/apps) 2023-05-31 18:21:42 +02:00
Yang Liu 2017ef192f [RV64_DYNAREC] Fixed 6B IMUL opcode (#812) 2023-05-30 21:01:18 +02:00
Yang Liu 04d3915171 [RV64_DYNAREC] Fixed geted32 (#811) 2023-05-30 20:42:49 +02:00
ptitSeb 2bdf3088a6 Added wrapped gdk_window_set_background_rgba function to gdk3 (for #809) 2023-05-28 22:53:50 +02:00
ptitSeb 9debf2678e Fixed wrapped gdk_threads_add_idle_full function to gdk3 (for #809) 2023-05-28 21:08:52 +02:00
ptitSeb e03c10142d Added wrapped gdk_threads_add_idle_full function to gdk3 (for #809) 2023-05-28 20:11:04 +02:00
ptitSeb 6213e7c390 [ARM64_DYNAREC] Fixed OF flag for ror32c emiter 2023-05-28 19:43:12 +02:00
ptitSeb 9264aa5e46 Added ignored 26 prefix to interpreter 2023-05-28 19:42:10 +02:00
ptitSeb 4c5e1d916a Added a few gstreamer wrapped function 2023-05-28 18:47:10 +02:00
ptitSeb d1ac3f3c24 Added wrapped g_settings_get_uint funciton (for #809) 2023-05-28 18:32:02 +02:00
ptitSeb ec9447ad5f Added GstTaskPoll to gtkclass wrapping 2023-05-28 18:31:05 +02:00
xctan 26b01d56f5 [RV64_DYNAREC] Added F3 0F B8 POPCNT opcode and fixed LOCK CMPXCHG16B for ML2 (#808)
* [RV64_DYNAREC] Added lock to F0 48 0F C7 LOCK CMPXCHG16B opcode

* [RV64_DYNAREC] Added F3 0F B8 POPCNT opcode

* [RV64_DYNAREC] Moved 16B lock to box64context
2023-05-28 17:17:09 +02:00
Yang Liu eb687748c5 [WRAPPER] Added some wayland function wrappers (#807) 2023-05-28 13:14:56 +02:00
Yang Liu 4b81cfcb47 [RV64_DYNAREC] Added more opcodes (#806)
* [RV64_DYNAREC] Added DC /6 FDIV opcode

* [RV64_DYNAREC] Added 66 0F 13 MOVLPD opcode

* [RV64_DYNAREC] Added 66 19 SBB opcode

* [RV64_DYNAREC] Added F0 29 LOCK SUB opcode
2023-05-28 11:19:12 +02:00
ptitSeb a7074f03f7 [RV64_DYNAREC] Small optim to AND with constant emiter 2023-05-28 07:48:21 +00:00
ptitSeb 0b67bba121 [DYNAREC] Do not track memory that is not accessible (should save some memory) 2023-05-28 09:39:26 +02:00
Yang Liu a791677534 [RV64_DYNAREC] Fixed 66 0F CMOV opcodes (#804) 2023-05-27 21:38:25 +02:00
ptitSeb be17a6cbf0 Fixed some potential issues when signal occurs with a (near) bad rsp 2023-05-25 14:56:13 +02:00
ptitSeb d2547672f3 Added partial support for TF flags (should help with eroneous debugger detection under wine) 2023-05-24 21:03:10 +02:00
Yang Liu 52d1a09b8a [RV64_DYNAREC] Fixed 66 0F 38 2B PACKUSDW opcode (#802)
* [RV64_DYNAREC] Fixed 66 0F 38 2B PACKUSDW opcode

* [RCFILE] Remove invalid options
2023-05-24 17:47:49 +02:00
Yang Liu 1d98aa54d5 [WRAPPER] Added 4 more libc dprintf wrappers (#798) 2023-05-22 16:22:23 +02:00
Yang Liu f56181bdab [WRAPPER] Added vwprintf (#794) 2023-05-20 12:32:25 +02:00
ptitSeb bc40c86f10 [RV64_DYNAREC] Fixed SSE reg Cache when a SSE change type (SS/SD/Vector) 2023-05-17 08:13:07 +00:00
Yang Liu d61f3e79e2 [WRAPPER] Fixed stack align on varargs (for #789) (#790) 2023-05-16 16:55:34 +02:00
Yang Liu 1d58879ae5 [WRAPPER] Added 1 more symbol for libc (for #787) (#788) 2023-05-15 13:08:19 +02:00
ptitSeb f115fe331b [RV64_DYNAREC] Fixed DF E0 opcode 2023-05-15 07:24:54 +00:00
Yang Liu 92ac8fed99 [RV64_DYNAREC] Added some missing fixes on GETEX (#785)
* [RV64_DYNAREC] Added some missing fixes on GETEX

* [RV64_DYNAREC] Fix BSWAP opcode
2023-05-15 09:17:26 +02:00
Yang Liu 877d31fefb [RV64_DYNAREC] Use the new x9 scratch register (#784) 2023-05-15 07:07:10 +02:00
ptitSeb 0d77c7f9a7 [RV64_DYNAREC] Small optim on GETEX helper macro 2023-05-14 09:43:54 +00:00
ptitSeb 0037f9eccb [RV64_DYNAREC] Fixed non-Zbb path for some 66 0F opcodes 2023-05-13 18:25:40 +00:00
ptitSeb ba51e24fd9 [RV64_DYNAREC] Added 66 0F 38 30-35/38-3B/3D-40 opcodes (for dav1d) 2023-05-13 17:36:16 +00:00
ptitSeb 7b9e6a57af [RV64_DYNAREC] Added 66 0F 63 opcode (for dav1d) 2023-05-13 15:50:14 +00:00
ptitSeb 7e9cab2b7d [RV64_DYNAREC] Added 66 0F 38 04/08/09/0A/1C/1D/1E/2B opcodes (for dav1d) 2023-05-13 15:31:06 +00:00
ptitSeb dd74ade44d [RV64_DYNAREC] Fixed neg16 SF flag generation 2023-05-13 15:28:06 +00:00
ptitSeb 9de2aa55cd [RV64_DYNAREC] Small optim for GETSEW(...) helper macro 2023-05-13 15:27:32 +00:00
ptitSeb 6ac2376aac [RV64_DYNAREC] Fixed ADC and SBC opcodes 2023-05-13 07:47:11 +00:00
ptitSeb 4fadb26cf6 [RV64_DYNAREC] Added x9 as a new scratch register 2023-05-13 07:46:29 +00:00
Yang Liu 61f14ffbbc [RV64_DYNAREC] Forget mmx float reg only needed (#782) 2023-05-12 08:13:22 +02:00
kaixindeken 377a55f60f fix exit doesnt free jump table completely (#781) 2023-05-12 07:52:53 +02:00
Yang Liu e32cb72c62 [RV64_DYNAREC] Added more 0F MMX opcodes and some fixes (#780)
* Added 0F 7F MOVQ opcode

* Added 0F 75 PCMPEQW opcode

* Added 0F 6F MOVQ opcode

* Added 0F EF PXOR opcode

* Added 0F 71 /6 PSLLW opcode

* Added 0F E5 PMULHW opcode

* Added 0F 60 PUNPCKLBW opcode

* Added 0F 68 PUNPCKHBW opcode

* Fixed some typos

* Added 0F 71 /2 PSRLW opcode

* Added 0F FD PADDW opcode

* Added 0F ED PADDSW opcode

* Added 0F 67 PACKUSWB opcode

* Added 0F F9 PSUBW opcode

* Added 0F 71 /4 PSRAW opcode

* Added 0F 69 PUNPCKHWD opcode

* Added 0F 6A PUNPCKHDQ opcode
2023-05-11 18:15:35 +02:00
Yang Liu dbd408c6d1 [RV64_DYNAREC] Added more opcodes and some fixes (#778)
* Added 64 80 opcodes and some fixes

* Added 80 /2 ADC opcode

* Added 0F 6E MOVD opcode

* Added 0F 61 PUNPCKLWD opcode

* Added 0F 62 PUNPCKLDQ opcode

* Added some MMX infra
2023-05-11 11:12:18 +02:00
Yang Liu 6e7bacb3c3 [ARM64_DYNAREC] Remove redundant code (#777) 2023-05-11 08:08:00 +02:00
Yang Liu 91f7078953 Added 1 libx11 symbol for #758 (#776) 2023-05-11 08:06:57 +02:00
ptitSeb 7787cb59f0 Don't Inc/Dec library refcount recursively (helps #240 but it's not enough) 2023-05-10 22:52:03 +02:00
ptitSeb dac27435b8 [TRACE] Improved again trace on PltResolver 2023-05-10 22:50:28 +02:00
ptitSeb 50cd5701ce [TRACE] Improved trace on PltResolver 2023-05-10 22:42:53 +02:00
ptitSeb adf4fb5ae0 [TRACE] Improved/Fixed vfprintf detailled trace 2023-05-10 22:26:06 +02:00
ptitSeb 1f4cc1cf88 Optimized Exit bridge managment 2023-05-10 17:21:14 +02:00
ptitSeb 92dd53177f Improved custom memory allocator 2023-05-10 16:24:01 +02:00
Yang Liu fe9e5bf21d [RV64_DYNAREC] Added more opcodes and some fixes (#775)
* Added 64 C6 MOV opcode

* Added 64 03 ADD opcode

* Added 64 81,83 opcodes

* Added D8 FDIV opcode

* Added DB FUCOMI opcode

* Fixed 66 0F 3A 09 ROUNDPD opcode

* Fixed review
2023-05-10 13:39:45 +02:00
Yang Liu 1ca4f6acf5 [RV64_DYNAREC] Added more opcodes and a small fix (#774)
* Added 67 0F 2E,2F (U)COMISS opcodes

* Added 66 0F 3A 09 ROUNDPD opcode

* Added 66 D1,D3 SHL opcodes

* Use ZEXTH if Zbb is available
2023-05-10 10:06:38 +02:00
Ilya114 392463b9f0 Added link to Wine guide, fixed link to Chinese readme (#773)
* Added Wine guide, fixed link to Chinese guide

* Update README.md
2023-05-09 16:28:34 +02:00
ptitSeb 4df1f85492 Added some more libgstreamer wrapped functions 2023-05-09 14:42:08 +02:00
ptitSeb ad79f878eb [DYNAREC] Some other small improvment to signal jmpbuf handling 2023-05-09 14:41:48 +02:00
ptitSeb 04a7437158 [DYNAREC] Small fix in DynaRun 2023-05-08 21:57:12 +02:00
ptitSeb 1fbeb6bd34 Added a few wrapped function to gcrypt and gnutls 2023-05-08 17:20:06 +02:00
ptitSeb 54cce67156 Hide segfault on quit from my_exit too 2023-05-08 15:29:54 +02:00
ptitSeb 7db5b33284 Some small changes to thread and fork and cloning x64emu_t struct 2023-05-08 15:20:52 +02:00
ptitSeb 6607ddb15d [TRACE] Better log for execv on Rolling log 2023-05-08 15:18:29 +02:00
ptitSeb f18c1b3998 Fixed fpu_fxsave/fpu_fxrstor utility function (might help Windows Unity3D games) 2023-05-08 15:07:55 +02:00
ptitSeb bd75b34f5d Added 4 XXX_chk function to wrapped libc (for #769) 2023-05-08 08:41:40 +02:00
ptitSeb 057de8f9be Added 1 extension to wrapped vulkan, and change a bit 1 of the procaddress (in sync with the others) 2023-05-07 22:01:44 +02:00
ptitSeb 404bfdc782 [ARM64_DYNAREC] Added F3 0F B8 opcode 2023-05-07 22:00:53 +02:00
ptitSeb b74a1b5a32 [ARM64_DYNAREC] Added 66 0F BA opcodes 2023-05-07 21:59:33 +02:00
Yang Liu 9f38e81735 [WRAPPER] Used RunFunctionFmt for better sign-extend handling (#768)
* [WRAPPER] Used RunFunctionFmt for better sign-extend handling

* [WRAPPER] Fixed some typos

* [WRAPPER] Use L for unsigned long for better portability

* [WRAPPER] More replace from U to L
2023-05-07 16:13:56 +02:00
ptitSeb 47ecde75ec [DYNAREC] Added BOX64_DYNAREC_MISSING to only print dynarec missing opcode 2023-05-07 15:54:37 +02:00
ptitSeb 07948ff6a7 [DYNAREC] Use Dynarec on Signal function when possible 2023-05-07 15:21:08 +02:00
ptitSeb 381bccfd6a [ARM64_DYNAREC] Fixed 64/65 F7 opcodes 2023-05-07 14:53:44 +02:00
ptitSeb 3221038bc6 [DYNAREC] Disabled custom mutex for now 2023-05-07 14:12:16 +02:00
ptitSeb 0359a65a00 [DYNAREC] Cosmetic fix 2023-05-07 11:41:47 +02:00
ptitSeb eb1b77ad01 [DYNAREC] Better handling for Calling UpdateFlags when Cache flags needs transform 2023-05-07 11:40:38 +02:00
ptitSeb 45c7bab8e4 [DYNAREC] Small improvment to signal handling on dirty block 2023-05-07 11:38:14 +02:00
ptitSeb 0a558652e3 [DYNAREC] Made FASTPAGE more agressive 2023-05-06 09:39:29 +02:00
ptitSeb 30126c9288 Adjusted default rcfile for steam 2023-05-06 09:38:23 +02:00
ptitSeb 39562edc45 Fixed some issue on malloc_hack_2 hack, but not enough so still disabled it 2023-05-06 09:37:16 +02:00
Yang Liu c19e513efb [RV64_DYNAREC] Fixed typos in (67) 88 MOV opcode (#767) 2023-05-06 08:56:05 +02:00
ptitSeb cf22cbcab5 Added 65 8D opcode ([ARM64_DYNAREC] too) (for #766) 2023-05-05 21:39:54 +02:00
xctan e444b277f8 [RV64_DYNAREC] Fixed 66 0F 3A 0B ROUNDSD opcode (#765) 2023-05-05 17:49:40 +02:00
ptitSeb 49dfbee211 Improved handling of x86_64 47bits memory (should help #763) 2023-05-05 13:49:06 +02:00
Yang Liu 3fc3875e82 [RV64_DYNAREC] Added more opcodes (#764)
* Added 67 8B MOV opcode

* Added 67 89 MOV opcode
2023-05-05 12:33:20 +02:00
Yang Liu a9099ce2c1 Added some mpg123 wrapped functions (#762)
* Added some mpg123 wrapped functions

* Added a warning to wrapperhelper README
2023-05-05 09:38:01 +02:00
Yang Liu ad9fc59d19 [RV64_DYNAREC] Added some AES opcodes (#761)
* Added 66 0F 3A DF AESKEYGENASSIST opcode

* Added 66 0F 38 DC AESENC opcode

* Added 66 0F 38 DD AESENCLAST opcode

* Added 66 0F 38 DE AESDEC opcode

* Added 66 0F 38 DF AESDECLAST opcode
2023-05-05 08:15:02 +02:00
ptitSeb 0e14d42dcf [ARM64_DYNAREC] Small improvment for signal handling 2023-05-04 21:34:13 +02:00
ptitSeb 987ff861fd Added some Hack for Windows int 2d call ([ARM64_DYNAREC] too) 2023-05-04 21:33:40 +02:00
ptitSeb f3f36e323b [DYNAREC] Print unimplemented opcode also when dumping dynablocks 2023-05-04 21:32:37 +02:00
Yang Liu f7326b0533 [RV64_DYNAREC] Added more opcode for Unciv and some fixes (#759)
* Added F2 AF SCASD opcode

* Added DD FST opcode

* Added DC FCOMP opcode

* Added DD FFREE opcode

* Added 66 0F 3A 21 INSERTPS opcode
2023-05-04 17:10:02 +02:00
ptitSeb dbde650339 Added 64/65 A1 opcode 2023-05-04 13:24:55 +02:00
Yang Liu a338e3fae8 [RV64_DYNAREC] Added more opcodes for Unciv (#757)
* Use dynarec64_67

* Added 66 0F 3A 44 PCLMULQDQ opcode

* Added 67 8D LEA opcode

* Added DF /5 FILD opcode

* Added D8 FCOMP opcode

* Added D8 FSUB opcode

* Added F0 0F B0 CMPXCHG opcode

* [ARM64_DYNAREC] Fixed a typo in CMPXCHG opcode
2023-05-04 12:02:50 +02:00
ptitSeb df59bf8811 [DYNAREC_TEST] Fixed handling or 0F AE opcodes 2023-05-04 10:43:23 +02:00
ptitSeb 99e669bb63 [DYNAREC_TEST] Better handling for FF /6 opcodes 2023-05-04 10:26:44 +02:00
ptitSeb 66b4dcf37a [DYNAREC] Improve handling of running block getting dirty while executing 2023-05-04 10:07:20 +02:00
ptitSeb 1462d5c6bd [DYNAREC_TEST] Improved 67 DB and 0F AE opcodes handling 2023-05-04 10:06:27 +02:00
ptitSeb 60d2efc74b Disabling free hack on malloc_hack_2, it seems to break steam for now 2023-05-03 19:53:21 +02:00
xctan 144b44e838 [RV64_DYNAREC] Fixed 66 0F C6 SHUFPD opcode (#756) 2023-05-03 18:34:30 +02:00
ptitSeb 3245ff59d3 [RV64_DYNAREC] Added several 67 prfixed opcodes 2023-05-03 14:39:42 +00:00
ptitSeb 3a4d58f114 Improved mallock_hack_2, trying to reduce potential memory leaks 2023-05-03 13:51:40 +02:00
ptitSeb 494f054ef4 [ARM64_DYNAREC] Added 67 88 opcode 2023-05-03 11:23:32 +02:00
Yang Liu 0079a08cb8 [RV64_DYNAREC] Added more opcodes for Bastion and some fixes (#753)
* Added AE SCASB opcode

* Some small fixes

* Added FSQRT opcode

* Treat all PREFETCHh opcodes as nop

* Added DF E0 FNSTSW opcode

* Added DD FSTP opcode
2023-05-03 08:18:49 +02:00
ptitSeb d31ff6a83f [RV64_DYNAREC] Added some more Zba and Zbb use to dynarec 2023-05-02 16:30:54 +00:00
ptitSeb 58abb54da5 [RV64_DYNAREC] Added undocumented BOX64_DYNAREC_RV64NOEXT to disable all RV64 CPU extensions 2023-05-02 15:35:01 +00:00
xctan 2fb4dccff0 [RV64_DYNAREC] Added more opcodes (#751)
* [RV64_DYNAREC] Fixed 66F0 opcodes

* [RV64] Added space between extensions and RISC-V

* [RV64_DYNAREC] Added 66 0F E6 CVTTPD2DQ opcode

* [RV64_DYNAREC] Added 0F 0D /1 PREFETCHW opcode

* [RV64_DYNAREC] Added F3 0F 2D CVTSS2SI opcode

* [RV64_DYNAREC] Fixed 66 0F E6 CVTTPD2DQ opcode

* [RV64_DYNAREC] Added D1 /3 RCR opcode
2023-05-02 15:00:31 +02:00
ptitSeb 45a4fc34d1 [RV64_DYNAREC] Improved 66 0F 3A 0B opcode 2023-05-02 09:13:21 +00:00
ptitSeb dc65627453 [RV64_DYNAREC] Added rev8 opcode to printer 2023-05-02 09:12:23 +00:00
ptitSeb d24cbaf556 [RV64_DYNAREC] Improved a bit the rv64 extension detection code 2023-05-02 09:11:43 +00:00
ptitSeb cbf71f678a Change default log value only if stdout is redirected, not box log output 2023-05-01 15:43:47 +02:00
ptitSeb c983418cb3 Added u_uastrncpy_XX to wrapped libicuXX (for #293) 2023-05-01 15:36:20 +02:00
ptitSeb 240c44b338 [RV64_DYNAREC] Added Zba optionnal optim to many helper functions 2023-05-01 12:43:02 +00:00
ptitSeb 505ac0021d [RV64_DYNAREC] Added Zbb path for 0F BC/BD and 66 0F BC/BD opcodes 2023-05-01 11:36:02 +00:00
ptitSeb c020154a2f [RV64_DYNAREC] Added Zbb path for 0F CF opcode 2023-05-01 10:34:10 +00:00
ptitSeb aac1663d75 [RV64_DYNAREC] Add detection of Zba, Zbb, Zbc and Zbs CPU extensions 2023-05-01 10:24:46 +00:00
Yang Liu 5b9d963d31 Added 66 64 8B MOV opcode (#749) 2023-04-30 17:53:00 +02:00
ptitSeb 31a6f5c4e3 [DYNAREC] Fixed DYNAREC_TEST false-positive when opcode use NOTEST and next opcode found a difference 2023-04-30 11:02:57 +02:00
ptitSeb 98535e572d [RV64_DYNAREC] Fixed potential issue on fastnan=0 for 0F 51 opcode 2023-04-30 08:15:05 +00:00
ptitSeb ffcfaba2fa [RV64_DYNAREC] Fixed issues with some x87 helpers functions (should help #748) 2023-04-30 07:38:29 +00:00
ptitSeb 464d868af5 Small improvment on x87 interpreter 2023-04-29 10:09:16 +02:00
ptitSeb 34a6e81f72 Introduced RunFunctionFmt (should help RV64 and other signe extended platform), conversion not finished 2023-04-28 20:59:16 +02:00
ptitSeb 57a9b520b0 Added wrapped libharfbuzz 2023-04-28 18:27:12 +02:00
xctan 6952970895 [RV64_DYNAREC] Added more opcodes (#747)
* [RV64_DYNAREC] Added 0F 52 RSQRTPS opcode

* [RV64_DYNAREC] Added C0 /1 ROR opcode

* [RV64_DYNAREC] Added 66 0F 3A 20 PINSRB opcode

* [RV64_DYNAREC] Added AA STOSB opcode

* [RV64_DYNAREC] Added 66 F0 {81,83} LOCK ADD opcode
2023-04-28 17:20:09 +02:00
ptitSeb 14e20e6435 Fix for local library open using dlopen that are then promoted to global with another dlopen (help java 17, probably other too) 2023-04-28 17:14:00 +02:00
Yang Liu 93abd016b4 [RV64_DYNAREC] Added more opcodes (#745)
* Added 66 0F 3A 0E PBLENDW opcode

* Added 66 0F 3A 22 PINSRD opcode

* Added 66 0F 7C HADDPD opcode

* Added 0F 53 RCPPS opcode

* Added 0F 51 SQRTPS opcode

* Added 66 0F 3A 0F PALIGNR opcode

* Added 66 0F 3A 16 PEXTRD/Q opcodes

* Added 9B FWAIT opcode

* Added a DD opcodes and some fixes

* Added DF FUCOMIP opcode

* Added DD D8 FSTP opcode

* Added D9 FC FRNDINT opcode and a small fix to ROUNDSD

* Added DF /7 FISTP opcode

* Added DB /3 FISTP opcode

* Added DD /3 FSTP opcode

* Fixed DF /3 FISTP opcode
2023-04-28 16:11:16 +02:00
ptitSeb 2ebde976db Improved x87 FIST(T)(P) opcode ([ARM64_DYNAREC] too) 2023-04-28 12:32:26 +02:00
Yang Liu dbaee7c49c [DYNAREC_RV64] Fixed 8F POP opcode (#746) 2023-04-28 11:15:07 +02:00
ptitSeb b6be4f8dde [DYNAREC] Defaulting to not tagging HotPage, it seems to work generaly better without now 2023-04-26 12:14:20 +02:00
ptitSeb 68a31c902a Added 1st implementation for _dl_find_object (for #742 and #711, maybe #487, #465, #410 and #210 too) 2023-04-26 12:07:31 +02:00
ptitSeb 78e6fbcf07 Some fixes to ehframe stack unwinding 2023-04-26 12:05:01 +02:00
ptitSeb 0403b684c4 Used wrapperhelper a bit on wraped libcrypto3 2023-04-26 09:38:12 +02:00
ptitSeb ccf05c6d83 Udpated README with RV64 2023-04-26 09:37:47 +02:00
Yang Liu a6a62007dc [RV64_DYNAREC] Added more opcodes (#743) 2023-04-25 14:09:23 +02:00
ptitSeb 549c42ac19 Improved/fixed (agaaaaain) Load/Unload of library (might help #740 &nd #742) 2023-04-25 14:03:28 +02:00
ptitSeb 6bfeb15655 Used wrapperhelper on wrapped gtk3 and gdk3 2023-04-24 19:21:25 +02:00
ptitSeb 69eb071fab Used wrapperhelper on wrapped libX11 2023-04-24 18:33:55 +02:00
ptitSeb 277a62a897 Used wrapperhelper on SDL2 and friends 2023-04-24 18:11:15 +02:00
ptitSeb 96da85d2c1 Used wrapperhelper on SDL1.2 and friends 2023-04-24 18:03:07 +02:00
ptitSeb b53b71a8ad Used wrapperhelper on wrapped pulseaudio 2023-04-24 17:53:36 +02:00
ptitSeb 009ffd609d Used wrapperhelper on wrapped liblzma 2023-04-24 17:46:25 +02:00
ptitSeb 50044f2f13 Used wrapperhelper on wrapped libmpg123 2023-04-24 17:40:08 +02:00
ptitSeb 0a2f4eb5be Used wrapperhelper on wrapped openal 2023-04-24 17:33:25 +02:00
ptitSeb 0ee25621d6 Used wrapperhelper on wrapped cairo and friends 2023-04-24 17:27:02 +02:00
xctan e64c542c6a [RV64_DYNAREC] Added more opcodes (#739)
* [RV64_DYNAREC] Added F0 0F C7 CMPXCHG8B/CMPXCHG16B opcode

* [RV64_DYNAREC] Added 66 83 /3 SBB opcode

* [RV64_DYNAREC] Added 66 FF /1 DEC opcode
2023-04-24 17:14:35 +02:00
ptitSeb 97ef3cccef Used wrapperhelper on gtk2/gdk2 wrapped libs 2023-04-24 16:33:43 +02:00
ptitSeb 766049afbb Made the to/from_complex function static inline (might help #738) 2023-04-24 15:32:49 +02:00
ptitSeb 4fff4f679f Used wrapperhelper on wrapped libatk 2023-04-24 11:36:43 +02:00
ptitSeb 2123f284de Used wrapperhelper on libcairo and libcairo-gobject 2023-04-24 11:29:02 +02:00
ptitSeb fb9b8fa625 Used wrapperhelper on wrapped libFAudio 2023-04-24 11:17:21 +02:00
ptitSeb d9e645b63f Used wrapperhelper on libflac 2023-04-24 11:09:39 +02:00
ptitSeb c2545c6762 Used wrapperhelper on wrapped freetype 2023-04-24 11:00:49 +02:00
ptitSeb c846d827cc Used wrapperhelper on wrapped fontconfig 2023-04-24 10:51:07 +02:00
ptitSeb f75179134d [RCFILE] Added profile for Stardew Valley 2023-04-24 10:47:35 +02:00
ptitSeb a30b22505c Used wrapperhelper on wrapper gstreamer and friends 2023-04-24 10:44:49 +02:00
ptitSeb bbf4082b1f Used wrapperhelper on glib2, gmodule2, gio2 and gconf2 wrapped lib 2023-04-24 10:26:50 +02:00
Yang Liu 84a9da2f06 [RV64_DYNAREC] Added more opcodes (#737)
* Added 66 0F C2 CMPPD opcode

* Added 66 0F 5B CVTPS2DQ opcode

* Added 66 0F 5E opcode

* Added 66 0F 50 PMOVMSKD opcode
2023-04-24 09:59:04 +02:00
Yang Liu 4f457e945a [RV64_DYNAREC] Added more opcodes (#736)
* Added 0F C3 MOVNTI opcode

* Added 66 0F DA PMINUB opcode

* Added 66 0F EA PMINSW opcode

* Added 66 0F 5D MINPD opcode

* Added 66 0F DE PMAXUB opcode

* Added 66 0F 5F MAXPD opcode

* Added 66 0F E5 PMULHW opcode

* Added 66 0F D5 PMULLW opcode
2023-04-24 08:08:42 +02:00
ptitSeb 64f081009d More rework on libc and libgl wrapped function signature 2023-04-23 21:02:23 +02:00
rajdakin 486bbae323 [HELPER] Added support for builtin type distinction (long/long long) (#735) 2023-04-23 20:56:14 +02:00
Yang Liu b49a1904df [RV64_DYNAREC] Added more 66 0F opcodes (#734)
* Added 66 0F ED PADDSW opcode

* Added 66 0F DC PADDUSB opcode

* Added 66 0F E0 PAVGB opcode

* Added 66 0F E3 PAVGW opcode

* Added 66 0F E1 PSRAW opcode

* Added 66 0F E2 PSRAD opcode

* Added 66 0F C6 SHUFPD opcode

* Added 66 0F 2B MOVNTPD opcode

* Added 66 0F E7 MOVNTDQ opcode

* Added 66 0F E9 PSUBSW opcode

* Added 66 0F D8 PSUBUSB opcode
2023-04-23 20:53:11 +02:00
ptitSeb 1a70b54129 Reworked a bit wrapped libc functions signatures 2023-04-23 19:13:00 +02:00
ptitSeb 70332c4f2b Cosmetic change to wrapped pthread private 2023-04-23 19:13:00 +02:00
ptitSeb 8789141d0f Improve an error message on python wrapper generator 2023-04-23 19:13:00 +02:00
Yang Liu 29e7497adc [RV64_DYNAREC] Added more opcodes (#733)
* Added 66 1B SBB opcode

* Added 66 0F E4 PMULHUW opcode

* Added 66 0F E8 PSUBSB opcode

* Added 1A SBB opcode

* Added F2 0F E6 CVTPD2DQ opcode

* Added 66 F7 /2 NOT opcode

* Small optimization
2023-04-23 17:31:06 +02:00
ptitSeb 8ecf28de9b Reworked libgl wrapped signatures 2023-04-23 16:57:53 +02:00
ptitSeb 66abc05259 Added a bunch of wrapped functions (for #725) 2023-04-23 15:25:53 +02:00
ptitSeb 5b04c49e74 [ARM64_DYNAREC] Small fix for 0F AE /7 opcode 2023-04-23 12:06:42 +02:00
Yang Liu f26e9758d5 [RV64_DYNAREC] Added more opcodes (#730)
* Added 65 opcodes

* Added 8E opcode

* Added CF IRET opcode

* Added 8F POP opcode

* Added 66 A5 MOVSW opcode

* Added D3 /1 ROR opcode

* Fixed D1 /1 ROR opcode

* Added F0 FF /0,/1 LOCK INC/DEC opcodes

* Added 66 AB STOSW opcode

* Added 1B SBB opcode
2023-04-23 11:58:47 +02:00
lizhuoheng 531cb89943 Added more gtk3 wrapped functions (#731) 2023-04-23 10:52:30 +02:00
lizhuoheng 24ead2f125 Added more gtk3 wrapped functions (#727) 2023-04-23 08:33:56 +02:00
xctan 225e50a32a [RV64_DYNAREC] Added more opcodes for SV (#726)
* [RV64_DYNAREC] Added 66 FF /0 INC opcode and fixed emit_add16

* [RV64_DYNAREC] Added 66 0F F9 PSUBW opcode

* [RV64_DYNAREC] Added 0F BA /6 BTR opcode

* [RV64_DYNAREC] Added 0F BA /5 BTS opcode

* [RV64_DYNAREC] Added 8C MOV opcode

* [RV64_DYNAREC] Added 66 8B MOV opcode
2023-04-22 17:06:03 +02:00
ptitSeb d546877e7d [DYNAREC] Fixed vsyscall bridge 2023-04-22 11:36:28 +02:00
ptitSeb 9657bd51d0 Another fix for dlopen with RTLD_NOLOAD when lib was already loaded elswhere (fixed pokewild) 2023-04-22 10:39:10 +02:00
ptitSeb fd47fc3d12 inc ref count for dlopen with RTL_NOLOAD 2023-04-22 10:21:40 +02:00
ptitSeb c74d8bb602 Fixed and improved __cxa_atexit handling 2023-04-22 10:12:09 +02:00
ptitSeb ec7844072f Fixed gtk2 apps, broken since #720 2023-04-21 18:24:33 +02:00
Yang Liu 128390d52e Added A1/A2/A3 MOV opcodes (#723) 2023-04-21 16:51:02 +02:00
xctan f7d23a4b9f [WRAPPER] Fix my___vsnprintf_chk (#722) 2023-04-21 12:12:25 +02:00
Yang Liu 2dec48f8af [RV64_DYNAREC] Added more opcodes (#721)
* Added 66 0F D2 PSRLD opcode

* Added 66 0F D1 PSRLW opcode

* Added 66 0F F1/F2 opcodes and some refactor

* Added F3 0F 70 PSHUFHW opcode

* Added 66 0F 16 MOVHPD opcode
2023-04-21 12:08:49 +02:00
ptitSeb 3f8ec8d46e Fixed a macro and change chinese comment to english 2023-04-21 10:51:56 +02:00
Yang Liu a607d1178f [RV64_DYNAREC] Added more opcodes (#719)
* Added 0F C2 CMPPS opcode

* Added 66 0F F6 PSADBW opcode

* Added 66 0F F5 PMADDWD opcode

* Added 66 0F 12 MOVLPD opcode

* Added 66 0F 51 SQRTPD opcode

* Added 66 0F D3 PSRLQ opcode

* Added some fastnan handling to make tests happy
2023-04-21 10:42:12 +02:00
lizhuoheng 1a3d412669 Added more gtk3 wrapped functions (#720) 2023-04-21 10:37:17 +02:00
ptitSeb ae08d21bf1 [DYNAREC] Fixed an optimisation in getDBSize helper function 2023-04-20 22:59:13 +02:00
Yang Liu 5f69e58f37 [RV64_DYNAREC] Added more opcodes (#718)
* Added F0 01 LOCK ADD opcode

* Added F2 0F 51 SQRTSD opcode

* Added FE /0,/1 INC/DEC opcodes
2023-04-20 18:23:25 +02:00
Yang Liu 84b0ee2284 [RV64_DYNAREC] Added more opcodes (#717)
* Added 66 0F 5A CVTPD2PS opcode

* Fixed 66 0F 14 opcode

* Added 0F 13 MOVLPS opcode
2023-04-20 15:27:38 +02:00
ptitSeb 4e9005be14 [DYNAREC] Try to test last opcode at end of block for unimplemented opcode 2023-04-20 11:57:18 +00:00
Yang Liu f280c64980 [RV64_DYNAREC] Added more opcodes and some fixes (#716)
* Fixed various bugs

* Added 66 0F 38 01 PHADDW opcode

* Added 66 0F 38 02 PHADDD opcode

* Added 66 0F EC PADDSB opcode

* Some small optimizations
2023-04-20 08:52:40 +02:00
ptitSeb d0ae6a9a7d [RV64_DYNAREC] Various fixes on many opcodes 2023-04-19 20:37:20 +00:00
ptitSeb 9aca360fe5 [DYNAREC] Fixed signature of x64test function 2023-04-19 20:37:20 +00:00
ptitSeb 5d92a3a891 Some sligth improvment to __vsnprintf_chk and vfprintf 2023-04-19 20:37:20 +00:00
ptitSeb 70787b0a6d [ARM64_DYNAREC] Fixed a small bug in 66 0F BC opcode 2023-04-19 21:47:02 +02:00
ptitSeb 206b8bc899 [RV64_DYNAREC] More fixes to a few opcodes 2023-04-19 16:00:21 +00:00
Yang Liu a0ea94b531 [RV64_DYNAREC] Remove 66 0F 3A 0B ROUNDSD opcode for now (#715) 2023-04-19 17:47:20 +02:00
ptitSeb 790a7a37d2 Fixed non-dynarec build 2023-04-19 15:23:02 +00:00
ptitSeb c0eace067a [RV64_DYNAREC] Some fixes and small improvement to a few opcodes 2023-04-19 14:28:37 +00:00
ptitSeb 9d6835737b [DYNAREC] Fixed faux-positive on DYNAREC_TEST when unimplemented opcode in dynarec are encountered 2023-04-19 14:28:37 +00:00
ptitSeb 1b4625cedd Added some weixin support (not really tested, for #711) 2023-04-19 15:09:20 +02:00
Yang Liu fba75e3122 [RV64_DYNAREC] Fixed some bugs (#714)
* Fixed F3 0F BD LZCNT opcode

* Fixed 66 29 SUB opcode
2023-04-19 14:00:46 +02:00
Yang Liu 91bf99d2a5 Fixed a broken link in README (#713) 2023-04-19 10:35:04 +02:00
xctan 6f29d2a5d8 [RV64_DYNAREC] Added more opcodes (#712)
* [RV64_DYNAREC] Added 64 33 XOR opcode

* [RV64_DYNAREC] Added 0F C8-CF BSWAP opcode

* [RV64_DYNAREC] Added 66 0F 3A 0B ROUNDSD opcode

* [RV64_DYNAREC] Added F3 0F BC TZCNT opcode

* [RV64_DYNAREC] Added F3 0F E6 CVTDQ2PD opcode

* [RV64_DYNAREC] Added F3 0F 5B CVTTPS2DQ opcode

* [RV64_DYNAREC] Fixed CVTTPS2DQ, CVTDQ2PD and printer
2023-04-19 10:11:22 +02:00
Yang Liu 008ef41261 [RV64_DYNAREC] Added more opcode and some fixes (#710)
* Added 64 88/89/C7 opcodes for test11

* Added more DF opcodes

* Fixed various bugs in x87/SSE/mmx infrastructure

* Added F2 0F 2D CVTSD2SI opcode and remove a TODO in CVTTSD2SI

* Fixed Invalid Operation handling DF opcodes (interpreter also)

* Added 32bits -> 16bits overflow test on DF opcodes
2023-04-18 15:01:17 +02:00
Yang Liu c61d341844 [ELF] Fixed a use-after-free issue (#709) 2023-04-18 10:10:35 +02:00
Yang Liu 49e5a48e42 [WRAPPER] Added more fontconfig wrapped functions (#708) 2023-04-18 08:25:44 +02:00
ptitSeb 9a97898ea4 [RV64_DYNAREC] Added F3 0F BD and 66 29 opcodes 2023-04-17 17:57:02 +00:00
ptitSeb cce1fa8928 [RV64_DYNAREC] Fixed SSE_LOOP_FQ helper macro 2023-04-17 16:45:30 +00:00
Yang Liu cddea1e4c1 [RV64_DYNAREC] Added more opcodes (#706)
* Added 0F 5E DIVPS opcoe

* Added 0F 55 ANDNPS opcode

* Added 0F 59 MULPS opcode

* Added 66 A9 TEST opcode

* Added 66 0F F4 PMULUDQ opcode

* Added 0F 5C SUBPS opcode

* Added 0F 17 MOVHPS opcode

* Added 66 F7 /3 NEG opcode
2023-04-17 15:44:45 +02:00
ptitSeb 2cbf5cbf7b Fixed issue with program using getopts 2023-04-17 14:35:50 +02:00
Yang Liu e360565266 [RV64_DYNAREC] Added more opcodes (#705)
* [RV64_DYNAREC] Added A6 CMPSB opcode

* [RV64_DYNAREC] Added 0F 12 MOVHLPS/MOVLPS opcodes

* Fixed A6 opcode

* Added FC CLD opcode

* Added 51 SQRTSS opcode

* Added 66 0F 64 PCMPGTB opcode

* Added 0F 5B CVTDQ2PS opcode

* Added 0F 58 ADDPS opcode

* Added 66 0F 65 PCMPGTW opcode
2023-04-17 13:07:26 +02:00
ptitSeb dce7be2775 Do less stuff in signal if it will not be printed out 2023-04-17 11:45:39 +02:00
Yang Liu 922e5beb3f [WRAPPER] Fixed mpg123 wrapper (#704) 2023-04-17 08:08:49 +02:00
ptitSeb 6c6b6f7f13 [DYNAREC] Do not compute db on nn-block jump if no dynarec_log is used 2023-04-16 23:51:42 +02:00
ptitSeb 798546302d Fixed __atomic_is_lock_free wrapped function signature 2023-04-16 21:41:10 +00:00
ptitSeb 65c6945fe3 [RCFILE] Adjusted one profile 2023-04-16 19:09:38 +02:00
ptitSeb e5820feedd Added more gtk2 wrapped functions, and fixed gconf2 wrapped one 2023-04-16 18:35:42 +02:00
ptitSeb df15bf5c59 Added some more gconf2 wrapped functions 2023-04-16 17:42:57 +02:00
ptitSeb 2ccd9da8e8 Added some wrapped function to libnss3 and friends 2023-04-16 17:28:03 +02:00
ptitSeb 18b5d6f1ed Added 2 more wrapped symbols to libm 2023-04-16 17:12:34 +02:00
ptitSeb a78fe12663 [ARM64_DYNAREC] fixed DF E0 opcode 2023-04-16 16:59:34 +02:00
ptitSeb 87fde19623 Do not compute name and other info if they are not shown on signal 2023-04-16 16:47:03 +02:00
ptitSeb 93a4201c66 Do not error out for missing weak R_X86_64_64 binding 2023-04-16 16:31:33 +02:00
ptitSeb 88369e0366 Fixed dependancies for musl programs 2023-04-16 16:31:01 +02:00
ptitSeb e50094e10a Prepend ld_library list instead of append 2023-04-16 15:36:50 +02:00
ptitSeb 4e74819bac Improved/fixed handling of dlopen with RTLD_NOLOAD flag 2023-04-16 15:31:35 +02:00
ptitSeb 084b54723a Fixed an entry on box64.box64rc 2023-04-16 15:31:02 +02:00
ptitSeb 60e830b64c Added 1 more wrapped function to libatomic 2023-04-16 15:21:50 +02:00
ptitSeb 0d52bb291c Added more implied dependancies for musl programs 2023-04-16 15:16:32 +02:00
ptitSeb 9e37c04fb2 Improved support for musl programs 2023-04-16 15:04:43 +02:00
ptitSeb 7870940532 Added some libxml2 and libxst wrapped functions 2023-04-16 12:01:02 +02:00
ptitSeb 3adf31c85b [DYNAREC] General fixes and improvment for multithread and jit program. Helps Java, mono and Unity3d program... (should help #519, #464, #433, #272, #232, #193, #112...) 2023-04-16 10:50:12 +02:00
ptitSeb 9b2c6caf22 Added 1 wrapped function to libdrm 2023-04-16 10:28:51 +02:00
ptitSeb 87b48ee3e5 Fixed segfault at exit of apps 2023-04-16 10:17:49 +02:00
ptitSeb 9880a488ac Another fix for dlopen/dlclose sequence (should be ok now, at last) 2023-04-16 09:32:54 +02:00
Yang Liu f59675e9bf [WRAPPER] Fixed a libFLAC func wrapper (for #701) (#702) 2023-04-16 09:23:27 +02:00
ptitSeb dd3ea0b5e6 More fixes for dlclose/dlopen sequences 2023-04-15 16:18:55 +02:00
ptitSeb 4dbb1f6101 [RV64_DYNAREC] Reorganized pass3 to reduce size of box binary and lower compilation time 2023-04-15 07:04:40 +00:00
ptitSeb ced38e86c4 [ARM64_DYNAREC] Changed name of a utility function 2023-04-15 09:03:09 +02:00
ptitSeb 927b804684 [ARM64_DYNAREC] Reorganized pass3 to reduce size of box binary and lower compilation time 2023-04-15 08:50:51 +02:00
ptitSeb 27de834abc Added 2 GL extensions 2023-04-14 18:22:52 +02:00
ptitSeb 7de8f63b2b Added 1 syscall 2023-04-14 18:22:27 +02:00
ptitSeb f042fe4713 [RV64_DYNAREC] Fixed C1/1 and 6B opcode, plus some slight adjustment to sse_get_reg_empty helper function 2023-04-14 14:50:20 +00:00
Yang Liu 27f3ba941f [RV64_DYNAREC] Added more opcodes for SV (#700)
* [RV64_DYNAREC] Added 66 0F F8 PSUBB opcode

* [RV64_DYNAREC] Added 66 0F FB PSUBQ opcode

* [RV64_DYNAREC] Added 66 0F 68 PUNPCKHBW opcode

* [RV64_DYNAREC] Added F2 0F 5A CVTSD2SS opcode

* [RV64_DYNAREC] Added F2 0F 12 MOVDDUP opcode

* [RV64_DYNAREC] Fixed F2 0F 5A CVTSD2SS opcode
2023-04-14 11:32:35 +02:00
xctan 9413d5deb4 [RV64_DYNAREC] Added more opcodes for SV (#699)
* [RV64_DYNAREC] Added D1 /0 ROL opcode

* [RV64_DYNAREC] Added D1 /1 ROR opcode

* [RV64_DYNAREC] Added {D0,D2} /1 ROR opcode

* [RV64_DYNAREC] Added C1 /1 ROR opcode

* [RV64_DYNAREC] Fixed ROR/ROL flags
2023-04-14 08:44:59 +02:00
Yang Liu 8a903f1e2c [TESTS] Make test09 deterministic (#698) 2023-04-13 20:00:56 +02:00
Yang Liu 9246f4925b [RV64_DYNAREC] Added more 66 0F opcodes for SV and some fixes (#697)
* [RV64_DYNAREC] Added 66 0F 38 00 PSHUFB opcode

* [RV64_DYNAREC] Added 66 0F 38 17 PTEST opcode

* [RV64_DYNAREC] Added 66 0F 38 3A PMINUW opcode

* [RV64_DYNAREC] Added 66 0F C4 PINSRW opcode

* [RV64_DYNAREC] Fixed F2 0F 70 PSHUFLW opcode

* [RV64_DYNAREC] Added 66 0F DD PADDUSW opcode

* [RV64_DYNAREC] Added 66 0F FC PADDB opcode
2023-04-13 19:07:10 +02:00
ptitSeb 128fb82c1c Added 1 more wrapped function to both libicu (for #690) 2023-04-13 15:56:05 +02:00
Yang Liu 3bf4a93a44 [RV64_DYNAREC] Added 0F AE /0,/1 opcodes (#696) 2023-04-13 14:47:20 +02:00
ptitSeb 6460447ae9 [RV64_DYNAREC] Segmented _00 file to improve build time 2023-04-13 11:49:36 +00:00
ptitSeb 344683927f Added wrapped libicuuc67 and libicui18n67, based on 72 version (for #690) 2023-04-13 13:20:45 +02:00
Yang Liu 828f088b6c [RV64_DYNAREC] Added more opcodes for SV and some fixes (#694)
* [RV64_DYNAREC] Added D3 C7 opcode

* [RV64_DYNAREC] Added 0F B3 BTR opcode

* [RV64_DYNAREC] Added D1 /4,6 SHL opcode

* [RV64_DYNAREC] Added 66 0F F3 PSLLQ opcode

* [RV64_DYNAREC] Fixed ROL opcode
2023-04-13 13:06:23 +02:00
ptitSeb d9f4730d0b Added 1 wrapped function to libicuuc72 (for #690) 2023-04-13 09:47:11 +00:00
xctan aa5d320707 [RV64_DYNAREC] Added more opcodes for SV (#693)
* [RV64_DYNAREC] Added 0F 5A CVTPS2PD opcode

* [RV64_DYNAREC] Added F8 CLC opcode

* [RV64_DYNAREC] Added 0F AE /{0,1} FXSAVE and FXRSTOR opcodes

* [RV64_DYNAREC] Added 9D POPF opcode

* [RV64_DYNAREC] Added 11 ADC opcode

* [RV64_DYNAREC] Revert "Added 0F AE /{0,1} FXSAVE and FXRSTOR opcodes"

* [RV64_DYNAREC] Fixed flags handling and CVTPS2PD
2023-04-13 10:33:45 +02:00
Jianfeng Liuandjfliu 69c77c0a24 exclude libstdc++.so.5 in dh_shlibdeps (#692)
Co-authored-by: jfliu <[email protected]>
2023-04-13 08:50:27 +02:00
ptitSeb 5ceedab213 Improve loading/unloading of libs, and fixed a regression when dlopen a lib after some dlclose 2023-04-12 18:20:16 +00:00
ptitSeb 1c4f3cbf19 [DYNAREC] Fixed for good handling of PROT_NOPROT in memory tracking 2023-04-12 10:24:48 +02:00
Yang Liu 90bf55e645 [RV64_DYNAREC] Add more opcodes for SV (#688)
* [RV64_DYNAREC] Added F2 0F 5F MAXSD opcode

* [RV64_DYNAREC] Added 0F A4 SHLD opcode

* [RV64_DYNAREC] Added F0 21 LOCK AND opcode

* [RV64_DYNAREC] Added 66 0F 71 opcodes
2023-04-12 08:52:12 +02:00
Yang Liu e066e920d0 Fixed broken in-project links (#689) 2023-04-11 21:22:18 +02:00
ptitSeb fceaac48a6 [RV64_DYNAREC] Added 0F 14/15 opcodes 2023-04-11 17:49:49 +00:00
xctan 4330b61217 [RV64_DYNAREC] Added more opcodes for SV (#687)
* [RV64_DYNAREC] Added F9 STC opcode

* [RV64_DYNAREC] Fixed F0 09 LOCK OR opcode

* [RV64_DYNAREC] Added C1 /0 ROL opcode

* [RV64_DYNAREC] Fixed F0 09 LOCK OR opcode
2023-04-11 17:20:55 +02:00
ptitSeb 97410042bd [RV64_DYNAREC] Fixed 0F BD opcode (Fixed SV) 2023-04-11 14:37:50 +00:00
Yang Liu 75592bec01 [RV64_DYNAREC] Added more opcodes for SV, some fixes & optims also (#686)
* [RV64_DYNAREC] Added F0 09 LOCK OR opcode

* [RV64_DYNAREC] Added 66 0F 59 MULPD opcode

* [RV64_DYNAREC] Added 66 0F 59 MULPD opcode

* [RV64_DYNAREC] Added 28 SUB opcode

* [RV64_DYNAREC] Added 66 0F 73 /6 PSLLQ opcode

* [RV64_DYNAREC] Added 66 0F 60 PUNPCKLBW opcode

* [RV64_DYNAREC] Added 0F 56 ORPS opcode & optims

* [RV64_DYNAREC] Added 0F 50 MOVMSKPS opcode

* [RV64_DYNAREC] Fixed typos (thanks to cosim!)
2023-04-11 15:05:37 +02:00
ptitSeb e96b1c8106 [RV64_DYNAREC] Added 0F BC/BD opcodes 2023-04-11 13:01:51 +00:00
Yang Liu fdb6908474 [RV64_DYNAREC] Fixed emit_sub8/16 (#685) 2023-04-11 09:11:33 +02:00
ptitSeb 5d63071849 [ELFLOADER] Improved handling of Failed-to-load library (and unloading of libs too) 2023-04-10 18:51:16 +02:00
ptitSeb 8c98c7b675 [DYNAREC] Improved/Fixed PROT_NOPROT handling from bridge 2023-04-10 18:51:16 +02:00
Yang Liu 5eb54321e8 [RV64_DYNAREC] Added more opcodes for SV (#684)
* [RV64_DYNAREC] Added 0F AB BTS opcode

* [RV64_DYNAREC] Added F0 81,83 /4 LOCK AND opcode

* [RV64_DYNAREC] Added F0 81,83 /1 LOCK OR opcode

* [RV64_DYNAREC] Added 66 0F 58 ADDPD opcode

* [RV64_DYNAREC] Added F2 0F 70 PSHUFLW opcode

* [RV64_DYNAREC] Added 0F AC SHRD opcode

* [RV64_DYNAREC] Fixed a copy-paste typo
2023-04-10 18:28:40 +02:00
ptitSeb 9ce44af204 Added some libxcb wrapped functions 2023-04-10 15:58:47 +02:00
ptitSeb 51e840a150 [ELFLOADER] Optimized RelocateElfRELA for subsequent identical symbols 2023-04-10 15:44:18 +02:00
ptitSeb f6b4ec0fdf Added some more wrapped function to libdbus 2023-04-10 15:43:28 +02:00
ptitSeb 8439a3add9 [ELFLOADER] Improved handling of default versions 2023-04-10 14:33:56 +02:00
Yang Liu 9b3511cc88 [RV64_DYNAREC] Added more opcode for SV and some fixes (#683)
* [RV64_DYNAREC] Added 66 0F 67 PACKUSWB opcode

* [RV64_DYNAREC] Added 66 0F 6B PACKSSDW opcode

* [INTERP] Fixed typos

* [RV64_DYNAREC] Fixed 0F BA /7 BTC opcode

* [RV64_DYNAREC] Added 0F BB BTC opcode
2023-04-10 14:10:58 +02:00
ptitSeb 48f80ebc93 Better trace for vfprintf 2023-04-10 11:11:35 +02:00
ptitSeb e1108c5e17 [DYNAREC] Destroy DynaBlock memory when freeing a lib 2023-04-10 11:10:43 +02:00
Ryan Fortner 1d6eee3262 add missing \ to debian rules (#681) 2023-04-09 22:22:05 +02:00
Yang Liu 14bcdee7e2 [RV64_DYNAREC] Added more 66 0F opcode for SV (#680)
* [RV64_DYNAREC] Added 66 0F 15 UNPCKHPD opcode

* [RV64_DYNAREC] Added 66 0F 73 /2 PSRLQ opcode

* [RV64_DYNAREC] Added 66 0F 6A PUNPCKHDQ opcode

* [RV64_DYNAREC] Added 66 0F 66 PCMPGTD opcode

* [RV64_DYNAREC] Added 66 0F 75 PCMPEQW opcode

* [RV64_DYNAREC] Added 66 0F D9 PSUBUSW opcode

* [RV64_DYNAREC] Added 66 0F C5 PEXTRW opcode
2023-04-09 14:33:26 +02:00
Yang Liu ec12de89c8 [RV64_DYNAREC] Small optim for F2 0F 5D MINSD opcode (#678) 2023-04-09 10:10:58 +02:00
ptitSeb 57e858ccc4 Added some more gstreamer wrapped function (in sync with box86) 2023-04-09 09:54:43 +02:00
ptitSeb 2c44452dc6 [ARM64_DYNAREC] Fixed edgecase on MINSD/MAXSD when comparing 0.0 and -0.0 2023-04-09 08:54:55 +02:00
Yang Liu 24f2720df4 [TESTS] Disable compiler optimizations for test17 and some related fixes (#677)
* [TESTS] Disable compiler optimizations for test17

* [INTERP] Fixed MAXSD/MINSD when both sources are 0

* [RV64_DYNAREC] Fixed F2 0F 5D MINSD opcode
2023-04-09 08:41:36 +02:00
Yang Liu d9c30c8942 [RV64_DYNAREC] Added more opcodes for SV and some fixes (#676)
* [RV64_DYNAREC] Added 66 0F 69 PUNPCKHWD opcode

* [RV64_DYNAREC] Added 66 0F D7 PMOVMSKB opcode

* [RV64_DYNAREC] Added 00 ADD opcode

* [RV64_DYNAREC] Fixed emit_xor32

* [RV64_DYNAREC] Added 66 0F 5C SUBPD opcode

* [RV64_DYNAREC] Added 66 0F EE PMAXSW opcode

* [RV64_DYNAREC] Added 66 0F 11 MOVUPD opcode

* [RV64_DYNAREC] Added 66 0F 10 MOVUPD opcode

* [RV64_DYNAREC] Added 66 0F 29 MOVAPD opcode
2023-04-08 19:22:00 +02:00
ptitSeb 6f3d70c69f [ARM64_DYNAREC] Optimized 66 0F 05/06/07 opcodes 2023-04-08 15:43:48 +02:00
ptitSeb 99948b601b Added 66 0F 38 07 opcode ([ARM64_DYNAREC] too) 2023-04-08 14:50:39 +02:00
Yang Liu 24a374500c [RV64_DYNAREC] Added more opcodes for Stardew Valley and some fixes (#674)
* [RV64_DYNAREC] Added 86 (LOCK)XCHG opcode

* [RV64_DYNAREC] Added 66 0F 61 PUNPCKLWD opcode

* [RV64_DYNAREC] Added 66 0F 72 /4 PSRAD opcode

* [RV64_DYNAREC] Added F0 81,83 /5 LOCK SUB opcode

* [RV64_DYNAREC] Fixed 86 (LOCK) XCHG opcode

* [RV64_DYNAREC] Fixed 87 (LOCK) XCHG opcode again

* [RV64_DYNAREC] Fixed 86 (LOCK) XCHG opcode again

* [RV64_DYNAREC] Fixed 66 0F 72 /4 PSRAD opcode
2023-04-08 14:49:35 +02:00
ptitSeb b9cd6d3505 [ARM64_DYNAREC] Fixed 66 0F 3A 0E opode 2023-04-08 14:08:45 +02:00
ptitSeb d9e907535e Added 66 0F 38 2A opcode ([ARM64_DYNAREC] too) 2023-04-08 13:53:21 +02:00
ptitSeb d1426e85b3 Added 66 0F 38 41 opcode 2023-04-08 13:41:29 +02:00
ptitSeb efdd052674 Added 66 0F 3A 41 opcode 2023-04-08 13:36:09 +02:00
ptitSeb 9964a0d9e5 [ARM64_DYNREC] Fixed (again) F2 0F E6 opcode 2023-04-08 13:28:21 +02:00
ptitSeb d3e1cff733 [ARM64_DYNAREC] Fixed 66 0F 38 40 opcode 2023-04-08 13:25:02 +02:00
ptitSeb b5096ad65e Fixed 66 0F 38 40 opcode 2023-04-08 13:24:36 +02:00
ptitSeb 56d0e03991 Added 66 0F 38 28 opcode ({ARM64_DYNAREC] too) 2023-04-08 13:14:38 +02:00
ptitSeb c765943fdf Added 66 0F 3A 42 opcode 2023-04-08 12:14:30 +02:00
ptitSeb 91898d1512 [ARM64_DYNAREC] No DYNAREC_TEST on 0F 52/53 opcodes, as those are aproximation and might trigger false positive 2023-04-08 11:51:04 +02:00
ptitSeb c4d9262abf [ARM64_DYNAREC] Added 66 0F 38 05/06 opcodes 2023-04-08 11:42:16 +02:00
ptitSeb 9b40854d27 Added 66 0F 38 06 opcode 2023-04-08 10:55:05 +02:00
ptitSeb 2092da2907 Fixed 66 0F 3A 08/09/0A/0B opcode 2023-04-08 10:47:42 +02:00
ptitSeb 9b9e489b61 [ARM64_DYNAREC] Fixed 66 0F 3A 08/09/0A/0B opcodes 2023-04-08 10:42:27 +02:00
ptitSeb 9f9831ac56 [ARM64_DYNAREC] Added 66 0F 38 14/15 opcodes 2023-04-08 10:08:44 +02:00
ptitSeb afe5148211 Added 66 0F 38 15 opcode 2023-04-08 10:08:16 +02:00
ptitSeb 5ab1606c47 Added 66 0F 38 0C opcode ([ARM64_DYNAREC] too) 2023-04-08 09:59:25 +02:00
ptitSeb b83ab97a8a [ARM64_DYNAREC] Fixed F2 0F D0 opcode 2023-04-08 09:47:59 +02:00
ptitSeb 6255932e48 [ARM64_DYNAREC] Fixed 66 0F 38 2B opcode 2023-04-08 09:39:34 +02:00
ptitSeb 9ad09a0166 Fixed 66 0F 38 2B opcode 2023-04-08 09:39:11 +02:00
ptitSeb 728a656df4 Added a few wrapped functions to libxcbxfixes (for #675) 2023-04-08 08:36:31 +02:00
ptitSeb 4933a70261 Fixed py wrapper generator for float complex on stack 2023-04-08 08:36:06 +02:00
ptitSeb 02c24dffdc [ARM64_DYNAREC] Fixed, again, FASTROUND=0 for 66 0F E6 opcode 2023-04-07 13:31:48 +02:00
Yang Liu aa7ee8e65d [RV64_DYNAREC] Added more opcodes for Stardew Valley and some fixes (#673)
* [RV64_DYNAREC] Added 66 0F D6 MOVQ opcode

* [RV64_DYNAREC] Added 66 0F 56 ORPD opcode

* [RV64_DYNAREC] Fixed emit_or32c

* [RV64_DYNAREC] Added 0F BA /7 BTC opcode
2023-04-07 13:30:19 +02:00
ptitSeb 64a6a28c30 [ARM64_DYNAREC] Added FASTNAN=0 path for MAXPD/MINPD 2023-04-07 13:15:58 +02:00
ptitSeb f8bdb8bd16 [ARM64_DYNAREC] Fixed 66 0F 5B opcode when FASTROUND=0 2023-04-07 12:58:39 +02:00
ptitSeb 2417faa39b [ARM64_DYNAREC] Fixed 66 0F D1/D2/D3 opcodes 2023-04-07 12:56:35 +02:00
ptitSeb 5c2f62657f Fixed float complex handling as parameter 2023-04-07 12:45:32 +02:00
ptitSeb ae34c7e1cc [ARM64_DYNAREC] Fix/Added 66 0F E1/E2/F1/F2/F3 opcodes 2023-04-07 12:39:26 +02:00
ptitSeb 07a3a0e1c8 [ARM64_DYNAREC] Handling of FASTROUND=0 for 66 0F E6 opcode 2023-04-07 12:39:26 +02:00
ptitSeb c43f4ea080 [ARM64_DYNAREC] Small optim to FASTROUND=0 part for F3 0F 2C/2D opcodes 2023-04-07 12:39:26 +02:00
Yang Liu 149414f233 [RV64_DYNAREC] Added more SSE opcodes for Stardew Valley (#672)
* [RV64_DYNAREC] Fixed 66 0F 73 /7 PSLLDQ opcode

* [RV64_DYNAREC] Added 66 0F 6D PUNPCKHQDQ opcode

* [RV64_DYNAREC] Added F2 0F 2C CVTTSD2SI opcode

* [RV64_DYNAREC] Added 66 0F 7F MOVDQA opcode

* [RV64_DYNAREC] Added 0F C6 SHUFPS opcode

* [RV64_DYNAREC] Added 66 0F 72 /6 PSLLD opcode

* [RV64_DYNAREC] Added 66 0F 74 PCMPEQB opcode

* [RV64_DYNAREC] Added 66 0F FA PSUBD opcode

* [RV64_DYNAREC] Added F2 0F 5D MINSD opcode
2023-04-07 11:34:05 +02:00
ptitSeb 14695faa43 [ARM64_DYNAREC] Handling of FASTROUND=0 for F2 0F E6 opcode 2023-04-07 10:29:52 +02:00
Yang Liu 1159c0530b [RV64_DYNAREC] Added more opcodes for Stardew Valley (#671)
* [RV64_DYNAREC] Fixed PADD opcode

* [RV64_DYNAREC] Added 66 0F 73 /7 PSLLDQ opcode

* [RV64_DYNAREC] Added F2 0F 58 ADDSD opcode

* [RV64_DYNAREC] Added F2 0F 59 MULSD opcode

* [RV64_DYNAREC] Added F3 0F 6F,7F MOVDQU opcode

* [RV64_DYNAREC] Fixed emit_shl32* flagg calculation

* [RV64_DYNAREC] Fixed 8D LEA opcode

* [RV64_DYNAREC] Fixed 66 0F FD PADDW opcode

* [RV64_DYNAREC] Fixed PSHUFD opcode
2023-04-07 08:08:14 +02:00
ptitSeb 053ecec70b [ARM64_DYNAREC] Fixes to 66 0F E1/E2 opcodes 2023-04-06 19:55:34 +02:00
ptitSeb 42601d8451 [ARM64_DYNAREC] Add FASTNAN=0 handling for 0F 5D/5F opcodes 2023-04-06 18:02:46 +02:00
ptitSeb 49392992da [ARM64_DYNAREC] Fixed/improved printer 2023-04-06 18:01:51 +02:00
ptitSeb 545c303058 Added gdk_x11_window_get_type to wrapped libgdk3 2023-04-06 11:36:06 +02:00
ptitSeb 086daef494 Added back some isnan testing to integer conversion (converting a nan, infinite or overflow value to int is UB, and so should be avoided for max cross platform compatibility) 2023-04-06 11:28:47 +02:00
ptitSeb 6898df1c86 [ARM64_DYNAREC] Added FASTROUD=0 to F3 0F 5B opcode 2023-04-06 11:27:34 +02:00
ptitSeb 307a019cb8 Try to add complex function in libm 2023-04-06 10:56:02 +02:00
ptitSeb 4ca16188c2 Updated 0F 2C/2D and 66 0F 2C/2D opcode on par with other float2int opcodes 2023-04-06 10:55:41 +02:00
Alfred E. Neumayer 53687387eb CMakeLists: Allow installation without any config files (#670)
This allows installation of box64 without any configuration files involved.
Intended usecase is packaging box64 with multiple variants in one package,
where multiple variants would step on each other during installation.
2023-04-06 08:11:29 +02:00
Yang Liu eff1cea890 [RV64_DYNAREC] Added more opcodes from SSE tests (#669)
* [RV64_DYNAREC] Added 66 0F 14 UNPCKLPD opcode

* [RV64_DYNAREC] Added 66 0F 57 XORPD opcode

* [RV64_DYNAREC] Added 66 0F 54 ANDPD opcode

* [RV64_DYNAREC] Added 66 0F 62 PUNPCKLDQ opcode

* [RV64_DYNAREC] Added 66 0F FD PADDW opcode

* [RV64_DYNAREC] Added 66 0F D4 PADDQ opcode

* [RV64_DYNAREC] Added 66 0F 55 ANDNPD opcode
2023-04-05 18:28:33 +02:00
ptitSeb 7867c3d906 Added 3 more syscall (for #99) 2023-04-05 14:02:52 +02:00
ptitSeb 5b5f421786 Added syscall 49 (for #99) 2023-04-05 12:07:17 +02:00
Yang Liu 77cc2a6b8e [INTERP] Added 66 0F 2B MOVNTPD opcode & fixed some edge cases (#668)
* [INTERP] Fixed shift amount issues

* [INTERP] Added 66 0F 2B MOVNTPD opcode

* [INTERP] Fixed float to int convert issues
2023-04-05 08:26:57 +02:00
Yang Liu e58ff89044 [RV64_DYNAREC] Added more opcodes for Stardew Valley (#666)
* [RV64_DYNAREC] Added 66 0F 70 PSHUFD opcode

* [RV64_DYNAREC] Added F2 0F 5E DIVSD opcode

* [RV64_DYNAREC] Added F2 0F 2A CVTSI2SD opcode
2023-04-04 22:01:59 +02:00
Yang Liu 57eae464a3 [RV64_DYNAREC] Added 0F BA /4 BT opcode & some fixes (#664)
* [RV64_DYNAREC] Simplified MOVAPS opcode

* [RV64_DYNAREC] Added 0F BA /4 BT opcode

* [RV64_DYNAREC] Fixed 0F 16 MOVHPS opcode
2023-04-04 14:37:25 +02:00
ptitSeb 8ec00e90ba Added 3 wrapped symbol to libxml2 2023-04-02 22:25:32 +02:00
ptitSeb a0f078718a [ARM64_DYNAREC] Fixed typo in 66 0F 5B opcode (fixed sound in many Unity3D games) 2023-04-02 22:16:37 +02:00
ptitSeb b3a2031484 [DYNAREC] Never protect bridge memory (ported from box86) 2023-04-02 18:45:04 +02:00
ptitSeb abf6e4856c [TRACE] Improved trace with xmm registers 2023-04-02 11:31:04 +00:00
Yang Liu 518e6782d8 [RV64_DYNAREC] Reverted changes to GETED and fixed emit_and32* (#663)
* [RV64_DYNAREC] Revert changes to GETED

* [RV64_DYNAREC] Fixed emit_and32*
2023-04-02 12:59:56 +02:00
Yang Liu 2a346ef0b9 [RV64_DYNAREC] Small fixes caught by cosim (#661)
* [RV64_DYNAREC] Fixed emit_xor16

* [RV64_DYNAREC] Fixed an issue with 66 83 /5 SUB

* [RV64_DYNAREC] Fixed GETED for 32bit

* [RV64_DYNAREC] Fixed more emit_xor*
2023-04-02 10:19:29 +02:00
ptitSeb 83a2b2080b [RV64_DYNAREC] Fixed 88 opcode 2023-04-01 19:31:48 +00:00
ptitSeb f21ecb32bb [RV64_DYNAREC] Added F3 0F 2C opcode, and worked on rounding 2023-04-01 18:42:59 +00:00
ptitSeb f810fa262d [RV64_DYNAREC] Some more fixes to float operations (fixes regression in WorldOfGoo) 2023-04-01 17:22:02 +00:00
ptitSeb a847f46edc [RV64_DYNAREC] Fixed F0 83 opcode (LR/SC are tricky to use on RV64) 2023-04-01 11:59:32 +00:00
ptitSeb e710bbcec8 Improved test17 and finetuned factorio profile to disable FASTROUND on Dynarec 2023-04-01 13:18:34 +02:00
ptitSeb 52f8fa1d5b Fixed 66 0F 5B opcodes 2023-04-01 13:18:34 +02:00
ptitSeb 5661de58a8 [ARM64_DYNAREC] Fixed and improved 66 0F 5A/5B opcodes 2023-04-01 13:18:34 +02:00
Yang Liu a1d5cb0e69 [RV64_DYNAREC] Added more opcodes for Stardew Valley (#660)
* [RV64_DYNAREC] Added F0 0F B1 /0 LOCK CMPXCHG opcode

* [RV64_DYNAREC] Added F0 81,83 /0 opcode

* [RV64_DYNAREC] Added 0F 16 MOVHPS opcode
2023-04-01 10:21:25 +02:00
ptitSeb 89ca436e91 [DYNAREC] Some fine-tunning to cosim 2023-04-01 09:34:54 +02:00
ptitSeb d5356bee99 Added a few more symbols to wrapped libnss3 and libnspr4 2023-04-01 08:58:02 +02:00
xctan 0384294cbf [RV64_DYNAREC] Added some DE opcodes (#659)
* [RV64_DYNAREC] Fixed FCOMIP opcode

* [RV64_DYNAREC] Added some DE opcodes

* [RV64_DYNAREC] Fixed register names in printer

* [RV64_DYNAREC] Remove reduncant variable
2023-04-01 08:35:52 +02:00
ptitSeb 0da1f7be27 [RV64_DYNAREC] Fixed issues with x87 handling, plus some fixes on cosim 2023-03-31 20:44:42 +00:00
ptitSeb b24f2f14f0 [DYNAREC] More improvement to TEST_DYNAREC 2023-03-31 21:00:15 +02:00
ptitSeb 40a1fab5e0 [ARM64_DYNAREC] No barrier before native call 2023-03-31 20:59:38 +02:00
ptitSeb 9464cbcf87 [ARM64_DYNAREC] Fixed rounding of 66 0F 38 08/09/0A/0B opcodes 2023-03-31 20:59:38 +02:00
rajdakin 4334a1985b [WRAPPER HELPER] First pass toward a better wrapper helper (#658) 2023-03-31 17:33:40 +02:00
Jai A P ba03124720 Add wrapperhelper from box86 (#657)
* Add wrapperhelper (created by @wannacu, from box86)

- Changes as compared to box86 version:
- Default Guest Triple x64
- Default Host Triple arm64
2023-03-31 14:42:28 +02:00
Yang Liu 27b1e28f63 [RV64_DYNAREC] Added more opcodes (#656)
* [RV64_DYNAREC] Added a TODO

* [RV64_DYNAREC] Added F3 0F 5D MINSS opcode

* [RV64_DYNAREC] Added F3 0F 5F MAXSS opcode
2023-03-31 14:06:22 +02:00
ptitSeb 4431ef7736 Added 66 0F 3A 08/09 opcodes ([ARM64_DYNAREC] too) 2023-03-31 12:23:35 +02:00
Yang Liu 4c86c8c264 [RV64_DYNAREC] Added more opcodes (#655)
* [RV64_DYNAREC] Added 66 0F 28 MOVAPD opcode

* [RV64_DYNAREC] Added 66 0F 2E,2F COMISD opcode

* [RV64_DYNAREC] Added F2 0F C2 CMPSD opcode

* [RV64_DYNAREC] Added 0F AE /3 STMXCSR opcode

* [RV64_DYNAREC] Added 0F AE /2 LDMXCSR opcode
2023-03-31 10:00:15 +02:00
Yang Liu 275550a9c3 [RV64_DYNAREC] Added more SS opcodes (#654)
* [RV64_DYNAREC] Added F3 0F 5E DIVSS opcode

* [RV64_DYNAREC] Small optim for 0F 2E,2F COMISS opcode

* [RV64_DYNAREC] Added F3 0F C2 CMPSS opcode

* [RV64_DYNAREC] Added 9C PUSHF opcode
2023-03-31 08:16:33 +02:00
ptitSeb 38cf61209e [RV64_DYNAREC] Some more fixes to a few opcode (thanks to cosim) 2023-03-30 20:25:16 +00:00
Yang Liu 8670e9e5aa [RV64_DYNAREC] Added 0F 2E,2F opcode & some fixes in printer (#653)
* [RV64_DYNAREC] Fixed some issues in printer

* [RV64_DYNAREC] Added 0F 2E,2F opcode
2023-03-30 19:54:34 +02:00
ptitSeb 260eeacbeb [DYNAREC] Better handling of forward blocks with unused opcode in between 2023-03-30 17:50:14 +00:00
ptitSeb 13b2aed936 [RV64_DYNAREC] Small cosmetic change with DUMP of fpu regs 2023-03-30 16:49:10 +00:00
ptitSeb 88431b9286 [DYNAREC] Changed again how the current IP is tracked in TEST_INTERPRETER mode 2023-03-30 16:46:42 +00:00
ptitSeb a12c6b7bef [RV64_DYNAREC] Fixed fpu regs unwind helper function 2023-03-30 16:45:45 +00:00
ptitSeb f81d99289f [RV64_DYNAREC] pass0 and 1 where missing fpu propagation 2023-03-30 15:19:34 +00:00
ptitSeb 97739f8852 [RV64_DYNAREC] Fixed F0 0F C1 XADD opcode 2023-03-30 14:25:49 +00:00
ptitSeb bdc0309296 [DYNAREC] This should make TEST_INTERPRETER faulty IP output more coherent (for good this time) 2023-03-30 13:51:13 +00:00
ptitSeb e1a5edefc1 [DYNAREC] This should make TEST_INTERPRETER foaulty IP output more coherent 2023-03-30 13:39:46 +00:00
ptitSeb 373c400cc3 [DYNAREC] Fixed TEST_INTERPRETER when jumping to a non-dynarec block 2023-03-30 13:15:57 +00:00
ptitSeb d93e53498d [DYNAREC] Fixed handling of x87 top and stack on TEST_INTERPRETER 2023-03-30 14:00:27 +02:00
xctan e82d526414 [RV64_DYNAREC] Added DF F0+i FCOMIP and DF /0 FILD opcodes (#649) 2023-03-30 12:08:40 +02:00
Yang Liu 0f11b55ba3 [RV64_DYNAREC] Added more opcodes (#651)
* [RV64_DYNAREC] Added 66 81,83 /2 ADC opcode

* [RV64_DYNAREC] Added 66 0F 73 /3 PSRLDQ opcode

* [RV64_DYNAREC] Added 66 0F 7E MOVD opcode

* [RV64_DYNAREC] Added F3 0F 5C SUBSS opcode

* [RV64_DYNAREC] Added 0F 54 ANDPS opcode

* [RV64_DYNAREC] Added 66 0F 6C PUNPCKLQDQ opcode
2023-03-29 17:49:50 +02:00
Yang Liu a665d2f62c [RV64_DYNAREC] Added some 66 0F Pxxx opcodes (#650)
* [RV64_DYNAREC] Fixed typos

* [RV64_DYNAREC] Added 66 0F FE PADDD opcode

* [RV64_DYNAREC] Added 66 0F DB PAND opcode

* [RV64_DYNAREC] Added 66 0F 76 PCMPEQD opcode

* [RV64_DYNAREC] Added 66 0F 72 /2 PSRLD opcode

* [RV64_DYNAREC] Added 66 0F DF PANDN opcode

* [RV64_DYNAREC] Added 66 0F EB POR opcode

* [RV64_DYNAREC] Fixed 66 0F 72 PSRLD opcode
2023-03-29 08:55:33 +02:00
ptitSeb 0baa5a82ad Added comment on how to build test18 (for #648) 2023-03-29 08:45:36 +02:00
Yang Liu 0ea1775084 [RV64_DYNAREC] Fixed more issues caught by cosim (#647)
* [RV64_DYNAREC] Fixed 0F AF IMUL opcode

* [RV64_DYNAREC] NOTEST on divs for brevity
2023-03-28 19:56:46 +02:00
ptitSeb 2fda0bd12b [DYNAREC] Some more improvment to TEST_INTERPRETER 2023-03-28 19:50:36 +02:00
ptitSeb 3b5c9e7a84 [RV64_DYNAREC] Fixed some edge case issues with conditionnal jumps 2023-03-28 13:32:46 +00:00
Yang Liu c0d8e7e245 [RV64_DYNAREC] Fixed issues caught by newly added cosim framework (#645)
* [RV64_DYNAREC] Fixed an issue in 0F AF IMUL opcode

* [RV64_DYNAREC] Fixed typos with LUI

* [RV64_DYNAREC] Fixed 66 D1,D3 /7 SAR opcode

* [RV64_DYNAREC] Fixed 66 69,6B IMUL opcode
2023-03-28 14:14:58 +02:00
ptitSeb d73ff21b27 [DYNAREC] Improved TEST_INTERPRETER with inter-block testing 2023-03-28 13:34:56 +02:00
xctan 4a90199f63 [RV64_DYNAREC] Added more D8 opcodes (#646)
* [RV64_DYNAREC] Added D8 /{1,4} opcodes

* [RV64_DYNAREC] Added D8 /6 FDIV opcode
2023-03-28 12:13:13 +02:00
ptitSeb 0dab0b5969 [DYNAREC] Cleaned up the TEST_INTERPRETER a bit 2023-03-28 09:59:20 +02:00
ptitSeb 8e9bdf4115 [RV64_DYNAREC] Fixed issue with RIP synchronizing on BOX64_DYNAREC_TEST 2023-03-27 22:20:48 +00:00
ptitSeb 613cbb8601 [ARM664_DYNAREC] Fixed a potential issue with RIP synchronizing on BOX64_DYNAREC_TEST 2023-03-28 00:20:09 +02:00
ptitSeb 8cf02324ce [DYNAREC] This should fix non-Trace build 2023-03-27 23:36:09 +02:00
ptitSeb 9f75f28e7a [DYNAREC] Added BOX64_DYNAREC_TEST to run interpeter and dynarec at the same time and compare states 2023-03-27 23:21:36 +02:00
ptitSeb feb4a39457 Improved handling of libssl/libcrypto version 1.1 and 3.0 2023-03-27 19:35:27 +00:00
xctan cca1fd6f19 [RV64_DYNAREC] Added D8 /0 FADD opcode (#642)
* [RV64_DYNAREC] Fix broken x87_get_cache()

* [RV64_DYNAREC] Added D8 /0 FADD opcode
2023-03-27 10:00:39 +02:00
josch 4fb126635c add manual page in pod format (#641) 2023-03-27 08:42:28 +02:00
ptitSeb 9f282c2898 [RV64_DYNAREC] More opcodes, and a few fixes too 2023-03-26 16:38:12 +00:00
ptitSeb be3b95db6b Fixed flag handling of PTEST opcode 2023-03-26 17:09:26 +02:00
ptitSeb c02b350b3d [ARM64_DYNAREC] Fixed flag handling of PTEST opcode 2023-03-26 16:13:24 +02:00
ptitSeb 85f6d8308a [RV64_DYNAREC] Added a bunch of opcodes, plus some improvments/fixes to SSE macros 2023-03-26 12:28:53 +00:00
ptitSeb 06f2750eef [ARM64_DYNAREC] Added 66 0F 38 17 opcode 2023-03-26 11:21:36 +02:00
ptitSeb 5f078848f1 [DYNAREC] Fixed rolling back for failled forward block 2023-03-26 10:23:00 +02:00
ptitSeb 6ff68849f8 |CMAKE] Added NO_LIB_INSTALL to not install x86_64 libs (they will probably need to be installed by some other mean) 2023-03-26 10:13:45 +02:00
josch 2ea036e02c fix some spelling mistakes (#640) 2023-03-26 09:59:00 +02:00
ptitSeb f58ac3e9bf Added wrapped libicuuc and libicui18n v72 (help Stardew Valley) 2023-03-26 07:58:05 +00:00
ptitSeb 56e161d1ff [RV64_DYNAREC] Fixed CreateJumpNext function 2023-03-25 22:23:02 +00:00
ptitSeb 85da2b7e23 [DYNAREC] Some fixes and small improvment to common codeblock generator 2023-03-25 22:22:22 +00:00
ptitSeb da7136ab7e [RV64_DYNAREC] One fix for this bug is enough 2023-03-25 20:44:40 +00:00
Yang Liu 73264b2e80 [RV64_DYNAREC] Fixes and some optims (#638) 2023-03-25 21:23:46 +01:00
ptitSeb 567d48f813 [RV64_DYNAREC] Some more fixes with sign extension issues 2023-03-25 20:23:07 +00:00
ptitSeb 0c3d350865 [RV64_DYNAREC] Fixed GETEDH helper macro, and small optim to F7 /0 /1 opcodes 2023-03-25 20:23:07 +00:00
ptitSeb 65211c94c3 [RV64_DYNAREC] Fixed rv64_lock_decifnot0b function 2023-03-25 20:23:07 +00:00
Jai A P b3b84f8357 Latest batch of PKGBUILD updates (#637)
* Latest batch of PKGBUILD updates

- New platforms added
- Combined PKGBUILD for all Raspberry Pi devices
- Combined PKGBUILD for all RockChip devices

* Fixes

- Fix arch in rv64 and x86_64
- Remove la64 since arch linux not available for platform

* No LARCH64 PKGBUILD
2023-03-25 20:50:31 +01:00
ptitSeb a49d12b887 [RV64_DYNAREC] Small optim on fetch segment offset 2023-03-25 17:17:44 +00:00
ptitSeb b5cb7e5649 Improved elf loading at specific addresses 2023-03-25 17:17:44 +00:00
Yang Liu c27c2b3487 [RV64_DYNAREC] Fixed minor issues (#636) 2023-03-25 18:17:17 +01:00
ptitSeb 56e9805562 Added wrapped libnuma 2023-03-25 12:01:23 +00:00
ptitSeb f197e750b6 Added some wrapped functions in pthread 2023-03-25 10:38:03 +00:00
ptitSeb 206bc9afb6 [RV64_DYNAREC] Added 66 0F EF PXOR opcode 2023-03-25 10:21:46 +00:00
ptitSeb ffcfa5b2cb Added support for running native SDL2_mixer (and image/ttf too) with emulated SDL2 2023-03-25 09:35:58 +00:00
ptitSeb afae5d80c7 [RV64][LA464][PPC64] Fixed some issues with VALIST handling 2023-03-25 09:25:25 +00:00
Yang Liu 5e680e0f66 [RV64_DYNAREC] Added more opcodes (#633)
* [RV64_DYNAREC] Added 81,83 /2 ADC opcode

* [RV64_DYNAREC] Added 34 XOR opcode

* [RV64_DYNAREC] Added 66 3B CMP opcode

* [RV64_DYNAREC] Added 66 09 OR opcode

* [RV64_DYNAREC] Added 66 D1,D3 /5 SHR opcode

* [RV64_DYNAREC] Added 30 XOR opcode

* [RV64_DYNAREC] Added F6 /5 IMUL opcode

* [RV64_DYNAREC] Added 0C OR opcode

* [RV64_DYNAREC] Added 2A SUB opcode

* [RV64_DYNAREC] Added 66 01 ADD opcode

* [RV64_DYNAREC] Added 81,83 /3 SBB opcode

* [RV64_DYNAREC] Added 66 69,6B LMUL opcode

* [RV64_DYNAREC] Added 66 03 ADD opcode

* [RV64_DYNAREC] Added 18 SBB opcode & some fixes & some optims

* [RV64_DYNAREC] Added F6 /2 NOT opcode

* [RV64_DYNAREC] Added C0 /0 ROL opcode & bug fixes

* [RV64_DYNAREC] Added 6A PUSH opcode
2023-03-24 17:21:06 +01:00
Yang Liu 45015d6106 [RV64_DYNAREC] Added more opcodes & some fixes & some optimizations (#632)
* [RV64_DYNAREC] Added 66 D1,D3 SAR opcode

* [RV64_DYNAREC] Added 66 F7 /7 IDIV opcode

* [RV64_DYNAREC] Fixed 32 XOR opcode

* [RV64_DYNAREC] Some small optims

* [RV64_DYNAREC] Added 66 33 XOR opcode

* [RV64_DYNAREC] Added 66 81,83 /6 XOR opcode

* [RV64_DYNAREC] Added 66 31 XOR opcode

* [RV64_DYNAREC] Fixed a typo in IDIV opcode

* [RV64_DYNAREC] Added A4 REP MOVSB opcode

* [RV64_DYNAREC] Fixed 66 35 XOR opcode

* [RV64_DYNAREC] Added 66 39 CMP opcode

* [RV64_DYNAREC] Added F6 /7 IDIV opcode

* [RV64_DYNAREC] Added 1C SBB opcode

* [RV64_DYNAREC] Added 66 05 ADD opcode
2023-03-24 13:12:42 +01:00
Yang Liu c3223245e5 [RV64_DYNAREC] Added more opcodes (#631)
* [RV64_DYNAREC] Added 80 /6 XOR opcode

* [RV64_DYNAREC] Added 02 ADD opcode

* [RV64_DYNAREC] Added 66 23 AND opcode

* [RV64_DYNAREC] Added 66 0B OR opcode

* [RV64_DYNAREC] Added 32 XOR opcode

* [RV64_DYNAREC] Added 08 OR opcode

* [RV64_DYNAREC] Added 20 AND opcode

* [ARM64_DYNAREC] Fixed a issue with 66 0F BE MOVSX opcode
2023-03-24 08:18:55 +01:00
xctan fdf43e5874 [RV64_DYNAREC] Added more opcodes and optimize printer output (#630)
* [RV64_DYNAREC] Added 08 OR opcode

* [RV64_DYNAREC] Improve printer output readability

* [RV64_DYNAREC] Added 66 0F BE MOVSX opcode

* [RV64_DYNAREC] Added 66 2B SUB opcode

* [RV64_DYNAREC] Optimize printer output for auipc

* [RV64_DYNAREC] Added F6 /6 DIV opcode

* [RV64_DYNAREC] Added 66 35 XOR opcode

* [RV64_DYNAREC] Fixed 66 0F BE MOVSX opcode
2023-03-24 08:15:44 +01:00
Yang Liu dcc1a5db52 [RV64_DYNAREC] Added more opcodes (#629)
* [RV64_DYNAREC] Added 66 83 /5 SUB opcode

* [RV64_DYNAREC] Added 2D SUB opcode

* [RV64_DYNAREC] Added F7 /3 NEG opcode

* [RV64_DYNAREC] Added 66 2D SUB opcode

* Fixed a typo

* [RV64_DYNAREC] Added 66 0D OR opcode

* [RV64_DYNAREC] Added 66 81,83 /4 AND opcode

* [RV64_DYNAREC] Added 66 F7 /0,1 TEST opcode

* [RV64_DYNAREC] Added 80 /1 OR opcode and fixed some potential issues
2023-03-23 20:25:22 +01:00
ptitSeb 46ed52032d |RV64_DYNAREC] Fixed an issue with F7 /7 IDIV opcode 2023-03-23 19:22:12 +00:00
Yang Liu 345a52b153 [RV64_DYNAREC] Added more opcodes (#628)
* [RV64_DYNAREC] Added D0 /7 SAR opcode

* [RV64_DYNAREC] Added 22 AND opcode
2023-03-23 16:43:33 +01:00
ptitSeb 2accb00adc Added/Fixed 66 0F 3A 14/15/16 opcodes ([ARM64_DYNAREC] too) 2023-03-23 13:35:21 +01:00
Yang Liu 65c672fa1c Update README (#626) 2023-03-23 11:59:21 +01:00
ptitSeb f430dafb30 Addedsome more syscall (for #616) 2023-03-23 10:41:48 +01:00
Yang Liu 44524c057d [RV64_DYNAREC] Added more opcodes (#625)
* [RV64_DYNAREC] Added 0B OR opcode

* [RV64_DYNAREC] Added 35 XOR opcode
2023-03-23 09:27:04 +01:00
Yang Liu a42322be99 [RV64_DYNAREC] Fixed F7 /6 DIV opcode (#624) 2023-03-23 08:50:24 +01:00
Yang Liu 6d8de238a0 [ARM64_DYNAREC] Fixed UFLAG_OP12 helper macro (#623) 2023-03-23 08:10:43 +01:00
Yang Liu c0d3135e54 [RV64_DYNAREC] Added A5 REP MOVSD opcode (#622)
And replace ADDI with SUBI for readability
2023-03-23 08:09:47 +01:00
xctan b8b5203d08 [RV64_DYNAREC] Fixed register name of float load/store (#621) 2023-03-23 08:08:12 +01:00
Sevan Janiyan f087afd796 docs/COMPILE.md: Use trusted.gpg.d (#620)
Installing the keys in the system location will likely cause fallout in upgrades.
Install into /etc/apt/trusted.gpg.d where it's commonly expected.
2023-03-23 08:05:15 +01:00
ptitSeb 91a230b38d [RV64_DYNAREC] Added F3 0F 2A/58/59/5A opcodes (and test07 run all in dynarec) 2023-03-22 20:25:08 +00:00
Yang Liu 72dc25abd1 [RV64_DYNAREC] Added more opcodes and some fixes (#619)
* [RV64_DYNAREC] Fixed SUB opcode

* [RV64_DYNAREC] Added F6 /4 MUL opcode

* [RV64_DYNAREC] Added 66 21 AND opcode
2023-03-22 20:33:09 +01:00
Yang Liu b85b3d9bbd [RV64_DYNAREC] Added more opcodes (#618)
* [RV64_DYNAREC] Added 80 /5 SUB opcode

* [ARM64_DYNAREC] Fixed a typo in emit_sub8c

* [RV64_DYNAREC] Added 2C SUB opcode
2023-03-22 19:23:08 +01:00
ptitSeb b6188abeeb [RV64_DYNAREC] Added F3 0F 10 and 11 opcodes 2023-03-22 17:55:06 +00:00
ptitSeb 1cd9fac9fb [RV64_DYNAREC] Added F2 0F 10 and 11 opcodes 2023-03-22 17:49:59 +00:00
ptitSeb f1a2a7cfe9 Added expl wrapped function (for #616) 2023-03-22 18:03:52 +01:00
xctan f7fdd0a63a [RV64_DYNAREC] Added more opcodes (#617)
* [RV64_DYNAREC] Added 38 CMP opcode

* [RV64_DYNAREC] Added 66 98 CBW opcode

* [RV64_DYNAREC] Added 80 /0 ADD opcode

* [RV64_DYNAREC] Added 64 2B SUB opcode

* [RV64_DYNAREC] Added 66 0F AF IMUL opcode

* [RV64_DYNAREC] Fixes and small optim
2023-03-22 17:47:11 +01:00
ptitSeb 79ec2ee8f7 [RV64_DYNAREC] Improved handling of Float/Double cache on functions calls 2023-03-22 12:34:45 +00:00
ptitSeb 5c4f0de1d0 [RV64_DYNAREC] Added some x87 D9 opcodes 2023-03-22 10:50:16 +00:00
xctan b9c1b1a5ea [RV64_DYNAREC] Added more opcodes (#614)
* [RV64_DYNAREC] Added 66 {81,83} /7 CMP opcode

* [RV64_DYNAREC] Added 66 {81,83} /0 ADD opcode

* [RV64_DYNAREC] Added 66 F7 /6 DIV opcode

* [RV64_DYNAREC] Added {D0,D2} /5 SHR opcode
2023-03-22 11:40:21 +01:00
Yang Liu 75036c43b5 [RV64_DYNAREC] Fixed 88 MOV opcode (#613) 2023-03-22 08:35:44 +01:00
Yang Liu 3656cd66ea [RV64_DYNAREC] Added more opcode (#612)
* [RV64_DYNAREC] Added 66 {90:97} NOP opcode

* [RV64_DYNAREC] Added more 16bit opcodes
2023-03-22 07:47:56 +01:00
Yang Liu da88b87279 [RV64_DYNAREC] Added AB STOSD opcode (#611) 2023-03-22 07:45:57 +01:00
ptitSeb 900f38779d [RV64_DYNAREC] Added x87/SSE/mmx infrastructure, and a few x87 D9 opcodes 2023-03-21 20:20:35 +00:00
ptitSeb d369ac8bf5 Added 2 wrapped function to libatomic (for #609) 2023-03-21 17:56:46 +01:00
xctan 244eca4b38 [RV64_DYNAREC] Added some opcodes (#608)
* [RV64_DYNAREC] Added 05 ADD opcode

* [RV64_DYNAREC] Added 0D OR opcode

* [RV64_DYNAREC] Added 0A OR opcode

* [RV64_DYNAREC] Fixed F_ZF in emit logic
2023-03-21 10:18:33 +01:00
xctan 67690748bd [RV64_DYNAREC] Added B0 MOV opcode and small optim (#607) 2023-03-21 08:31:41 +01:00
xctan 218ceb8a2a [RV64_DYNAREC] Fixed lr.d and sc.d instruction name in printer (#606) 2023-03-21 08:30:47 +01:00
Yang Liu 39ec81117d [RV64_DYNAREC] Added 19 SBB opcode (#605) 2023-03-20 21:10:31 +01:00
Yang Liu 70f91204b1 [RV64_DYNAREC] Added F0 0F C1 LOCK XADD opcode (#604)
* [RV64_DYNAREC] Added F0 0F C1 LOCK XADD opcode

* [RV64_DYNAREC] Added lr/sc support for printer
2023-03-20 19:24:53 +01:00
xctan f4739ae147 [RV64_DYNAREC] Added 6B IMUL opcode (#603) 2023-03-20 16:54:47 +01:00
xctan 518125b836 [RV64_DYNAREC] Added C0 /{4,5,6,7} opcode (#601)
* [RV64_DYNAREC] Added C0 /5 SHR opcode

* [RV64_DYNAREC] Added C0 /{4,6,7} opcode

* [RV64_DYNAREC] Fixed EBBACK macro
2023-03-20 16:53:13 +01:00
xctan 7d4b353780 [RV64_DYNAREC] Added {21,23} AND opcode (#602) 2023-03-20 16:21:11 +01:00
Yang Liu dbede8d6df [RV64_DYNAREC] Added more opcode (#600)
* [RV64_DYNAREC] Added F6 /{0,1} TEST opcode

* [RV64_DYNAREC] Added 25 AND opcode

* [RV64_DYNAREC] Added 3D CMP opcode

* [RV64_DYNAREC] Added A9 TEST opcode
2023-03-20 13:26:09 +01:00
Yang Liu 5c48c72b56 [RV64_DYNAREC] Added 66 89 MOV opcode (#599) 2023-03-20 13:24:42 +01:00
Yang Liu 8f52a3a3cc [RV64_DYNAREC] Added 66 3D CMP opcode (#598) 2023-03-20 11:48:09 +01:00
Yang Liu 61a6af1de7 [RV64_DYNAREC] Added 80 /3 SBB opcode (#597)
* [RV64_DYNAREC] Simplify SET_DFNONE

* [RV64_DYNARC] Fixed 80 /3 AND opcode

* [RV64_DYNAREC] Added 80 /3 SBB opcode
2023-03-20 11:09:59 +01:00
ptitSeb 77f8bea615 [RV64_DYNAREC] Preparing float/double handling 2023-03-20 09:44:57 +00:00
ptitSeb bb49bc7844 [TRACE] Better debug info for ov_read function 2023-03-20 09:44:30 +00:00
Yang Liu c56ad76d18 [RV64_DYNAREC] Added 80 /4 AND opcode (#594) 2023-03-20 08:17:54 +01:00
ptitSeb b5dd04aa12 Added 1 more libxkbcommon wrapped function (for Heroic) 2023-03-19 17:44:54 +01:00
ptitSeb 788724a1ca Added 1 more libxcb wrapped function (for Heroic) 2023-03-19 17:43:38 +01:00
ptitSeb d577eb338c Added 2 more libasound wrapped function (for Heroic) 2023-03-19 17:42:01 +01:00
ptitSeb 639ce20ecc Added 1 more gio2 and gtk3 wrapped function (for Heroic) 2023-03-19 17:39:45 +01:00
ptitSeb 27b6715910 Added 2 more libcups wrapped functions (for Heroic) 2023-03-19 17:36:46 +01:00
ptitSeb b8ef8565e8 Added some more atspi wrapped symbols (for Heroic) 2023-03-19 17:27:23 +01:00
ptitSeb 6d2f855af2 Added some more atk wrapped symbols (for Heroic) 2023-03-19 17:23:59 +01:00
ptitSeb ae81bbb441 [RV64_DYNAREC] Various fixes and improvements, getting dynarec more stable now 2023-03-19 14:12:20 +00:00
ptitSeb 7db570af13 Rmoved the 32bits->64bits wrapper hack (there might be some regression, but it's needed for riscv and other architectures wich sign extend ther 32bits values) 2023-03-19 11:52:34 +01:00
ptitSeb 6a21831894 Now handling the BIND_NOW flags in elf header 2023-03-19 11:28:24 +01:00
ptitSeb ee49851de4 [RV64_DYNAREC] Various important fixes 2023-03-19 09:46:09 +00:00
Yang Liu e1ca614f1c [RV64_DYNAREC] Added more opcode (#591)
* [RV64_DYNAREC] Added 84 TEST opcode

* [RV64_DYNAREC] Added 64 8B MOV opcode

* [RV64_DYNAREC] Added {B4,B5,B6,B7} MOV opcode

* [RV64_DYNAREC] Added 3C CMP opcode

* [RV64_DYNAREC] Added {81,83} /1 OR opcode

* [RV64_DYNAREC] Fixed MOV opcode
2023-03-19 10:28:33 +01:00
xctan 01d1ea0b90 Added FF /0 INC opcode (#592) 2023-03-19 09:40:52 +01:00
ptitSeb 59ada379e2 [RV64_DYNAREC] Small optim on last_ip 2023-03-18 21:18:12 +00:00
Yang Liu 52715c9220 [RV64_DYNAREC] Fixed BF MOVSX opcode (#590) 2023-03-18 21:44:40 +01:00
ptitSeb 4409fb9b21 [RV64_DYNAREC] Fixed Jcc opcodes for large block 2023-03-18 20:29:41 +00:00
Yang Liu e845d02242 [RV64_DYNAREC] Fixed 63 MOVSXD opcode (#589) 2023-03-18 21:27:28 +01:00
Yang Liu 35ed5b3c9b [RV64_DYNAREC] Fixed B6 MOVZX opcode (#588) 2023-03-18 21:09:24 +01:00
Yang Liu 2567088192 [RV64_DYNAREC] Added 33 XOR opcode (#587) 2023-03-18 20:56:40 +01:00
Yang Liu 26a083e700 [RV64_DYNAREC] A8 TEST opcode (#586) 2023-03-18 20:56:17 +01:00
ptitSeb 8c4c87112c [RV64_DYNAREC] Some optims on XOR opcodes 2023-03-18 18:12:47 +00:00
Yang Liu d052603335 [CI] Avoid copying files (#584) 2023-03-18 19:00:26 +01:00
ptitSeb 01395fc579 [ARM64_DYNAREC] Fixed some special cases for the Double Pop optim (fixed steamwebhelper and all chrome/libcef based apps) 2023-03-18 18:36:10 +01:00
ptitSeb bbe15eab7e Added some wrapped function to libnspr4 2023-03-18 16:07:49 +01:00
ptitSeb 015842ed83 Added many wrapped functons to libnss 2023-03-18 16:05:10 +01:00
ptitSeb d76f346648 Added 1 wrapped function to libexpat 2023-03-18 15:37:13 +01:00
ptitSeb 34a5ab7498 Added some wrapped functions to libcurl 2023-03-18 15:35:39 +01:00
ptitSeb 72e537e951 Added some wrapped functions to libgio2 and libglib2 2023-03-18 15:28:20 +01:00
ptitSeb 670c067891 Added some wrapped function to libatspi 2023-03-18 15:04:39 +01:00
ptitSeb 5ec4616614 Added a wrapped function to libxcbdri3 2023-03-18 14:48:06 +01:00
ptitSeb bae9ef77e5 Added some more wrapped function to libatk 2023-03-18 14:45:56 +01:00
ptitSeb b2484afe96 [RV64_DYNAREC] Fixed an issue with UFLAG_OP12 helper macro 2023-03-18 13:41:23 +00:00
ptitSeb e2e7479b8e Added some libatk wrapped functions 2023-03-18 14:31:36 +01:00
ptitSeb cad38fe6da [RV64_DYNAREC] Added F7 except /3 opcodes, plus some fixes (and test05 run all in dynarec now) 2023-03-18 13:23:43 +00:00
ptitSeb f5bfb537da Added 3 more function to libasound 2023-03-18 14:20:24 +01:00
ptitSeb e7f8ebaf77 Added some wrapped function to libdrm 2023-03-18 14:14:30 +01:00
ptitSeb 29eab14f79 [ARM64_DYNAREC] Fixed a potential issue with F7/7 IDIV opcode 2023-03-18 14:03:34 +01:00
ptitSeb febcc8995d Removed an optim on TLS, it break things (fix regression on exiting many games, like Valheim) 2023-03-18 11:57:44 +01:00
ptitSeb 72cc87b012 [RV64_DYNAREC] Added 66 C1 opcodes 2023-03-18 10:29:47 +00:00
ptitSeb 5705e471b7 [RV64_DYNAREC] Added 69 IMUL opcode 2023-03-18 10:12:17 +00:00
ptitSeb d8e30eb793 [RV64_DYNAREC] Added 0F BF MOVSX opcode 2023-03-18 09:27:43 +00:00
ptitSeb 2c903dcb67 [RV64_DYNAREC] Added 0F BE MOVSX opcode 2023-03-18 09:23:26 +00:00
ptitSeb 2d3aafefe1 [RV64_DYNAREC] Added 66 C7 MOV opcode 2023-03-18 09:15:28 +00:00
ptitSeb 5b1f16d7e9 [RV64_DYNAREC] Added 09 OR opcode 2023-03-18 09:09:58 +00:00
ptitSeb 4b74a1be58 [RV64_DYNAREC] Added D3 /4 /5 SHL opcode 2023-03-18 08:55:51 +00:00
ptitSeb 2aeb77736f [RV64_DYNAREC] Added D3/7 SAR opcode 2023-03-18 08:41:31 +00:00
ptitSeb 4a9d2d92d3 [RV64_DYNAREC] Added 99 CDQ opcode 2023-03-18 08:27:34 +00:00
ptitSeb 15c051e3ad [RV64_DYNAREC] Added 63 MOVSXD opcode 2023-03-18 08:20:21 +00:00
ptitSeb 6ee2fbf88c [RV64_DYNAREC] Added 88 MOV opcode 2023-03-18 08:14:08 +00:00
ptitSeb 5665653b7d [RV64_DYNAREC] Added 83 /1 OR opcode 2023-03-18 07:57:09 +00:00
ptitSeb e7c0480bc3 [RV64_DYNAREC] Added 0F B6/B7 MOVZX opcodes 2023-03-18 07:44:18 +00:00
Yang Liuandxctan 241cec6e43 Enable test for RV64 and ARM64 in CI (#583)
If we can pass the environment variable `QEMU_LD_PREFIX=/usr/{riscv64,aarch64}-linux-gnu/lib/`
to ctest, it should also work and be cleaner, but I don't know how to do it as
I am not familiar with cmake.

Note that TEGRAX1 is not currently working because of a mismatch in GLIBC version.
Therefore, we skipped this platform.

Co-authored-by: xctan <[email protected]>
2023-03-18 07:38:02 +01:00
ptitSeb d8328b6f6e Added some wrapped libfreetype symbols (for #581) 2023-03-17 11:50:26 +01:00
xctan 9e91f6f8d9 [RV64_DYNAREC] Added 03 ADD opcode (#582) 2023-03-17 11:19:22 +01:00
xctan 69b381fb66 [RV64_DYNAREC] Added 2B SUB opcode (#580) 2023-03-17 10:50:47 +01:00
Yang Liu ffa74500e6 [RV64_DYNAREC] Added 0F AF IMUL opcode (#579) 2023-03-17 10:39:57 +01:00
xctan 356c135cbe [RV64_DYNAREC] Added 3B CMP opcode (#578) 2023-03-17 10:37:05 +01:00
Yang Liu 9e05a02bbf [RV64_DYNAREC] Added C1 /(4/6) SHL opcode (#577) 2023-03-17 07:55:14 +01:00
ptitSeb b63dcabca4 [RV64_DYNAREC] Added some C9 LEAVE opcode (after test01, now test02 fully runs on Dynarec) 2023-03-16 20:10:16 +00:00
ptitSeb cc9191382f [RV64_DYNAREC] Added some 66 0F prefixed opcodes 2023-03-16 20:06:18 +00:00
ptitSeb 0e86633cde [ARM64_DYNAREC] Fixed ARM64 build 2023-03-16 19:04:01 +00:00
ptitSeb 9212e832e6 [DYNAREC] Fixed RV64 build and moved some functions between common and arch specific 2023-03-16 19:02:26 +00:00
ptitSeb 848763bb5c [DYNAREC] Grouped common function in dynarec_native_functions.c 2023-03-16 19:48:58 +01:00
ptitSeb 076357a2c4 [RV64_DYNAREC] Added 81/83 /4 AND and /6 XOR opcodes 2023-03-16 18:02:02 +00:00
ptitSeb daea5487ba [RV64_DYNAREC] Added a bunch of 0F prefixed opcodes 2023-03-16 16:40:53 +00:00
ptitSeb dbd1b977fc [ARM64_DYNAREC] Added FF /2 CALL, /4 JMP and /6 PUSH opcodes 2023-03-16 15:39:40 +00:00
ptitSeb 5d14667536 [RV64_DYNAREC] Added E9/EB JMP opcodes 2023-03-16 15:26:42 +00:00
ptitSeb ab289f8392 [ARM64_DYNAREC] Some small cleanup 2023-03-16 16:21:38 +01:00
xctan fa4584555d [RV64_DYNAREC] Added 68 PUSH opcode (#575) 2023-03-16 16:06:38 +01:00
xctan 4b2a340bc7 [RV64_DYNAREC] Added 98 CWDE opcode (#574)
* [RV64_DYNAREC] Added 98 CWDE opcode

* [RV64_DYNAREC] Added 90 XCHG opcode
2023-03-16 15:29:07 +01:00
ptitSeb 7cb9a5064a [RV64_DYNAREC] Added 70-7F Jcc condition jump opcodes, plus a ton of fixes and a few optims 2023-03-16 14:26:35 +00:00
Yang Liu 4b6ec02517 [RV64_DYNAREC] Added (81/83) /7 CMP opcode (#571)
* [RV64_DYNAREC] Added (81/83) /7 CMP opcode

* [RV64_DYNAREC] Added B[8-F] MOV opcode

* [RV64_DYNAREC] Added another C7 MOV opcode

* [RV64_DYNAREC] Zeroup for MOV32w
2023-03-16 09:52:30 +01:00
xctan 9ea3b34e7e [RV64_DYNAREC] Added 01 ADD opcode (#573) 2023-03-16 07:57:08 +01:00
xctan 440c6d2d9a [RV64_DYNAREC] Added {C1,D1} /{5,7} opcode and some fixes (#569)
* [RV64_DYNAREC] Added C1 /5 SHR opcode and some fixes

* [RV64_DYNAREC] Added D1 /{5,7} opcode
2023-03-16 07:51:32 +01:00
Yang Liu e579450af6 [RV64_DYNAREC] Optimize MOV64 emitter (#572) 2023-03-16 07:43:53 +01:00
Yang Liu 50e463917c [RV64_DYNAREC] Added F3 0F 1E NOP opcode (#570) 2023-03-16 07:32:58 +01:00
ptitSeb a3ad297f92 [RV64_PRINTER] Added C2/RETN and C3/RET opocde, along with fixes to jmp_to_next 2023-03-15 22:45:09 +00:00
ptitSeb 6707640fa3 [RV64_DYNAREC] A few more fixes to the printer 2023-03-15 22:44:20 +00:00
ptitSeb 50bc5c8398 [RV64_DYNAREC] Update rv64_printer with new reg allocation 2023-03-15 22:17:10 +00:00
ptitSeb 281065b5d4 [RV64_DYNAREC] Added CC (and NativeCall) opcode, and shuffle around some xFlags /xRIP and x6 mapping 2023-03-15 21:43:00 +00:00
ptitSeb f64d21e8c2 [RV64_DYNAREC] Implemented a solutionfor the problematic F_OF flag (use F_OF2 now) 2023-03-15 19:11:19 +00:00
ptitSeb d5284a5704 [RV64_DYNAREC] Added E8 CALL opcode, and fixed some issue with many macros 2023-03-15 18:05:40 +00:00
Yang Liu 9b2b603c8d [RV64_DYNAREC] Added 80 /7 CMP opcode (#567) 2023-03-15 16:11:28 +01:00
Yang Liu 6f85a204a9 [RV64_DYNAREC] Added C6 MOV opcode (#566) 2023-03-15 12:37:42 +01:00
Yang Liu b5f3d2565a [RV64_DYNAREC] Added 39 CMP opcode and some fixes (#565) 2023-03-15 08:00:26 +01:00
ptitSeb 2fdf52afb8 Added 66 0F 38 29 PCMPEQQ opcde ([ARM64_DYNAREC] too) (for #558) 2023-03-14 18:30:50 +01:00
xctan a651cf33f4 [RV64_DYNAREC] Added {81,83} /0 ADD opcode (#564) 2023-03-14 14:07:18 +01:00
Yang Liu 9e15d771c8 [RV64_DYNAREC] Added 85 TEST opcode (#563) 2023-03-14 12:03:14 +01:00
xctan c48a2252d0 [RV64_DYNAREC] Added C1 /7 SAR opcode (#559) 2023-03-14 09:16:59 +01:00
Yang Liu 978cd2ec51 [RV64_DYNAREC] Small optimization for 31 XOR opcode (#561) 2023-03-14 08:36:07 +01:00
Yang Liu 79f3afc2eb [RV64_DYNAREC] Added 31 XOR opcode (#560)
* [RV64_DYNAREC] Move things around

* [RV64_DYNAREC] Added 31 XOR opcode
2023-03-14 08:22:22 +01:00
ptitSeb 602142dc45 [ARM64_DYNAREC] Small optim when putting 0 in a memory location 2023-03-13 23:26:35 +01:00
ptitSeb a4b6e99858 [ARM64_DYNAREC] Use STUR/LDUR when possible, plus some other small improvments 2023-03-13 23:18:29 +01:00
ptitSeb 8730f2b073 [ARM64_DYNAREC] Optimised double push/pop with stp/ldp opcode 2023-03-13 17:55:51 +01:00
ptitSeb 20a6e66e11 [ARM64_DYNAREC] Removed child leftover, it's not implemented anymore 2023-03-13 17:43:55 +01:00
ptitSeb 94d397b8c5 [RV64_DYNAREC] Removed child leftover, it's not implemented anymore 2023-03-13 16:25:08 +00:00
ptitSeb adceb9eabb [RV64_DYNAREC] Some small optim to geted 2023-03-13 16:07:57 +00:00
Yang Liu 19a06a8755 [RV64_DYNAREC] Fixed scratch register conflict for SUB (#556) 2023-03-13 15:50:48 +01:00
ptitSeb 87790a8d7a [RV64_DYNAREC] Added 1 more scratch register (it was already saved/restored) 2023-03-13 12:13:18 +00:00
ptitSeb a6d32f4a62 [RV64_DYNAREC] Fixed rv64_epilog_fast, but it's not used for now 2023-03-13 12:12:45 +00:00
xctan a5f9bda131 [RV64_DYNAREC] Added 8B MOV opcode (#555) 2023-03-13 12:50:32 +01:00
ptitSeb 327b2355c1 [DYNAREC] Fixed missing X_PEND need at end of block for unimplemented opcode 2023-03-13 10:54:37 +00:00
ptitSeb 20308faef1 [ARM64_DYNAREC] Added unimplemented handling of CRC32 opcode (to avoid stopping blocks) 2023-03-13 10:38:32 +01:00
Yang Liu 170ab57f55 [RV64_DYNAREC] Added (81/83) SUB opcode (#554) 2023-03-13 10:32:29 +01:00
Yang Liu 874054f3bb [RV64_DYNAREC] Added 29 SUB opcode (#553)
* [RV64_DYNAREC] Added 29 SUB opcode

* [RV64_DYNAREC] Clear flags if needed
2023-03-13 08:17:50 +01:00
ptitSeb a08f3c4c9e Tried to optimize TLS fetching 2023-03-12 21:43:20 +01:00
ptitSeb c0f98bb0ec Cleanup mutex wrapping 2023-03-12 21:42:49 +01:00
ptitSeb 42b067dc39 [DYNAREC] Fix some potential issue in the next jump handling 2023-03-12 18:12:57 +01:00
ptitSeb 089e3816a8 [ARM64_DYNAREC] Added 66 0F 3A 0A opcode 2023-03-12 17:17:24 +01:00
ptitSeb ae15532477 [ARM64_DYNAREC] Added (F2/F3) A7 opcode 2023-03-12 17:03:21 +01:00
ptitSeb b8ee806a80 Expose POPCNT capability too 2023-03-12 16:33:30 +01:00
ptitSeb 9186f5eeeb [ARM64_DYNAREC] Added 66 0F 3A 0E opcode 2023-03-12 16:32:42 +01:00
ptitSeb 216e70756c [ARM64_DYNAREC] Added F4 opcode 2023-03-12 16:16:34 +01:00
ptitSeb 5a52922cd2 Added support for SSE4.1, and added a couple of opcode ([ARM64_DYNAREC] too) 2023-03-12 16:04:15 +01:00
ptitSeb 55edf30ecf [ARM64_DYNAREC] Fixed build 2023-03-12 14:42:15 +01:00
ptitSeb d231539504 [DYNAREC] Some renaming for the sake of consistancy 2023-03-12 13:26:35 +00:00
ptitSebandYang Liu 262ec3ed3c Rv64 dynarec (#550)
* [RV64_DYNAREC] Pushed the rv64_lock.h
* [RV64_DYNAREC] Add initial support for atomic functions
* [RV64_DYNAREC] Added some basic infrastructure for the Dynarec (and 1 opcode)
* [RV64_DYNAREC] Add a disassembler for RV64 instructions
* [RV64_DYNAREC] Added 86 MOV opcode, and some fixes too
* [RV64_DYNAREC] Added 8D LEA opcode
* [RV64_DYNAREC] Added POP reg opcode
* [RV64_DYNAREC] Various fixes and small optims

---------

Co-authored-by: Yang Liu <[email protected]>
2023-03-12 14:04:57 +01:00
ptitSeb 38a5e55745 [DYNAREC] Small optim for 66 0F 6D opcode 2023-03-11 10:48:03 +01:00
ptitSeb 8a4562c0a9 [DYNAREC] Soma need FASTROUND disabled for it's physics engine 2023-03-11 10:47:20 +01:00
ptitSeb 760c313f65 Start of new dev. cycle 2023-03-11 10:43:44 +01:00
ptitSeb 706ebc39eb Merge pull request #547 from ryanfortner/main
add -dnogit=1 flag to debian rules
2023-03-10 20:15:57 +01:00
Ryan Fortner 46dfbf826d add -dnogit=1 flag to debian rules 2023-03-10 13:19:00 -05:00
975 changed files with 64721 additions and 20269 deletions

No files matched your search

+12 -2
View File
@@ -92,10 +92,20 @@ jobs:
make -j$(nproc) VERBOSE=1
- name: "Test Box64"
if: ${{ matrix.platform == 'X64' }}
if: ${{ matrix.platform != 'TEGRAX1' }}
run: |
if [[ ${{ matrix.platform }} != 'X64' ]]; then
sudo apt-get -y install qemu-user
fi
cd build
ctest -j$(nproc)
if [[ ${{ matrix.platform }} == 'RISCV' ]]; then
QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
elif [[ ${{ matrix.platform }} != 'X64' ]]; then
QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
else
ctest -j$(nproc) --rerun-failed --output-on-failure
fi
- name: "Upload Artifact"
uses: actions/upload-artifact@v3
+3
View File
@@ -65,3 +65,6 @@ backup/
!/LLVMprivateGenerator/Makefile
!/LLVMprivateGenerator/main.cpp
!/LLVMprivateGenerator/registered_structs.cpp
# macOS
.DS_Store
+135 -41
View File
@@ -30,23 +30,27 @@ if(LARCH64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
endif()
if(RV64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC ON CACHE BOOL "")
set(PAGE16K OFF CACHE BOOL "")
endif()
if(PPC64LE)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
set(PAGE16K OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A OR M1)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR LX2160A)
set(PAGE16K OFF CACHE BOOL "")
@@ -66,23 +70,26 @@ endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
option(RV64_DYNAREC "Set to ON to use RISC-V Dynamic Recompilation" ${RV64_DYNAREC})
option(PAGE8K "Set to ON if host device have PageSize of 8K (instead of 4K)" ${PAGE8K})
option(PAGE16K "Set to ON if host device have PageSize of 16K (instead of 4K)" ${PAGE16K})
option(PAGE64K "Set to ON if host device have PageSize of 64K (instead of 4K)" ${PAGE64K})
option(STATICBUILD "Set to ON to have a static build (Warning, not working)" ${STATICBUILD})
option(NO_LIB_INSTALL "Set ON to not install a few x86_64 libs that are used by many program" ${NO_LIB_INSTALL})
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
if(NOT PYTHONINTERP_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
message( FATAL_ERROR "You need a Python interpreter, CMake will exit." )
endif()
if(${PYTHON_VERSION_MAJOR} LESS 3)
message( FATAL_ERROR "You need a Python 3 interpretor, CMake will exit." )
message( FATAL_ERROR "You need a Python 3 interpreter, CMake will exit." )
endif()
else()
find_package(Python3)
if(NOT Python3_Interpreter_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
message( FATAL_ERROR "You need a Python interpreter, CMake will exit." )
endif()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
@@ -208,6 +215,12 @@ if(ARM_DYNAREC)
enable_language(ASM)
include_directories("${BOX64_ROOT}/src/dynarec/arm64")
set(DYNAREC ON)
elseif(RV64_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DRV64)
enable_language(ASM)
include_directories("${BOX64_ROOT}/src/dynarec/rv64")
set(DYNAREC ON)
else()
set(DYNAREC OFF)
endif()
@@ -254,32 +267,9 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64int3.c"
"${BOX64_ROOT}/src/emu/x87emu_private.c"
"${BOX64_ROOT}/src/emu/x64primop.c"
"${BOX64_ROOT}/src/emu/x64run.c"
"${BOX64_ROOT}/src/emu/x64run0f.c"
"${BOX64_ROOT}/src/emu/x64run64.c"
"${BOX64_ROOT}/src/emu/x64run66.c"
"${BOX64_ROOT}/src/emu/x64run660f.c"
"${BOX64_ROOT}/src/emu/x64run6664.c"
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run66f0.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64run670f.c"
"${BOX64_ROOT}/src/emu/x64run6766.c"
"${BOX64_ROOT}/src/emu/x64run67660f.c"
"${BOX64_ROOT}/src/emu/x64rund8.c"
"${BOX64_ROOT}/src/emu/x64rund9.c"
"${BOX64_ROOT}/src/emu/x64runda.c"
"${BOX64_ROOT}/src/emu/x64rundb.c"
"${BOX64_ROOT}/src/emu/x64rundc.c"
"${BOX64_ROOT}/src/emu/x64rundd.c"
"${BOX64_ROOT}/src/emu/x64runde.c"
"${BOX64_ROOT}/src/emu/x64rundf.c"
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
"${BOX64_ROOT}/src/emu/x64runf30f.c"
"${BOX64_ROOT}/src/emu/x64run_private.c"
"${BOX64_ROOT}/src/emu/x64syscall.c"
"${BOX64_ROOT}/src/emu/x86syscall.c"
"${BOX64_ROOT}/src/emu/x64tls.c"
"${BOX64_ROOT}/src/emu/x64trace.c"
"${BOX64_ROOT}/src/librarian/librarian.c"
@@ -294,6 +284,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
"${BOX64_ROOT}/src/libtools/signals.c"
"${BOX64_ROOT}/src/libtools/threads.c"
"${BOX64_ROOT}/src/tools/bitutils.c"
"${BOX64_ROOT}/src/tools/box64stack.c"
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
@@ -306,6 +297,34 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
)
set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64run.c"
"${BOX64_ROOT}/src/emu/x64run0f.c"
"${BOX64_ROOT}/src/emu/x64run64.c"
"${BOX64_ROOT}/src/emu/x64run66.c"
"${BOX64_ROOT}/src/emu/x64run660f.c"
"${BOX64_ROOT}/src/emu/x64run6664.c"
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run66f0.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64run67_32.c"
"${BOX64_ROOT}/src/emu/x64run670f.c"
"${BOX64_ROOT}/src/emu/x64run6766.c"
"${BOX64_ROOT}/src/emu/x64run67660f.c"
"${BOX64_ROOT}/src/emu/x64rund8.c"
"${BOX64_ROOT}/src/emu/x64rund9.c"
"${BOX64_ROOT}/src/emu/x64runda.c"
"${BOX64_ROOT}/src/emu/x64rundb.c"
"${BOX64_ROOT}/src/emu/x64rundc.c"
"${BOX64_ROOT}/src/emu/x64rundd.c"
"${BOX64_ROOT}/src/emu/x64runde.c"
"${BOX64_ROOT}/src/emu/x64rundf.c"
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
"${BOX64_ROOT}/src/emu/x64runf30f.c"
)
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
@@ -318,6 +337,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedcairogobject.c"
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX64_ROOT}/src/wrapped/wrappedcrypto3.c"
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
@@ -355,6 +375,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcmusl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcrypt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
@@ -366,6 +387,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/wrappedlibharfbuzz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibibus.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
@@ -373,6 +395,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibnuma.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpci.c"
@@ -383,6 +406,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsndfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibusb1.c"
@@ -467,6 +491,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsmime3.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX64_ROOT}/src/wrapped/wrappedtbbbind.c"
"${BOX64_ROOT}/src/wrapped/wrappedtbbmalloc.c"
"${BOX64_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
"${BOX64_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
@@ -488,6 +513,10 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
"${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc67.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n67.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc72.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n72.c"
)
# If BOX64_ROOT contains a ".c", the build breaks...
@@ -529,6 +558,8 @@ if(DYNAREC)
set(DYNAREC_SRC
"${BOX64_ROOT}/src/dynarec/dynablock.c"
"${BOX64_ROOT}/src/dynarec/dynarec_native.c"
"${BOX64_ROOT}/src/dynarec/dynarec_native_functions.c"
"${BOX64_ROOT}/src/emu/x64test.c"
)
endif()
@@ -575,9 +606,57 @@ if(ARM_DYNAREC)
)
endif()
if(RV64_DYNAREC)
set(DYNAREC_SRC
${DYNAREC_SRC}
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_functions.c"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_printer.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_jmpnext.c"
"${BOX64_ROOT}/src/rv64detect.c"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_prolog.S"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_epilog.S"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_next.S"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_lock.S"
)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_helper.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_tests.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_math.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_logic.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_shift.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_1.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_2.c"
"${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_64.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_65.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_d8.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_db.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dc.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_dd.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_de.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f.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_f30f.c"
)
endif()
if(DYNAREC)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped/generated/wrapper.h"
set(DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped/generated/wrapper.h"
${DYNAREC_PASS}
"${BOX64_ROOT}/src/dynarec/dynarec_native_pass.c"
)
@@ -592,6 +671,8 @@ if(DYNAREC)
set_target_properties(native_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
add_library(native_pass3 OBJECT ${DYNAREC_PASS})
set_target_properties(native_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
add_library(test_interpreter OBJECT ${INTERPRETER})
set_target_properties(test_interpreter PROPERTIES COMPILE_FLAGS "-DTEST_INTERPRETER")
add_dependencies(native_pass0 WRAPPERS)
add_dependencies(native_pass1 WRAPPERS)
add_dependencies(native_pass2 WRAPPERS)
@@ -603,6 +684,7 @@ if(DYNAREC)
$<TARGET_OBJECTS:native_pass1>
$<TARGET_OBJECTS:native_pass2>
$<TARGET_OBJECTS:native_pass3>
$<TARGET_OBJECTS:test_interpreter>
)
endif()
@@ -611,16 +693,18 @@ 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 ${ELFLOADER_SRC} ${WRAPPEDS}
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
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} ${WRAPPEDS}
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
VERBATIM)
endif()
add_library(interpreter OBJECT ${INTERPRETER})
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
@@ -634,6 +718,7 @@ endif()
if(DYNAREC)
target_link_libraries(${BOX64} dynarec)
endif()
target_link_libraries(${BOX64} interpreter)
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
@@ -657,6 +742,7 @@ endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "riscv64" _riscv64)
if(_x86_64 OR _aarch64)
add_definitions(-DCONFIG_64BIT)
@@ -665,13 +751,17 @@ endif()
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX64}
RUNTIME DESTINATION bin)
configure_file(system/box64.conf.cmake system/box64.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
if(NOT NO_CONF_INSTALL)
configure_file(system/box64.conf.cmake system/box64.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
endif()
if(NOT NO_LIB_INSTALL)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
endif()
endif()
if(NOT TARGET uninstall)
@@ -705,6 +795,8 @@ set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
if(_aarch64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
elseif(__riscv64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "riscv64")
elseif(_x86_64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "x86_64")
else()
@@ -795,14 +887,14 @@ add_test(sse_asm ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_asm PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
add_test(sse_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile17.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
@@ -828,6 +920,8 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
+10 -8
View File
@@ -1,8 +1,8 @@
![Official logo](img/Box64Logo.png "Official Logo")
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
![build](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) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![issues](https://img.shields.io/github/issues/ptitSeb/box64)
@@ -14,11 +14,11 @@ You can find many Box64 videos on the [MicroLinux](https://www.youtube.com/chann
Since Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates with DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than using only the interpreter. Some high level information on how DynaRec works can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Box64 integrates with DynaRec (dynamic recompiler) for the ARM64 and RV64 platform, providing a speed boost between 5 to 10 times faster than using only the interpreter. Some high level information on how DynaRec works can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](../src/emu/x64primop.c) for copyright details
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](src/emu/x64primop.c) for copyright details
<img src="img/Box64Icon.png" width="96" height="96">
<img src="docs/img/Box64Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
@@ -29,7 +29,7 @@ Usage
There are a few environment variables to control the behaviour of Box64.
See [here](USAGE.md) for all the environment variables and what they do.
See [here](docs/USAGE.md) for all the environment variables and what they do.
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
@@ -37,14 +37,15 @@ Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault sig
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md).
> Compilation instructions can be found [here](docs/COMPILE.md)\
> Instructions for installing Wine for Box64 can be found [here](docs/X64WINE.md)
----
Version history/Change log
----
The change log is available [here](CHANGELOG.md).
The change log is available [here](docs/CHANGELOG.md).
----
@@ -114,6 +115,7 @@ So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their major code contribution on the RV64 Dynarec: ksco, xctan
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* For their continous advertisement of box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+113
View File
@@ -0,0 +1,113 @@
# box64
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux 上用户空间的 x86_64 应用模拟器(支持运行原生库)
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[English](docs/README.md)
Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux 程序(比如游戏),注意主机系统需要是 64 位小端。
您可以在 [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) 和 [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube 频道上找到许多 Box64 视频。
由于 Box64 使用一些“系统”库的原生版本,如 libc、libm、SDL 和 OpenGL 等,因此很容易与大多数应用程序集成和使用,并且在许多情况下性能会相当不错。可以在[这里](https://box86.org/index.php/2021/06/game-performances/)查看一些性能测试的样例。
Box64 集成了适用于 ARM64 平台的 DynaRec(动态重编译器),速度可以比纯解释模式快 5 到 10 倍。可以在[这里](https://box86.org/2021/07/inner-workings-a-high%E2%80%91level-view-of-box86-and-a-low%E2%80%91level-view-of-the-dynarec/)找到有关 DynaRec 工作原理的一些信息。
一些 x64 内部操作码使用 “Realmode X86 Emulator Library” 的部分内容,有关版权详细信息,请参见 [x64primop.c](../src/emu/x64primop.c)。
<img src="docs/img/Box64Icon.png" width="96" height="96">
LOGO 由 @grayduck 制作,感谢!
----
使用方法
----
有若干环境变量可以控制 Box64 的行为。
可在[这里](docs/USAGE.md)查看所有环境变量及其作用。
注意:Box64 的 Dynarec 使用具有内存保护和段错误信号处理的机制来执行 JIT 代码。所以,如果想使用 GDB 调试使用 JIT 代码的程序(如 Mono/Unity3D),这会触发许多“正常”的段错误。建议在 GDB 中使用类似 `handle SIGSEGV nostop` 来防止它每个段错误处停止。如果你想捕获段错误,可以在 `signals.c` 的 `my_memprotectionhandler` 中设置断点。
----
编译/安装
----
编译说明可以在[这里](docs/COMPILE.md)查看。
----
版本历史
----
版本日志在[这里](docs/CHANGELOG.md)。
----
32位平台的注意事项
----
因为 Box64 的工作原理是直接将函数调用从 x86_64 转换为主机系统,所以主机系统(运行 Box64 的系统)需要有 64 位库。Box64 不包含任何 64 位 <-> 32 位的转换。
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname`,当它的参数为 `-m` 时返回 `x86_64`。
----
关于 Unity 游戏模拟的注意事项
----
运行 Unity 游戏应该没什么问题,但还应该注意,许多 Unity3D 游戏需要 OpenGL 3+,这在 ARM SBC 上可能会比较棘手。同时许多较新的 Unity3D游戏(如 KSP)也使用 BC7 压缩纹理,很多 ARM 的集成显卡并不支持。
> 提示:如果游戏开始后没有显示任何东西就退出了,在 Pi4 上可以使用 `MESA_GL_VERSION_OVERRIDE=3.2`,在 Panfrost 上则可以使用 `PAN_MESA_DEBUG=gl3` 来使用更高的配置。
----
关于GTK程序的注意事项
----
box64 封装了 GTK,包括 gtk2 和 gtk3。
----
关于 Steam 的注意事项
----
请注意,Steam 是 32/64 位的混合体,所以还需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,但与大多数使用 libcef/chromium 的东西一样,它目前无法在 box64 上正常工作。所以,现在 box64 上暂时不能运行 Steam。
----
关于 Wine 的注意事项
----
box64 支持 Wine64,Proton 应该也能运行。请注意,64 位 Wine 包含有 32 位组件,以便能够运行 32 位 Windows 程序。32 位应用程序需要 box86,否则无法运行。在 box64 和 box86 都存在并工作的系统上,64 位的 Wine 可以同时运行 32 位和 64 位 Windows 程序(分别使用 `wine` 和 `wine64`)。请注意,目前在 Wine 7.+ 中实现的 Wine 时间在 64 位进程中的新 32bit PE 尚不支持。我测试了 Wine 7.5 64 位可以正常工作,但是更新的版本可能还不行。
----
关于 Vulkan 注意事项
----
Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过测试,因此根据您的显卡,某些扩展可能会丢失。
----
结语
----
我要感谢所有为 box64 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠和 LoongArch 迁移:[xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box64,请不要忘记提及!)
+5 -5
View File
@@ -1,6 +1,6 @@
box64 (0.2.2) unstable; urgency=low
* Added a hacked version for overriden malloc/free functions, enabling libcef (and derivative) to work.
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
* Added rcfile handling: box64 now read "/etc/box64.box64rc" and "~/.box64rc" and apply per process parameters
* Added BOX64_DYNAREC_CALLRET to optimized CALL/RET opcode using semi-direct native CALL/RET (get more than 10% speedup)
* Added BOX64_DYNAREC_FORWARD to allow bigger Dynarec block to be build (can get more then 30% of Speedup!)
@@ -17,7 +17,7 @@ box64 (0.2.2) unstable; urgency=low
* Some special cases fixes for dlopen (fixes deadcells, maybe others too)
* Improved mmap mapping, espcially with MAP_32BITS flag
* More wrapped functions and syscalls
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* More support on the RV64 port
* More support to build under musl environment
@@ -27,7 +27,7 @@ box64 (0.2.2) unstable; urgency=low
box64 (0.2.0) unstable; urgency=low
* Wrapped more vulkan function, dxvk 2.0 now works
* Added support for overriden malloc/free functions
* Added support for overridden malloc/free functions
* Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size)
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
@@ -92,7 +92,7 @@ box64 (0.1.8) unstable; urgency=low
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* Added some more Syscall
* Wrapped Vulkan library. Vulkan and dxvk now supported!
* Support building on PPC64LE (interpretor only)
* Added support for Risc-V (interpretor only)
* Support building on PPC64LE (interpreter only)
* Added support for Risc-V (interpreter only)
-- Sebastien Chevalier <[email protected]> Tue, 18 Jan 2022 11:20:33 -0500
+3 -2
View File
@@ -6,7 +6,8 @@
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DARM_DYNAREC=1
-DARM_DYNAREC=1 \
-DNOGIT=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.6
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
+8 -8
View File
@@ -1,6 +1,6 @@
v0.2.2
======
* Added a hacked version for overriden malloc/free functions, enabling libcef (and derivative) to work.
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
=> Steam Large mode and new BigPicture are working
=> Heroic Launcher is working
* Added rcfile handling: box64 now read `/etc/box64.box64rc` and `~/.box64rc` and apply per process parameters
@@ -22,7 +22,7 @@ v0.2.2
* Some special cases fixes for dlopen (fixes deadcells, maybe others too)
* Improved mmap mapping, espcially with MAP_32BITS flag
* More wrapped functions and syscalls
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Lots of improvment in the Rounding of float & double (Dynarec and Interpreter), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* More support on the RV64 port
* More support to build under musl environment
@@ -30,7 +30,7 @@ v0.2.2
v0.2.0
======
* Wrapped more vulkan function, dxvk 2.0 now works
* Added support for overriden malloc/free functions
* Added support for overridden malloc/free functions
* Refactor Dynarec memory management, reducing memory footprint (from 20% to 40% of Dynarec size)
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
@@ -80,8 +80,8 @@ v0.1.8
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* Added some more Syscall
* Wrapped Vulkan library. Vulkan and dxvk now supported!
* Support building on PPC64LE (interpretor only)
* Added support for Risc-V (interpretor only)
* Support building on PPC64LE (interpreter only)
* Added support for Risc-V (interpreter only)
v0.1.6
======
@@ -97,7 +97,7 @@ v0.1.6
* Some residual fixes on thread attribute handling
* Better handling of app that want 32bits jumps, like unity3d/mono (thanks mogery)
* More ARM hardware option in CMake (Phytium, NX...)
* Added loongarch64 support (interpretor only)
* Added loongarch64 support (interpreter only)
* Some fixes to elfloader
* Added a mecanism to cancel a Dynarec block construction if it triggers a segfault (instead of a crash)
@@ -120,7 +120,7 @@ v0.1.4
v0.1.2
======
* OpenSource!
* A few more opcode added to the Interpretor and the Dynarec
* A few more opcode added to the Interpreter and the Dynarec
* Improved Native Function calling
* Added some function to limit allocated memory to 47bits space (for Wine)
* Improved and Fixed the functions to limit allocated memory to 32bits space
@@ -134,7 +134,7 @@ v0.1.0
* Some fixes to a few function signature
* Improvement to Signal handling, and internal mutex handling
* A few fixes to some dynarec opcodes
* A few fixes to some interpretor opcodes
* A few fixes to some interpreter opcodes
v0.0.8
======
+47 -129
View File
@@ -1,45 +1,57 @@
Compiling/Installing
----
#### Debian-based Linux
### Debian-based Linux
You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to install precompiled box64 debs, updated every 24 hours.
```
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
wget -O- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/box64-debs-archive-keyring.gpg
sudo apt update && sudo apt install box64 -y
wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg
sudo apt update && sudo apt install box64-generic-arm -y
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
#### for RK3399
----
Using a 64bit OS:
### The general approach is:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
mkdir build; cd build; cmake .. ${OPTIONS}
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
- You can use `make -j1`, `make -j2` to prevent running out of memory
- You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
#### For instance, if you want to build box64 for Generic ARM64 Linux platforms, it would look like this:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -D ARM_DYNAREC=ON -D CMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
sudo systemctl restart systemd-binfmt
```
----
#### for RK3399
Using a 64bit OS:
```
-D RK3399=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for RK3588 / RK3588S
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D RK3588=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Raspberry Pi 3
@@ -55,16 +67,8 @@ run out of memory at some point and need to run the build again.
Still, this can be faster if your build is attended.
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRPI3ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
-D RPI3ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
make
# or e.g. make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Raspberry Pi 4
@@ -72,15 +76,7 @@ sudo systemctl restart systemd-binfmt
Warning, you need a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D RPI4ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for TEGRA X1
@@ -88,31 +84,16 @@ sudo systemctl restart systemd-binfmt
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D TEGRAX1=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for ODROID N2/N2+
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DODROIDN2=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D ODROIDN2=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Snapdragon 845
@@ -120,32 +101,14 @@ sudo systemctl restart systemd-binfmt
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D SD845=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
----
#### for Phytium
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D PHYTIUM=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for M1
@@ -153,38 +116,15 @@ sudo systemctl restart systemd-binfmt
Only test on Asahi for now, using the default "16K page" kernel
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DM1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
-D M1=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
```
#### for Other ARM64 Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
#### for LoongArch
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DLARCH64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D LARCH64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for RISC-V
@@ -192,15 +132,7 @@ sudo systemctl restart systemd-binfmt
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DRV64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j`nproc`
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D RV64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for PowerPC 64 LE
@@ -208,15 +140,7 @@ sudo systemctl restart systemd-binfmt
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DPPC64LE=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D PPC64LE=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for LX2160A
@@ -224,22 +148,16 @@ sudo systemctl restart systemd-binfmt
Using a 64bit OS:
```
git clone https://github.com/ptitSeb/box64
cd box64
mkdir build; cd build; cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j$(nproc)
sudo make install
```
If it's the first install, you also need:
```
sudo systemctl restart systemd-binfmt
-D LX2160A=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for x86_64 Linux
```
-D LD80BITS=1 -D NOALIGN=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -D NOLOADADDR=ON; make -j$(nproc)`).
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -DNOLOADADDR=ON; make -j$(nproc)`).
----
### use ccmake
@@ -257,7 +175,7 @@ The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both opti
#### To have a Trace Enabled build
To have a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. But you will need to have the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime.
To have a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. But you will need to have the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime. Use version v3.2.1, as later version changed the API and will no longer work with box64
#### To have ARM Dynarec
@@ -282,4 +200,4 @@ The tests are very basic and only tests some functionality for now.
Debian Packaging
----
Box64 can also be packaged into a .deb file with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`.
Box64 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you might want in `debian/rules`.
-119
View File
@@ -1,119 +0,0 @@
# box64
![Official logo](img/Box64Logo.png "Official Logo")
Linux上用户空间的x86_64应用模拟器
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[English](README.md)
在ARM或其他非X86_64架构的Linux操作系统上,使用Box64可以运行x86_64 Linux程序(例如游戏),请注意,主机系统需要**64位小端**。
您可以在Youtube的[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)或[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)频道找到更多Box64视频。
Box64使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以它很容易与大多数应用程序集成和使用,并且在很多情况下性能会出奇的高。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看示例的基准测试分析。
Box64为ARM64平台集成了DynaRec(动态重编译器),比仅使用解释器提升5到10倍性能。关于Dynarec如何工作的更多信息,可以在[这里](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)找到。
注:DynaRec需要针对不同平台编写一部分汇编代码,目前仅支持ARM64。
一些x64内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x64primop.c](../src/emu/x64primop.c)了解版权详情
<img src="img/Box64Icon.png" width="96" height="96">
Logo和图标由grayduck制作,感谢!
----
使用方法
----
若干环境变量可以设置Box64的行为。
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
请注意:Box64的Dynarec提供了一种机制来处理JIT代码,包含内存保护和段错误信号处理程序。简单地说,如果您想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),您仍然会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的东西,不要在每个段错误时都停止,如果您想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
----
编译/安装
----
> 编译说明可以在[这里](COMPILE.md)查看。
----
版本历史
----
版本日志在[这里](CHANGELOG.md)。
----
32位平台的注意事项
----
Box64的工作原理是直接将函数调用从x86_64转换到主机系统,主机系统(Box64运行的系统)需要有64位的库。Box64并不包括任何64位<->32位的转换。
所以请理解,Box64只能运行64位的Linux二进制文件。对于32位的二进制文件,需要Box86(在64位的操作系统上需要所有的multiarch库或一些proot技巧)。
请注意,许多(基于mojo的)安装程序,即使存在x86_64版本,但在检测到架构为ARM64时会退回到"x86",这时会尝试使用(如果有)box86进行安装。这时你可以使用一个假的"uname",当它的参数为"-m"时返回"x86_64"。
----
关于Unity游戏模拟的注意事项
----
当前Unity游戏模拟是一件碰运气的事情。Unity使用Mono(它的信号表示,并不总能100%成功模拟)。
您还应该注意,一些Unity3D游戏需要OpenGL 3+,目前在ARM SBC(单板计算机)上提供OpenGL 3+是很棘手的。
所以,并不是所有的Unity游戏都能工作,而且可能需要很高的OpenGL配置,但现在很多游戏都能工作。
提示:如果游戏开始后在显示任何东西之前退出,在Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
----
关于GTK程序的注意事项
----
GTK 庫現在包裝在 box64 上,但只有 gtk2,而不是 gtk3(與 box86 相反)。
----
关于Steam的注意事项
----
Steam并不是32位/64位混合的,而是32位的,因此您需要Box86才能运行Steam。Steam也使用64位的本地服务器程序,但像大多数使用libcef/chromium的程序一样,在box64上暂时无法正常工作。
所以:目前在box64上无法运行Steam。
----
关于Wine的注意事项
----
box64支持64位Wine,但请注意,64位的Wine还包含32位的组件,以便能够运行32位的Windws程序。32位程序需要Box86,没有它就不能运行。在Box64和Box86共存的系统上,设置64位Wine可以同时运行32位和64位windows程序(只需分别使用 `wine` 和 `wine64`)。
----
关于Vulkan注意事项
----
Box64 包裝 Vulkan 庫。但請注意,它僅使用 RX550 卡進行了測試,根據您的圖形卡,可能會缺少某些擴展。
----
结语
----
我要感谢所有为 box64 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* 硬件捐赠和LoongArch迁移:[xiaoji](https://www.linuxgame.cn)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box64,请不要忘记提及!)
+30 -6
View File
@@ -38,7 +38,7 @@ Enables/Disables the logging of `dlsym` errors.
#### BOX64_TRACE_FILE *
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
End the filename with `+` to have thetrace appended instead of overwriten
End the filename with `+` to have thetrace appended instead of overwritten
Use `stderr` to use this instead of default `stdout`
#### BOX64_TRACE *
@@ -130,9 +130,14 @@ Enables/Disables trace for generated code.
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
#### BOX64_NODYNAREC *
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpreter)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX64_DYNAREC_TEST *
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
* 0 : No comparison
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different
#### BOX64_DYNAREC_BIGBLOCK *
Enables/Disables Box64's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
@@ -178,12 +183,12 @@ Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (will crash if blacks are invalidate, so probably incompatible with JIT/Dynarec)
#### BOX64_DYNAREC_HOTPAGE *
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Track HotPage, and disable execution of a page beeing writen for N attempts (default is 4)
Handling of HotPage (Page being both executed and written)
* 0 : Don't track hotpage (Default)
* 1-255 : Track HotPage, and disable execution of a page being written for N attempts
#### BOX64_DYNAREC_FASTPAGE *
Will use a faster handling of HotPage (Page beeing both executed and writen)
Will use a faster handling of HotPage (Page being both executed and written)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
@@ -192,11 +197,26 @@ Detect MonoBleedingEdge and apply conservative settings
* 0 : Don't detect MonoBleedingEdge
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX64_DYNAREC_JVM *
Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX64_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
#### BOX64_DYNAREC_MISSING *
Dynarec print the missing opcodes
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
* 1 : Will print the missing opcodes
#### BOX64_DYNAREC_AGE *
Dynarec will check if black can be freed when that atteins a certain age (in dynablock creation count)
* 0 : do not age dynablocks (don't try to free old one)
* XXXX: try to free block that are at least XXXX old (default 10240)
#### BOX64_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
@@ -306,3 +326,7 @@ Those variables are only valid inside a rcfile:
#### BOX64_EXIT
* 0 : Nothing special
* 1 : Just exit, don't try to run the program
#### BOX64_RESERVE_HIGH
* 0 : Don't try to pe-reserve high memory (beyond 47bits) (Default)
* 1 : Try to reserve (without allocating it) memory beyond 47bits (seems unstable)
+465
View File
@@ -0,0 +1,465 @@
=head1 NAME
box64 - Linux Userspace x86_64 Emulator with a twist
=head1 SYNOPSIS
B<box64> [B<--help>] [B<--version>] I<executable>
=head1 DESCRIPTION
B<Box64> lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux
systems, like ARM (host system needs to be 64-bit little-endian). Since B<Box64>
uses the native versions of some "system" libraries, like libc, libm, SDL, and
OpenGL, it's easy to integrate and use with most applications, and performance
can be surprisingly high in many cases. B<Box64> integrates with DynaRec (dynamic
recompiler) for the ARM64 platform, providing a speed boost between 5 to 10
times faster than using only the interpreter.
=head1 OPTIONS
=over 8
=item B<-h,--help>
Print box64 help and quit.
=item B<-v,--version>
Print box64 version and quit.
=back
=head1 CONFIGURATION FILE
B<Box64> now have configurations files. There are 2 files loaded.
F</etc/box4.box64rc> and F<~/.box64rc>. Both files have the same syntax, and is
basically an ini files. Section in square brackets define the process name, and
the rest is the environment variable. B<Box64> comes with a default file that
should be installed for better stability. Note that the priority is:
F<~/.bashrc> > F</etc/box64.box64rc> > command line So, your settings in
F<~/.bashrc> may override the setting from your command line. Example:
[factorio]
BOX64_DYNAREC_SAFEFLAGS=0
BOX64_DYNAREC_BIGBLOCK=2
BOX64_DYNAREC_FORWARD=1024
BOX64_DYNAREC_CALLRET=1
=head1 VARIABLES FOR RCFILE ONLY
=over 8
=item B<BOX64_NOSANDBOX=0|1>
When set to 1, add C<--no-sandbox> to command line arguments (useful for chrome
based programs).
=item B<BOX64_EXIT>=I<0|1>
When set to 1, just exit, don't try to run the program.
=back
=head1 VARIABLES ONLY FOR ENVIRONMENT AND NOT RCFILE
=over 8
=item B<BOX64_NOBANNER>=I<0|1>
When set to 1, don't prints the banner including version and build.
=item B<BOX64_LD_PRELOAD>=I<lib1>[:I<lib2>:...]
Force loading libraries with the binary. PreLoaded libs can be emulated or
native, and are treated the same way as if they were comming from the binary.
=item B<BOX64_ENV>=I<env=val>
Add an variable with value to the environment.
=item B<BOX64_ENV1>=I<env=val> B<BOX64_ENV2>=I<env=val> ...
Add arbitrary many variables using B<BOX64_ENV1>, B<BOX64_ENV2>, ...
=item B<BOX64_NORCFILES>
No rc files (like F</etc/box64.box64rc> and F<~/.box64rc>) will be loaded.
=back
=head1 VARIABLES FOR BOTH ENVIRONMENT AND RCFILE
=over 8
=item B<BOX64_LOG>=I<0|NONE|1|INFO|2|DEBUG|3|DUMP>
Controls the Verbosity level of the logs
* 0 or NONE : No message (except some fatal error). (Default.)
* 1 or INFO : Show some minimum log (Example: libraries not found)
* 2 or DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3 or DUMP : All DEBUG plus DUMP of all ELF Info.
=item B<BOX64_ROLLING_LOG>=I<0|1|N>
Show last few wrapped function call when a Signal is caught. Incompatible with
B<BOX64_LOG> > 1 (may need B<BOX64_SHOWSEGV=1> also)
* 0: No last function call printed (Default.)
* 1: Last 16 wrapped functions calls printed when a signal is printed.
* N: Last N wrapped functions calls printed when a signal is printed.
=item B<BOX64_LD_LIBRARY_PATH>=I</path/to/libs>
Path to look for x86_64 libraries. Default is current folder and C<lib> in
current folder. Also, F</usr/lib/x86_64-linux-gnu> and
F</lib/x86_64-linux-gnu> are added if they exist.
=item B<BOX64_PATH>=I</path/to/bins>
Path to look for x86_64 executable. Default is current folder and C<bin> in
current folder.
=item B<BOX64_DLSYM_ERROR>=I<0|1>
Enables/Disables the logging of `dlsym` errors.
* 0 : Don't log `dlsym` errors. (Default.)
* 1 : Log dlsym errors.
=item B<BOX64_TRACE_FILE>=I</path/to/file>
Send all log and trace to a file instead of C<stdout>. Also, if name contains
C<%pid> then this is replaced by the actual C<PID> of B<box64> instance. End
the filename with `+` to have thetrace appended instead of overwritten Use
C<stderr> to use this instead of default C<stdout>.
=item B<BOX64_TRACE>=I<0|1|symbolname|0xXXXXXXX-0xYYYYYYY>
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
* 0 : No trace. (Default.)
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done.
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found).
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
=item B<BOX64_TRACE_INIT>=I<0|1>
Use B<BOX64_TRACE_INIT> instead of B<BOX_TRACE> to start trace before the
initialization of libraries and the running program
* 0 : No trace. (Default.)
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
=item B<BOX64_TRACE_START>=I<NNNNNNN>
Only on builds with trace enabled. Start trace only after I<NNNNNNNN> opcode
execute (number is an `uint64_t`).
=item B<BOX64_TRACE_XMM>=I<0|1>
Only on builds with trace enabled.
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the XMM registers.
=item B<BOX64_TRACE_EMM>=I<0|1>
Only on builds with trace enabled.
* 0 : The EMM (i.e. MMX) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the EMM registers.
=item B<BOX64_TRACE_COLOR>=I<0|1>
Only on builds with trace enabled.
* 0 : The general registers will always be the default white color. (Default.)
* 1 : The general registers will change color in the dumps when they changed value.
=item B<BOX64_LOAD_ADDR>=I<0xXXXXXXXX>
Try to load at C<0xXXXXXX> main binary (if binary is a PIE).
=item B<BOX64_NOSIGSEGV>=I<0|1>
Disable handling of SigSEGV. (Very useful for debugging.)
* 0 : Let the x86 program set sighandler for SEGV (Default.)
* 1 : Disable the handling of SigSEGV.
=item B<BOX64_NOSIGILL>=I<0|1>
Disable handling of SigILL (to ease debugging mainly).
* 0 : Let x86 program set sighandler for Illegal Instruction
* 1 : Disables the handling of SigILL
=item B<BOX64_SHOWSEGV>=I<0|1>
Show Segfault signal even if a signal handler is present
* 0 : Don"t force show the SIGSEGV analysis (Default.)
* 1 : Show SIGSEGV detail, even if a signal handler is present
=item B<BOX64_SHOWBT>=I<0|1>
Show some Backtrace (Nativ e and Emulated) whgen a signal (SEGV, ILL or BUS) is caught
* 0 : Don"t show backtraces (Default.)
* 1 : Show Backtrace detail (for native, box64 is rename as the x86_64 binary run)
=item B<BOX64_X11THREADS>=I<0|1>
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
* 0 : Don't force call XInitThreads. (Default.)
* 1 : Call XInitThreads as soon as libX11 is loaded.
=item B<BOX64_X11GLX>=I<0|1>
Force libX11's GLX extension to be present.
* 0 : Do not force libX11's GLX extension to be present.
* 1 : GLX will always be present when using XQueryExtension. (Default.)
=item B<BOX64_DYNAREC_DUMP>=I<0|1|2>
Enables/disables Box64's Dynarec's dump.
* 0 : Disable Dynarec's blocks dump. (Default.)
* 1 : Enable Dynarec's blocks dump.
* 2 : Enable Dynarec's blocks dump with some colors.
=item B<BOX64_DYNAREC_LOG>=I<0|1|2|3>
Set the level of DynaRec's logs.
* 0 : NONE : No Logs for DynaRec. (Default.)
* 1 :INFO : Minimum Dynarec Logs (only unimplemented OpCode).
* 2 : DEBUG : Debug Logs for Dynarec (with details on block created / executed).
* 3 : VERBOSE : All of the above plus more.
=item B<BOX64_DYNAREC>=I<0|1>
Enables/Disables Box64's Dynarec.
* 0 : Disables Dynarec.
* 1 : Enable Dynarec. (Default.)
=item B<BOX64_DYNAREC_TRACE>=I<0|1>
Enables/Disables trace for generated code. Like regular Trace, this will slow
down the program a lot and generate huge logs.
* 0 : Disable trace for generated code. (Default.)
* 1 : Enable trace for generated code
=item B<BOX64_NODYNAREC>=I<0xXXXXXXXX-0xYYYYYYYY>
Forbid dynablock creation in the interval specified (helpfull for debugging
behaviour difference between Dynarec and Interpretor)
=item B<BOX64_DYNAREC_TEST>=I<0|1>
Enables/Disables test for generated code. This will run interpreter along the Dynacrec, so this will slow
down the program a lot.
* 0 : No test for generated code. (Default.)
* 1 : Enable Tests for generated code
=item B<BOX64_DYNAREC_BIGBLOCK>=I<0|1|2|3>
Enables/Disables Box64's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps, but only for blocks in elf memory)
* 3 : Build Dynarec block bigger (don't stop when block overlaps, for all type of memory)
=item B<BOX64_DYNAREC_FORWARD>=I<0|XXX>
Define Box64's Dynarec max allowed forward value when building Block.
* 0 : No forward value. When current block end, don't try to go further even if there are previous forward jumps
* XXX : Allow up to XXXX bytes of gap when building a Block after the block end to next forward jump (Default: 128)
=item B<BOX64_DYNAREC_STRONGMEM>=I<0|1|2>
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
=item B<BOX64_DYNAREC_X87DOUBLE>=I<0|1>
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (default, faster)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
=item B<BOX64_DYNAREC_FASTNAN>=I<0|1>
Enable/Disable generation of -NAN
* 0 : Generate -NAN like on x86
* 1 : Don't do anything special with NAN, to go as fast as possible (default, faster)
=item B<BOX64_DYNAREC_FASTROUND>=I<0|1>
Enable/Disable generation of precise x86 rounding
* 0 : Generate float/double -> int rounding like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (default, faster)
=item B<BOX64_DYNAREC_SAFEFLAGS>=I<0|1|2>
Handling of flags on CALL/RET opcodes
* 0 : Treat CALL/RET as if it never needs any flags (faster but not advised)
* 1 : most of RET will need flags, most of CALLS will not (Default)
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
=item B<BOX64_DYNAREC_CALLRET>=I<0|1>
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (will crash if blacks are invalidate, so probably incompatible with JIT/Dynarec)
=item B<BOX64_DYNAREC_HOTPAGE>=I<0|1-255>
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Track HotPage, and disable execution of a page beeing writen for N attempts (default is 4)
=item B<BOX64_DYNAREC_FASTPAGE>=I<0|1>
Will use a faster handling of HotPage (Page beeing both executed and writen)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
=item B<BOX64_DYNAREC_BLEEDING_EDGE>=I<0|1>
Detect MonoBleedingEdge and apply conservative settings
* 0 : Don't detect MonoBleedingEdge
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
=item B<BOX64_DYNAREC_WAIT>=I<0|1>
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
=item B<BOX64_SSE_FLUSHTO0>=I<0|1>
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
* 1 : Direct apply of SSE Flush to 0 flag
=item B<BOX64_X87_NO80BITS>=I<0|1>
Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
=item B<BOX64_LIBCEF>=I<0|1>
Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
=item B<BOX64_LIBGL>=I<libXXXX|/PATH/TO/libGLXXX>
You can also use B<SDL_VIDEO_GL_DRIVER>
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
=item B<BOX64_EMULATED_LIBS>=I<XXXX[:YYYY:...]>
Force lib XXXX (and YYYY...) to be emulated (and not wrapped) Some games uses
an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is
automatical added to emulated libs, and same for Don't Starve (and Together /
Server variant) that use an old SDL2 too
=item B<BOX64_ALLOWMISSINGLIBS>=I<0|1>
Allow Box64 to continue even if a library is missing.
* 0 : Box64 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
=item B<BOX64_PREFER_WRAPPED>=I<0|1>
Box64 will use wrapped libs even if the lib is specified with absolute path
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
* 1 : Use Wrapped native libs even if path is absolute
=item B<BOX64_PREFER_EMULATED>=I<0|1>
Box64 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL,
vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
=item B<BOX64_CRASHHANDLER>=I<0|1>
Box64 will use a dummy crashhandler.so library
* 0 : Use Emulated crashhandler.so library if needed
* 1 : Use an internal dummy (completly empty) crashhandler.so library (defaut)
=item B<BOX64_MALLOC_HACK>=I<0|1|2>
How Box64 will handle hooking of malloc operators
* 0 : Don't allow malloc operator to be redirected, rewriting code to use regular function (Default)
* 1 : Allow malloc operator to be redirected (not advised)
* 2 : Like 0, but track special mmap / free (some redirected functions were inlined and cannot be redirected)
=item B<BOX64_NOPULSE>=I<0|1>
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
=item B<BOX64_NOGTK>=I<0|1>
Disables the loading of wrapped GTK libraries.
* 0 : Load wrapped GTK libraries if found. (Default.)
* 1 : Disables loading wrapped GTK libraries.
=item B<BOX64_NOVULKAN>=I<0|1>
Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
=item B<BOX64_BASH>=I<yyyy>
Define x86_64 bash to launch script. Will use yyyy as x86_64 bash to launch
script. yyyy needs to be a full path to a valid x86_64 version of bash
=item B<BOX64_JITGDB>=I<0|1|2>
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting. When in gdb, you need to find the correct thread yourself (the one with `my_box64signalhandler` in is stack) then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box64signalhandler`, just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting. Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`. This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
=cut
+6 -8
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-arm64-git
pkgver=r1495.e6e9fae
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -15,24 +15,22 @@ source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm64-git}"
cd "${srcdir}/${pkgname%-arm64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
[[ ! -d ./build ]] && mkdir build
cmake -B build -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-arm64-git}/build"
cd "${srcdir}/${pkgname%-arm64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm64-git}/build"
cd "${srcdir}/${pkgname%-arm64-git}/build"
make DESTDIR="${pkgdir}/" install
}
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=r1495.e6e9fae
pkgname=box64-asahi-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -9,30 +9,28 @@ url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
provides=("${pkgname%-git}" "${pkgname%-asahi-git}-git" "${pkgname%-asahi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-asahi-git}-git" "${pkgname%-asahi-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
cd "${srcdir}/${pkgname%-asahi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
cd "${srcdir}/${pkgname%-asahi-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DM1=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
cd "${srcdir}/${pkgname%-asahi-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
cd "${srcdir}/${pkgname%-asahi-git}/build"
make DESTDIR="${pkgdir}/" install
}
+6 -8
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-lx2160a-git
pkgver=r1495.e6e9fae
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -15,24 +15,22 @@ source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-lx2160a-git}"
cd "${srcdir}/${pkgname%-lx2160a-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-lx2160a-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
[[ ! -d ./build ]] && mkdir build
cmake -B build -DLX2160A=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-lx2160a-git}/build"
cd "${srcdir}/${pkgname%-lx2160a-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-lx2160a-git}/build"
cd "${srcdir}/${pkgname%-lx2160a-git}/build"
make DESTDIR="${pkgdir}/" install
}
-38
View File
@@ -1,38 +0,0 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-lx2160a-git
pkgver=r1495.e6e9fae
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-lx2160a-git}-git" "${pkgname%-lx2160a-git}")
conflicts=("${pkgname%-git}" "${pkgname%-lx2160a-git}-git" "${pkgname%-lx2160a-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-lx2160a-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-lx2160a-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLX2160A=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
build() {
cd "$srcdir/${pkgname%-lx2160a-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-lx2160a-git}/build"
make DESTDIR="${pkgdir}/" install
}
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=r1495.e6e9fae
pkgname=box64-odroid-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -9,30 +9,28 @@ url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
provides=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
conflicts=("${pkgname%-git}" "${pkgname%-odroid-git}-git" "${pkgname%-odroid-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
cd "${srcdir}/${pkgname%-odroid-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
cd "${srcdir}/${pkgname%-odroid-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DODROIDN2=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
cd "${srcdir}/${pkgname%-odroid-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
cd "${srcdir}/${pkgname%-odroid-git}/build"
make DESTDIR="${pkgdir}/" install
}
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-arm64-git
pkgver=r1495.e6e9fae
pkgname=box64-phytium-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -9,30 +9,28 @@ url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
provides=("${pkgname%-git}" "${pkgname%-phytium-git}-git" "${pkgname%-phytium-git}")
conflicts=("${pkgname%-git}" "${pkgname%-phytium-git}-git" "${pkgname%-phytium-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm64-git}"
cd "${srcdir}/${pkgname%-phytium-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
cd "${srcdir}/${pkgname%-phytium-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DPHYTIUM=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-arm64-git}/build"
cd "${srcdir}/${pkgname%-phytium-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm64-git}/build"
cd "${srcdir}/${pkgname%-phytium-git}/build"
make DESTDIR="${pkgdir}/" install
}
+49
View File
@@ -0,0 +1,49 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-rpi-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%-rpi-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
pkgver() {
cd "${srcdir}/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
# Check for Pi version number
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
_piversion=4
elif [[ ${_pimodel} =~ "Raspberry Pi 3" ]]; then
_piversion=3
else
# This RPI is not supported or this device is not a pi.
# We should cancel then the build.
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3 (2/1/0 isn't supported).\033[00m"
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DRPI${_piversion}ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
}
-38
View File
@@ -1,38 +0,0 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=r1495.e6e9fae
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make DESTDIR="${pkgdir}/" install
}
+51
View File
@@ -0,0 +1,51 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3xxx-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
_rkmodel=`tr -d '\0' < /proc/device-tree/compatible`
pkgver() {
cd "${srcdir}/${pkgname%-rk3xxx-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3xxx-git}"
# Check for RockChip version number
if [[ ${_rkmodel} =~ "rk3326" ]]; then
_rksuffix=3326
elif [[ ${_rkmodel} =~ "rk3399" ]]; then
_rksuffix=3399
elif [[ ${_rkmodel} =~ "rk3588" ]]; then
_rksuffix=3588
else
# This RKxxxx is not supported or this device is not RockChip based.
# We should cancel then the build.
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RockChip model 3326/3399/3588.\033[00m"
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected RockChip verion number is: \033[01;31m${_rksuffix}\033[01m.\033[00m"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DRK${_rksuffix}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
make DESTDIR="${pkgdir}/" install
}
@@ -1,38 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-tegra-git
pkgver=r1495.e6e9fae
pkgname=box64-rv64-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
arch=('riscv64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}-git" "${pkgname%-tegra-git}")
provides=("${pkgname%-git}" "${pkgname%-rv64-git}-git" "${pkgname%-rv64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rv64-git}-git" "${pkgname%-rv64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-tegra-git}"
cd "${srcdir}/${pkgname%-rv64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
cd "${srcdir}/${pkgname%-rv64-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DRV64=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-tegra-git}/build"
cd "${srcdir}/${pkgname%-rv64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-tegra-git}/build"
cd "${srcdir}/${pkgname%-rv64-git}/build"
make DESTDIR="${pkgdir}/" install
}
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=r1495.e6e9fae
pkgname=box64-sd845-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -9,30 +9,28 @@ url="https://github.com/ptitSeb/box64"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
provides=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
conflicts=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
cd "${srcdir}/${pkgname%-sd845-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
cd "${srcdir}/${pkgname%-sd845-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DSD845=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
cd "${srcdir}/${pkgname%-sd845-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
cd "${srcdir}/${pkgname%-sd845-git}/build"
make DESTDIR="${pkgdir}/" install
}
+6 -8
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-tegra-git
pkgver=r1495.e6e9fae
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
@@ -15,24 +15,22 @@ source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-tegra-git}"
cd "${srcdir}/${pkgname%-tegra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
[[ ! -d ./build ]] && mkdir build
cmake -B build -DTEGRAX1=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-tegra-git}/build"
cd "${srcdir}/${pkgname%-tegra-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-tegra-git}/build"
cd "${srcdir}/${pkgname%-tegra-git}/build"
make DESTDIR="${pkgdir}/" install
}
+7 -9
View File
@@ -1,10 +1,10 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-x64-git
pkgver=r1495.e6e9fae
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
arch=('x86_64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
makedepends=('git' 'cmake' 'make')
@@ -14,24 +14,22 @@ source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x64-git}"
cd "${srcdir}/${pkgname%-x64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
fi
[[ ! -d ./build ]] && mkdir build
cmake -B build -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "$srcdir/${pkgname%-x64-git}/build"
cd "${srcdir}/${pkgname%-x64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x64-git}/build"
cd "${srcdir}/${pkgname%-x64-git}/build"
make DESTDIR="${pkgdir}/" install
}
-37
View File
@@ -1,37 +0,0 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box64-x64-git
pkgver=r1495.e6e9fae
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box64"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-x64-git}-git" "${pkgname%-x64-git}")
source=('git+https://github.com/ptitSeb/box64')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x64-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr
fi
}
build() {
cd "$srcdir/${pkgname%-x64-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x64-git}/build"
make DESTDIR="${pkgdir}/" install
}
+3 -1
View File
@@ -4,6 +4,8 @@
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
```sh
mv ./PKGBUILD-<your-platform> ./PKGBUILD
# use the below line if you need a DEBUG build
# sed -i 's/RelWithDebInfo/Debug/g' ./PKGBUILD
cd ..
makepkg -si
```
@@ -12,7 +14,7 @@ This will copy the PKGBUILD for your platform (where you type your platform name
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
### 2. What platforms are currently supported.
All specified in [COMPILE.md](../docs/COMPILE.md).
All specified in [COMPILE.md](../docs/COMPILE.md) except for LARCH64, PPC64LE and SW64.
### 3. Any advantages with this solution?
This might give you some advantages like:
+41 -25
View File
@@ -152,10 +152,10 @@ class FunctionConvention(object):
self.values = valid_chars
# Free letters: B FG J QR T XYZab e gh jk mno qrst xyz
conventions = {
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A']),
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X']),
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'P', 'A'])
}
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', '0', '1']
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', '0', '1']
assert(all(all(c not in conv.values[:i] and c in sortedvalues for i, c in enumerate(conv.values)) for conv in conventions.values()))
class FunctionType(str):
@@ -384,7 +384,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
# If you find no problem, comment the error below, add a "pass" line (so python is happy)
# and open a ticket so I can fix this.
raise NotImplementedError("Some functions are only implemented under one condition (probably) ({0}:{1})"
.format(k, filename) + " [extra note in the script]")
.format(k, filename) + " [extra note in the script]\nProblematic function{}: {}".format(("" if len(funsname[k]) == 1 else "s"), funsname[k]))
for f in funsname[k]:
if f in ['_fini', '_init', '__bss_start', '__data_start', '_edata', '_end']:
continue # Always allow those symbols [TODO: check if OK]
@@ -825,7 +825,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
allowed_fpr : str = "fd"
# Sanity checks
forbidden_simple: str = "EDKVOSNMHPA"
forbidden_simple: str = "EDKVOSNMHPAxX"
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(allowed_conv.values))
assert(all(c not in allowed_regs for c in allowed_simply))
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
@@ -880,6 +880,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
#include "emu/x87emu_private.h"
#include "regs.h"
#include "x64emu.h"
#define COMPLEX_IMPL
#include "complext.h"
extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
@@ -908,12 +910,14 @@ def main(root: str, files: Iterable[Filename], ver: str):
#define __WRAPPER_H_
#include <stdint.h>
#include <string.h>
#include "complext.h"
typedef struct x64emu_s x64emu_t;
// the generic wrapper pointer functions
typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
// list of defined wrapper
// E = current x86emu struct
// v = void
@@ -933,6 +937,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
// M = ... automatically sending 2 args
// A = va_list
// 0 = constant 0, 1 = constant 1
// x = float complex
// X = double complex
""",
"fntypes.h": """
@@ -994,10 +1000,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Rewrite the wrapper.c file:
# i and u should only be 32 bits
td_types = {
# E v c w i I C W u U f d D K l L p V O S N M H P A
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int64_t", "int64_t", "uint8_t", "uint16_t", "uint64_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*", "void*"],
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t"],
# E v c w i I C W u U f d K l L p V O S N M P A
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int64_t", "int64_t", "uint8_t", "uint16_t", "uint64_t", "uint64_t", "float", "double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "void*", "void*"]
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "void*", "void*"]
}
assert(all(k in conventions for k in td_types))
for k in conventions:
@@ -1032,11 +1038,11 @@ def main(root: str, files: Iterable[Filename], ver: str):
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=(int64_t)fn({0});", # i should be int32_t
"R_RAX=(int32_t)fn({0});", # i
"R_RAX=(int64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint64_t)fn({0});", # u should be uint32_t
"R_RAX=(uint32_t)fn({0});", # u
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
@@ -1053,17 +1059,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
'from_complexf(emu, fn({0})));', # x
'from_complex(emu, fn({0})));' # X
],
conventions['W']: [
"\n#error Invalid return type: emulator\n", # E
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=(int64_t)fn({0});", # i should be int32_t
"R_RAX=(int32_t)fn({0});", # i
"R_RAX=(int64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint64_t)fn({0});", # u should be uint32_t
"R_RAX=(uint32_t)fn({0});", # u
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
@@ -1082,27 +1090,27 @@ def main(root: str, files: Iterable[Filename], ver: str):
}
# vreg: value is in a general register
# E v c w i I C W u U f d D K l L p V O S N M H P A
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1]
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1, 0, 0]
# vxmm: value is in a XMM register
# E v c w i I C W u U f d D K l L p V O S N M H P A
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2]
# vother: value is elsewere
# E v c w i I C W u U f d D K l L p V O S N M H P A
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# vstack: value is on the stack (or out of register)
# E v c w i I C W u U f d D K l L p V O S N M H P A
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1]
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 2]
arg_r = [
"", # E
"", # v
"(int8_t){p}, ", # c
"(int16_t){p}, ", # w
"(int64_t){p}, ", # i should int32_t
"(int32_t){p}, ", # i
"(int64_t){p}, ", # I
"(uint8_t){p}, ", # C
"(uint16_t){p}, ", # W
"(uint64_t){p}, ", # u should uint32_t
"(uint32_t){p}, ", # u
"(uint64_t){p}, ", # U
"", # f
"", # d
@@ -1119,6 +1127,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
"\n#error Use pp instead\n", # H
"", # P
"(void*){p}, ", # A
"", # x
"", # X
]
arg_x = [
"", # E
@@ -1146,6 +1156,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # H
"", # P
"", # A
"to_complexf(emu, {p}),",# x
"to_complex(emu, {p})," # X
]
arg_o = [
"emu, ", # E
@@ -1173,17 +1185,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # H
"", # P
"", # A
"", # x
"", # X
]
arg_s = [
"", # E
"", # v
"*(int8_t*)(R_RSP + {p}), ", # c
"*(int16_t*)(R_RSP + {p}), ", # w
"*(int64_t*)(R_RSP + {p}), ", # i should be int32_t
"*(int32_t*)(R_RSP + {p}), ", # i
"*(int64_t*)(R_RSP + {p}), ", # I
"*(uint8_t*)(R_RSP + {p}), ", # C
"*(uint16_t*)(R_RSP + {p}), ", # W
"*(uint64_t*)(R_RSP + {p}), ", # u should be uint32_t
"*(uint32_t*)(R_RSP + {p}), ", # u
"*(uint64_t*)(R_RSP + {p}), ", # U
"*(float*)(R_RSP + {p}), ", # f
"*(double*)(R_RSP + {p}), ", # d
@@ -1200,6 +1214,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
"*(unsigned __int128)(R_RSP + {p}), ", # H
"*(void**)(R_RSP + {p}), ", # P
"*(void**)(R_RSP + {p}), ", # A
"*(complexf_t*)(R_RSP + {p}), ", # x
"*(complex_t*)(R_RSP + {p}), ", # X
]
# Asserts
@@ -1438,6 +1454,6 @@ if __name__ == '__main__':
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.16") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.17") != 0:
exit(2)
exit(0)
+72 -16
View File
@@ -76,7 +76,7 @@ int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
uint32_t tid = (uint32_t)GetTID();
#define GO(A, B) \
i = (native_lock_storeifref2_d(&A, 0, tid)==tid); \
@@ -138,11 +138,24 @@ static void init_mutexes(box64context_t* context)
pthread_mutexattr_destroy(&attr);
#else
#ifdef USE_CUSTOM_MUTEX
native_lock_store(&context->mutex_trace, 0);
native_lock_store(&context->mutex_tls, 0);
native_lock_store(&context->mutex_thread, 0);
native_lock_store(&context->mutex_bridge, 0);
native_lock_store(&context->mutex_dyndump, 0);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_trace, &attr);
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutex_init(&context->mutex_dyndump, &attr);
pthread_mutexattr_destroy(&attr);
#endif
pthread_mutex_init(&context->mutex_lock, NULL);
#endif
}
@@ -191,7 +204,7 @@ box64context_t *NewBox64Context(int argc)
initCycleLog(context);
context->deferedInit = 1;
context->deferredInit = 1;
context->sel_serial = 1;
init_custommem_helper(context);
@@ -200,8 +213,7 @@ box64context_t *NewBox64Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
// create the vsyscalls
@@ -212,6 +224,8 @@ box64context_t *NewBox64Context(int argc)
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
// get handle to box64 itself
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
context->dlprivate = NewDLPrivate();
@@ -229,6 +243,22 @@ box64context_t *NewBox64Context(int argc)
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->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;
initAllHelpers(context);
return context;
@@ -251,8 +281,6 @@ void FreeBox64Context(box64context_t** context)
if(ctx->maplib)
FreeLibrarian(&ctx->maplib, NULL);
FreeDictionnary(&ctx->versym);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
@@ -265,11 +293,13 @@ void FreeBox64Context(box64context_t** context)
// stop trace now
if(ctx->dec)
DeleteX64TraceDecoder(&ctx->dec);
if(ctx->dec32)
DeleteX86TraceDecoder(&ctx->dec32);
if(ctx->zydis)
DeleteX64Trace(ctx);
if(ctx->deferedInitList)
box_free(ctx->deferedInitList);
if(ctx->deferredInitList)
box_free(ctx->deferredInitList);
/*box_free(ctx->argv);*/
@@ -325,7 +355,9 @@ void FreeBox64Context(box64context_t** context)
finiAllHelpers(ctx);
#ifndef DYNAREC
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#else
pthread_mutex_destroy(&ctx->mutex_trace);
pthread_mutex_destroy(&ctx->mutex_lock);
pthread_mutex_destroy(&ctx->mutex_tls);
@@ -339,20 +371,44 @@ void FreeBox64Context(box64context_t** context)
}
int AddElfHeader(box64context_t* ctx, elfheader_t* head) {
int idx = ctx->elfsize;
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
int idx = 0;
while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
if(idx == ctx->elfsize) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
} else {
ctx->elfs[idx] = head;
}
ctx->elfs[idx] = head;
ctx->elfsize++;
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
return idx;
}
void RemoveElfHeader(box64context_t* ctx, elfheader_t* head) {
if(GetTLSBase(head)) {
// should remove the tls info
int tlsbase = GetTLSBase(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)
if(ctx->elfs[i] == head) {
ctx->elfs[i] = NULL;
return;
}
}
int AddTLSPartition(box64context_t* context, int tlssize) {
int oldsize = context->tlssize;
// should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
context->tlssize += 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
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 2
#define BOX64_REVISION 2
#define BOX64_REVISION 3
#endif //__BOX64_VERSION_H_
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef __BUILD_INFO_H__
#define __BUILD_INFO_H__
void PrintBox64Version();
void PrintBox64Version(void);
#endif //__BUILD_INFO_H__
+261 -59
View File
@@ -26,6 +26,7 @@
#include "threads.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/dynablock_private.h"
#include "dynarec/native_lock.h"
#include "dynarec/dynarec_next.h"
@@ -41,12 +42,17 @@ static uintptr_t box64_jmptbldefault0[1<<JMPTABL_SHIFT0];
// lock addresses
KHASH_SET_INIT_INT64(lockaddress)
static kh_lockaddress_t *lockaddress = NULL;
#ifdef USE_CUSTOM_MUTEX
static uint32_t mutex_prot;
static uint32_t mutex_blocks;
#else
static pthread_mutex_t mutex_prot;
static pthread_mutex_t mutex_blocks;
#endif
#else
static pthread_mutex_t mutex_prot;
static pthread_mutex_t mutex_blocks;
#endif
#if defined(PAGE64K)
#define MEMPROT_SHIFT 16
#define MEMPROT_SHIFT2 (16+16)
@@ -67,6 +73,7 @@ typedef struct memprot_s
uint8_t* prot;
uint8_t* hot;
} memprot_t;
//#define TRACE_MEMSTAT
#ifdef TRACE_MEMSTAT
static uint64_t memprot_allocated = 0, memprot_max_allocated = 0;
#endif
@@ -110,14 +117,14 @@ typedef struct blockmark_s {
#define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t))
#define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t))
static void printBlock(blockmark_t* b, void* start)
void printBlock(blockmark_t* b, void* start)
{
printf_log(LOG_INFO, "========== Block is:\n");
printf_log(LOG_NONE, "========== Block is:\n");
do {
printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
printf_log(LOG_NONE, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size);
b = NEXT_BLOCK(b);
} while(b->next.x32);
printf_log(LOG_INFO, "===================\n");
printf_log(LOG_NONE, "===================\n");
}
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
@@ -181,6 +188,8 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
}
}
#define THRESHOLD (128-2*sizeof(blockmark_t))
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
{
(void)block;
@@ -190,25 +199,26 @@ static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
s->next.fill = 1;
// check if a new mark is worth it
if(s->next.size>size+2*sizeof(blockmark_t))
if(s->next.size>size+2*sizeof(blockmark_t)+THRESHOLD) {
size_t old_size = s->next.size;
s->next.size = size;
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
if(n!=m) {
// new mark
blockmark_t *m = NEXT_BLOCK(s);
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
m->next.size = old_size - (size + sizeof(blockmark_t));
n->prev.fill = 0;
n->prev.size = m->next.size;
n = m;
} else {
n->prev.fill = 1;
}
if(pstart && sub==*pstart) {
// get the next free block
m = (blockmark_t*)*pstart;
while(m->next.fill)
m = NEXT_BLOCK(m);
*pstart = (void*)m;
while(n->next.fill)
n = NEXT_BLOCK(n);
*pstart = (void*)n;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
@@ -222,7 +232,7 @@ static size_t freeBlock(void *block, void* sub, void** pstart)
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
if (m!=s && s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size + sizeof(blockmark_t);
n->prev.size = m->next.size;
@@ -235,7 +245,7 @@ static size_t freeBlock(void *block, void* sub, void** pstart)
s->next.size += n->next.size + sizeof(blockmark_t);
n2->prev.size = s->next.size;
}
if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) {
if(pstart && (uintptr_t)*pstart>(uintptr_t)s) {
*pstart = (void*)s;
}
// return free size at current block (might be bigger)
@@ -258,7 +268,7 @@ static int expandBlock(void* block, void* sub, size_t newsize)
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
return 0; // free space too short
// ok, doing the alloc!
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<THRESHOLD+2*sizeof(blockmark_t))
s->next.size += n->next.size+sizeof(blockmark_t);
else
s->next.size = newsize+sizeof(blockmark_t);
@@ -283,7 +293,61 @@ static size_t sizeBlock(void* sub)
return s->next.size;
}
#define THRESHOLD (128-2*sizeof(blockmark_t))
// return 1 if block is coherent, 0 if not (and printf the issues)
int printBlockCoherent(int i)
{
if(i<0 || i>=n_blocks) {
printf_log(LOG_NONE, "Error, %d should be between 0 and %d\n", i, n_blocks);
return 0;
}
int ret = 1;
blockmark_t* m = (blockmark_t*)p_blocks[i].block;
// check if first is correct
blockmark_t* first = getNextFreeBlock(m);
if(p_blocks[i].first && p_blocks[i].first!=first) {printf_log(LOG_NONE, "First %p and stored first %p differs for block %d\n", first, p_blocks[i].first, i); ret = 0;}
// check if maxfree is correct, with no hint
size_t maxfree = getMaxFreeBlock(m, p_blocks[i].size, NULL);
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree without hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree, i); ret = 0;}
// check if maxfree from first is correct
maxfree = getMaxFreeBlock(m, p_blocks[i].size, p_blocks[i].first);
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree with hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree, i); ret = 0;}
// check chain
blockmark_t* last = (blockmark_t*)(((uintptr_t)m)+p_blocks[i].size-sizeof(blockmark_t));
while(m<last) {
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, m->next.size, n, n->next.size, i);
ret = 0;
}
m = n;
}
if(m!=last) {
printf_log(LOG_NONE, "Last block %p is behond expexted block %p for block %d\n", m, last, i);
ret = 0;
}
return ret;
}
void testAllBlocks()
{
size_t total = 0;
size_t fragmented_free = 0;
size_t max_free = 0;
for(int i=0; i<n_blocks; ++i) {
printBlockCoherent(i);
total += p_blocks[i].size;
if(max_free<p_blocks[i].maxfree)
max_free = p_blocks[i].maxfree;
blockmark_t* m = (blockmark_t*)p_blocks[i].block;
while(m->next.x32) {
if(!m->next.fill)
fragmented_free += m->next.size;
m = NEXT_BLOCK(m);
}
}
printf_log(LOG_NONE, "Total %d blocks, for %zd allocated memory, max_free %zd, toatal fragmented free %zd\n", n_blocks, total, max_free, fragmented_free);
}
static size_t roundSize(size_t size)
{
@@ -314,9 +378,7 @@ void* customMalloc(size_t size)
if(sub) {
if(rsize-size<THRESHOLD)
size = rsize;
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
if(sub==p_blocks[i].first)
p_blocks[i].first = getNextFreeBlock(sub);
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);
mutex_unlock(&mutex_blocks);
@@ -353,8 +415,8 @@ void* customMalloc(size_t size)
n->prev.fill = 0;
n->prev.size = m->next.size;
// alloc 1st block
void* ret = allocBlock(p_blocks[i].block, p, size, NULL);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
void* ret = allocBlock(p_blocks[i].block, p, 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);
return ret;
}
@@ -377,7 +439,7 @@ void* customRealloc(void* p, size_t size)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
if(expandBlock(p_blocks[i].block, sub, size)) {
if(sub<p_blocks[i].first && p+size<p_blocks[i].first)
if(sub<p_blocks[i].first && p+size>=p_blocks[i].first)
p_blocks[i].first = getNextFreeBlock(sub);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
mutex_unlock(&mutex_blocks);
@@ -405,10 +467,7 @@ void customFree(void* p)
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
void* n = NEXT_BLOCK((blockmark_t*)sub);
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
if(sub<=p_blocks[i].first)
p_blocks[i].first = getPrevFreeBlock(n);
size_t newfree = freeBlock(p_blocks[i].block, sub, &p_blocks[i].first);
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
mutex_unlock(&mutex_blocks);
return;
@@ -423,6 +482,7 @@ void customFree(void* p)
#define NCHUNK 64
typedef struct mmaplist_s {
blocklist_t chunks[NCHUNK];
size_t minage[NCHUNK];
mmaplist_t* next;
} mmaplist_t;
@@ -464,11 +524,13 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
#ifdef TRACE_MEMSTAT
static uint64_t dynarec_allocated = 0;
#endif
uintptr_t AllocDynarecMap(size_t size)
uintptr_t AllocDynarecMap(size_t size, size_t age)
{
if(!size)
return 0;
static int current = 0;
size = roundSize(size);
mmaplist_t* list = mmaplist;
@@ -476,8 +538,32 @@ uintptr_t AllocDynarecMap(size_t size)
list = mmaplist = (mmaplist_t*)box_calloc(1, sizeof(mmaplist_t));
// check if there is space in current open ones
int i = 0;
int current_i = 0;
uintptr_t sz = size + 2*sizeof(blockmark_t);
while(1) {
size_t newage = 0;
if(box64_dynarec_age && current==current_i && (!list->minage[i] || list->minage[i]<=age)) {
//check age of blocks for cleaning
blockmark_t* sub = (blockmark_t*)list->chunks[i].block;
uintptr_t end = (uintptr_t)list->chunks[i].block+list->chunks[i].size-sizeof(blockmark_t);
while(sub && (uintptr_t)sub<end) {
blockmark_t* n = NEXT_BLOCK(sub);
dynablock_t* db = NULL;
if(n->next.fill)
db = *(dynablock_t**)((uintptr_t)n+sizeof(blockmark_t));
if(db) {
size_t new_age = AgeDynablock(db, age);
if(!new_age) // db has been removed
n = sub; // go back 1 step
else if(new_age<newage || !newage)
newage = new_age;
}
sub = n;
}
list->minage[i] = newage;
}
if(current==current_i)
current++;
if(list->chunks[i].maxfree>=size) {
// looks free, try to alloc!
size_t rsize = 0;
@@ -493,6 +579,8 @@ uintptr_t AllocDynarecMap(size_t size)
}
// check if new
if(!list->chunks[i].size) {
if(current_i+1==current)
current = 0;
// alloc a new block, aversized or not, we are at the end of the list
size_t allocsize = (sz>MMAPSIZE)?sz:MMAPSIZE;
// allign sz with pagesize
@@ -518,6 +606,7 @@ uintptr_t AllocDynarecMap(size_t size)
list->chunks[i].block = p;
list->chunks[i].first = p;
list->chunks[i].size = allocsize;
list->minage[i] = age + box64_dynarec_age;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
@@ -536,6 +625,7 @@ uintptr_t AllocDynarecMap(size_t size)
}
// next chunk...
++i;
++current_i;
if(i==NCHUNK) {
i = 0;
if(!list->next)
@@ -557,10 +647,7 @@ void FreeDynarecMap(uintptr_t addr)
if ((addr>(uintptr_t)list->chunks[i].block)
&& (addr<((uintptr_t)list->chunks[i].block+list->chunks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
void* n = NEXT_BLOCK((blockmark_t*)sub);
size_t newfree = freeBlock(list->chunks[i].block, sub, NULL);
if(sub<=list->chunks[i].first)
list->chunks[i].first = getPrevFreeBlock(n);
size_t newfree = freeBlock(list->chunks[i].block, sub, &list->chunks[i].first);
if(list->chunks[i].maxfree < newfree)
list->chunks[i].maxfree = newfree;
return;
@@ -589,6 +676,7 @@ static uintptr_t getDBSize(uintptr_t addr, size_t maxsize, dynablock_t** db)
uintptr_t* block = box64_jmptbl3[idx3][idx2][idx1];
if(block == box64_jmptbldefault0)
return (((addr>>JMPTABL_START1)+1)<<JMPTABL_START1);
maxsize+=idx0; // need to adjust maxsize to "end in current block"
if (maxsize>JMPTABLE_MASK0)
maxsize = JMPTABLE_MASK0;
while(block[idx0]==(uintptr_t)native_next) {
@@ -600,6 +688,51 @@ static uintptr_t getDBSize(uintptr_t addr, size_t maxsize, dynablock_t** db)
return (addr&~JMPTABLE_MASK0)+idx0+1;
}
void freeJmpTable(uintptr_t addr)
{
uintptr_t idx3, idx2, idx1, idx0;
idx3 = (((uintptr_t)addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
idx2 = (((uintptr_t)addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
idx1 = (((uintptr_t)addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
idx0 = (((uintptr_t)addr) )&JMPTABLE_MASK0;
if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
return;
}
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
return;
}
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
return;
}
uintptr_t* tbl0 = box64_jmptbl3[idx3][idx2][idx1];
for(int i=0; i<1<<JMPTABL_SHIFT0; ++i)
if(tbl0[i]!=(uintptr_t)native_next)
return;
box64_jmptbl3[idx3][idx2][idx1] = box64_jmptbldefault0;
box_free(tbl0);
#ifdef TRACE_MEMSTAT
jmptbl_allocated -= (1<<JMPTABL_SHIFT0)*sizeof(uintptr_t);
#endif
uintptr_t** tbl1 = box64_jmptbl3[idx3][idx2];
for(int i=0; i<1<<JMPTABL_SHIFT1; ++i)
if(tbl1[i]!=box64_jmptbldefault0)
return;
box64_jmptbl3[idx3][idx2] = box64_jmptbldefault1;
box_free(tbl1);
#ifdef TRACE_MEMSTAT
jmptbl_allocated -= (1<<JMPTABL_SHIFT1)*sizeof(uintptr_t*);
#endif
uintptr_t*** tbl2 = box64_jmptbl3[idx3];
for(int i=0; i<1<<JMPTABL_SHIFT2; ++i)
if(tbl2[i]!=box64_jmptbldefault1)
return;
box64_jmptbl3[idx3] = box64_jmptbldefault2;
box_free(tbl2);
#ifdef TRACE_MEMSTAT
jmptbl_allocated -= (1<<JMPTABL_SHIFT2)*sizeof(uintptr_t**);
#endif
}
// each dynmap is 64k of size
void addDBFromAddressRange(uintptr_t addr, size_t size)
@@ -614,14 +747,18 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
dynablock_t* db = NULL;
uintptr_t end = addr+size;
uintptr_t old_addr = 0;
while (start_addr<end) {
start_addr = getDBSize(start_addr, end-start_addr, &db);
old_addr = getDBSize(start_addr, end-start_addr, &db);
if(db) {
if(destroy)
FreeRangeDynablock(db, addr, size);
else
MarkRangeDynablock(db, addr, size);
}
/*if(destroy && start_addr && ((start_addr&~JMPTABLE_MASK0)!=(old_addr&~JMPTABLE_MASK0)))
freeJmpTable(start_addr);*/ // cannot free jmpTable as some dynablock might rely on direct address (for fixed IP jmp/call)
start_addr = old_addr;
}
}
@@ -770,6 +907,28 @@ dynablock_t* getDB(uintptr_t addr)
return *(dynablock_t**)(ret - sizeof(void*));
}
int getNeedTest(uintptr_t addr)
{
uintptr_t idx3, idx2, idx1, idx0;
idx3 = ((addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
idx2 = ((addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
idx1 = ((addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
idx0 = ((addr) )&JMPTABLE_MASK0;
uintptr_t ret = (uintptr_t)box64_jmptbl3[idx3][idx2][idx1][idx0];
dynablock_t* db = *(dynablock_t**)(ret - sizeof(void*));
return db?((ret!=(uintptr_t)db->block)?1:0):0;
}
uintptr_t getJumpAddress64(uintptr_t addr)
{
uintptr_t idx3, idx2, idx1, idx0;
idx3 = ((addr)>>JMPTABL_START3)&JMPTABLE_MASK3;
idx2 = ((addr)>>JMPTABL_START2)&JMPTABLE_MASK2;
idx1 = ((addr)>>JMPTABL_START1)&JMPTABLE_MASK1;
idx0 = ((addr) )&JMPTABLE_MASK0;
return (uintptr_t)box64_jmptbl3[idx3][idx2][idx1][idx0];
}
// Remove the Write flag from an adress range, so DB can be executed safely
void protectDB(uintptr_t addr, uintptr_t size)
{
@@ -795,14 +954,16 @@ void protectDB(uintptr_t addr, uintptr_t size)
uint32_t prot = memprot[i>>16].prot[i&0xffff];
uint32_t dyn = prot&PROT_DYN;
uint32_t mapped = prot&PROT_MMAP;
prot&=~PROT_CUSTOM;
if(!prot)
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
if((prot&PROT_WRITE)) {
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC; // need to use atomic exchange?
} else
memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC_R;
prot&=~PROT_CUSTOM;
if(!(dyn&PROT_NOPROT)) {
if(prot&PROT_WRITE) {
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC; // need to use atomic exchange?
} else
memprot[i>>16].prot[i&0xffff] = prot|mapped|PROT_DYNAREC_R;
}
}
mutex_unlock(&mutex_prot);
}
@@ -824,14 +985,16 @@ void unprotectDB(uintptr_t addr, size_t size, int mark)
i=(((i>>16)+1)<<16)-1; // next block
} else {
uint32_t prot = memprot[i>>16].prot[i&0xffff];
if(prot&PROT_DYNAREC) {
prot&=~PROT_DYN;
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
memprot[i>>16].prot[i&0xffff] = prot; // need to use atomic exchange?
} else if(prot&PROT_DYNAREC_R)
memprot[i>>16].prot[i&0xffff] = prot&~PROT_CUSTOM;
if(!(prot&PROT_NOPROT)) {
if(prot&PROT_DYNAREC) {
prot&=~PROT_DYN;
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
memprot[i>>16].prot[i&0xffff] = prot; // need to use atomic exchange?
} else if(prot&PROT_DYNAREC_R)
memprot[i>>16].prot[i&0xffff] = prot&~PROT_CUSTOM;
}
}
}
mutex_unlock(&mutex_prot);
@@ -977,11 +1140,13 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
uint32_t old_prot = memprot[i>>16].prot[i&0xffff];
uint32_t dyn=(old_prot&PROT_DYN);
uint32_t mapped=(old_prot&PROT_MMAP);
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
} else if(dyn && !(prot&PROT_WRITE)) {
dyn = PROT_DYNAREC_R;
if(!(dyn&PROT_NOPROT)) {
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
} else if(dyn && !(prot&PROT_WRITE)) {
dyn = PROT_DYNAREC_R;
}
}
memprot[i>>16].prot[i&0xffff] = prot|dyn|mapped;
}
@@ -1017,7 +1182,13 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
{
setProtection(addr, size, prot|PROT_MMAP);
if(prot)
setProtection(addr, size, prot|PROT_MMAP);
else {
mutex_lock(&mutex_prot);
addMapMem(addr, addr+size-1);
mutex_unlock(&mutex_prot);
}
}
void refreshProtection(uintptr_t addr)
@@ -1026,8 +1197,10 @@ void refreshProtection(uintptr_t addr)
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(memprot[idx>>16].prot!=memprot_default) {
int prot = memprot[idx>>16].prot[idx&0xffff];
int ret = mprotect((void*)(idx<<MEMPROT_SHIFT), box64_pagesize, prot&~PROT_CUSTOM);
if(!(prot&PROT_DYNAREC)) {
int ret = mprotect((void*)(idx<<MEMPROT_SHIFT), box64_pagesize, prot&~PROT_CUSTOM);
printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(idx<<MEMPROT_SHIFT), prot, ret, ret?strerror(errno):"ok");
}
}
mutex_unlock(&mutex_prot);
}
@@ -1279,7 +1452,7 @@ int unlockCustommemMutex()
{
int ret = 0;
int i = 0;
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
uint32_t tid = (uint32_t)GetTID();
#define GO(A, B) \
i = (native_lock_storeifref2_d(&A, 0, tid)==tid); \
@@ -1312,7 +1485,7 @@ void relockCustommemMutex(int locks)
static void init_mutexes(void)
{
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
native_lock_store(&mutex_blocks, 0);
native_lock_store(&mutex_prot, 0);
#else
@@ -1332,6 +1505,34 @@ static void atfork_child_custommem(void)
init_mutexes();
}
void reserveHighMem()
{
char* p = getenv("BOX64_RESERVE_HIGH");
if(!p || p[0]=='0')
return; // don't reserve by default
intptr_t cur = 1LL<<47;
mapmem_t* m = mapmem;
while(m && (m->end<cur)) {
m = m->next;
}
while (m) {
uintptr_t addr = 0, end = 0;
if(m->begin>cur) {
void* ret = mmap64((void*)cur, m->begin-cur, 0, MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
printf_log(LOG_DEBUG, "Reserve %p-%p => %p (%s)\n", (void*)cur, m->begin, ret, strerror(errno));
printf_log(LOG_DEBUG, "mmap %p-%p\n", m->begin, m->end);
if(ret!=(void*)-1) {
addr = cur;
end = m->begin;
}
}
cur = m->end + 1;
m = m->next;
if(addr)
addMapMem(addr, end);
}
}
void init_custommem_helper(box64context_t* ctx)
{
(void)ctx;
@@ -1360,9 +1561,10 @@ void init_custommem_helper(box64context_t* ctx)
mapmem->begin = 0x0;
mapmem->end = (uintptr_t)LOWEST - 1;
loadProtectionFromMap();
reserveHighMem();
// check if PageSize is correctly defined
if(box64_pagesize != (1<<MEMPROT_SHIFT)) {
printf_log(LOG_NONE, "Error: PageSize configuation is wrong: configured with %d, but got %zd\n", 1<<MEMPROT_SHIFT, box64_pagesize);
printf_log(LOG_NONE, "Error: PageSize configuration is wrong: configured with %d, but got %zd\n", 1<<MEMPROT_SHIFT, box64_pagesize);
exit(-1); // abort or let it continue?
}
}
@@ -1446,7 +1648,7 @@ void fini_custommem_helper(box64context_t *ctx)
box_free(p_blocks[i].block);
#endif
box_free(p_blocks);
#ifndef DYNAREC
#ifndef USE_CUSTOM_MUTEX
pthread_mutex_destroy(&mutex_prot);
pthread_mutex_destroy(&mutex_blocks);
#endif
+96 -9
View File
@@ -130,6 +130,7 @@
}
#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);}
// ADD / SUB
@@ -141,6 +142,7 @@
#define ADDSw_REG(Rd, Rn, Rm) EMIT(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 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 ADDSxw_REG(Rd, Rn, Rm) EMIT(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))
@@ -151,6 +153,7 @@
#define ADDSw_U12(Rd, Rn, imm12) EMIT(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) EMIT(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 SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
@@ -160,6 +163,7 @@
#define SUBSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, 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 SUBSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define CMPSx_REG(Rn, Rm) SUBSx_REG(xZR, Rn, Rm)
#define CMPSw_REG(Rn, Rm) SUBSw_REG(wZR, Rn, Rm)
@@ -176,6 +180,7 @@
#define SUBw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSw_U12(Rd, Rn, imm12) EMIT(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 SUBSxw_U12(Rd, Rn, imm12) EMIT(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)
@@ -221,6 +226,7 @@
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
#define LDRz_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.is32bits)?0b10:0b11, 0b01, ((uint32_t)((imm12)>>(rex.is32bits?2:3)))&0xfff, Rn, Rt))
#define LDS_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
@@ -232,6 +238,7 @@
#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 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 LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
@@ -249,6 +256,41 @@
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
#define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
#define LDU_gen(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | (opc)<<22 | ((imm9)&0x1ff)<<12 | (Rn)<<5 | (Rt))
#define LDURx_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b11, 0b01, imm9, Rn, Rt))
#define LDURw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b10, 0b01, imm9, Rn, Rt))
#define LDURxw_I9(Rt, Rn, imm9) EMIT(LDU_gen((rex.w)?0b11:0b10, 0b01, imm9, Rn, Rt))
#define LDURz_I9(Rt, Rn, imm9) EMIT(LDU_gen((rex.is32bits)?0b10:0b11, 0b01, imm9, Rn, Rt))
#define LDURH_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b01, 0b01, imm9, Rn, Rt))
#define LDURB_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, 0b01, imm9, Rn, Rt))
#define LDURSW_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b10, 0b10, imm9, Rn, Rt))
#define LDURSHw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b01, 0b11, imm9, Rn, Rt))
#define LDURSHx_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b01, 0b10, imm9, Rn, Rt))
#define LDURSHxw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b01, (rex.w)?0b10:0b11, imm9, Rn, Rt))
#define LDURSBw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, 0b11, imm9, Rn, Rt))
#define LDURSBx_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, 0b10, imm9, Rn, Rt))
#define LDURSBxw_I9(Rt, Rn, imm9) EMIT(LDU_gen(0b00, (rex.w)?0b10:0b11, imm9, Rn, Rt))
#define LDxw(A, B, C) if(unscaled) {LDURxw_I9(A, B, C);} else {LDRxw_U12(A, B, C);}
#define LDz(A, B, C) if(unscaled) {LDURz_I9(A, B, C);} else {LDRz_U12(A, B, C);}
#define LDx(A, B, C) if(unscaled) {LDURx_I9(A, B, C);} else {LDRx_U12(A, B, C);}
#define LDW(A, B, C) if(unscaled) {LDURw_I9(A, B, C);} else {LDRw_U12(A, B, C);}
#define LDH(A, B, C) if(unscaled) {LDURH_I9(A, B, C);} else {LDRH_U12(A, B, C);}
#define LDB(A, B, C) if(unscaled) {LDURB_I9(A, B, C);} else {LDRB_U12(A, B, C);}
#define LDSW(A, B, C) if(unscaled) {LDURSW_I9(A, B, C);} else {LDRSW_U12(A, B, C);}
#define LDSHxw(A, B, C) if(unscaled) {LDURSHxw_I9(A, B, C);} else {LDRSHxw_U12(A, B, C);}
#define LDSHx(A, B, C) if(unscaled) {LDURSHx_I9(A, B, C);} else {LDRSHx_U12(A, B, C);}
#define LDSHw(A, B, C) if(unscaled) {LDURSHw_I9(A, B, C);} else {LDRSHw_U12(A, B, C);}
#define LDSBxw(A, B, C) if(unscaled) {LDURSBxw_I9(A, B, C);} else {LDRSBxw_U12(A, B, C);}
#define LDSBx(A, B, C) if(unscaled) {LDURSBx_I9(A, B, C);} else {LDRSBx_U12(A, B, C);}
#define LDSBw(A, B, C) if(unscaled) {LDURSBw_I9(A, B, C);} else {LDRSBw_U12(A, B, C);}
#define STxw(A, B, C) if(unscaled) {STURxw_I9(A, B, C);} else {STRxw_U12(A, B, C);}
#define STz(A, B, C) if(unscaled) {STURz_I9(A, B, C);} else {STRz_U12(A, B, C);}
#define STx(A, B, C) if(unscaled) {STURx_I9(A, B, C);} else {STRx_U12(A, B, C);}
#define STW(A, B, C) if(unscaled) {STURw_I9(A, B, C);} else {STRw_U12(A, B, C);}
#define STH(A, B, C) if(unscaled) {STURH_I9(A, B, C);} else {STRH_U12(A, B, C);}
#define STB(A, B, C) if(unscaled) {STURB_I9(A, B, C);} else {STRB_U12(A, B, C);}
// STR
#define STR_gen(size, op1, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm9)<<12 | (op2)<<10 | (Rn)<<5 | (Rt))
#define STRx_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b11, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
@@ -257,6 +299,7 @@
#define STRw_S9_preindex(Rt, Rn, imm9) EMIT(STR_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
#define STRxw_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(rex.w?0b11:0b10, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define STRB_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b00, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define STRH_S9_preindex(Rt, Rn, imm9) EMIT(STR_gen(0b01, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
#define STRH_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b01, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define ST_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
@@ -265,11 +308,13 @@
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
#define STRxw_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
#define STRz_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.is32bits)?0b10:0b11, 0b01, ((uint32_t)((imm12)>>(rex.is32bits?2:3)))&0xfff, Rn, Rt))
#define STU_gen(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | (opc)<<22 | ((imm9)&0x1ff)<<12 | (Rn)<<5 | (Rt))
#define STURx_I9(Rt, Rn, imm9) EMIT(STU_gen(0b11, 0b00, imm9, Rn, Rt))
#define STURw_I9(Rt, Rn, imm9) EMIT(STU_gen(0b10, 0b00, imm9, Rn, Rt))
#define STURxw_I9(Rt, Rn, imm9) EMIT(STU_gen((rex.w)?0b11:0b10, 0b00, imm9, Rn, Rt))
#define STURz_I9(Rt, Rn, imm9) EMIT(STU_gen((rex.is32bits)?0b10:0b11, 0b00, imm9, Rn, Rt))
#define STURH_I9(Rt, Rn, imm9) EMIT(STU_gen(0b01, 0b00, imm9, Rn, Rt))
#define STURB_I9(Rt, Rn, imm9) EMIT(STU_gen(0b00, 0b00, imm9, Rn, Rt))
@@ -282,6 +327,7 @@
#define STRB_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define STRH_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define STRxw_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, 0b011, 0, Rn, Rt))
#define STRz_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
// LOAD/STORE PAIR
#define MEMPAIR_gen(size, L, op2, imm7, Rt2, Rn, Rt) ((size)<<31 | 0b101<<27 | (op2)<<23 | (L)<<22 | (imm7)<<15 | (Rt2)<<10 | (Rn)<<5 | (Rt))
@@ -309,6 +355,18 @@
// PUSH / POP helper
#define POP1(reg) LDRx_S9_postindex(reg, xRSP, 8)
#define PUSH1(reg) STRx_S9_preindex(reg, xRSP, -8)
#define POP2(reg1, reg2) LDPx_S7_postindex(reg1, reg2, xRSP, 16)
#define PUSH2(reg1, reg2) STPx_S7_preindex(reg2, reg1, xRSP, -16)
#define POP1_32(reg) LDRw_S9_postindex(reg, xRSP, 4)
#define PUSH1_32(reg) STRw_S9_preindex(reg, xRSP, -4)
#define POP2_32(reg1, reg2) LDPw_S7_postindex(reg1, reg2, xRSP, 8)
#define PUSH2_32(reg1, reg2) STPw_S7_preindex(reg2, reg1, xRSP, -8)
#define POP1z(reg) if(rex.is32bits) {POP1_32(reg);} else {POP1(reg);}
#define PUSH1z(reg) if(rex.is32bits) {PUSH1_32(reg);} else {PUSH1(reg);}
#define POP2z(reg1, reg2) if(rex.is32bits) {POP2_32(reg1, reg2);} else {POP2(reg1, reg2);}
#define PUSH2z(reg1, reg2) if(rex.is32bits) {PUSH2_32(reg1, reg2);} else {PUSH2(reg1, reg2);}
// LOAD/STORE Acquire Exclusive
#define MEMAX_gen(size, L, Rs, Rn, Rt) ((size)<<30 | 0b001000<<24 | (L)<<22 | (Rs)<<16 | 1<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
@@ -380,9 +438,11 @@
#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 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 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))
@@ -477,6 +537,7 @@
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
#define MOVz_REG(Rd, Rm) if(rex.is32bits) {MOVw_REG(Rd, Rm);} else {MOVx_REG(Rd, Rm);}
#define LSLw_IMM(Rd, Rm, lsl) ORRw_REG_LSL(Rd, xZR, Rm, lsl)
#define LSLx_IMM(Rd, Rm, lsl) ORRx_REG_LSL(Rd, xZR, Rm, lsl)
#define LSLxw_IMM(Rd, Rm, lsl) ORRxw_REG_LSL(Rd, xZR, Rm, lsl)
@@ -726,6 +787,15 @@
#define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR_vector(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
#define VLD128(A, B, C) if(unscaled) {VLDR128_I9(A, B, C);} else {VLDR128_U12(A, B, C);}
#define VLD64(A, B, C) if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);}
#define VLD32(A, B, C) if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);}
#define VLD16(A, B, C) if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);}
#define VST128(A, B, C) if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);}
#define VST64(A, B, C) if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);}
#define VST32(A, B, C) if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);}
#define VST16(A, B, C) if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);}
#define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
#define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
#define VLDR64_S9_preindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b11, Rn, Rt))
@@ -1025,7 +1095,7 @@
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMLAS(Sd, Sn, Sm) EMIT(FMLA_vector(0, 0, 0, Sm, Sn, Sd))
#define VFMLAQS(Sd, Sn, Sm) EMIT(FMLA_vector(1, 0, 0, Sm, Sn, Sd))
#define CFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
#define VFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
// DIV
#define FDIV_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1223,6 +1293,12 @@
#define FCVT_D_S(Dd, Sn) EMIT(FCVT_precision(0b00, 0b01, Sn, Dd))
#define FCVT_S_D(Sd, Dn) EMIT(FCVT_precision(0b01, 0b00, Dn, Sd))
#define FCVTN_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10110<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert Vn from 2*Double to lower Vd as 2*float and clears the upper half, use FPCR rounding
#define FCVTN(Vd, Vn) EMIT(FCVTN_vector(0, 1, Vn, Vd))
// Convert Vn from 2*Double to higher Vd as 2*float, use FPCR rounding
#define FCVTN2(Vd, Vn) EMIT(FCVTN_vector(1, 1, Vn, Vd))
#define FCVTXN_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10110<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert Vn from 2*Double to lower Vd as 2*float and clears the upper half
#define FCVTXN(Vd, Vn) EMIT(FCVTXN_vector(0, 1, Vn, Vd))
@@ -1258,6 +1334,10 @@
#define VFRINTIS(Vd,Vn) EMIT(FRINT_vector(0, 1, 1, 0, 1, Vn, Vd))
#define VFRINTISQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 0, 1, Vn, Vd))
#define VFRINTIDQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 1, 1, Vn, Vd))
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
#define VFRINTRDQ(Vd,Vn, mode) EMIT(FRINT_vector(1, 0, (mode)&1, 1, ((mode)>>1)&1, Vn, Vd))
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
#define VFRINTRSQ(Vd,Vn, mode) EMIT(FRINT_vector(1, 0, (mode)&1, 0, ((mode)>>1)&1, Vn, Vd))
#define FRINTI_scalar(type, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | 0b111<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINTIS(Sd, Sn) EMIT(FRINTI_scalar(0b00, Sn, Sd))
@@ -1638,10 +1718,17 @@
#define UADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b01, Rn, Rd))
#define UADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b10, Rn, Rd))
// Population Count per byte
#define CNT_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CNT_8(Rd, Rn) EMIT(CNT_vector(0, 0b00, Rn, Rd))
#define CNTQ_8(Rd, Rn) EMIT(CNT_vector(1, 0b00, Rn, Rd))
// MOV Immediate
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_16(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000, ((imm8)&0b11111), Rd))
#define MOVI_32(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
// SHLL and eXtend Long
#define SHLL_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b10100<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1711,35 +1798,35 @@
#define SMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 0, Vn, Vd))
#define SMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 0, Vn, Vd))
#define SMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 0, Vn, Vd))
#define SMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 0, Vn, Vd))
//#define SMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 0, Vn, Vd))
#define UMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 0, Vn, Vd))
#define UMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 0, Vn, Vd))
#define UMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 0, Vn, Vd))
#define UMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 0, Vn, Vd))
//#define UMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 0, Vn, Vd))
#define SMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 1, Vn, Vd))
#define SMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 1, Vn, Vd))
#define SMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 1, Vn, Vd))
#define SMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 1, Vn, Vd))
//#define SMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 1, Vn, Vd))
#define UMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 1, Vn, Vd))
#define UMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 1, Vn, Vd))
#define UMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 1, Vn, Vd))
#define UMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 1, Vn, Vd))
//#define UMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 1, Vn, Vd))
#define SMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 0, Vn, Vd))
#define SMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 0, Vn, Vd))
#define SMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 0, Vn, Vd))
#define SMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 0, Vn, Vd))
//#define SMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 0, Vn, Vd))
#define UMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 0, Vn, Vd))
#define UMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 0, Vn, Vd))
#define UMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 0, Vn, Vd))
#define UMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 0, Vn, Vd))
//#define UMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 0, Vn, Vd))
#define SMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 1, Vn, Vd))
#define SMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 1, Vn, Vd))
#define SMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 1, Vn, Vd))
#define SMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 1, Vn, Vd))
//#define SMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 1, Vn, Vd))
#define UMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 1, Vn, Vd))
#define UMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 1, Vn, Vd))
#define UMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 1, Vn, Vd))
#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
//#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
// HADD vector
#define HADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 1<<10 | (Rn)<<5 | (Rd))
+26 -4
View File
@@ -15,8 +15,10 @@
.global arm64_lock_write_dd
.global arm64_lock_read_dq
.global arm64_lock_write_dq
.global arm64_lock_xchg
.global arm64_lock_xchg_dd
.global arm64_lock_xchg_d
.global arm64_lock_xchg_h
.global arm64_lock_xchg_b
.global arm64_lock_storeifnull
.global arm64_lock_storeifnull_d
.global arm64_lock_storeifref
@@ -97,13 +99,13 @@ arm64_lock_write_dq:
ret
arm64_lock_xchg:
arm64_lock_xchg_dd:
dmb ish
arm64_lock_xchg_0:
arm64_lock_xchg_dd_0:
// address is x0, value is x1, return old value in x0
ldaxr x2, [x0]
stlxr w3, x1, [x0]
cbnz w3, arm64_lock_xchg_0
cbnz w3, arm64_lock_xchg_dd_0
mov x0, x2
ret
@@ -117,6 +119,26 @@ arm64_lock_xchg_d_0:
mov w0, w2
ret
arm64_lock_xchg_h:
dmb ish
arm64_lock_xchg_h_0:
// address is x0, value is x1, return old value in x0
ldaxrh w2, [x0]
stlxrh w3, w1, [x0]
cbnz w3, arm64_lock_xchg_h_0
mov w0, w2
ret
arm64_lock_xchg_b:
dmb ish
arm64_lock_xchg_b_0:
// address is x0, value is x1, return old value in x0
ldaxrb w2, [x0]
stlxrb w3, w1, [x0]
cbnz w3, arm64_lock_xchg_b_0
mov w0, w2
ret
arm64_lock_storeifnull:
dmb ish
1:
+7 -1
View File
@@ -28,11 +28,17 @@ extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
extern uintptr_t arm64_lock_xchg_dd(void* p, uintptr_t val);
// Atomicaly exchange value at [p] with val, return old p
extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
// Atomicaly exchange value at [p] with val, return old p
extern uint32_t arm64_lock_xchg_h(void* p, uint32_t val);
// Atomicaly exchange value at [p] with val, return old p
extern uint32_t arm64_lock_xchg_b(void* p, uint32_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return old [p] value
extern uint32_t arm64_lock_storeifnull_d(void*p, uint32_t val);
+173 -14
View File
@@ -160,13 +160,60 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
if(isMask(opcode, "1x111000010iiiiiiiii01nnnnnttttt", &a)) {
int size = (opcode>>30)&3;
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDR %s, [%s], %s0x%x", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
snprintf(buff, sizeof(buff), "LDUR %s, [%s], %s0x%x", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x111000010iiiiiiiii11nnnnnttttt", &a)) {
int size = (opcode>>30)&3;
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDR %s, [%s, %s0x%x]!", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
snprintf(buff, sizeof(buff), "LDUR %s, [%s, %s0x%x]!", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x111000010iiiiiiiii00nnnnnttttt", &a)) {
int size = (opcode>>30)&3;
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "00111000010iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "01111000010iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDRUH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "001110001x0iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDRUSB %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "011110001x0iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDRUSH %s, [%s, %s0x%x]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "10111000100iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "LDRUSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x111000000iiiiiiiii00nnnnnttttt", &a)) {
int size = (opcode>>30)&3;
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "STUR %s, [%s, %s0x%x]", (size==0b10)?Wt[Rt]:Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "00111000000iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "STURB %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "01111000000iiiiiiiii00nnnnnttttt", &a)) {
int offset = signExtend(imm, 9);
snprintf(buff, sizeof(buff), "STRUH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x11100101iiiiiiiiiiiinnnnnttttt", &a)) {
@@ -903,6 +950,28 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "VCMEQ V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// MIN/MAX
if(isMask(opcode, "0QU01110ff1mmmmm0110o1nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[((sf)<<1) | a.Q];
snprintf(buff, sizeof(buff), "%c%s V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.o?"MIN":"MAX", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// MOV immediate (not)shifted 8bits
if(isMask(opcode, "0Q00111100000iii111001iiiiiddddd", &a)) {
const char* Y[] = {"8B", "16B"};
const char* Vd = Y[a.Q];
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
return buff;
}
// MOV immediate (not)shifted 16bits & 32bits
if(isMask(opcode, "0Q00111100000iiif00001iiiiiddddd", &a)) {
const char* Y[] = {"2S", "4S", "4H", "8H"};
const char* Vd = Y[(sf<<1)| a.Q];
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
return buff;
}
// Shift
if(isMask(opcode, "0QU011110hhhhrrr000001nnnnnddddd", &a)) {
@@ -1039,6 +1108,72 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// FRINTI
if(isMask(opcode, "0Q1011101f100001100110nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFRINTI %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "00011110ff100111110000nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FRINTI %c%d, %c%d", s, Rd, s, Rn);
return buff;
}
// FRINTN
if(isMask(opcode, "0Q0011100f100001100010nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFRINTN %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "000111100f100100010000nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FRINTN %c%d, %c%d", s, Rd, s, Rn);
return buff;
}
// FRINTM
if(isMask(opcode, "0Q0011100f100001100110nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFRINTM %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "000111100f100101010000nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FRINTM %c%d, %c%d", s, Rd, s, Rn);
return buff;
}
// FRINTP
if(isMask(opcode, "0Q0011101f100001100010nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFRINTP %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "000111100f100100110000nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FRINTP %c%d, %c%d", s, Rd, s, Rn);
return buff;
}
// FRINTZ
if(isMask(opcode, "0Q0011101f100001100110nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFRINTZ %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "000111100f100101110000nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FRINTZ %c%d, %c%d", s, Rd, s, Rn);
return buff;
}
//CMP
if(isMask(opcode, "00011110ff1mmmmm001000nnnnn0c000", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
@@ -1048,6 +1183,16 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "FCMP %c%d, %c%d", s, Rn, s, Rm);
return buff;
}
//FCMP vector
if(isMask(opcode, "0QU01110cf1mmmmm111001nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
int n = (sf==0)?2:1;
n *= a.Q?2:1;
int op = (a.c<<1) | (a.U);
const char* OP[] = {"EQ", "GE", "??", "GT"};
snprintf(buff, sizeof(buff), "FCMP%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", OP[op], a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
//FMIN/FMAX
if(isMask(opcode, "00011110ff1mmmmm01oo10nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
@@ -1061,6 +1206,27 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "F%sNM%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
if(isMask(opcode, "0Q001110of1mmmmm111101nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
int n = (sf==0)?2:1;
n *= a.Q?2:1;
snprintf(buff, sizeof(buff), "F%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// NEG
if(isMask(opcode, "0Q101110ff100000101110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "NEG%s V%d.%s, V%d.%s", a.Q?"Q":"", Rd, Vd, Rn, Vd);
return buff;
}
// SSHL vector
if(isMask(opcode, "0QU01110ff1mmmmm010rS1nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "%c%s%sSHL%s V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.r?"R":"", a.S?"Q":"", a.Q?"Q":"", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// FCVT
if(isMask(opcode, "f0011110pp10010U000000nnnnnddddd", &a)) {
@@ -1236,14 +1402,6 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// MOV immediate
if(isMask(opcode, "0Q00111100000iii111001iiiiiddddd", &a)) {
const char* Y[] = {"8B", "16B"};
const char* Vd = Y[a.Q];
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
return buff;
}
// LD1/ST1 single structure
if(isMask(opcode, "0Q0011010L000000cc0Sffnnnnnttttt", &a)) {
int scale = a.c;
@@ -1272,9 +1430,9 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
sz = 4;
int offset = signExtend(imm, 9);
if(!offset)
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rt, XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s, %s0x%x]", a.L?"LD":"ST", Y[sz], Rt, XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
// LDR/STR vector immediate
@@ -1285,9 +1443,9 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
sz = 4;
int offset = imm<<sz;
if(!offset)
snprintf(buff, sizeof(buff), "%sR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
snprintf(buff, sizeof(buff), "%sR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rt, XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%sR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
snprintf(buff, sizeof(buff), "%sR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rt, XtSp[Rn], imm);
return buff;
}
@@ -1365,6 +1523,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
// DMB ISH
if(isMask(opcode, "11010101000000110011nnnn10111111", &a)) {
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
return buff;
}
File diff suppressed because it is too large. Load diff
+139 -112
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -42,6 +41,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
@@ -65,7 +65,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
CALL(native_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
@@ -74,6 +74,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x05:
INST_NAME("SYSCALL");
NOTEST(x1);
SMEND();
GETIP(addr);
STORE_XEMU_CALL(xRIP);
@@ -94,7 +95,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
CALL(native_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
@@ -106,7 +107,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(arm_ud, -1);
CALL(native_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
@@ -118,7 +119,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 1:
INST_NAME("PREFETCHW");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PST_L1_STREAM_U12(ed, fixedaddress);
break;
default: //???
@@ -138,8 +139,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
}
break;
case 0x11:
@@ -152,8 +153,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -168,7 +169,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOVLPS Gx,Ex");
GETGX(v0, 1);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 0, ed);
}
break;
@@ -180,7 +181,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
SMWRITE2();
}
@@ -212,7 +213,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOVHPS Gx,Ex");
SMREAD();
GETGX(v0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
break;
@@ -224,7 +225,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 1, ed);
SMWRITE2();
}
@@ -237,22 +238,22 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
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");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
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");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
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");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff, 7, rex, NULL, 0, 0);
PLD_L3_KEEP_U12(ed, fixedaddress);
break;
default:
@@ -279,8 +280,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress);
}
break;
case 0x29:
@@ -293,8 +294,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -309,8 +310,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
}
break;
@@ -321,24 +322,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
s0 = fpu_get_scratch(dyn);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
}
GETEXSS(s0, 0, 0);
FCMPS(v0, s0);
FCOMI(x1, x2);
break;
case 0x31:
INST_NAME("RDTSC");
NOTEST(x1);
MESSAGE(LOG_DUMP, "Need Optimization\n");
CALL(ReadTSC, xRAX); // will return the u64 in xEAX
LSRx(xRDX, xRAX, 32);
MOVw_REG(xRAX, xRAX); // wipe upper part
CALL(ReadTSC, x3); // will return the u64 in x3
LSRx(xRDX, x3, 32);
MOVw_REG(xRAX, x3); // wipe upper part
break;
case 0x38:
@@ -386,8 +381,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
REVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
LDRxw_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
LDxw(gd, ed, fixedaddress);
REVxw(gd, gd);
}
break;
@@ -398,9 +393,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
REVxw(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
REVxw(x1, gd);
STRxw_U12(x1, ed, fixedaddress);
STxw(x1, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -420,7 +415,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(q1, 1);
u8 = F8;
if(u8>15) {
VEOR(q0, q0, q0);
VEOR(q0, q0, q0);
} else if(u8>7) {
d0 = fpu_get_scratch(dyn);
VEOR(d0, d0, d0);
@@ -443,9 +438,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3); \
CSELxw(gd, ed, gd, YES); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0); \
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); \
LDRxw_U12(gd, ed, fixedaddress); \
LDxw(gd, ed, fixedaddress); \
if(!rex.w) {MOVw_REG(gd, gd);} \
}
@@ -472,7 +467,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
// EX is memory
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, (0xfff<<3)-8, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, (0xfff<<3)-8, 7, rex, NULL, 0, 0);
LDRx_U12(x1, ed, fixedaddress+0);
LSRx(x1, x1, 31);
BFIx(gd, x1, 0, 1);
@@ -495,13 +490,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
GETEX(q0, 0, 0);
GETGX_empty(q1);
v0 = fpu_get_scratch(dyn);
// more precise
if(q1==q0)
v1 = fpu_get_scratch(dyn);
else
else
v1 = q1;
VFRSQRTEQS(v0, q0);
VFMULQS(v1, v0, q0);
@@ -511,6 +507,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x53:
INST_NAME("RCPPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
GETEX(q0, 0, 0);
GETGX_empty(q1);
if(q0 == q1)
@@ -597,6 +594,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box64_dynarec_fastnan && v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VANDQ(v0, v0, q0);
VBICQ(q0, v1, q0);
VORRQ(v0, v0, q0);
}
VFMINQS(v0, v0, v1);
break;
case 0x5E:
@@ -611,6 +617,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box64_dynarec_fastnan && v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VANDQ(v0, v0, q0);
VBICQ(q0, v1, q0);
VORRQ(v0, v0, q0);
}
VFMAXQS(v0, v0, v1);
break;
case 0x60:
@@ -675,7 +690,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VMOVeD(q0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(q0, 1, ed);
}
SQXTUN_8(v0, q0);
@@ -711,7 +726,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(v1, 0);
VMOVeD(q0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(q0, 1, ed);
}
SQXTN_16(v0, q0);
@@ -731,12 +746,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FMOVSw(v0, ed);
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
if(rex.w) {
VLDR64_U12(v0, ed, fixedaddress);
VLD64(v0, ed, fixedaddress);
} else {
VLDR32_U12(v0, ed, fixedaddress);
VLD32(v0, ed, fixedaddress);
}
}
break;
@@ -750,8 +764,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeD(v0, 0, v1, 0);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
break;
case 0x70:
@@ -818,7 +832,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
u8 = F8;
if (u8) {
i32 = -1;
@@ -997,11 +1011,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(ed, ed);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
if(rex.w) {
VSTR64_U12(v0, ed, fixedaddress);
VST64(v0, ed, fixedaddress);
} else {
VSTR32_U12(v0, ed, fixedaddress);
VST32(v0, ed, fixedaddress);
}
SMWRITE2();
}
@@ -1014,8 +1028,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
VMOV(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -1065,16 +1079,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} \
BFIx(eb1, x3, eb2, 8); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0); \
STRB_U12(x3, ed, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0); \
STB(x3, ed, fixedaddress); \
SMWRITE(); \
}
GOCOND(0x90, "SET", "Eb");
#undef GO
case 0xA2:
INST_NAME("CPUID");
NOTEST(x1);
MOVx_REG(x1, xRAX);
CALL_(my_cpuid, -1, 0);
break;
@@ -1088,10 +1103,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
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)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
LDxw(x1, x3, fixedaddress);
ed = x1;
}
if(rex.w) {
@@ -1136,10 +1151,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
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)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
@@ -1209,7 +1224,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxsave64):((void*)fpu_fxsave32), -1);
}
@@ -1221,12 +1236,12 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(rex.w?((void*)fpu_fxrstor64):((void*)fpu_fxrstor32), -1);
}
break;
case 2:
case 2:
INST_NAME("LDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
@@ -1241,18 +1256,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
INST_NAME("STMXCSR Md");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
STRw_U12(x4, ed, fixedaddress);
STW(x4, ed, fixedaddress);
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
GETED(0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(arm_clflush, -1, 0);
CALL_(native_clflush, -1, 0);
break;
default:
DEFAULT;
@@ -1302,10 +1317,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
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)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
@@ -1347,8 +1362,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UBFXxw(gd, eb1, eb2*8, 8);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRB_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0);
LDB(gd, ed, fixedaddress);
}
break;
case 0xB7:
@@ -1360,8 +1375,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UBFXxw(gd, ed, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRH_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDH(gd, ed, fixedaddress);
}
break;
@@ -1377,8 +1392,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDxw(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
@@ -1394,8 +1409,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDxw(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
@@ -1405,7 +1420,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
@@ -1419,8 +1434,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDxw(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
@@ -1430,7 +1445,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
@@ -1444,8 +1459,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDRxw_U12(x1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
LDxw(x1, wback, fixedaddress);
ed = x1;
}
u8 = F8;
@@ -1454,7 +1469,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
@@ -1474,10 +1489,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
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)
ADDx_REG_LSL(x3, wback, x1, 2+rex.w); //(&ed)+=r1*4;
LDRxw_U12(x1, x3, fixedaddress);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
@@ -1497,7 +1512,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LSLxw_REG(x4, x4, x2);
EORxw_REG(ed, ed, x4);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
STxw(ed, wback, fixedaddress);
SMWRITE();
}
break;
@@ -1548,8 +1563,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SBFXxw(gd, wback, wb2, 8);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, 0);
LDRSBxw_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0);
LDSBxw(gd, ed, fixedaddress);
}
break;
case 0xBF:
@@ -1561,8 +1576,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTHxw(gd, ed);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRSHxw_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDSHxw(gd, ed, fixedaddress);
}
break;
@@ -1577,21 +1592,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0: VFCMEQQS(v0, v0, v1); break; // Equal
case 1: VFCMGTQS(v0, v1, v0); break; // Less than
case 2: VFCMGEQS(v0, v1, v0); break; // Less or equal
case 3: VFCMEQQS(v0, v0, v0);
case 3: VFCMEQQS(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v1, v1);
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v1, v1);
VANDQ(v0, v0, q0);
}
VMVNQ(v0, v0);
VMVNQ(v0, v0);
break; // NaN (NaN is not equal to himself)
case 4: VFCMEQQS(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: VFCMGTQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 6: VFCMGEQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
case 7: VFCMEQQS(v0, v0, v0);
case 7: VFCMEQQS(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v1, v1);
q0 = fpu_get_scratch(dyn);
VFCMEQQS(q0, v1, v1);
VANDQ(v0, v0, q0);
}
break; // not NaN
@@ -1604,8 +1619,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
STxw(gd, ed, fixedaddress);
}
break;
case 0xC4:
@@ -1617,7 +1632,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
VMOVQHfrom(v0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&3;
VLD1_16(v0, u8, wback);
}
@@ -1631,7 +1646,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = (F8)&3;
VMOVHto(gd, v0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
u8 = (F8)&3;
LDRH_U12(gd, wback, u8*2);
}
@@ -1641,7 +1656,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGX(v0, 1);
if(!MODREG) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
v1 = -1; // to avoid a warning
} else
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
@@ -1723,7 +1738,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
USHL_8(q1, q1, v0); // shift
UADDLV_8(q1, q1); // accumalte
VMOVBto(gd, q1, 0);
break;
break;
case 0xD8:
INST_NAME("PSUBUSB Gm, Em");
nextop = F8;
@@ -1814,8 +1829,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
} else {
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
}
break;
case 0xE8:
@@ -1832,7 +1847,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(q0, 0);
SQSUB_16(v0, v0, q0);
break;
case 0xEA:
INST_NAME("PMINSW Gx,Ex");
nextop = F8;
GETGM(v0);
GETEM(q0, 0);
SMIN_16(v0, v0, q0);
break;
case 0xEB:
INST_NAME("POR Gm, Em");
nextop = F8;
@@ -1854,7 +1875,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(d1, 0);
SQADD_16(d0, d0, d1);
break;
case 0xEE:
INST_NAME("PMAXSW Gx,Ex");
nextop = F8;
GETGM(v0);
GETEM(q0, 0);
SMAX_16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gm,Em");
nextop = F8;
+119 -58
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -23,8 +22,6 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
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)
{
(void)ip; (void)rep; (void)need_epilog;
@@ -35,10 +32,12 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t gd, ed, eb1, eb2, gb1, gb2;
uint8_t wback, wb1, wb2, wb;
int64_t i64, j64;
uint64_t u64;
int v0, v1;
int q0;
int d0;
int64_t fixedaddress;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(wb1);
@@ -55,12 +54,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
GETREX();
switch(opcode) {
@@ -93,9 +87,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
VLD64(v0, x4, fixedaddress); // upper part reseted
}
break;
case 2:
@@ -111,9 +105,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR32_U12(v0, x4, fixedaddress);
VLD32(v0, x4, fixedaddress);
}
break;
default:
@@ -133,9 +127,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVQ(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR128_U12(v0, x4, fixedaddress);
VST128(v0, x4, fixedaddress);
SMWRITE2();
}
break;
@@ -150,9 +144,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeD(d0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR64_U12(v0, x4, fixedaddress);
VST64(v0, x4, fixedaddress);
SMWRITE2();
}
break;
@@ -167,9 +161,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeS(q0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR32_U12(v0, x4, fixedaddress);
VST32(v0, x4, fixedaddress);
SMWRITE2();
}
break;
@@ -191,9 +185,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR128_U12(v0, ed, fixedaddress);
VLD128(v0, ed, fixedaddress);
}
break;
default:
@@ -260,7 +254,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UBFXxw(gd, eb1, eb2*8, 8);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRB_REG(gd, ed, x4);
}
break;
@@ -293,7 +287,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x39:
INST_NAME("CMP Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -315,26 +309,31 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x63:
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRSW_REG(gd, ed, x4);
}
if(rex.is32bits) {
// ARPL here
DEFAULT;
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
LDRw_REG(gd, ed, x4);
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRSW_REG(gd, ed, x4);
}
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRw_REG(gd, ed, x4);
}
}
}
break;
@@ -535,7 +534,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRB_REG(x4, wback, x4);
ed = x4;
}
@@ -549,7 +548,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
STRxw_REG(gd, ed, x4);
SMWRITE2();
}
@@ -564,11 +563,71 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRxw_REG(gd, ed, x4);
}
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 = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
MOVxw_REG(gd, ed);
}
else if(!rex.w && !rex.is32bits) {
MOVw_REG(gd, gd); //truncate the higher 32bits as asked
}
}
break;
case 0x8F:
INST_NAME("POP FS:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
if(MODREG) {
POP1z(xRAX+(nextop&7)+(rex.b<<3));
} else {
POP1z(x2); // so this can handle POP [ESP] and maybe some variant too
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0, 0, rex, NULL, 0, 0);
if(ed==xRSP) {
STRz_REG(x2, ed, x4);
} else {
// complicated to just allow a segfault that can be recovered correctly
SUBz_U12(xRSP, xRSP, rex.is32bits?4:8);
STRz_REG(x2, ed, x4);
ADDz_U12(xRSP, xRSP, rex.is32bits?4:8);
}
}
break;
case 0xA1:
INST_NAME("MOV EAX,FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
LDRxw_REG(xRAX, x1, x4);
break;
case 0xA3:
INST_NAME("MOV FS:Od,EAX");
grab_segdata(dyn, addr, ninst, x4, seg);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
STRxw_REG(xRAX, x1, x4);
SMWRITE2();
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
@@ -581,12 +640,12 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0;
eb2 = 0;
}
MOV32w(x3, u8);
BFIx(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
u8 = F8;
MOV32w(x3, u8);
STRB_REG(x3, ed, x4);
@@ -602,7 +661,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_REG(x3, ed, x4);
@@ -813,9 +872,10 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xF7:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 0:
case 1:
@@ -893,8 +953,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRDX, x4);
} else {
if(ninst
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETEDO(x6, 0);
@@ -917,6 +977,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2)
@@ -929,7 +990,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
@@ -955,7 +1016,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
@@ -984,7 +1045,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
GETEDOx(x6, 0);
GETEDOz(x6, 0);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
} else {
@@ -1006,22 +1067,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
STPx_S7_preindex(x4, xRIP, xSP, -16);
}
PUSH1(xRIP);
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst);
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
GETEDOx(x6, 0);
GETEDOz(x6, 0);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 6: // Push Ed
INST_NAME("PUSH Ed");
GETEDOx(x6, 0);
PUSH1(ed);
GETEDOz(x6, 0);
PUSH1z(ed);
break;
default:
+205 -24
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -35,6 +34,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t gd, ed;
uint8_t wback, wb1;
int64_t fixedaddress;
int unscaled;
int lock;
MAYUSE(u8);
MAYUSE(u16);
@@ -49,14 +49,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the 66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
GETREX();
if(rex.w && opcode!=0x0f) // rex.w cancels "66", but not for 66 0f type of prefix
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
switch(opcode) {
@@ -87,7 +82,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_add16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -294,6 +289,70 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
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_PENDING);
gd = xRAX + (opcode&7);
UXTHw(x1, gd);
emit_inc16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
break;
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_PENDING);
gd = xRAX + (opcode&7);
UXTHw(x1, gd);
emit_dec16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
break;
case 0x60:
if(rex.is32bits) {
INST_NAME("PUSHA 16 (32bits)");
MOVw_REG(x1, xRSP);
STRH_S9_preindex(xRAX, xRSP, -2);
STRH_S9_preindex(xRCX, xRSP, -2);
STRH_S9_preindex(xRDX, xRSP, -2);
STRH_S9_preindex(xRBX, xRSP, -2);
STRH_S9_preindex(x1, xRSP, -2);
STRH_S9_preindex(xRBP, xRSP, -2);
STRH_S9_preindex(xRSI, xRSP, -2);
STRH_S9_preindex(xRDI, xRSP, -2);
} else {
DEFAULT;
}
break;
case 0x61:
if(rex.is32bits) {
INST_NAME("POPA 16 (32bits)");
MOVw_REG(x1, xRSP);
LDRH_S9_postindex(xRDI, xRSP, 2);
LDRH_S9_postindex(xRSI, xRSP, 2);
LDRH_S9_postindex(xRBP, xRSP, 2);
LDRH_S9_postindex(x1, xRSP, 2);
LDRH_S9_postindex(xRBX, xRSP, 2);
LDRH_S9_postindex(xRDX, xRSP, 2);
LDRH_S9_postindex(xRCX, xRSP, 2);
LDRH_S9_postindex(xRAX, xRSP, 2);
} else {
DEFAULT;
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
break;
@@ -424,7 +483,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -445,7 +504,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(ed, x1, 0, 16);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
SMDMB();
TSTx_mask(ed, 1, 0, 0); // mask=1
B_MARK(cNE);
@@ -462,7 +521,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gd, x1, 0, 16);
}
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
@@ -473,8 +532,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
STRH_U12(gd, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
STH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
@@ -488,12 +547,25 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
SMREADLOCK(lock);
LDRH_U12(x1, ed, fixedaddress);
LDH(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
break;
case 0x8C:
INST_NAME("MOV EW, Seg");
nextop=F8;
u8 = (nextop&0x38)>>3;
LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
if((nextop&0xC0)==0xC0) { // reg <= seg
UXTHw(xRAX+(nextop&7)+(rex.b<<3), x3);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x3, wback, fixedaddress);
SMWRITE2();
}
break;
case 0x90:
case 0x91:
@@ -522,16 +594,22 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA1:
INST_NAME("MOV EAX,Od");
u64 = F64;
MOV64x(x1, u64);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
LDRH_U12(x2, x1, 0);
BFIx(xRAX, x2, 0, 16);
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
u64 = F64;
MOV64x(x1, u64);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
STRH_U12(xRAX, x1, 0);
SMWRITE();
break;
@@ -563,6 +641,46 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xA7:
switch(rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
LDRH_S9_postindex(x1, xRSI, 2);
LDRH_S9_postindex(x2, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
CBNZx_MARK(xRCX);
B_MARK3_nocond;
MARK2; // Part with DF==1
LDRH_S9_postindex(x1, xRSI, -2);
LDRH_S9_postindex(x2, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((rep==1)?cEQ:cNE);
CBNZx_MARK2(xRCX);
MARK3; // end
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
default:
INST_NAME("CMPSW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, 2);
LDRH_U12(x1, xRSI, 0);
LDRH_U12(x2, xRDI, 0);
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -595,6 +713,67 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xAD:
if(rep) {
INST_NAME("REP LODSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
LDRH_S9_postindex(xRAX, xRSI, 2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LDRH_S9_postindex(xRAX, xRSI, -2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
// done
} else {
INST_NAME("STOSW");
GETDIR(x3, 2);
LDRH_U12(xRAX, xRSI, 0);
ADDx_REG(xRSI, xRSI, x3);
}
break;
case 0xAF:
switch(rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
UXTHw(x1, xRAX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
LDRH_S9_postindex(x2, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CMPSw_REG(x1, x2);
B_MARK3((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);
CBNZx_MARK2(xRCX);
MARK3; // end
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
default:
INST_NAME("SCASW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, 2);
UXTHw(x1, xRAX);
LDRH_U12(x2, xRDI, 0);
ADDx_REG(xRDI, xRDI, x3);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
break;
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
@@ -707,10 +886,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x1, u16);
BFIx(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<1, 1, rex, &lock, 0, 2);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
MOV32w(x1, u16);
STRH_U12(x1, ed, fixedaddress);
STH(x1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
@@ -821,7 +1000,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
@@ -885,6 +1064,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("IDIV Ew");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
GETSEW(x1, 0);
UXTHw(x2, xRAX);
@@ -896,7 +1076,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
@@ -918,6 +1098,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
}
break;
default:
DEFAULT;
}
File diff suppressed because it is too large. Load diff
+7 -14
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -22,8 +21,6 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
@@ -34,14 +31,10 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
int64_t j64;
int v0, v1;
int64_t fixedaddress;
int unscaled;
MAYUSE(j64);
// REX prefix before the 66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
GETREX();
/*if(rex.w && opcode!=0x0f) { // rex.w cancels "66", but not for 66 0f type of prefix
MESSAGE(LOG_DUMP, "Here!\n");
@@ -66,8 +59,8 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
VLDR64_REG(v1, ed, x4);
}
FCMPD(v0, v1);
@@ -83,7 +76,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR64_REG(v0, ed, x4);
SMWRITE();
}
@@ -109,7 +102,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.w) {
STRx_REG(gd, ed, x4);
} else {
@@ -135,7 +128,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.w) {
LDRx_REG(gd, ed, x4);
} else {
+18 -22
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -34,6 +33,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
@@ -44,12 +44,8 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0/66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
GETREX();
switch(opcode) {
case 0x09:
@@ -64,7 +60,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
@@ -93,7 +89,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
B_MARK(cNE);
BFIx(ed, gd, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK3(cNE);
// Aligned version
@@ -123,7 +119,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(xRAX, x1, 0, 16);
SMDMB();
break;
case 0xC1:
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -137,7 +133,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_add16(dyn, ninst, x5, gd, x3, x4);
BFIx(ed, x5, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
ADDxw_REG(x4, x1, x5);
@@ -177,7 +173,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
@@ -188,7 +184,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
@@ -209,7 +205,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
@@ -231,7 +227,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
@@ -253,7 +249,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
@@ -274,7 +270,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_and16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
@@ -295,7 +291,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
@@ -306,7 +302,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
@@ -327,7 +323,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_xor16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
@@ -369,7 +365,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_inc16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_inc16(dyn, ninst, x1, x3, x4);
@@ -388,7 +384,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_dec16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRH(x1, wback);
emit_dec16(dyn, ninst, x1, x3, x4);
+143 -34
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -22,14 +21,6 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGX(a, w) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
@@ -38,8 +29,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2;
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;
@@ -55,12 +47,14 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(lock);
MAYUSE(cacheupd);
// REX prefix before the 67 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
if(rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
@@ -186,8 +180,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
s0 = fpu_get_scratch(dyn);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
FCOMI(x1, x2);
@@ -210,8 +204,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
break;
default:
@@ -229,8 +223,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
VMOV(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE();
}
break;
@@ -239,6 +233,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xB6:
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
GETGD;
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0; \
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
UBFXxw(gd, eb1, eb2*8, 8);
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 0);
LDB(gd, ed, fixedaddress);
}
break;
case 0xB7:
INST_NAME("MOVZX Gd, Ew");
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UBFXxw(gd, ed, 0, 16);
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDH(gd, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
@@ -563,6 +591,54 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
case 0x63:
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDSW(gd, ed, fixedaddress);
}
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDW(gd, ed, fixedaddress);
}
}
break;
case 0x66:
opcode=F8;
switch(opcode) {
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
STH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -640,7 +716,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb1 = xRAX+(gd&3);
}
if(gb2) {
gd = x4;
UBFXw(gd, gb1, gb2*8, 8);
} else {
gd = gb1; // no need to extract
}
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
BFIx(eb1, gd, eb2*8, 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
STB(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
@@ -648,8 +757,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
STRxw_U12(gd, ed, fixedaddress);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
STxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
@@ -661,9 +770,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
SMREADLOCK(lock);
LDRxw_U12(gd, ed, fixedaddress);
LDxw(gd, ed, fixedaddress);
}
break;
@@ -674,8 +783,7 @@ uintptr_t dynarec64_67(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
// should a geted32 be created, to use 32bits regs instead of 64bits?
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=gd) {
MOVw_REG(gd, ed);
}
@@ -763,10 +871,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
STRxw_U12(x3, ed, fixedaddress);
STxw(x3, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
@@ -914,9 +1022,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRAX, x2);
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETED32(0);
@@ -939,6 +1047,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
if(!rex.w) {
SET_DFNONE(x2)
@@ -951,7 +1060,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRDX, x4);
} else {
if(ninst && dyn->insts
&& dyn->insts[ninst-1].x64.addr
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
+17 -17
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -31,6 +30,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t ed;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
@@ -185,8 +185,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
} else {
@@ -198,8 +198,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
} else {
@@ -211,8 +211,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
@@ -225,8 +225,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
@@ -240,8 +240,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
} else {
@@ -253,8 +253,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, s0, v1);
} else {
@@ -266,8 +266,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
} else {
@@ -279,8 +279,8 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, s0, v1);
} else {
+23 -23
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -33,6 +32,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int i1, i2, i3;
@@ -180,21 +180,21 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1);
CALL(native_f2xm1, -1);
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);
CALL(arm_fyl2x, -1);
CALL(native_fyl2x, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_ftan, -1);
CALL(native_ftan, -1);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
@@ -207,7 +207,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fpatan, -1);
CALL(native_fpatan, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xF4:
@@ -215,14 +215,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1);
CALL(native_fxtract, -1);
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);
CALL(arm_fprem1, -1);
CALL(native_fprem1, -1);
break;
case 0xF6:
INST_NAME("FDECSTP");
@@ -245,14 +245,14 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1);
CALL(native_fprem, -1);
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);
CALL(arm_fyl2xp1, -1);
CALL(native_fyl2xp1, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xFA:
@@ -269,7 +269,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fsincos, -1);
CALL(native_fsincos, -1);
break;
case 0xFC:
INST_NAME("FRNDINT");
@@ -277,7 +277,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1);
CALL(native_frndint, -1);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
u8 = x87_setround(dyn, ninst, x1, x2, x3);
@@ -294,19 +294,19 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fscale, -1);
CALL(native_fscale, -1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fsin, -1);
CALL(native_fsin, -1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fcos, -1);
CALL(native_fcos, -1);
break;
@@ -328,8 +328,8 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
if(!ST_IS_F(0)) {
FCVT_D_S(v1, v1);
}
@@ -343,24 +343,24 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(s0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
if(!ST_IS_F(0)) {
FCVT_S_D(v1, v1);
}
VSTR32_U12(v1, ed, fixedaddress);
VST32(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
@@ -376,7 +376,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
@@ -385,7 +385,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
wb1 = 1;
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
+20 -21
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -33,6 +32,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int64_t j64;
@@ -189,15 +189,15 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
SXTL_32(v1, v1); // i32 -> i64
SCVTFDD(v1, v1); // i64 -> double
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
@@ -211,11 +211,11 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FRINTZD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_do_pop(dyn, ninst, x3);
@@ -224,7 +224,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
@@ -238,11 +238,11 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
@@ -251,7 +251,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
@@ -265,11 +265,11 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
@@ -277,7 +277,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if((PK(0)==0xDB && ((PK(1)>>3)&7)==7) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
// the FLD is immediatly followed by an FSTP
LDRx_U12(x5, ed, 0);
@@ -291,20 +291,19 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else
rex.rex = 0;
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
if(box64_x87_no80bits) {
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v1, ed, fixedaddress);
} else {
if(ed!=x1) {
MOVx_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1);
CALL(native_fld, -1);
}
}
break;
@@ -312,20 +311,20 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSTP tbyte");
if(box64_x87_no80bits) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, wback, fixedaddress);
} else {
#if 0
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL(arm_fstp, -1);
CALL(native_fstp, -1);
#else
// Painfully long, straight conversion from the C code, shoud be optimized
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
FMOVxD(x1, v1);
// do special value first
TSTx_mask(x1, 1, 0b00000, 0b111110); //0x7fffffffffffffffL
+17 -17
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -31,6 +30,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t wback;
int64_t fixedaddress;
int unscaled;
int v1, v2;
MAYUSE(v2);
@@ -182,24 +182,24 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
@@ -207,8 +207,8 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
@@ -217,32 +217,32 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
break;
}
+16 -16
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -31,6 +30,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t ed;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int64_t j64;
@@ -161,13 +161,13 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, ed, fixedaddress);
break;
case 1:
INST_NAME("FISTTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
// those are ARM 8.5 opcode!
@@ -180,11 +180,11 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
STx(x2, ed, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STRw_U12(x5, ed, fixedaddress);
STx(x5, ed, fixedaddress);
MARK3;
#endif
x87_do_pop(dyn, ninst, x3);
@@ -192,36 +192,36 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 4:
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_frstor, -1);
CALL(native_frstor, -1);
break;
case 6:
INST_NAME("FSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_fsave, -1);
CALL(native_fsave, -1);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
if(dyn->n.x87stack) {
@@ -234,7 +234,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ANDw_mask(x2, x2, 0, 2);
}
BFIw(x3, x2, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_U12(x3, ed, fixedaddress); // store whole sw flags
STH(x3, ed, fixedaddress); // store whole sw flags
break;
default:
DEFAULT;
+17 -17
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -31,6 +30,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t wback;
int64_t fixedaddress;
int unscaled;
int v1, v2;
MAYUSE(v2);
@@ -191,8 +191,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIADD ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -202,8 +202,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -213,8 +213,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -225,8 +225,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FICOMP ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -238,8 +238,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISUB ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -249,8 +249,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -260,8 +260,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
@@ -271,8 +271,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
VLDR16_U12(v2, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
+114 -52
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -34,6 +33,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int s0;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(s0);
MAYUSE(v2);
@@ -59,7 +59,8 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
BFIw(x1, x2, 11, 3); // inject top
BFIw(xRAX, x1, 0, 16);
STRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
BFIx(xRAX, x1, 0, 16);
break;
case 0xE8:
case 0xE9:
@@ -151,8 +152,8 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRSHw_U12(x1, wback, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDSHw(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
SCVTFSw(v1, x1);
} else {
@@ -162,7 +163,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -172,10 +173,11 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
VFCVTZSs(s0, v1);
@@ -183,13 +185,16 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
}
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VMOVSto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst, x3);
break;
@@ -197,7 +202,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -206,10 +211,11 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
@@ -219,13 +225,16 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VMOVSto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
@@ -233,7 +242,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
@@ -242,7 +251,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
@@ -255,13 +264,16 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
VMOVSto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
@@ -269,50 +281,100 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
INST_NAME("FBLD ST0, tbytes");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbld, -1);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
LDRx_U12(x1, wback, fixedaddress);
SCVTFDx(v1, x1);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_I64);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, wback, fixedaddress);
if(!ST_IS_I64(0)) {
if(rex.is32bits) {
// need to also feed the STll stuff...
ADDx_U12(x4, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ANDw_mask(x1, x1, 0, 2); //mask=7
}
ADDx_REG_LSL(x1, x4, x1, 4); // fpu_ll is 2 i64
VSTR64_U12(v1, x1, 8); // ll
}
SCVTFDD(v1, v1);
if(rex.is32bits) {
VSTR64_U12(v1, x1, 0); // ref
}
}
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbst, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
if(!ST_IS_I64(0)) {
u8 = x87_setround(dyn, ninst, x1, x2, x4);
}
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STRx_U12(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
if(ST_IS_I64(0)) {
VST64(v1, wback, fixedaddress);
} else {
#if 0
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
#else
if(rex.is32bits) {
// need to check STll first...
ADDx_U12(x5, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
VMOVQDto(x3, v1, 0);
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ANDw_mask(x1, x1, 0, 2); //mask=7
}
ADDx_REG_LSL(x1, x5, x1, 4); // fpu_ll is 2 i64
LDRx_U12(x5, x1, 0); // ref
SUBx_REG(x5, x5, x3);
CBNZx_MARK2(x5);
LDRx_U12(x5, x1, 8); // ll
STx(x5, wback, fixedaddress);
B_MARK3(c__);
MARK2;
}
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
}
x87_do_pop(dyn, ninst, x3);
break;
default:
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -16,7 +15,6 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "../tools/bridge_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
+1 -3
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -16,7 +15,6 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "../tools/bridge_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
@@ -432,7 +430,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
STRB_U12(s5, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
+1 -3
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -16,7 +15,6 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "../tools/bridge_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
@@ -327,7 +325,7 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
if(c==1) {
LSRxw(s3, s1, rex.w?62:30);
EORxw_REG_LSR(s3, s3, s3, 1);
BFIw(xFlags, s4, F_OF, 1);
BFIw(xFlags, s3, F_OF, 1);
}
}
}
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -16,7 +15,6 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "../tools/bridge_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
+55 -59
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -34,6 +33,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
@@ -46,12 +46,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
GETREX();
switch(opcode) {
case 0x00:
@@ -65,15 +61,15 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = xRAX + (nextop&7) + (rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
UBFXw(x1, wback, wb2*8, 8);
UBFXw(x1, wback, wb2*8, 8);
emit_add8(dyn, ninst, x1, x2, x4, x3);
BFIx(wback, x1, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x4, x5);
@@ -92,7 +88,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -113,15 +109,15 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wback = xRAX + (nextop&7) + (rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
UBFXw(x1, wback, wb2*8, 8);
UBFXw(x1, wback, wb2*8, 8);
emit_or8(dyn, ninst, x1, x2, x4, x3);
BFIx(wback, x1, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_or8(dyn, ninst, x1, x2, x4, x5);
@@ -140,7 +136,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -187,7 +183,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
}
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
ASRxw(x1, gd, 3); // r1 = (gd>>3)
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
MARKLOCK;
@@ -219,11 +215,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wb2 = 0;
} else {
} else {
wback = (nextop&7);
wb2 = (wback>>2)*8;
wback = xRAX+(wback&3);
}
}
UBFXx(x2, wback, wb2, 8);
wb1 = 0;
ed = x2;
@@ -236,7 +232,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
BFIx(xRAX, x2, 0, 8);
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x2, wback);
CMPSxw_REG(x6, x2);
@@ -246,7 +242,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZx_MARKLOCK(x4);
// done
MARK;
UFLAG_IF {emit_cmp32(dyn, ninst, rex, x6, x2, x3, x4, x5);}
UFLAG_IF {emit_cmp8(dyn, ninst, x6, x2, x3, x4, x5);}
BFIx(xRAX, x2, 0, 8);
}
SMDMB();
@@ -275,7 +271,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRAX, x1);
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK3(cNE);
// Aligned version
@@ -343,7 +339,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
}
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
ASRxw(x1, gd, 3); // r1 = (gd>>3)
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
MARKLOCK;
@@ -378,7 +374,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(gd, x1);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
@@ -415,7 +411,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
SMDMB();
MARKLOCK;
LDAXPxw(x2, x3, wback);
@@ -444,7 +440,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
}
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -455,7 +451,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_and32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -464,7 +460,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
SMDMB();
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -475,7 +471,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
@@ -502,7 +498,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -522,7 +518,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -543,7 +539,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -564,7 +560,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -584,7 +580,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -604,7 +600,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -624,7 +620,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
wb1 = 0;
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MARKLOCK;
@@ -669,7 +665,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_add32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -680,7 +676,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZx_MARKLOCK(x3);
SMDMB();
B_NEXT_nocond;
MARK; // unaligned! also, not enough
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
@@ -699,7 +695,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -719,7 +715,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -739,7 +735,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -758,7 +754,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_and32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -777,7 +773,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
@@ -788,7 +784,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZx_MARKLOCK(x3);
SMDMB();
B_NEXT_nocond;
MARK; // unaligned! also, not enough
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
@@ -807,7 +803,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x5, i64);
emit_xor32(dyn, ninst, rex, ed, x5, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
MARKLOCK;
@@ -833,7 +829,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
SMDMB();
break;
case 0x86:
INST_NAME("LOCK XCHG Eb, Gb");
// Do the swap
@@ -856,7 +852,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
SMDMB();
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
// do the swap with exclusive locking
LDAXRB(x1, ed);
@@ -879,7 +875,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
GETGD;
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
@@ -895,7 +891,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(gd, x1);
}
break;
case 0xF6:
nextop = F8;
switch((nextop>>3)&7) {
@@ -917,7 +913,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
EBBACK;
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
MVNw_REG(x1, x1);
@@ -930,7 +926,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
}
break;
case 0xFE:
nextop = F8;
switch((nextop>>3)&7)
@@ -944,7 +940,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_inc8(dyn, ninst, x1, x2, x4);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_inc8(dyn, ninst, x1, x3, x4);
@@ -962,7 +958,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_dec8(dyn, ninst, x1, x2, x4);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
emit_dec8(dyn, ninst, x1, x3, x4);
@@ -987,7 +983,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
@@ -1016,7 +1012,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
@@ -1041,7 +1037,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
}
break;
default:
DEFAULT;
}
+82 -20
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -36,6 +35,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
int q0;
int d0, d1;
int64_t fixedaddress;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
@@ -57,8 +57,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress); // upper part reseted
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress); // upper part reseted
}
break;
case 0x11:
@@ -71,8 +71,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
d0 = sse_get_reg(dyn, ninst, x1, ed, 1);
VMOVeD(d0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -87,8 +87,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
VMOVeD(v0, 1, v0, 0);
break;
@@ -154,6 +154,42 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x38: // these are some more SSSE4.2+ opcodes
opcode = F8;
switch(opcode) {
case 0xF0:
INST_NAME("(unsupported) CRC32 Gd, Eb)");
nextop = F8;
addr = fakeed(dyn, addr, ninst, nextop);
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0xF1:
INST_NAME("(unsupported) CRC32 Gd, Ed)");
nextop = F8;
addr = fakeed(dyn, addr, ninst, nextop);
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_ud, -1);
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
default:
DEFAULT;
}
break;
case 0x51:
INST_NAME("SQRTSD Gx, Ex");
@@ -261,7 +297,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cLS); //Less than or equal
B_NEXT(cCC); //Less than
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
@@ -299,7 +335,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
FCMPD(v0, v1);
B_NEXT(cGE); //Greater than or equal
B_NEXT(cGT); //Greater than
VMOVeD(v0, 0, v1, 0); // to not erase uper part
#endif
break;
@@ -334,9 +370,9 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
VLDR128_U12(v1, ed, fixedaddress);
VLD128(v1, ed, fixedaddress);
}
VFADDPQS(v0, v0, v1);
break;
@@ -365,7 +401,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("ADDSUBPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
@@ -385,13 +421,39 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
GETEXSD(v1, 0, 0);
GETEX(v1, 0, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIDQ(v0, v1);
x87_restoreround(dyn, ninst, u8);
VFCVTNSQD(v0, v0); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
if(box64_dynarec_fastround) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIDQ(v0, v1);
x87_restoreround(dyn, ninst, u8);
VFCVTNSQD(v0, v0); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if(i) {
VMOVeD(d0, 0, v1, i);
FRINTID(d0, d0);
} else {
FRINTID(d0, v1);
}
FCVTZSwD(x1, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
MOVw_REG(x1, x4);
VMOVQSfrom(v0, i, x1);
}
x87_restoreround(dyn, ninst, u8);
VMOVQDfrom(v0, 1, xZR);
}
break;
case 0xF0:
@@ -405,8 +467,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 7, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress);
}
break;
+75 -21
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
@@ -35,6 +34,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
int q0, q1;
int d0, d1;
int64_t fixedaddress;
int unscaled;
int64_t j64;
MAYUSE(d0);
@@ -58,8 +58,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VLDR32_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v0, ed, fixedaddress);
}
break;
case 0x11:
@@ -71,8 +71,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
VMOVeS(q0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, 0);
VSTR32_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -83,9 +83,9 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
VTRNQ1_32(q0, q1, q1);
@@ -98,9 +98,9 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
q1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
VLDR128_U12(q1, ed, fixedaddress);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
VTRNQ2_32(q0, q1, q1);
@@ -143,7 +143,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
@@ -168,7 +168,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
@@ -239,9 +239,27 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x5B:
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
GETEX(d0, 0, 0) ;
GETEX(v1, 0, 0) ;
GETGX_empty(v0);
VFCVTZSQS(v0, d0);
if(box64_dynarec_fastround) {
VFCVTZSQS(v0, v1);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for(int i=0; i<4; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
VMOVeS(d0, 0, v1, i);
VFCVTZSs(d0, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
VMOVQSfrom(d0, 0, x4);
VMOVeS(v0, i, d0, 0);
}
}
break;
case 0x5C:
@@ -305,8 +323,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress);
}
break;
case 0x70:
@@ -341,8 +359,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
break;
case 0x7F:
@@ -353,12 +371,48 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xB8:
INST_NAME("POPCNT Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
nextop = F8;
v1 = fpu_get_scratch(dyn);
GETGD;
if(MODREG) {
GETED(0);
if(rex.w)
VMOVQDfrom(v1, 0, ed);
else {
MOVxw_REG(x1, ed); // need to clear uper part
VMOVQDfrom(v1, 0, x1);
}
} else {
if(rex.w) {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, ed, fixedaddress);
} else {
GETED(0); // just load and clear the upper part
VMOVQDfrom(v1, 0, ed);
}
}
CNT_8(v1, v1);
UADDLV_8(v1, v1);
VMOVQDto(gd, v1, 0);
IFX(X_ALL) {
MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF));
BICw(xFlags, xFlags, x1);
CBNZx(gd, 4+4);
BFIw(xFlags, xFlags, F_ZF, 1);
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
@@ -421,8 +475,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOV(v0, v1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
break;
+107 -470
View File
@@ -1,7 +1,6 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <math.h>
@@ -13,7 +12,6 @@
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -28,332 +26,6 @@
#include "custommem.h"
#include "bridge.h"
void arm_fstp(x64emu_t* emu, void* p)
{
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, p);
else
memcpy(p, &STld(0).ld, 10);
}
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
{
(void)emu;
dynarec_log(LOG_DEBUG, "R%lu=0x%lx (%lu)\n", n, reg, reg);
}
void arm_f2xm1(x64emu_t* emu)
{
ST0.d = exp2(ST0.d) - 1.0;
}
void arm_fyl2x(x64emu_t* emu)
{
ST(1).d = log2(ST0.d)*ST(1).d;
}
void arm_ftan(x64emu_t* emu)
{
ST0.d = tan(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fpatan(x64emu_t* emu)
{
ST1.d = atan2(ST1.d, ST0.d);
}
void arm_fxtract(x64emu_t* emu)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
}
void arm_fprem(x64emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
void arm_fyl2xp1(x64emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
}
void arm_fsincos(x64emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_frndint(x64emu_t* emu)
{
ST0.d = fpu_round(emu, ST0.d);
}
void arm_fscale(x64emu_t* emu)
{
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
}
void arm_fsin(x64emu_t* emu)
{
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fcos(x64emu_t* emu)
{
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void arm_fbld(x64emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
}
void arm_fild64(x64emu_t* emu, int64_t* ed)
{
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).sq = tmp;
STll(0).sref = ST0.sq;
}
void arm_fbstp(x64emu_t* emu, uint8_t* ed)
{
fpu_fbst(emu, ed);
}
void arm_fistp64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).sref==ST(0).sq) {
memcpy(ed, &STll(0).sq, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
void arm_fistt64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
int64_t tmp = ST0.d;
memcpy(ed, &tmp, sizeof(tmp));
}
void arm_fld(x64emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).uref = ST0.q;
}
void arm_ud(x64emu_t* emu)
{
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
}
void arm_priv(x64emu_t* emu)
{
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
}
void arm_fsave(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
void arm_frstor(x64emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
void arm_fprem1(x64emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void arm_aesimc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void arm_aesmc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void arm_aesdlast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
void arm_aeselast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void arm_aesd(x64emu_t* emu, int xmm)
{
arm_aesdlast(emu, xmm);
arm_aesimc(emu, xmm);
}
void arm_aese(x64emu_t* emu, int xmm)
{
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
void arm_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void arm_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void arm_clflush(x64emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
#define XMM0 0
#define XMM8 16
#define X870 8
@@ -386,7 +58,7 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
dyn->n.fpuused[reg] = 0;
if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D)
if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_I64)
dyn->n.neoncache[reg].v = 0;
}
// Get an MMX double reg
@@ -434,7 +106,8 @@ int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
}
for(int i=0; i<24; ++i)
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return dyn->insts[ninst].n.neoncache[i].t;
// not in the cache yet, so will be fetched...
@@ -448,7 +121,8 @@ int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a)
return NEON_CACHE_ST_D;
for(int i=0; i<24; ++i)
if((dyn->n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->n.neoncache[i].t==NEON_CACHE_ST_D)
|| dyn->n.neoncache[i].t==NEON_CACHE_ST_D
|| dyn->n.neoncache[i].t==NEON_CACHE_ST_I64)
&& dyn->n.neoncache[i].n==a)
return dyn->n.neoncache[i].t;
// not in the cache yet, so will be fetched...
@@ -466,6 +140,17 @@ int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
return i;
return -1;
}
int neoncache_get_st_f_i64(dynarec_arm_t* dyn, int ninst, int a)
{
/*if(a+dyn->insts[ninst].n.stack_next-st<0)
// The STx has been pushed at the end of instructon, so stop going back
return -1;*/
for(int i=0; i<24; ++i)
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64 || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
{
for(int i=0; i<24; ++i)
@@ -474,6 +159,14 @@ int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
return i;
return -1;
}
int neoncache_get_st_f_i64_noback(dynarec_arm_t* dyn, int ninst, int a)
{
for(int i=0; i<24; ++i)
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64 || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
{
for(int i=0; i<24; ++i)
@@ -482,6 +175,14 @@ int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
return i;
return -1;
}
int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a)
{
for(int i=0; i<24; ++i)
if((dyn->n.neoncache[i].t==NEON_CACHE_ST_I64 || dyn->n.neoncache[i].t==NEON_CACHE_ST_F)
&& dyn->n.neoncache[i].n==a)
return i;
return -1;
}
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
@@ -491,7 +192,7 @@ static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int
a = dyn->insts[ninst].n.combined2;
} else
a = dyn->insts[ninst].n.combined1;
int i = neoncache_get_st_f_noback(dyn, ninst, a);
int i = neoncache_get_st_f_i64_noback(dyn, ninst, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_combined, ninst=%d combined%c %d i=%d (stack:%d/%d)\n", ninst, (a == dyn->insts[ninst].n.combined2)?'2':'1', a ,i, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
@@ -510,7 +211,7 @@ static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int
return;
while(ninst>=0) {
a+=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: add pop'd ST (going backward)
int i = neoncache_get_st_f(dyn, ninst, a);
int i = neoncache_get_st_f_i64(dyn, ninst, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d, i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
@@ -545,7 +246,7 @@ static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
}
int i = neoncache_get_st_f_noback(dyn, ninst, a);
int i = neoncache_get_st_f_i64_noback(dyn, ninst, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d(%d/%d), i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
@@ -566,7 +267,7 @@ static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a)
{
int i = neoncache_get_current_st_f(dyn, a);
int i = neoncache_get_current_st_f_i64(dyn, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d i=%d\n", ninst, a, dyn->n.stack, i);
if(i<0) return;
dyn->n.neoncache[i].t = NEON_CACHE_ST_D;
@@ -599,31 +300,23 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
if( neoncache_get_current_st(dyn, ninst, a)==NEON_CACHE_ST_F
&& neoncache_get_current_st(dyn, ninst, b)==NEON_CACHE_ST_F )
return NEON_CACHE_ST_F;
// don't combine i64, it's only for load/store
/*if( neoncache_get_current_st(dyn, ninst, a)==NEON_CACHE_ST_I64
&& neoncache_get_current_st(dyn, ninst, b)==NEON_CACHE_ST_I64 )
return NEON_CACHE_ST_I64;*/
return NEON_CACHE_ST_D;
}
int isPred(dynarec_arm_t* dyn, int ninst, int pred) {
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
if(dyn->insts[ninst].pred[i]==pred)
return pred;
return -1;
}
int getNominalPred(dynarec_arm_t* dyn, int ninst) {
if((ninst<=0) || !dyn->insts[ninst].pred_sz)
return -1;
if(isPred(dyn, ninst, ninst-1)!=-1)
return ninst-1;
return dyn->insts[ninst].pred[0];
}
int isCacheEmpty(dynarec_arm_t* dyn, int ninst) {
static int isCacheEmpty(dynarec_native_t* dyn, int ninst) {
if(dyn->insts[ninst].n.stack_next) {
return 0;
}
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64)
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
return 0;
}
@@ -631,7 +324,7 @@ int isCacheEmpty(dynarec_arm_t* dyn, int ninst) {
}
static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int i2 = dyn->insts[ninst].x64.jmp_insts;
if(i2<0)
return 1;
@@ -646,7 +339,9 @@ static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
for(int i=0; i<24 && !ret; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_I64)
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
ret = 1;
}
@@ -678,48 +373,6 @@ static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
return ret;
}
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
return 0;
}
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int ret = 0;
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
return ret;
}
void neoncacheUnwind(neoncache_t* cache)
{
if(cache->swapped) {
@@ -727,7 +380,7 @@ void neoncacheUnwind(neoncache_t* cache)
int a = -1;
int b = -1;
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F || cache->neoncache[j].t == NEON_CACHE_ST_I64)) {
if(cache->neoncache[j].n == cache->combined1)
a = j;
else if(cache->neoncache[j].n == cache->combined2)
@@ -751,7 +404,7 @@ void neoncacheUnwind(neoncache_t* cache)
if(cache->stack_push) {
// unpush
for(int j=0; j<24; ++j) {
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F || cache->neoncache[j].t == NEON_CACHE_ST_I64)) {
if(cache->neoncache[j].n<cache->stack_push)
cache->neoncache[j].v = 0;
else
@@ -796,6 +449,7 @@ void neoncacheUnwind(neoncache_t* cache)
break;
case NEON_CACHE_ST_F:
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_I64:
cache->x87cache[x87reg] = cache->neoncache[i].n;
cache->x87reg[x87reg] = i;
++x87reg;
@@ -813,7 +467,6 @@ void neoncacheUnwind(neoncache_t* cache)
}
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S64 (uint64_t)(int64_t)*(int32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
@@ -853,64 +506,8 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
return 0; //Form [reg1 + reg2<<N + XXXXXX]
}
}
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
(void)dyn; (void)addr; (void)ninst;
if((nextop&0xC0)==0xC0)
return addr;
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
if((sib&0x7)==5) {
addr+=4;
}
} else if((nextop&7)==5) {
addr+=4;
}
} else {
if((nextop&7)==4) {
++addr;
}
if(nextop&0x80) {
addr+=4;
} else {
++addr;
}
}
return addr;
}
#undef F8
#undef F32
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
(void)dyn;
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
if(!addr || !getProtection(addr))
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(!addr || !getProtection(addr))
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
#undef PK32
#undef PK
}
#undef F32S64
const char* getCacheName(int t, int n)
{
@@ -918,6 +515,7 @@ const char* getCacheName(int t, int n)
switch(t) {
case NEON_CACHE_ST_D: sprintf(buff, "ST%d", n); break;
case NEON_CACHE_ST_F: sprintf(buff, "st%d", n); break;
case NEON_CACHE_ST_I64: sprintf(buff, "STi%d", n); break;
case NEON_CACHE_MM: sprintf(buff, "MM%d", n); break;
case NEON_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case NEON_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
@@ -927,20 +525,59 @@ const char* getCacheName(int t, int n)
return buff;
}
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst)
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
{
// check flags cache
if(dyn->insts[ninst].f_entry.dfnone || dyn->insts[ninst].f_entry.pending)
return 0;
if(dyn->insts[ninst].x64.state_flags)
return 0;
// check neoncache
neoncache_t* n = &dyn->insts[ninst].n;
if(n->news || n->stack || n->stack_next)
return 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].v)
return 0;
return 1;
if(box64_dynarec_dump) {
printf_x64_instruction(rex.is32bits?my_context->dec32:my_context->dec, &dyn->insts[ninst].x64, name);
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d/%d",
(box64_dynarec_dump>1)?"\e[32m":"",
(void*)(dyn->native_start+dyn->insts[ninst].address),
dyn->insts[ninst].size/4,
ninst,
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].x64.may_set?"may":"set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smread, dyn->smwrite);
if(dyn->insts[ninst].pred_sz) {
dynarec_log(LOG_NONE, ", pred=");
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);
}
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts>=0)
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)
dynarec_log(LOG_NONE, ", jmp=out");
if(dyn->last_ip)
dynarec_log(LOG_NONE, ", last_ip=%p", (void*)dyn->last_ip);
for(int ii=0; ii<24; ++ii) {
switch(dyn->insts[ninst].n.neoncache[ii].t) {
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_I64: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_NONE:
default: break;
}
}
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack)
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
}
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
{
dynarec_log(LOG_NONE, "\t%08x\t%s\n", opcode, arm64_print(opcode, (uintptr_t)dyn->block));
}
+13 -58
View File
@@ -1,46 +1,7 @@
#ifndef __DYNAREC_ARM_FUNCTIONS_H__
#define __DYNAREC_ARM_FUNCTIONS_H__
typedef struct x64emu_s x64emu_t;
void arm_fstp(x64emu_t* emu, void* p);
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n);
void arm_f2xm1(x64emu_t* emu);
void arm_fyl2x(x64emu_t* emu);
void arm_ftan(x64emu_t* emu);
void arm_fpatan(x64emu_t* emu);
void arm_fxtract(x64emu_t* emu);
void arm_fprem(x64emu_t* emu);
void arm_fyl2xp1(x64emu_t* emu);
void arm_fsincos(x64emu_t* emu);
void arm_frndint(x64emu_t* emu);
void arm_fscale(x64emu_t* emu);
void arm_fsin(x64emu_t* emu);
void arm_fcos(x64emu_t* emu);
void arm_fbld(x64emu_t* emu, uint8_t* ed);
void arm_fild64(x64emu_t* emu, int64_t* ed);
void arm_fbstp(x64emu_t* emu, uint8_t* ed);
void arm_fistp64(x64emu_t* emu, int64_t* ed);
void arm_fistt64(x64emu_t* emu, int64_t* ed);
void arm_fld(x64emu_t* emu, uint8_t* ed);
void arm_fsave(x64emu_t* emu, uint8_t* ed);
void arm_frstor(x64emu_t* emu, uint8_t* ed);
void arm_fprem1(x64emu_t* emu);
void arm_aesd(x64emu_t* emu, int xmm);
void arm_aese(x64emu_t* emu, int xmm);
void arm_aesdlast(x64emu_t* emu, int xmm);
void arm_aeselast(x64emu_t* emu, int xmm);
void arm_aesimc(x64emu_t* emu, int xmm);
void arm_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void arm_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void arm_clflush(x64emu_t* emu, void* p);
void arm_ud(x64emu_t* emu);
void arm_priv(x64emu_t* emu);
#include "../dynarec_native_functions.h"
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
@@ -60,38 +21,32 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
// ---- Neon cache functions
// Get type for STx
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a);
// Get if STx is FLOAT or DOUBLE
// Get if STx is FLOAT
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a);
// Get if STx is FLOAT or I64
int neoncache_get_st_f_i64(dynarec_arm_t* dyn, int ninst, int a);
// Get actual type for STx
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a);
// Get actual STx is FLOAT or DOUBLE
// Get actual STx is FLOAT
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a);
// Get actual STx is FLOAT or I64
int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a);
// Back-propagate a change float->double
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
// Combine and propagate if needed (pass 1 only)
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
// FPU Cache transformation (for loops)
int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
// FPU Cache transformation (for loops) // Specific, need to be written par backend
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_arm_t* dyn, int ninst, int pred);
int getNominalPred(dynarec_arm_t* dyn, int ninst);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
int getedparity(dynarec_native_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta);
const char* getCacheName(int t, int n);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex);
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+445 -87
View File
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "debug.h"
#include "box64context.h"
@@ -18,7 +18,6 @@
#include "x64trace.h"
#include "dynarec_native.h"
#include "../dynablock_private.h"
#include "../tools/bridge_private.h"
#include "custommem.h"
#include "arm64_printer.h"
@@ -26,12 +25,19 @@
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_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 absmax, uint32_t mask, rex_t rex, int *l, int s, int delta)
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, rex_t rex, int *l, int s, int delta)
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
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(unscaled)
*unscaled = 0;
if(lock==2)
*l = 0;
uint8_t ret = x2;
@@ -49,11 +55,16 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if((sib&0x7)==5) {
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
if(tmp && (!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256))) {
MOV64x(scratch, tmp);
ADDx_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
LSLx(ret, xRAX+sib_reg, (sib>>6));
if(sib>>6) {
LSLx(ret, xRAX+sib_reg, (sib>>6));
} else
ret = xRAX+sib_reg;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
*fixaddress = tmp;
}
} else {
@@ -71,14 +82,22 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
}
} else if((nextop&7)==5) {
uint64_t tmp = F32S64;
int64_t tmp = F32S64;
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
} else if(tmp<0x1000) {
} 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) { // 3 opcodes to load immediate is cheap enough
MOV64x(ret, tmp+addr+delta);
} else {
@@ -103,10 +122,12 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
if(nextop&0x80)
i64 = F32S;
else
else
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask))) {
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) {
ADDx_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
@@ -165,12 +186,149 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
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, xRAX+sib_reg, (sib>>6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
}
} else {
switch(lock) {
case 1: addLockAddress((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, xRAX+(sib&0x7), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x7);
}
}
} else if((nextop&7)==5) {
uint64_t tmp = F32;
MOV32w(ret, tmp);
switch(lock) {
case 1: addLockAddress(tmp); break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
} else {
ret = xRAX+(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>-256) && (i32<256))
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x07), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x07);
}
} else {
ret = xRAX+(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, xRAX+(sib&0x07), xRAX+sib_reg, (sib>>6));
} else {
scratch = xRAX+(sib&0x07);
}
} else
scratch = xRAX+(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, xRAX+(sib&0x07), scratch);
} else {
ADDw_REG(scratch, scratch, xRAX+(sib&0x07));
}
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
PASS3(int tmp = xRAX+(sib&0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
}
}
}
*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 absmax, uint32_t mask, rex_t rex, int* l, int s, int delta)
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* 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;
@@ -188,12 +346,14 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if((sib&0x7)==5) {
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
if(tmp && (!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256))) {
MOV64x(scratch, tmp);
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
}
} else {
switch(lock) {
@@ -234,10 +394,12 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
if(nextop&0x80)
i64 = F32S;
else
else
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask))) {
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, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
@@ -298,10 +460,12 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
/* 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 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, int s)
{
MAYUSE(dyn); MAYUSE(ninst);
if(unscaled)
*unscaled = 0;
uint8_t ret = x2;
uint8_t scratch = x3;
*fixaddress = 0;
@@ -322,7 +486,11 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
case 1: offset = F8S; break;
case 2: offset = F16S; break;
}
if(offset && (offset>absmax || offset<absmin || (offset&mask))) {
if(offset && (offset>=absmax && offset<=absmin && !(offset&mask))) {
*fixaddress = offset;
offset = 0;
}
if(offset && (unscaled && offset>-256 && offset<256)) {
*fixaddress = offset;
offset = 0;
}
@@ -376,6 +544,16 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
return addr;
}
static void exit_block(dynarec_arm_t* dyn, int ninst)
{
ADR_S20(x5, (intptr_t)dyn->enter - (uintptr_t)dyn->block);
LDAXRw(x4, x5);
SUBw_U12(x4, x4, 1);
STLXRw(x3, x4, x5);
CBNZw(x3, 4-4*4);
}
#define EXIT_SIZE (4*5)
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
@@ -388,8 +566,11 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
} else {
GETIP_(ip);
}
NOTEST(x2);
TABLE64(x2, (uintptr_t)arm64_epilog);
SMEND();
if(box64_dynarec_age)
exit_block(dyn, ninst);
BR(x2);
}
@@ -402,6 +583,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
if(reg!=xRIP) {
MOVx_REG(xRIP, reg);
}
NOTEST(x2);
uintptr_t tbl = getJumpTable64();
MAYUSE(tbl);
TABLE64(x3, tbl);
@@ -414,6 +596,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
UBFXx(x2, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
LDRx_REG_LSL3(x2, x3, x2);
} else {
NOTEST(x2);
uintptr_t p = getJumpTableAddress64(ip);
MAYUSE(p);
TABLE64(x3, p);
@@ -425,30 +608,35 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
}
CLEARIP();
#ifdef HAVE_TRACE
//MOVx(x3, 15); no access to PC reg
//MOVx(x3, 15); no access to PC reg
#endif
SMEND();
if(box64_dynarec_age)
exit_block(dyn, ninst);
BLR(x2); // save LR...
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
{
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Ret to epilog\n");
POP1(xRIP);
MOVx_REG(x1, xRIP);
POP1z(xRIP);
MOVz_REG(x1, xRIP);
SMEND();
if(box64_dynarec_callret) {
// pop the actual return address for ARM stack
LDPx_S7_offset(x2, x6, xSP, 0);
CBZx(x6, 5*4);
CBZx(x6, 5*4+(box64_dynarec_age?EXIT_SIZE:0));
ADDx_U12(xSP, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
CBNZx(x6, 2*4+(box64_dynarec_age?EXIT_SIZE:0));
if(box64_dynarec_age)
exit_block(dyn, ninst);
BLR(x2);
// not the correct return address, regular jump
}
uintptr_t tbl = getJumpTable64();
NOTEST(x2);
MOV64x(x2, tbl);
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
LDRx_REG_LSL3(x2, x2, x3);
@@ -458,34 +646,39 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
LDRx_REG_LSL3(x2, x2, x3);
if(box64_dynarec_age)
exit_block(dyn, ninst);
BLR(x2); // save LR
CLEARIP();
}
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
{
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Retn to epilog\n");
POP1(xRIP);
POP1z(xRIP);
if(n>0xfff) {
MOV32w(w1, n);
ADDx_REG(xRSP, xRSP, x1);
ADDz_REG(xRSP, xRSP, x1);
} else {
ADDx_U12(xRSP, xRSP, n);
ADDz_U12(xRSP, xRSP, n);
}
MOVx_REG(x1, xRIP);
MOVz_REG(x1, xRIP);
SMEND();
if(box64_dynarec_callret) {
// pop the actual return address for ARM stack
LDPx_S7_offset(x2, x6, xSP, 0);
CBZx(x6, 5*4);
CBZx(x6, 5*4+(box64_dynarec_age?EXIT_SIZE:0));
ADDx_U12(xSP, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
CBNZx(x6, 2*4+(box64_dynarec_age?EXIT_SIZE:0));
if(box64_dynarec_age)
exit_block(dyn, ninst);
BLR(x2);
// not the correct return address, regular jump
}
uintptr_t tbl = getJumpTable64();
NOTEST(x2);
MOV64x(x2, tbl);
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
LDRx_REG_LSL3(x2, x2, x3);
@@ -495,6 +688,8 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
LDRx_REG_LSL3(x2, x2, x3);
if(box64_dynarec_age)
exit_block(dyn, ninst);
BLR(x2); // save LR
CLEARIP();
}
@@ -505,29 +700,42 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
// POP IP
POP1(xRIP);
// POP CS
POP1(x2);
NOTEST(x2);
if(is64bits) {
POP1(xRIP);
POP1(x2);
POP1(xFlags);
} else {
POP1_32(xRIP);
POP1_32(x2);
POP1_32(xFlags);
}
// x2 is CS
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_CS]));
MOVZw(x1, 0);
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
STRx_U12(x1, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
// POP EFLAGS
POP1(xFlags);
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
// clean EFLAGS
MOV32w(x1, 0x3F7FD7);
ANDx_REG(xFlags, xFlags, x1);
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0);
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0); // xFlags | 0b10
SET_DFNONE(x1);
// POP RSP
POP1(x3);
if(is64bits) {
POP1(x3); //rsp
POP1(x2); //ss
} else {
POP1_32(x3); //rsp
POP1_32(x2); //ss
}
// POP SS
POP1(x2);
STRH_U12(x2, xEmu, offsetof(x64emu_t, segs[_SS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
// set new RSP
MOVx_REG(xRSP, x3);
// Ret....
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
SMEND();
if(box64_dynarec_age)
exit_block(dyn, ninst);
BR(x2);
CLEARIP();
}
@@ -662,7 +870,9 @@ static void x87_reset(dynarec_arm_t* dyn)
dyn->n.swapped = 0;
dyn->n.barrier = 0;
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].t == NEON_CACHE_ST_F || dyn->n.neoncache[i].t == NEON_CACHE_ST_D)
if(dyn->n.neoncache[i].t == NEON_CACHE_ST_F
|| dyn->n.neoncache[i].t == NEON_CACHE_ST_D
|| dyn->n.neoncache[i].t == NEON_CACHE_ST_I64)
dyn->n.neoncache[i].v = 0;
}
@@ -723,7 +933,9 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t)
dyn->n.stack_push+=1;
// move all regs in cache, and find a free one
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D)
||(dyn->n.neoncache[j].t == NEON_CACHE_ST_F)
||(dyn->n.neoncache[j].t == NEON_CACHE_ST_I64))
++dyn->n.neoncache[j].n;
int ret = -1;
for(int i=0; i<8; ++i)
@@ -732,13 +944,7 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t)
else if(ret==-1) {
dyn->n.x87cache[i] = 0;
ret=dyn->n.x87reg[i]=fpu_get_reg_x87(dyn, t, 0);
#if STEP == 1
// need to check if reg is compatible with float
if((ret>15) && (t == NEON_CACHE_ST_F))
dyn->n.neoncache[ret].t = NEON_CACHE_ST_D;
#else
dyn->n.neoncache[ret].t = X87_ST0;
#endif
}
return ret;
}
@@ -752,7 +958,9 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
dyn->n.stack_push+=1;
// move all regs in cache
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D)
||(dyn->n.neoncache[j].t == NEON_CACHE_ST_F)
||(dyn->n.neoncache[j].t == NEON_CACHE_ST_I64))
++dyn->n.neoncache[j].n;
for(int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1)
@@ -874,10 +1082,29 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
}
#ifdef HAVE_TRACE
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_stackcount(dyn, ninst, s1);
// Synch top & stack counter
int a = dyn->n.x87stack;
if(a) {
// Add x87stack to emu fpu_stack
LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDw_U12(s2, s2, a);
} else {
SUBw_U12(s2, s2, -a);
}
STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
if(a>0) {
SUBw_U12(s2, s2, a);
} else {
ADDw_U12(s2, s2, -a);
}
ANDw_mask(s2, s2, 0, 2); //mask=7
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
}
int ret = 0;
for (int i=0; (i<8) && (!ret); ++i)
if(dyn->n.x87cache[i] != -1)
@@ -887,7 +1114,9 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
// prepare offset to fpu => s1
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
if(!a) {
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
}
// loop all cache entries
for (int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1) {
@@ -896,7 +1125,31 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3);
}
}
#endif
static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// go back with the top & stack counter
int a = dyn->n.x87stack;
if(a) {
// Sub x87stack to emu fpu_stack
LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
SUBw_U12(s2, s2, a);
} else {
ADDw_U12(s2, s2, -a);
}
STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
// Add x87stack to top, with and 7
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
if(a>0) {
ADDw_U12(s2, s2, a);
} else {
SUBw_U12(s2, s2, -a);
}
ANDw_mask(s2, s2, 0, 2); //mask=7
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
}
}
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
{
@@ -904,7 +1157,9 @@ int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
for (int i=0; i<8; ++i) {
if(dyn->n.x87cache[i]==st) {
#if STEP == 1
if(t==NEON_CACHE_ST_D && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F))
if(t==NEON_CACHE_ST_D && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F || dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_I64))
neoncache_promote_double(dyn, ninst, st);
else if(t==NEON_CACHE_ST_F && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_I64))
neoncache_promote_double(dyn, ninst, st);
#endif
return i;
@@ -950,7 +1205,9 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int populate, int s1, int s2, i
int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
for(int ii=0; ii<24; ++ii)
if((dyn->n.neoncache[ii].t == NEON_CACHE_ST_F || dyn->n.neoncache[ii].t == NEON_CACHE_ST_D)
if((dyn->n.neoncache[ii].t == NEON_CACHE_ST_F
|| dyn->n.neoncache[ii].t == NEON_CACHE_ST_D
|| dyn->n.neoncache[ii].t == NEON_CACHE_ST_I64)
&& dyn->n.neoncache[ii].n==st)
return ii;
assert(0);
@@ -988,6 +1245,9 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F) {
FCVT_D_S(31, dyn->n.x87reg[ret]);
VSTR64_REG_LSL3(31, s1, s2);
} else if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_I64) {
SCVTFDD(31, dyn->n.x87reg[ret]);
VSTR64_REG_LSL3(31, s1, s2);
} else {
VSTR64_REG_LSL3(dyn->n.x87reg[ret], s1, s2);
}
@@ -1005,7 +1265,7 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
#if STEP == 1
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F)
if(dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_F || dyn->n.neoncache[dyn->n.x87reg[ret]].t==NEON_CACHE_ST_I64)
neoncache_promote_double(dyn, ninst, st);
#endif
// prepare offset to fpu => s1
@@ -1036,7 +1296,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// refresh the value
MESSAGE(LOG_DUMP, "\tRefresh x87 Cache for ST%d\n", st);
#if STEP == 1
if(dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F)
if(dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F || dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_I64)
neoncache_promote_double(dyn, ninst, st);
#endif
ADDx_U12(s1, xEmu, offsetof(x64emu_t, x87));
@@ -1197,7 +1457,7 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
}
}
#ifdef HAVE_TRACE
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
for (int i=0; i<8; ++i)
@@ -1205,7 +1465,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
VLDR64_U12(dyn->n.mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
}
}
#endif
// SSE / SSE2 helpers
@@ -1297,7 +1556,7 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
}
}
#ifdef HAVE_TRACE
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
for (int i=0; i<16; ++i)
@@ -1305,7 +1564,6 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
VSTR128_U12(dyn->n.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
}
}
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
@@ -1364,10 +1622,20 @@ static int findCacheSlot(dynarec_arm_t* dyn, int ninst, int t, int n, neoncache_
case NEON_CACHE_ST_F:
if (t==NEON_CACHE_ST_D)
return i;
if (t==NEON_CACHE_ST_I64)
return i;
break;
case NEON_CACHE_ST_D:
if (t==NEON_CACHE_ST_F)
return i;
if (t==NEON_CACHE_ST_I64)
return i;
break;
case NEON_CACHE_ST_I64:
if (t==NEON_CACHE_ST_F)
return i;
if (t==NEON_CACHE_ST_D)
return i;
break;
case NEON_CACHE_XMMR:
if(t==NEON_CACHE_XMMW)
@@ -1392,7 +1660,7 @@ static void swapCache(dynarec_arm_t* dyn, int ninst, int i, int j, neoncache_t *
quad =1;
if(cache->neoncache[j].t==NEON_CACHE_XMMR || cache->neoncache[j].t==NEON_CACHE_XMMW)
quad =1;
if(!cache->neoncache[i].v) {
// a mov is enough, no need to swap
MESSAGE(LOG_DUMP, "\t - Moving %d <- %d\n", i, j);
@@ -1407,7 +1675,7 @@ static void swapCache(dynarec_arm_t* dyn, int ninst, int i, int j, neoncache_t *
}
// SWAP
neon_cache_t tmp;
MESSAGE(LOG_DUMP, "\t - Swaping %d <-> %d\n", i, j);
MESSAGE(LOG_DUMP, "\t - Swapping %d <-> %d\n", i, j);
// There is no VSWP in Arm64 NEON to swap 2 register contents!
// so use a scratch...
#define SCRATCH 31
@@ -1452,12 +1720,13 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
VLDR128_U12(i, xEmu, offsetof(x64emu_t, xmm[n]));
break;
case NEON_CACHE_MM:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
VLDR64_U12(i, xEmu, offsetof(x64emu_t, mmx[i]));
break;
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_F:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
case NEON_CACHE_ST_I64:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
if((*s3_top) == 0xffff) {
LDRw_U12(s3, xEmu, offsetof(x64emu_t, top));
*s3_top = 0;
@@ -1478,12 +1747,15 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
if(t==NEON_CACHE_ST_F) {
FCVT_S_D(i, i);
}
break;
if(t==NEON_CACHE_ST_I64) {
VFCVTZSQD(i, i);
}
break;
case NEON_CACHE_NONE:
case NEON_CACHE_SCR:
default: /* nothing done */
MESSAGE(LOG_DUMP, "\t - ignoring %s\n", getCacheName(t, n));
break;
break;
}
cache->neoncache[i].n = n;
cache->neoncache[i].t = t;
@@ -1500,12 +1772,13 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
VSTR128_U12(i, xEmu, offsetof(x64emu_t, xmm[n]));
break;
case NEON_CACHE_MM:
MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n));
MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n));
VSTR64_U12(i, xEmu, offsetof(x64emu_t, mmx[n]));
break;
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_F:
MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n));
case NEON_CACHE_ST_I64:
MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n));
if((*s3_top)==0xffff) {
LDRw_U12(s3, xEmu, offsetof(x64emu_t, top));
*s3_top = 0;
@@ -1524,14 +1797,16 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
*s2_val = 0;
if(t==NEON_CACHE_ST_F) {
FCVT_D_S(i, i);
} else if (t==NEON_CACHE_ST_I64) {
SCVTFDD(i, i);
}
VSTR64_U12(i, s2, offsetof(x64emu_t, x87));
break;
break;
case NEON_CACHE_NONE:
case NEON_CACHE_SCR:
default: /* nothing done */
MESSAGE(LOG_DUMP, "\t - ignoring %s\n", getCacheName(t, n));
break;
break;
}
cache->neoncache[i].v = 0;
}
@@ -1653,6 +1928,23 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.neoncache[i].t, cache.neoncache[i].n));
FCVT_D_S(i, i);
cache.neoncache[i].t = NEON_CACHE_ST_D;
} else if(cache.neoncache[i].t == NEON_CACHE_ST_D && cache_i2.neoncache[i].t == NEON_CACHE_ST_I64) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.neoncache[i].t, cache.neoncache[i].n));
VFCVTZSQD(i, i);
cache.neoncache[i].t = NEON_CACHE_ST_I64;
} else if(cache.neoncache[i].t == NEON_CACHE_ST_F && cache_i2.neoncache[i].t == NEON_CACHE_ST_I64) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.neoncache[i].t, cache.neoncache[i].n));
VFCVTZSQS(i, i);
cache.neoncache[i].t = NEON_CACHE_ST_D;
} else if(cache.neoncache[i].t == NEON_CACHE_ST_I64 && cache_i2.neoncache[i].t == NEON_CACHE_ST_F) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.neoncache[i].t, cache.neoncache[i].n));
SCVTFDD(i, i);
FCVT_S_D(i, i);
cache.neoncache[i].t = NEON_CACHE_ST_F;
} else if(cache.neoncache[i].t == NEON_CACHE_ST_I64 && cache_i2.neoncache[i].t == NEON_CACHE_ST_D) {
MESSAGE(LOG_DUMP, "\t - Convert %s\n", getCacheName(cache.neoncache[i].t, cache.neoncache[i].n));
SCVTFDD(i, i);
cache.neoncache[i].t = NEON_CACHE_ST_D;
} else if(cache.neoncache[i].t == NEON_CACHE_XMMR && cache_i2.neoncache[i].t == NEON_CACHE_XMMW)
{ cache.neoncache[i].t = NEON_CACHE_XMMW; }
else if(cache.neoncache[i].t == NEON_CACHE_XMMW && cache_i2.neoncache[i].t == NEON_CACHE_XMMR) {
@@ -1680,18 +1972,18 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
int go = 0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
if(dyn->f.pending!=SF_SET && dyn->f.pending!=SF_SET_PENDING)
go = 1;
case SF_SET:
if(dyn->f.pending!=SF_SET && dyn->f.pending!=SF_SET_PENDING)
go = 1;
break;
case SF_SET_PENDING:
if(dyn->f.pending!=SF_SET
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
&& dyn->f.pending!=SF_PENDING)
go = 1;
break;
case SF_PENDING:
if(dyn->f.pending!=SF_SET
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
@@ -1704,32 +1996,34 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(go) {
if(dyn->f.pending!=SF_PENDING) {
LDRw_U12(s1, xEmu, offsetof(x64emu_t, df));
j64 = (GETMARK3)-(dyn->native_size);
j64 = (GETMARKF2)-(dyn->native_size);
CBZw(s1, j64);
}
CALL_(UpdateFlags, -1, 0);
MARK3;
MARKF2;
}
#endif
}
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) {
if(cacheupd&1)
fpuCacheTransform(dyn, ninst, s1, s2, s3);
if(cacheupd&2)
fpuCacheTransform(dyn, ninst, s1, s2, s3);
if(cacheupd&1)
flagsCacheTransform(dyn, ninst, s1);
}
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_reflectcache(dyn, ninst, s1, s2, s3);
if(trace_emm)
mmx_reflectcache(dyn, ninst, s1);
if(trace_xmm)
sse_reflectcache(dyn, ninst, s1);
mmx_reflectcache(dyn, ninst, s1);
sse_reflectcache(dyn, ninst, s1);
}
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// need to undo some things on the x87 tracking
x87_unreflectcache(dyn, ninst, s1, s2, s3);
}
#endif
void fpu_reset(dynarec_arm_t* dyn)
{
@@ -1753,3 +2047,67 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MVNw_REG(s4, s4);
BFIw(xFlags, s4, F_PF, 1);
}
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
{
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
#if STEP > 1
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
dyn->n = dyn->insts[ninst].n;
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
if(box64_dynarec_dump)
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
for(int i=0; i<24; ++i)
if(dyn->insts[reset_n].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
MESSAGE(LOG_DEBUG, " ==> ");
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
MESSAGE(LOG_DEBUG, " -> ");
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
if(dyn->n.combined1 || dyn->n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
if(dyn->n.stack_push || dyn->n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
}
// propagate ST stack state, especial stack pop that are deferred
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
{
if(dyn->n.stack_pop) {
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D
|| dyn->n.neoncache[j].t == NEON_CACHE_ST_F
|| dyn->n.neoncache[j].t == NEON_CACHE_ST_I64)) {
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
dyn->n.neoncache[j].v = 0;
else
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
}
dyn->n.stack_pop = 0;
}
dyn->n.stack = dyn->n.stack_next;
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
}
+140 -81
View File
@@ -67,8 +67,8 @@
wback = 0; \
} else { \
SMREAD() \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
addr = geted(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 GETEDx(D) if(MODREG) { \
@@ -76,8 +76,17 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
LDRx_U12(x1, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
LDx(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDz(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
LDz(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDw(D) if((nextop&0xC0)==0xC0) { \
@@ -85,8 +94,8 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL,0, D); \
LDRw_U12(x1, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL,0, D); \
LDW(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSEDw(D) if((nextop&0xC0)==0xC0) { \
@@ -96,8 +105,8 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, D); \
LDSW(x1, wback, fixedaddress); \
wb = ed = x1; \
}
#define GETED32(D) if(MODREG) { \
@@ -105,8 +114,8 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(x1, wback, fixedaddress); \
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((nextop&0xC0)==0xC0) { \
@@ -116,8 +125,8 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
LDRSW_U12(x1, wback, fixedaddress); \
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
@@ -126,18 +135,18 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
addr = geted(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; \
}
#define GETED32H(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
LDRxw_U12(hint, wback, fixedaddress); \
ed = hint; \
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) { \
@@ -146,9 +155,9 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
ed = ret; \
LDRxw_U12(ed, wback, fixedaddress); \
LDxw(ed, wback, fixedaddress); \
}
#define GETED32W(hint, ret, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
@@ -156,23 +165,23 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
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; \
LDRxw_U12(ed, wback, fixedaddress); \
LDxw(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STRxw_U12(ed, wback, fixedaddress); SMWRITE();}
#define WBACK if(wback) {STxw(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0)
#define WBACKx if(wback) {STRx_U12(ed, wback, fixedaddress); SMWRITE();}
#define WBACKx if(wback) {STx(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0)
#define WBACKw if(wback) {STRw_U12(ed, wback, fixedaddress); SMWRITE();}
#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 = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRxw_REG(x1, wback, O); \
ed = x1; \
}
@@ -183,10 +192,20 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRx_REG(x1, wback, O); \
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 = xRAX+(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_REG(x1, wback, O); \
ed = x1; \
}
#define GETSEDOw(O, D) if((nextop&0xC0)==0xC0) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
SXTWx(x1, ed); \
@@ -194,7 +213,7 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
LDRSW_REG(x1, wback, O); \
wb = ed = x1; \
}
@@ -214,8 +233,8 @@
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDH(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
}
@@ -227,8 +246,8 @@
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRH_U12(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDH(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
@@ -240,15 +259,15 @@
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDRSHx_U12(i, wback, fixedaddress);\
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDSHw(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
// Write ed back to original register / memory
#define EWBACK if(wb1) {STRH_U12(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, 0, 16);}
#define EWBACK EWBACKW(ed)
// Write w back to original register / memory
#define EWBACKW(w) if(wb1) {STRH_U12(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);}
#define EWBACKW(w) if(wb1) {STH(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFIx((xRAX+((nextop&0x38)>>3)+(rex.r<<3)), gd, 0, 16);
//GETEB will use i for ed, and can use r3 for wback.
@@ -266,8 +285,8 @@
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRB_U12(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, D); \
LDB(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
@@ -286,10 +305,10 @@
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, D); \
ADDx_REG(x3, wback, i); \
if(wback!=x3) wback = x3; \
LDRB_U12(i, wback, fixedaddress); \
LDB(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
@@ -308,8 +327,8 @@
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRSBx_U12(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, D); \
LDSBx(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
@@ -328,13 +347,13 @@
ed = i; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, NULL, 0, D); \
LDRB_U12(i, wback, fixedaddress); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, D); \
LDB(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_U12(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);}
#define EBBACK if(wb1) {STB(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);}
//GETGB will use i for gd
#define GETGB(i) if(rex.rex) { \
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
@@ -379,15 +398,15 @@
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
VLD128(a, ed, fixedaddress); \
}
// Put Back EX if it was a memory and not an emm register
#define PUTEX(a) \
if(!MODREG) { \
VSTR128_U12(a, ed, fixedaddress); \
VST128(a, ed, fixedaddress); \
SMWRITE2(); \
}
@@ -399,8 +418,8 @@
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
VLDR64_U12(a, ed, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
VLD64(a, ed, fixedaddress); \
}
// Get Ex as a single, not a quad (warning, x1 get used)
@@ -410,8 +429,8 @@
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, NULL, 0, D); \
VLDR32_U12(a, ed, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, D); \
VLD32(a, ed, fixedaddress); \
}
// Get GM, might use x1, x2 and x3
@@ -425,15 +444,15 @@
a = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7)); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR64_U12(a, ed, fixedaddress); \
VLD64(a, ed, fixedaddress); \
}
// Put Back EM if it was a memory and not an emm register
#define PUTEM(a) \
if(!MODREG) { \
VSTR64_U12(a, ed, fixedaddress); \
VST64(a, ed, fixedaddress); \
SMWRITE2(); \
}
@@ -455,17 +474,19 @@
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
#define MARK dyn->insts[ninst].mark = dyn->native_size
#define GETMARK dyn->insts[ninst].mark
#define MARK2 dyn->insts[ninst].mark2 = dyn->native_size
#define GETMARK2 dyn->insts[ninst].mark2
#define MARK3 dyn->insts[ninst].mark3 = dyn->native_size
#define GETMARK3 dyn->insts[ninst].mark3
#define MARKF dyn->insts[ninst].markf = dyn->native_size
#define GETMARKF dyn->insts[ninst].markf
#define MARKSEG dyn->insts[ninst].markseg = dyn->native_size
#define GETMARKSEG dyn->insts[ninst].markseg
#define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size
#define MARK dyn->insts[ninst].mark = dyn->native_size
#define GETMARK dyn->insts[ninst].mark
#define MARK2 dyn->insts[ninst].mark2 = dyn->native_size
#define GETMARK2 dyn->insts[ninst].mark2
#define MARK3 dyn->insts[ninst].mark3 = dyn->native_size
#define GETMARK3 dyn->insts[ninst].mark3
#define MARKF dyn->insts[ninst].markf = dyn->native_size
#define GETMARKF dyn->insts[ninst].markf
#define MARKF2 dyn->insts[ninst].markf2 = dyn->native_size
#define GETMARKF2 dyn->insts[ninst].markf2
#define MARKSEG dyn->insts[ninst].markseg = dyn->native_size
#define GETMARKSEG dyn->insts[ninst].markseg
#define MARKLOCK dyn->insts[ninst].marklock = dyn->native_size
#define GETMARKLOCK dyn->insts[ninst].marklock
// Branch to MARK if cond (use j64)
@@ -504,6 +525,10 @@
#define B_MARK2_nocond \
j64 = GETMARK2-(dyn->native_size); \
B(j64)
// Branch to MARK2 if reg is 0 (use j64)
#define CBZx_MARK2(reg) \
j64 = GETMARK2-(dyn->native_size); \
CBZx(reg, j64)
// Branch to MARK2 if reg is not 0 (use j64)
#define CBNZx_MARK2(reg) \
j64 = GETMARK2-(dyn->native_size); \
@@ -717,7 +742,7 @@
LDP_REGS(R12, R13); \
LDP_REGS(R14, R15)
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
#define SET_DFNONE(S) if(!dyn->f.dfnone) {STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
@@ -759,17 +784,17 @@
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
#define JUMP(A, C)
#endif
#ifndef BARRIER
#define BARRIER(A)
#define BARRIER(A)
#endif
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, 0, offsetof(x64emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A1, xEmu, offsetof(x64emu_t, op1));STRxw_U12(A2, xEmu, offsetof(x64emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
@@ -786,6 +811,10 @@
#define FTABLE64(A, V)
#endif
#define ARCH_INIT() \
dyn->doublepush = 0; \
dyn->doublepop = 0;
#if STEP < 2
#define GETIP(A)
#define GETIP_(A)
@@ -828,7 +857,7 @@
#define MODREG ((nextop&0xC0)==0xC0)
void arm64_epilog();
void arm64_epilog(void);
void* arm64_next(x64emu_t* emu, uintptr_t addr);
#ifndef STEPNAME
@@ -969,30 +998,31 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
#define fpu_purgecache STEPNAME(fpu_purgecache)
#define mmx_purgecache STEPNAME(mmx_purgecache)
#define x87_purgecache STEPNAME(x87_purgecache)
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
#define CacheTransform STEPNAME(CacheTransform)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* 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 absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* 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 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, int s);
// generic x64 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
@@ -1116,16 +1146,19 @@ int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
#if STEP == 0
#define ST_IS_F(A) 0
#define ST_IS_I64(A) 0
#define X87_COMBINE(A, B) NEON_CACHE_ST_D
#define X87_ST0 NEON_CACHE_ST_D
#define X87_ST(A) NEON_CACHE_ST_D
#elif STEP == 1
#define ST_IS_F(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_F)
#define ST_IS_I64(A) (neoncache_get_current_st(dyn, ninst, A)==NEON_CACHE_ST_I64)
#define X87_COMBINE(A, B) neoncache_combine_st(dyn, ninst, A, B)
#define X87_ST0 neoncache_get_current_st(dyn, ninst, 0)
#define X87_ST(A) neoncache_get_current_st(dyn, ninst, A)
#else
#define ST_IS_F(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_F)
#define ST_IS_I64(A) (neoncache_get_st(dyn, ninst, A)==NEON_CACHE_ST_I64)
#if STEP == 3
#define X87_COMBINE(A, B) neoncache_st_coherency(dyn, ninst, A, B)
#else
@@ -1154,15 +1187,18 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn);
// reset the cache with n
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);
// purge MMX cache
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
// purge x87 cache
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
@@ -1202,7 +1238,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
#if STEP < 3
#define MAYUSE(A) (void)A
#else
#define MAYUSE(A)
#define MAYUSE(A)
#endif
#define GOCOND(B, T1, T2) \
@@ -1295,4 +1331,27 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
, cNE, cEQ, X_SF|X_OF|X_ZF) \
break
#define NOTEST(s1) \
if(box64_dynarec_test) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.test)); \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean));\
}
#define SKIPTEST(s1) \
if(box64_dynarec_test) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean));\
}
#define GOTEST(s1, s2) \
if(box64_dynarec_test) { \
MOV32w(s2, 1); \
STRw_U12(s2, xEmu, offsetof(x64emu_t, test.test)); \
}
#define GETREX() \
rex.rex = 0; \
if(!rex.is32bits) \
while(opcode>=0x40 && opcode<=0x4f) { \
rex.rex = opcode; \
opcode = F8; \
}
#endif //__DYNAREC_ARM64_HELPER_H__
+13
View File
@@ -8,4 +8,17 @@ void CreateJmpNext(void* addr, void* next)
uint32_t* block = (uint32_t*)addr;
LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
BR(x2);
}
int CreateEnter(void* addr, void* enter)
{
if(enter) {
uint32_t* block = (uint32_t*)addr;
ADR_S20(x2, (intptr_t)enter - (intptr_t)addr);
LDAXRw(x1, x2);
ADDw_U12(x1, x1, 1);
STLXRw(x3, x1, x2);
CBNZw(x3, 4-4*4);
}
return 4*5;
}
+7 -4
View File
@@ -5,6 +5,8 @@
dyn->insts[ninst].x64.addr = addr; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
#define ENTER()
#define MESSAGE(A, ...)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define READFLAGS(A) \
@@ -22,7 +24,7 @@
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_native_t*)customRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\
dyn->insts = (instruction_native_t*)dynaRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t)*dyn->cap); \
dyn->cap *= 2; \
} \
@@ -40,9 +42,10 @@
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box64_dynarec_log>=LOG_INFO) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
if(box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of %sOpcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, rex.is32bits?"32bits ":"",\
PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
+1
View File
@@ -1,5 +1,6 @@
#define INIT
#define FINI
#define ENTER()
#define MESSAGE(A, ...)
#define EMIT(A)
#define NEW_INST \
+6 -8
View File
@@ -2,19 +2,17 @@
#define FINI \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>dyn->insts[ninst].size)?dyn->insts[ninst].x64.size:dyn->insts[ninst].size)/15; \
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
}
#define ENTER() dyn->block_prolog = CreateEnter(NULL, NULL)
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->native_size+=4
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
if(isInstClean(dyn, ninst) && dyn->last_ip!=ip) \
dyn->last_ip = 0; \
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>dyn->insts[ninst-1].size)?dyn->insts[ninst-1].x64.size:dyn->insts[ninst-1].size)/15; \
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; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
#define INST_NAME(name)
#define TABLE64(A, V) {Table64(dyn, (V)); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q); EMIT(0);}
#define TABLE64(A, V) {Table64(dyn, (V), 2); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
+12 -59
View File
@@ -3,68 +3,21 @@
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x64.size, dyn->insts[ninst].size/4); \
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
#define EMIT(A) \
if(box64_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (uint32_t)(A), arm64_print(A, (uintptr_t)dyn->block));} \
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
dyn->block += 4; dyn->native_size += 4; \
dyn->insts[ninst].size2 += 4
#define ENTER() dyn->block += CreateEnter(dyn->block, dyn->enter)
#define EMIT(A) \
do{ \
if(box64_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
if((uintptr_t)dyn->block<dyn->tablestart) \
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
dyn->block += 4; dyn->native_size += 4; \
dyn->insts[ninst].size2 += 4; \
}while(0)
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst && isInstClean(dyn, ninst)) { \
if(dyn->last_ip!=ip) dyn->last_ip = 0; \
} \
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4);
#define INST_EPILOG
#define INST_NAME(name) \
if(box64_dynarec_dump) {\
printf_x64_instruction(my_context->dec, &dyn->insts[ninst].x64, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d/%d", \
(box64_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->native_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
ninst, \
dyn->insts[ninst].x64.barrier, \
dyn->insts[ninst].x64.state_flags, \
dyn->f.pending, \
dyn->f.dfnone, \
dyn->insts[ninst].x64.may_set?"may":"set", \
dyn->insts[ninst].x64.set_flags, \
dyn->insts[ninst].x64.gen_flags, \
dyn->insts[ninst].x64.use_flags, \
dyn->insts[ninst].x64.need_before, \
dyn->insts[ninst].x64.need_after, \
dyn->smread, dyn->smwrite); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);\
} \
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts>=0)\
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);\
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)\
dynarec_log(LOG_NONE, ", jmp=out"); \
if(dyn->last_ip) \
dynarec_log(LOG_NONE, ", last_ip=%p", (void*)dyn->last_ip);\
for(int ii=0; ii<24; ++ii) { \
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_NONE: \
default: break; \
} \
} \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) \
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack); \
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":""); \
}
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q); MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);}
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex)
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V), 3); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q, 3); MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);}
+26 -18
View File
@@ -9,13 +9,14 @@ typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
#define NEON_CACHE_ST_F 2
#define NEON_CACHE_MM 3
#define NEON_CACHE_XMMW 4
#define NEON_CACHE_XMMR 5
#define NEON_CACHE_SCR 6
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
#define NEON_CACHE_ST_F 2
#define NEON_CACHE_ST_I64 3
#define NEON_CACHE_MM 4
#define NEON_CACHE_XMMW 5
#define NEON_CACHE_XMMR 6
#define NEON_CACHE_SCR 7
typedef union neon_cache_s {
int8_t v;
struct {
@@ -57,19 +58,19 @@ typedef struct neoncache_s {
typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
int dfnone; // if defered flags is already set to df_none
int dfnone; // if deferred flags is already set to df_none
} flagcache_t;
typedef struct instruction_arm64_s {
instruction_x64_t x64;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t address; // (start) address of the arm emitted instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, or barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
int size; // size of the arm emitted instruction
int size2; // size of the arm emitted instrucion after pass2
int pred_sz; // size of predecessor list
int *pred; // predecessor array
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markf, markf2;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
@@ -87,7 +88,8 @@ typedef struct dynarec_arm_s {
int32_t cap;
uintptr_t start; // start of the block
uint32_t isize; // size in byte of x64 instructions included
void* block; // memory pointer where next instruction is emited
uint32_t block_prolog; // size in byte of block prolog (not part of 1st instruction)
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
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state) TODO: move to a cache something
@@ -95,6 +97,7 @@ typedef struct dynarec_arm_s {
int table64size;// size of table (will be appended at end of executable code)
int table64cap;
uintptr_t tablestart;
uintptr_t jmp_next; // address of the jump_next address
flagcache_t f;
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
uintptr_t* next; // variable array of "next" jump address
@@ -110,6 +113,10 @@ typedef struct dynarec_arm_s {
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
int32_t forward_size; // size at the forward point
int forward_ninst; // ninst at the forward point
uint8_t doublepush;
uint8_t doublepop;
uint8_t always_test;
int* enter;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
@@ -117,16 +124,17 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
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 Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
void CreateJmpNext(void* addr, void* next);
int CreateEnter(void* addr, void* enter);
#define GO_TRACE() \
GETIP_(ip); \
#define GO_TRACE(A, B) \
GETIP(addr); \
MOVx_REG(x1, xRIP); \
STORE_XEMU_CALL(xRIP); \
MOV32w(x2, 1); \
CALL(PrintTrace, -1); \
MOV32w(x2, B); \
CALL(A, -1); \
LOAD_XEMU_CALL(xRIP)
#endif //__DYNAREC_ARM_PRIVATE_H_
+157 -47
View File
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/mman.h>
@@ -9,7 +8,6 @@
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -37,6 +35,39 @@ uint32_t X31_hash_code(void* addr, int len)
return (uint32_t)h;
}
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
{
if(db) {
if(db->gone)
return NULL; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "InvalidDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
// remove jumptable
setJumpTableDefault64(db->x64_addr);
db->done = 0;
db->gone = 1;
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
void FreeInvalidDynablock(dynablock_t* db, int need_lock)
{
if(db) {
if(!db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeInvalidDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
FreeDynarecMap((uintptr_t)db->actual_block);
customFree(db);
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
}
void FreeDynablock(dynablock_t* db, int need_lock)
{
if(db) {
@@ -50,6 +81,8 @@ void FreeDynablock(dynablock_t* db, int need_lock)
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
if(db->previous)
FreeInvalidDynablock(db->previous, 0);
FreeDynarecMap((uintptr_t)db->actual_block);
customFree(db);
if(need_lock)
@@ -57,14 +90,65 @@ void FreeDynablock(dynablock_t* db, int need_lock)
}
}
size_t AgeDynablock(dynablock_t* db, size_t age)
{
if(db) {
dynarec_log(LOG_DEBUG, "AgeDynablock %p %p-%p, age=%zu, db:age/romove=%zu/%d\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, age, db->age, db->try_remove);
if(db->age>age || !db->done || db->gone)
return db->age;
dynablock_t* actual = getDB((uintptr_t)db->x64_addr);
if(actual != db) {
printf_log(LOG_INFO, "Warning, AgeDynablock with a rogue db %p instead of %p for %p\n", db, actual, db->x64_addr);
return age + box64_dynarec_age;
}
int need_test = getNeedTest((uintptr_t)db->x64_addr);
if(db->try_remove) {
if(need_test && !*db->active_count) {
db = InvalidDynablock(db, 0);
FreeInvalidDynablock(db, 0);
return 0;
} else {
db->try_remove = 0;
db->age = age + box64_dynarec_age; // re-arm the wait
}
} else {
if(need_test || (getProtection((uintptr_t)db->x64_addr)&PROT_NOPROT) || db->always_test || !db->active_count || *db->active_count) {
// don't mess with this kind of dynablock...
db->age = age+box64_dynarec_age*2;
} else if(setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block)) {
dynarec_log(LOG_DEBUG, "Marking block %p at %p for later removal\n", db, db->x64_addr);
db->age = age+box64_dynarec_age;
db->try_remove = 1;
} else {
db->age = age+box64_dynarec_age*2; // failed to swap, try again later
}
}
return db->age;
}
return 0;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->need_test)
return; // already done
dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1);
db->need_test = 1;
setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block);
if(!setJumpTableIfRef64(db->x64_addr, db->jmpnext, db->block)) {
dynablock_t* old = db;
db = getDB((uintptr_t)old->x64_addr);
if(!old->gone && db!=old) {
printf_log(LOG_INFO, "Warning, couldn't mark block as dirty for %p, block=%p, current_block=%p\n", old->x64_addr, old, db);
// the block is lost, need to invalidate it...
old->gone = 1;
old->done = 0;
if(!db || db->previous)
FreeInvalidDynablock(old, 1);
else
db->previous = old;
}
} else {
db->try_remove = 0;
}
}
}
@@ -78,7 +162,7 @@ static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2
static int MarkedDynablock(dynablock_t* db)
{
if(db) {
if(db->need_test)
if(getNeedTest((uintptr_t)db->x64_addr))
return 1; // already done
}
return 0;
@@ -90,9 +174,8 @@ void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
if(!db)
return;
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x64_addr, (void*)db->x64_size);
if(!MarkedDynablock(db))
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1))
MarkDynablock(db);
}
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
@@ -133,18 +216,20 @@ void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
}
extern size_t box64_counter;
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock, int is32bits)
{
if(hasAlternate((void*)addr))
return NULL;
dynablock_t* block = getDB(addr);
if(block || !create)
if(block || !create) {
if(block) block->age = box64_counter+box64_dynarec_age;
return block;
}
if(need_lock) {
if(box64_dynarec_wait) {
@@ -153,13 +238,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
return NULL;
}
}
block = getDB(addr); // just in case
if(block) {
if(need_lock)
block = getDB(addr); // just in case
if(block) {
mutex_unlock(&my_context->mutex_dyndump);
return block;
return block;
}
}
block = AddNewDynablock(addr);
@@ -168,25 +251,27 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
block->x64_addr = (void*)addr;
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
FreeDynablock(block, 0);
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock64(block, filladdr);
void* ret = FillBlock64(block, filladdr, (addr==filladdr)?0:1, is32bits);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
customFree(block);
block = NULL;
}
// check size
if(block && (block->x64_size || (!block->x64_size && !block->done))) {
if(block) {
int blocksz = block->x64_size;
if(blocksz>my_context->max_db_size)
my_context->max_db_size = blocksz;
// fill-in jumptable
if(!addJumpTableIfDefault64(block->x64_addr, block->block)) {
if(!addJumpTableIfDefault64(block->x64_addr, block->dirty?block->jmpnext:block->block)) {
FreeDynablock(block, 0);
block = getDB(addr);
MarkDynablock(block); // just in case...
} else {
if(block->x64_size)
block->done = 1; // don't validate the block if the size is null, but keep the block
@@ -200,15 +285,20 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
return block;
}
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1, is32bits);
if(db && db->done && db->block && getNeedTest(addr)) {
if(db->always_test)
sched_yield(); // just calm down...
if(!db->try_remove && AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
emu->test.test = 0;
if(box64_dynarec_fastpage) {
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(hash==db->hash) // seems ok, run it without reprotecting it
if(hash==db->hash) { // seems ok, run it without reprotecting it
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
return db;
}
db->done = 0; // invalidating the block, it's already not good
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
@@ -220,52 +310,72 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create)
}
}
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(mutex_trylock(&my_context->mutex_dyndump)) {
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
return NULL;
}
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
dynablock_t* old = InvalidDynablock(db, need_lock);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, 0);
db = internalDBGetBlock(emu, addr, addr, create, need_lock, is32bits);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
db->need_test = 0;
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
} else
db->try_remove = 0;
}
mutex_unlock(&my_context->mutex_dyndump);
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
if(!db || !db->block || !db->done)
emu->test.test = 0;
return db;
}
dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr)
dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int is32bits)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p%s\n", (void*)addr, (void*)filladdr, is32bits?" 32bits":"");
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1, is32bits);
if(db && db->done && db->block && getNeedTest(filladdr)) {
if(db->always_test)
sched_yield(); // just calm down...
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
dynablock_t* old = InvalidDynablock(db, need_lock);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, 0);
db = internalDBGetBlock(emu, addr, filladdr, create, need_lock, is32bits);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
db->need_test = 0;
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
addJumpTableIfDefault64(db->x64_addr, db->block);
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
} else
db->try_remove = 0;
}
mutex_unlock(&my_context->mutex_dyndump);
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
if(!db || !db->block || !db->done)
emu->test.test = 0;
return db;
}
+8 -4
View File
@@ -9,17 +9,21 @@ typedef struct instsize_s {
typedef struct dynablock_s {
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
int size;
struct dynablock_s* previous; // a previous block that might need to be freed
void* x64_addr;
uintptr_t x64_size;
int size;
uint32_t hash;
uint8_t need_test;
uint8_t done;
uint8_t gone;
uint8_t dummy;
int isize;
uint8_t always_test;
uint8_t dirty; // if need to be tested as soon as it's created
instsize_t* instsize;
void* jmpnext; // a branch jmpnext code when block is marked
size_t age; //age of the block
int try_remove; // block marked as try removed
int isize;
uint32_t* active_count; // is this block currently being executed, or NULL if not tracked
} dynablock_t;
#endif //__DYNABLOCK_PRIVATE_H_
+62 -72
View File
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
@@ -8,7 +7,6 @@
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -31,6 +29,7 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
{
int is32bits = (R_CS == 0x23);
#ifdef HAVE_TRACE
if(!addr) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
@@ -38,27 +37,28 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
}
#endif
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1);
dynablock_t* block = NULL;
if(hasAlternate((void*)addr)) {
printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
uintptr_t old_addr = addr;
addr = (uintptr_t)getAlternate((void*)addr); // set new address
R_RIP = addr; // but also new RIP!
*x3 = addr; // and the RIP in x27 register
printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
block = DBAlternateBlock(emu, old_addr, addr, is32bits);
} else
block = DBGetBlock(emu, addr, 1, is32bits);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr); // set new address
R_RIP = addr; // but also new RIP!
*x3 = addr; // and the RIP in x27 register
printf_log(LOG_DEBUG, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1);
}
if(!block) {
#ifdef HAVE_TRACE
#ifdef HAVE_TRACE
if(LOG_INFO<=box64_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
#endif
//tableupdate(native_epilog, addr, table);
return native_epilog;
}
#endif
//tableupdate(native_epilog, addr, table);
return native_epilog;
}
if(!block->done) {
// not finished yet... leave linker
@@ -81,19 +81,21 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
void DynaCall(x64emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_RIP; // not sure if it should still be inside DynaCall!
}
struct __jmp_buf_tag jmpbuf[1] = {0};
int skip = 0;
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
emu->jmpbuf = jmpbuf;
if((skip = sigsetjmp(emu->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", emu->segs[_FS]);
addr = R_RIP; // not sure if it should still be inside DynaCall!
#ifdef DYNAREC
if(box64_dynarec_test) {
if(emu->test.clean)
x64test_check(emu, R_RIP);
emu->test.clean = 0;
}
#endif
}
#ifdef DYNAREC
if(!box64_dynarec)
@@ -111,14 +113,18 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
R_RIP = addr;
emu->df = d_none;
while(!emu->quit) {
dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
int is32bits = (emu->segs[_CS]==0x23);
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
if(!block || !block->block || !block->done) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
dynarec_log(LOG_DEBUG, "%04d|Calling Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
if(box64_dynarec_test)
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,emu);
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x64 instructions (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize ,block->hash, emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
native_prolog(emu, block->block);
@@ -128,16 +134,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
emu->quit = 0;
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_RIP;
}
}
}
}
emu->quit = 0; // reset Quit flags...
@@ -156,29 +152,28 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
#endif
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
emu->jmpbuf = old_jmpbuf;
}
int DynaRun(x64emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
#ifdef DYNAREC
int jmpbuf_reset = 1;
#endif
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
#ifdef DYNAREC
jmpbuf_reset = 1;
#endif
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
struct __jmp_buf_tag jmpbuf[1] = {0};
int skip = 0;
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
emu->jmpbuf = jmpbuf;
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
#ifdef DYNAREC
if(box64_dynarec_test) {
if(emu->test.clean)
x64test_check(emu, R_RIP);
emu->test.clean = 0;
}
#endif
}
#ifdef DYNAREC
if(!box64_dynarec)
#endif
@@ -186,14 +181,18 @@ int DynaRun(x64emu_t* emu)
#ifdef DYNAREC
else {
while(!emu->quit) {
dynablock_t* block = DBGetBlock(emu, R_RIP, 1);
int is32bits = (emu->segs[_CS]==0x23);
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
if(!block || !block->block || !block->done) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
if(box64_dynarec_test)
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu);
// block is here, let's run it!
native_prolog(emu, block->block);
}
@@ -202,20 +201,11 @@ int DynaRun(x64emu_t* emu)
emu->quit = 0;
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
}
}
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
emu->jmpbuf = old_jmpbuf;
return 0;
#endif
}
+29 -6
View File
@@ -2,22 +2,45 @@
#define __DYNAREC_ARCH__H_
#ifdef ARM64
#include "arm64/arm64_printer.h"
#include "arm64/dynarec_arm64_private.h"
#include "arm64/dynarec_arm64_functions.h"
#define instruction_native_t instruction_arm64_t
#define dynarec_native_t dynarec_arm_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#include "arm64/arm64_printer.h"
#include "arm64/dynarec_arm64_private.h"
#include "arm64/dynarec_arm64_functions.h"
#elif defined(LA464)
#include "la464/la464_printer.h"
#include "la464/dynarec_la464_private.h"
#include "la464/dynarec_la464_functions.h"
#define instruction_native_t instruction_la464_t
#define dynarec_native_t dynarec_la464_t
#define ADDITIONNAL_DEFINITION()
#define OTHER_CACHE()
#include "la464/la464_printer.h"
#include "la464/dynarec_la464_private.h"
#include "la464/dynarec_la464_functions.h"
#elif defined(RV64)
#define instruction_native_t instruction_rv64_t
#define dynarec_native_t dynarec_rv64_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#include "rv64/rv64_printer.h"
#include "rv64/dynarec_rv64_private.h"
#include "rv64/dynarec_rv64_functions.h"
#else
#error Unsupported platform
#endif
+2
View File
@@ -5,6 +5,8 @@
#include "arm64/dynarec_arm64_helper.h"
#elif defined(LA464)
#include "la464/dynarec_la464_helper.h"
#elif defined(RV64)
#include "rv64/dynarec_rv64_helper.h"
#else
#error Unsupported architecture
#endif
+101 -77
View File
@@ -1,6 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
@@ -10,7 +9,6 @@
#include "custommem.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -25,6 +23,8 @@
#include "dynarec_arch.h"
#include "dynarec_next.h"
size_t box64_counter = 0;
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
@@ -75,7 +75,7 @@ void add_next(dynarec_native_t *dyn, uintptr_t addr) {
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 64;
dyn->next = (uintptr_t*)customRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -84,11 +84,13 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
uintptr_t best = 0;
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
if(dyn->next[i]) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
}
}
++i;
}
@@ -265,7 +267,7 @@ void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size)
}
// add a value to table64 (if needed) and gives back the imm19 to use in LDR_literal
int Table64(dynarec_native_t *dyn, uint64_t val)
int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
{
// find the value if already present
int idx = -1;
@@ -276,10 +278,14 @@ int Table64(dynarec_native_t *dyn, uint64_t val)
if(idx==-1) {
if(dyn->table64size == dyn->table64cap) {
dyn->table64cap+=16;
dyn->table64 = (uint64_t*)customRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
if(pass<3) // do not resize on pass3, it's not the same type of memory anymore
dyn->table64 = (uint64_t*)dynaRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
}
idx = dyn->table64size++;
dyn->table64[idx] = val;
if(idx < dyn->table64cap)
dyn->table64[idx] = val;
else
printf_log(LOG_NONE, "Warning, table64 bigger than expected %d vs %d\n", idx, dyn->table64cap);
}
// calculate offset
int delta = dyn->tablestart + idx*sizeof(uint64_t) - (uintptr_t)dyn->block;
@@ -304,7 +310,8 @@ static void fillPredecessors(dynarec_native_t* dyn)
dyn->insts[i+1].pred_sz++;
}
}
dyn->predecessor = (int*)customMalloc(pred_sz*sizeof(int));
int alloc_size = pred_sz;
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -321,11 +328,10 @@ static void fillPredecessors(dynarec_native_t* dyn)
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
// updateNeed goes backward, from last intruction to top
static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
need |= dyn->insts[ninst].x64.need_after;
@@ -379,33 +385,31 @@ void CancelBlock64(int need_lock)
mutex_lock(&my_context->mutex_dyndump);
dynarec_native_t* helper = (dynarec_native_t*)current_helper;
current_helper = NULL;
if(!helper) {
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
return;
if(helper) {
dynaFree(helper->next);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart))
dynaFree(helper->table64);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = NULL;
}
}
customFree(helper->next);
customFree(helper->insts);
customFree(helper->predecessor);
customFree(helper->table64);
if(helper->dynablock && helper->dynablock->actual_block)
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
else if(helper->dynablock && helper->block)
FreeDynarecMap((uintptr_t)helper->block-sizeof(void*));
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr);
uintptr_t native_pass0(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
size_t sz = 4*sizeof(void*);
void* actual_p = (void*)AllocDynarecMap(sz);
void* actual_p = (void*)AllocDynarecMap(sz, box64_counter);
void* p = actual_p + sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
@@ -416,16 +420,16 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
block->age = box64_counter + box64_dynarec_age;
*(dynablock_t**)actual_p = block;
*(void**)(p+2*sizeof(void*)) = native_epilog;
CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
block->need_test = 0;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
return block;
}
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bits) {
/*
A Block must have this layout:
@@ -460,18 +464,19 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
helper.start = addr;
uintptr_t start = addr;
helper.cap = 128;
helper.insts = (instruction_native_t*)customCalloc(helper.cap, sizeof(instruction_native_t));
++box64_counter;
helper.insts = (instruction_native_t*)dynaCalloc(helper.cap, sizeof(instruction_native_t));
// pass 0, addresses, x64 jump addresses, overall size of the block
uintptr_t end = native_pass0(&helper, addr);
uintptr_t end = native_pass0(&helper, addr, alternate, is32bits);
// no need for next anymore
customFree(helper.next);
dynaFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64(0);
return CreateEmptyBlock(block, addr);;
return CreateEmptyBlock(block, addr);
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
@@ -489,6 +494,8 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(helper.insts[i].x64.jmp) {
uintptr_t j = helper.insts[i].x64.jmp;
if(j<start || j>=end || j==helper.insts[i].x64.addr) {
if(j==helper.insts[i].x64.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x64.jmp_insts = -1;
helper.insts[i].x64.need_after |= X_PEND;
} else {
@@ -511,79 +518,76 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
pos = updateNeed(&helper, pos, 0);
// pass 1, float optimisations, first pass for flags
native_pass1(&helper, addr);
native_pass1(&helper, addr, alternate, is32bits);
// pass 2, instruction size
native_pass2(&helper, addr);
native_pass2(&helper, addr, alternate, is32bits);
// keep size of instructions for signal handling
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
size_t native_size = (helper.native_size+helper.block_prolog+7)&~7; // round the size...
// ok, now allocate mapped memory, with executable flag on
size_t sz = sizeof(void*) + helper.native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
// dynablock_t* block (arm insts) table64 jmpnext code instsize
void* actual_p = (void*)AllocDynarecMap(sz);
void* p = actual_p + sizeof(void*);
void* next = p + helper.native_size + helper.table64size*sizeof(uint64_t);
void* instsize = next + 4*sizeof(void*);
size_t sz = sizeof(void*) // dynablock_t*
+ native_size // block (arm insts)
+ helper.table64size*sizeof(uint64_t) // table64
+ 4*sizeof(void*) // jmpnext code
+ (box64_dynarec_age?sizeof(void*):0) // enter_count
+ insts_rsize; // instsize
void* actual_p = (void*)AllocDynarecMap(sz, box64_counter);
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*) + (box64_dynarec_age?sizeof(void*):0);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock64(0);
return NULL;
}
helper.block = p;
block->actual_block = actual_p;
block->active_count = box64_dynarec_age?(next + 4*sizeof(void*)):NULL;
block->age = box64_counter + box64_dynarec_age;
helper.native_start = (uintptr_t)p;
helper.tablestart = helper.native_start + helper.native_size;
helper.insts_size = 0; // reset
helper.tablestart = (uintptr_t)tablestart;
helper.jmp_next = (uintptr_t)next+sizeof(void*);
helper.instsize = (instsize_t*)instsize;
*(dynablock_t**)actual_p = block;
helper.table64cap = helper.table64size;
dynaFree(helper.table64);
helper.table64 = (uint64_t*)helper.tablestart;
helper.enter = block->active_count;
// pass 3, emit (log emit native opcode)
if(box64_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize);
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64");
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
int oldtable64size = helper.table64size;
size_t oldnativesize = helper.native_size;
size_t oldinstsize = helper.insts_size;
helper.native_size = 0;
helper.table64size = 0; // reset table64 (but not the cap)
native_pass3(&helper, addr);
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
printf_log(LOG_NONE, "%p:", dump);
for(; dump<(uint8_t*)helper.insts[i+1].x64.addr; ++dump)
printf_log(LOG_NONE, " %02X", *dump);
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
}
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
//TODO: Cancel block and return empty one
}
// add table64 if needed
if(helper.table64size) {
memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
}
helper.insts_size = 0; // reset
native_pass3(&helper, addr, alternate, is32bits);
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
customFree(helper.insts);
instruction_native_t* pass2_insts = helper.insts;
helper.insts = NULL;
customFree(helper.table64);
helper.table64 = NULL;
helper.instsize = NULL;
customFree(helper.predecessor);
dynaFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = next+sizeof(void*);
block->always_test = helper.always_test;
block->dirty = block->always_test;
*(dynablock_t**)next = block;
*(void**)(next+2*sizeof(void*)) = native_next;
CreateJmpNext(block->jmpnext, next+2*sizeof(void*));
block->need_test = 0;
*(void**)(next+3*sizeof(void*)) = native_next;
CreateJmpNext(block->jmpnext, next+3*sizeof(void*));
//block->x64_addr = (void*)start;
block->x64_size = end-start;
// all done...
@@ -591,15 +595,35 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abbort if it as
if((block->hash != hash)) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
AddHotPage(addr);
CancelBlock64(0);
return NULL;
}
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
for(int i=0; i<helper.size-1; ++i) {
printf_log(LOG_NONE, "%p:", dump);
for(; dump<(uint8_t*)pass2_insts[i+1].x64.addr; ++dump)
printf_log(LOG_NONE, " %02X", *dump);
printf_log(LOG_NONE, "\t%d -> %d\n", pass2_insts[i].size2, pass2_insts[i].size);
}
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
dynaFree(pass2_insts);
CancelBlock64(0);
return NULL;
}
dynaFree(pass2_insts);
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "BOX64: Warning, ists_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)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%ld, cancelling\n", block->x64_addr, block->x64_size);
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
AddHotPage(addr);
block->need_test = 1;
block->dirty = 1;
//protectDB(addr, end-addr);
}
current_helper = NULL;
+475
View File
@@ -0,0 +1,475 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "tools/bridge_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "emu/x87emu_private.h"
#include "x64trace.h"
#include "signals.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "bridge.h"
#include "dynarec_native_functions.h"
void native_fstp(x64emu_t* emu, void* p)
{
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, p);
else
memcpy(p, &STld(0).ld, 10);
}
void native_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
{
(void)emu;
dynarec_log(LOG_DEBUG, "R%lu=0x%lx (%lu)\n", n, reg, reg);
}
void native_f2xm1(x64emu_t* emu)
{
ST0.d = exp2(ST0.d) - 1.0;
}
void native_fyl2x(x64emu_t* emu)
{
ST(1).d = log2(ST0.d)*ST(1).d;
}
void native_ftan(x64emu_t* emu)
{
ST0.d = tan(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_fpatan(x64emu_t* emu)
{
ST1.d = atan2(ST1.d, ST0.d);
}
void native_fxtract(x64emu_t* emu)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
}
void native_fprem(x64emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C0 = ((tmp32s>>2)&1);
}
void native_fyl2xp1(x64emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
}
void native_fsincos(x64emu_t* emu)
{
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_frndint(x64emu_t* emu)
{
ST0.d = fpu_round(emu, ST0.d);
}
void native_fscale(x64emu_t* emu)
{
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
}
void native_fsin(x64emu_t* emu)
{
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_fcos(x64emu_t* emu)
{
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_fbld(x64emu_t* emu, uint8_t* ed)
{
fpu_fbld(emu, ed);
}
void native_fild64(x64emu_t* emu, int64_t* ed)
{
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).sq = tmp;
STll(0).sref = ST0.sq;
}
void native_fbstp(x64emu_t* emu, uint8_t* ed)
{
fpu_fbst(emu, ed);
}
void native_fistp64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).sref==ST(0).sq) {
memcpy(ed, &STll(0).sq, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
void native_fistt64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
int64_t tmp = ST0.d;
memcpy(ed, &tmp, sizeof(tmp));
}
void native_fld(x64emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
STld(0).uref = ST0.q;
}
void native_ud(x64emu_t* emu)
{
if(box64_dynarec_test)
emu->test.test = 0;
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
}
void native_priv(x64emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
}
void native_singlestep(x64emu_t* emu)
{
emit_signal(emu, SIGTRAP, (void*)R_RIP, 1);
}
void native_fsave(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
void native_frstor(x64emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
void native_fprem1(x64emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C0 = ((tmp32s>>2)&1);
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void native_aesimc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void native_aesmc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void native_aesdlast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
void native_aeselast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void native_aesd(x64emu_t* emu, int xmm)
{
native_aesdlast(emu, xmm);
native_aesimc(emu, xmm);
}
void native_aese(x64emu_t* emu, int xmm)
{
native_aeselast(emu, xmm);
native_aesmc(emu, xmm);
}
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void 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;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
return 0;
}
int CacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
int ret = 0;
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=1;
OTHER_CACHE()
return ret;
}
int isPred(dynarec_native_t* dyn, int ninst, int pred) {
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
if(dyn->insts[ninst].pred[i]==pred)
return pred;
return -1;
}
int getNominalPred(dynarec_native_t* dyn, int ninst) {
if((ninst<=0) || !dyn->insts[ninst].pred_sz)
return -1;
if(isPred(dyn, ninst, ninst-1)!=-1)
return ninst-1;
return dyn->insts[ninst].pred[0];
}
#define F8 *(uint8_t*)(addr++)
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
(void)dyn; (void)addr; (void)ninst;
if((nextop&0xC0)==0xC0)
return addr;
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
if((sib&0x7)==5) {
addr+=4;
}
} else if((nextop&7)==5) {
addr+=4;
}
} else {
if((nextop&7)==4) {
++addr;
}
if(nextop&0x80) {
addr+=4;
} else {
++addr;
}
}
return addr;
}
#undef F8
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
(void)dyn;
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
if(!addr || !getProtection(addr))
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // "absolute" jump, maybe the GOT (well, RIP relative in fact)
uintptr_t a1 = addr + 6 + (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(!addr || !getProtection(addr))
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
#undef PK32
#undef PK
}
+65
View File
@@ -0,0 +1,65 @@
#ifndef __DYNAREC_NATIVE_FUNCTIONS_H__
#define __DYNAREC_NATIVE_FUNCTIONS_H__
#include <stdint.h>
#include "dynarec_arch.h"
typedef struct x64emu_s x64emu_t;
void native_fstp(x64emu_t* emu, void* p);
void native_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n);
void native_f2xm1(x64emu_t* emu);
void native_fyl2x(x64emu_t* emu);
void native_ftan(x64emu_t* emu);
void native_fpatan(x64emu_t* emu);
void native_fxtract(x64emu_t* emu);
void native_fprem(x64emu_t* emu);
void native_fyl2xp1(x64emu_t* emu);
void native_fsincos(x64emu_t* emu);
void native_frndint(x64emu_t* emu);
void native_fscale(x64emu_t* emu);
void native_fsin(x64emu_t* emu);
void native_fcos(x64emu_t* emu);
void native_fbld(x64emu_t* emu, uint8_t* ed);
void native_fild64(x64emu_t* emu, int64_t* ed);
void native_fbstp(x64emu_t* emu, uint8_t* ed);
void native_fistp64(x64emu_t* emu, int64_t* ed);
void native_fistt64(x64emu_t* emu, int64_t* ed);
void native_fld(x64emu_t* emu, uint8_t* ed);
void native_fsave(x64emu_t* emu, uint8_t* ed);
void native_frstor(x64emu_t* emu, uint8_t* ed);
void native_fprem1(x64emu_t* emu);
void native_aesd(x64emu_t* emu, int xmm);
void native_aese(x64emu_t* emu, int xmm);
void native_aesdlast(x64emu_t* emu, int xmm);
void native_aeselast(x64emu_t* emu, int xmm);
void native_aesimc(x64emu_t* emu, int xmm);
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_clflush(x64emu_t* emu, void* p);
void native_ud(x64emu_t* emu);
void native_priv(x64emu_t* emu);
void native_singlestep(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
// predecessor access
int isPred(dynarec_native_t* dyn, int ninst, int pred);
int getNominalPred(dynarec_native_t* dyn, int ninst);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
ADDITIONNAL_DEFINITION()
#endif //__DYNAREC_NATIVE_FUNCTIONS_H__
+76 -73
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
@@ -27,7 +26,7 @@
#error No STEP defined
#endif
uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits)
{
int ok = 1;
int ninst = 0;
@@ -45,11 +44,15 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
dyn->forward_size = 0;
dyn->forward_ninst = 0;
fpu_reset(dyn);
ARCH_INIT();
int reset_n = -1;
dyn->last_ip = (dyn->insts && dyn->insts[0].pred_sz)?0:ip; // RIP is always set at start of block unless there is a predecessor!
dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz))?0:ip; // RIP is always set at start of block unless there is a predecessor!
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3
// ok, go now
INIT;
if(box64_dynarec_age) {
ENTER();
}
while(ok) {
ip = addr;
if (reset_n!=-1) {
@@ -60,44 +63,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
dyn->f.pending = 0;
fpu_reset(dyn);
} else {
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
#if STEP > 1
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
dyn->n = dyn->insts[ninst].n;
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
if(box64_dynarec_dump)
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
for(int i=0; i<24; ++i)
if(dyn->insts[reset_n].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
MESSAGE(LOG_DEBUG, " ==> ");
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
MESSAGE(LOG_DEBUG, " -> ");
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
if(dyn->n.combined1 || dyn->n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
if(dyn->n.stack_push || dyn->n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
fpu_reset_cache(dyn, ninst, reset_n);
dyn->f = dyn->insts[reset_n].f_exit;
if(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT) {
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
@@ -110,36 +76,33 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
}
}
reset_n = -1;
} else if(ninst && (dyn->insts[ninst].pred_sz!=1 || dyn->insts[ninst].pred[0]!=ninst-1))
} else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
dyn->last_ip = 0; // reset IP if some jump are comming here
// propagate ST stack state, especial stack pop that are defered
if(dyn->n.stack_pop) {
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D || dyn->n.neoncache[j].t == NEON_CACHE_ST_F)) {
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
dyn->n.neoncache[j].v = 0;
else
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
}
dyn->n.stack_pop = 0;
}
dyn->n.stack = dyn->n.stack_next;
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
fpu_propagate_stack(dyn, ninst);
NEW_INST;
if(!ninst) {
GOTEST(x1, x2);
}
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
fpu_reset_scratch(dyn);
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
}
if(box64_dynarec_test) {
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(x64test_init, 1);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
#ifdef HAVE_TRACE
if(my_context->dec && box64_dynarec_trace) {
else if(my_context->dec && box64_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE();
GO_TRACE(PrintTrace, 1);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
}
@@ -157,11 +120,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
pk = PK(0);
}
rex.rex = 0;
while(pk>=0x40 && pk<=0x4f) {
rex.rex = pk;
++addr;
pk = PK(0);
}
rex.is32bits = is32bits;
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);
@@ -189,8 +154,18 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
++ii;
if(ii<dyn->size && !dyn->insts[ii].pred_sz) {
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
// may need to skip opcodes to advance
++ninst;
NEW_INST;
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
INST_NAME("Skipped opcode");
INST_EPILOG;
addr += dyn->insts[ii].x64.size;
++ii;
}
}
if((dyn->insts[ii].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
@@ -241,16 +216,30 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
}
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
if(ok<0) {
ok = 0; need_epilog=1;
#if STEP == 0
if(ninst) {
--ninst;
if(!dyn->insts[ninst].x64.barrier) {
BARRIER(BARRIER_FLOAT);
}
dyn->insts[ninst].x64.need_after |= X_PEND;
++ninst;
}
#endif
}
++ninst;
#if STEP == 0
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
@@ -259,6 +248,18 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
if(ok && (ninst==dyn->size))
#endif
{
#if STEP == 0
if(dyn->forward) {
// stopping too soon
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst+1;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
#endif
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
@@ -272,12 +273,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr)
dyn->insts[ninst].x64.need_after |= X_PEND;
#endif
++ninst;
NOTEST(x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
NOTEST(x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
+9 -2
View File
@@ -4,17 +4,24 @@
#ifdef ARM64
void arm64_next(void) EXPORTDYN;
void arm64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void arm64_epilog() EXPORTDYN;
void arm64_epilog(void) EXPORTDYN;
#define native_next arm64_next
#define native_prolog arm64_prolog
#define native_epilog arm64_epilog
#elif defined(LA464)
void la464_next(void) EXPORTDYN;
void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void la464_epilog() EXPORTDYN;
void la464_epilog(void) EXPORTDYN;
#define native_next la464_next
#define native_prolog la464_prolog
#define native_epilog la464_epilog
#elif defined(RV64)
void rv64_next(void) EXPORTDYN;
void rv64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void rv64_epilog(void) EXPORTDYN;
#define native_next rv64_next
#define native_prolog rv64_prolog
#define native_epilog rv64_epilog
#else
#error Unsupported architecture
#endif
+43 -1
View File
@@ -14,8 +14,10 @@
#define native_lock_write_dd(A, B) arm64_lock_write_dd(A, B)
#define native_lock_read_dq(A, B, C) arm64_lock_read_dq(A, B, C)
#define native_lock_write_dq(A, B, C) arm64_lock_write_dq(A, B, C)
#define native_lock_xchg(A, B) arm64_lock_xchg(A, B)
#define native_lock_xchg_dd(A, B) arm64_lock_xchg_dd(A, B)
#define native_lock_xchg_d(A, B) arm64_lock_xchg_d(A, B)
#define native_lock_xchg_h(A, B) arm64_lock_xchg_h(A, B)
#define native_lock_xchg_b(A, B) arm64_lock_xchg_b(A, B)
#define native_lock_storeifref(A, B, C) arm64_lock_storeifref(A, B, C)
#define native_lock_storeifref_d(A, B, C) arm64_lock_storeifref_d(A, B, C)
#define native_lock_storeifref2_d(A, B, C) arm64_lock_storeifref2_d(A, B, C)
@@ -27,6 +29,46 @@
#define native_lock_decifnot0(A) arm64_lock_decifnot0(A)
#define native_lock_store(A, B) arm64_lock_store(A, B)
#elif defined(RV64)
#include "rv64/rv64_lock.h"
#define USE_CAS
// RV64 is quite strict (or at least strongly recommand) on what you can do between an LD.A and an SD.A
// That basicaly forbid to call a function, so there cannot be READ / WRITE separated
// And so need to use a Compare and Swap mecanism instead
// no byte or 2-bytes atomic access on RISC-V
#define native_lock_xchg_dd(A, B) rv64_lock_xchg_dd(A, B)
#define native_lock_xchg_d(A, B) rv64_lock_xchg_d(A, B)
#define native_lock_storeifref(A, B, C) rv64_lock_storeifref(A, B, C)
#define native_lock_storeifref_d(A, B, C) rv64_lock_storeifref_d(A, B, C)
#define native_lock_storeifref2_d(A, B, C) rv64_lock_storeifref2_d(A, B, C)
#define native_lock_storeifnull(A, B) rv64_lock_storeifnull(A, B)
#define native_lock_storeifnull_d(A, B) rv64_lock_storeifnull_d(A, B)
#define native_lock_decifnot0b(A) rv64_lock_decifnot0b(A)
#define native_lock_storeb(A, B) rv64_lock_storeb(A, B)
#define native_lock_incif0(A) rv64_lock_incif0(A)
#define native_lock_decifnot0(A) rv64_lock_decifnot0(A)
#define native_lock_store(A, B) rv64_lock_store(A, B)
#define native_lock_cas_d(A, B, C) rv64_lock_cas_d(A, B, C)
#define native_lock_cas_dd(A, B, C) rv64_lock_cas_dd(A, B, C)
#define native_lock_xchg_b(A, B) rv64_lock_xchg_b(A, B)
#define native_lock_cas_b(A, B, C) rv64_lock_cas_b(A, B, C)
#define native_lock_cas_h(A, B, C) rv64_lock_cas_h(A, B, C)
#define native_lock_read_b(A) tmpcas=*(uint8_t*)(A)
#define native_lock_write_b(A, B) rv64_lock_cas_b(A, tmpcas, B)
#define native_lock_read_h(A) tmpcas=*(uint16_t*)(A)
#define native_lock_write_h(A, B) rv64_lock_cas_h(A, tmpcas, B)
#define native_lock_read_d(A) tmpcas=*(uint32_t*)(A)
#define native_lock_write_d(A, B) rv64_lock_cas_d(A, tmpcas, B)
#define native_lock_read_dd(A) tmpcas=*(uint64_t*)(A)
#define native_lock_write_dd(A, B) rv64_lock_cas_dd(A, tmpcas, B)
// there is no atomic move on 16bytes, so faking it
#define native_lock_read_dq(A, B, C) *A=tmpcas=((uint64_t*)(C))[0]; *B=((uint64_t*)(C))[1];
#define native_lock_write_dq(A, B, C) rv64_lock_cas_dq(C, A, tmpcas, B);
#else
#error Unsupported architecture
#endif
+43
View File
@@ -0,0 +1,43 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "bridge.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "dynarec_rv64_helper.h"
int isSimpleWrapper(wrapper_t fun);
uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode;
opcode = PK(0);
switch(opcode) {
case 0x00 ... 0x3f: addr = dynarec64_00_0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break;
case 0x40 ... 0x7f: addr = dynarec64_00_1(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break;
case 0x80 ... 0xbf: addr = dynarec64_00_2(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break;
case 0xc0 ... 0xff: addr = dynarec64_00_3(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break;
}
return addr;
}
+454
View File
@@ -0,0 +1,454 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "bridge.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "dynarec_rv64_helper.h"
int isSimpleWrapper(wrapper_t fun);
uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
uint8_t gd, ed;
int8_t i8;
int32_t i32, tmp;
int64_t i64, j64;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint32_t u32;
uint64_t u64;
uint8_t wback, wb1, wb2, wb;
int64_t fixedaddress;
int lock;
int cacheupd = 0;
opcode = F8;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
MAYUSE(wb);
MAYUSE(lock);
MAYUSE(cacheupd);
switch(opcode) {
case 0x00:
INST_NAME("ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_add8(dyn, ninst, x1, x2, x4, x5);
EBBACK(x5, 0);
break;
case 0x01:
INST_NAME("ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x02:
INST_NAME("ADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_add8(dyn, ninst, x2, x1, x4, x5);
GBBACK(x5);
break;
case 0x03:
INST_NAME("ADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x04:
INST_NAME("ADD AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_add8c(dyn, ninst, x1, u8, x3, x4, x5);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x05:
INST_NAME("ADD EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6);
break;
case 0x08:
INST_NAME("OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_or8(dyn, ninst, x1, x2, x4, x5);
EBBACK(x5, 0);
break;
case 0x09:
INST_NAME("OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x0A:
INST_NAME("OR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_or8(dyn, ninst, x2, x1, x4, x5);
GBBACK(x5);
break;
case 0x0B:
INST_NAME("OR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0C:
INST_NAME("OR AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_or8c(dyn, ninst, x1, u8, x3, x4, x5);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x0D:
INST_NAME("OR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x0F:
switch(rep) {
case 0:
addr = dynarec64_0F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
case 1:
addr = dynarec64_F20F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
case 2:
addr = dynarec64_F30F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
default:
DEFAULT;
}
break;
case 0x11:
INST_NAME("ADC Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
WBACK;
break;
case 0x18:
INST_NAME("SBB Eb, Gb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_sbb8(dyn, ninst, x1, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(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);
nextop = F8;
GETEB(x2, 0);
GETGB(x1);
emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5);
GBBACK(x5);
break;
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x1C:
INST_NAME("SBB AL, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_sbb8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
break;
case 0x20:
INST_NAME("AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_and8(dyn, ninst, x1, x2, x4, x5);
EBBACK(x4, 0);
break;
case 0x21:
INST_NAME("AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x22:
INST_NAME("AND Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_and8(dyn, ninst, x2, x1, x4, x5);
GBBACK(x5);
break;
case 0x23:
INST_NAME("AND Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_and32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x24:
INST_NAME("AND AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_and8c(dyn, ninst, x1, u8, x3, x4);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x25:
INST_NAME("AND EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x28:
INST_NAME("SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_sub8(dyn, ninst, x1, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 0x29:
INST_NAME("SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x2A:
INST_NAME("SUB Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_sub8(dyn, ninst, x2, x1, x4, x5, x6);
GBBACK(x5);
break;
case 0x2B:
INST_NAME("SUB Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x2C:
INST_NAME("SUB AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_sub8c(dyn, ninst, x1, u8, x2, x3, x4, x5);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x2D:
INST_NAME("SUB EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5);
break;
case 0x30:
INST_NAME("XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_xor8(dyn, ninst, x1, x2, x4, x5);
EBBACK(x5, 0);
break;
case 0x31:
INST_NAME("XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
if(ed!=gd) {
WBACK;
}
break;
case 0x32:
INST_NAME("XOR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_xor8(dyn, ninst, x2, x1, x4, x5);
GBBACK(x5);
break;
case 0x33:
INST_NAME("XOR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x34:
INST_NAME("XOR AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_xor8c(dyn, ninst, x1, u8, x3, x4);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x35:
INST_NAME("XOR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x38:
INST_NAME("CMP Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x39:
INST_NAME("CMP Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
break;
case 0x3A:
INST_NAME("CMP Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB(x1, 0);
GETGB(x2);
emit_cmp8(dyn, ninst, x2, x1, x3, x4, x5, x6);
break;
case 0x3B:
INST_NAME("CMP Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
emit_cmp32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
break;
case 0x3C:
INST_NAME("CMP AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
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;
case 0x3D:
INST_NAME("CMP EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
default:
DEFAULT;
}
return addr;
}
+297
View File
@@ -0,0 +1,297 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "bridge.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "dynarec_rv64_helper.h"
int isSimpleWrapper(wrapper_t fun);
uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
uint8_t gd, ed;
int8_t i8;
int32_t i32, tmp;
int64_t i64, j64;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint32_t u32;
uint64_t u64;
uint8_t wback, wb1, wb2, wb;
int64_t fixedaddress;
int lock;
int cacheupd = 0;
opcode = F8;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
MAYUSE(wb);
MAYUSE(lock);
MAYUSE(cacheupd);
switch(opcode) {
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
INST_NAME("INC Reg (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
emit_inc32(dyn, ninst, rex, gd, x1, x2, x3, x4);
break;
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
emit_dec32(dyn, ninst, rex, gd, x1, x2, x3, x4);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
PUSH1z(gd);
break;
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
INST_NAME("POP reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
POP1z(gd);
break;
case 0x60:
if(rex.is32bits) {
INST_NAME("PUSHAD");
AND(x1, xRSP, xMASK);
PUSH1_32(xRAX);
PUSH1_32(xRCX);
PUSH1_32(xRDX);
PUSH1_32(xRBX);
PUSH1_32(x1);
PUSH1_32(xRBP);
PUSH1_32(xRSI);
PUSH1_32(xRDI);
} else {
DEFAULT;
}
break;
case 0x61:
if(rex.is32bits) {
INST_NAME("POPAD");
POP1_32(xRDI);
POP1_32(xRSI);
POP1_32(xRBP);
POP1_32(x1);
POP1_32(xRBX);
POP1_32(xRDX);
POP1_32(xRCX);
POP1_32(xRAX);
} else {
DEFAULT;
}
break;
case 0x63:
if(rex.is32bits) {
// this is ARPL opcode
DEFAULT;
} else {
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
ADDIW(gd, xRAX+(nextop&7)+(rex.b<<3), 0);
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LW(gd, ed, fixedaddress);
}
} else {
if(MODREG) { // reg <= reg
AND(gd, xRAX+(nextop&7)+(rex.b<<3), xMASK);
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LWU(gd, ed, fixedaddress);
}
}
}
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_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x67:
addr = dynarec64_67(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x68:
INST_NAME("PUSH Id");
i64 = F32S;
if(PK(0)==0xC3) {
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
TABLE64(x3, addr-4);
LW(x1, x3, 0);
PUSH1z(x1);
} else {
MOV64z(x3, i64);
PUSH1z(x3);
}
break;
case 0x69:
INST_NAME("IMUL Gd, Ed, Id");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETGD;
GETED(4);
i64 = F32S;
MOV64xw(x4, i64);
if(rex.w) {
// 64bits imul
UFLAG_IF {
MULH(x3, ed, x4);
MUL(gd, ed, x4);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
MULxw(gd, ed, x4);
}
} else {
// 32bits imul
UFLAG_IF {
MUL(gd, ed, x4);
UFLAG_RES(gd);
SRLI(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
} else {
MULxw(gd, ed, x4);
}
ZEROUP(gd);
}
break;
case 0x6A:
INST_NAME("PUSH Ib");
i64 = F8S;
MOV64z(x3, i64);
PUSH1z(x3);
break;
case 0x6B:
INST_NAME("IMUL Gd, Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETGD;
GETED(1);
i64 = F8S;
MOV64xw(x4, i64);
if(rex.w) {
// 64bits imul
UFLAG_IF {
MULH(x3, ed, x4);
MUL(gd, ed, x4);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
MUL(gd, ed, x4);
}
} else {
// 32bits imul
UFLAG_IF {
MUL(gd, ed, x4);
UFLAG_RES(gd);
SRLI(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
} else {
MULW(gd, ed, x4);
}
ZEROUP(gd);
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
i8 = F8S; \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
GETFLAGS; \
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
B##NO##_safe(x1, 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); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
B##YES##_safe(x1, i32); \
}
GOCOND(0x70, "J", "ib");
#undef GO
default:
DEFAULT;
}
return addr;
}
+847
View File
@@ -0,0 +1,847 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <signal.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "bridge.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "dynarec_rv64_helper.h"
int isSimpleWrapper(wrapper_t fun);
uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
uint8_t gd, ed;
int8_t i8;
int32_t i32, tmp;
int64_t i64, j64;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint32_t u32;
uint64_t u64;
uint8_t wback, wb1, wb2, wb;
int64_t fixedaddress;
int lock;
int cacheupd = 0;
opcode = F8;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
MAYUSE(wb);
MAYUSE(lock);
MAYUSE(cacheupd);
switch(opcode) {
case 0x80:
nextop = F8;
switch((nextop>>3)&7) {
case 0: // ADD
INST_NAME("ADD Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK(x5, 0);
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK(x5, 0);
break;
case 2: // ADC
INST_NAME("ADC Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK(x5, 0);
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK(x5, 0);
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEB(x1, 1);
u8 = F8;
if(u8) {
ADDI(x2, xZR, 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;
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);
GETED((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);
GETED((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);
GETED((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x9);
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);
GETED((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x6);
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);
GETED((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);
GETED((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);
GETED((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);
GETED((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else {
if(!rex.w && MODREG) {
AND(x1, ed, xMASK);
ed = x1;
}
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
}
break;
}
break;
case 0x84:
INST_NAME("TEST Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop=F8;
GETEB(x1, 0);
GETGB(x2);
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x85:
INST_NAME("TEST Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop=F8;
GETGD;
GETED(0);
emit_test32(dyn, ninst, rex, ed, gd, x3, x4, x5);
break;
case 0x86:
INST_NAME("(LOCK)XCHG Eb, Gb");
nextop = F8;
if(MODREG) {
GETGB(x1);
GETEB(x2, 0);
MV(x4, gd);
MV(gd, ed);
MV(ed, x4);
GBBACK(x4);
EBBACK(x4, 0);
} else {
GETGB(x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
SMDMB();
LBU(x1, ed, 0);
SB(gd, ed, 0);
SMDMB();
gd = x1;
GBBACK(x3);
}
break;
case 0x87:
INST_NAME("(LOCK)XCHG Ed, Gd");
nextop = F8;
if(MODREG) {
GETGD;
GETED(0);
MVxw(x1, gd);
MVxw(gd, ed);
MVxw(ed, x1);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
SMDMB();
ANDI(x3, ed, (1<<(2+rex.w))-1);
BNE_MARK(x3, xZR);
MARKLOCK;
LRxw(x1, ed, 1, 0);
SCxw(x3, gd, ed, 0, 1);
BNE_MARKLOCK(x3, xZR);
B_MARK2_nocond;
MARK;
LDxw(x1, ed, 0);
SDxw(gd, ed, 0);
MARK2;
SMDMB();
MVxw(gd, x1);
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb1 = xRAX+(gd&3);
}
gd = x4;
if(gb2) {
SRLI(x4, gb1, 8);
gb1 = x4;
}
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
ANDI(gd, gb1, 0xff);
if(eb2) {
MOV64x(x1, 0xffffffffffff00ffLL);
AND(x1, eb1, x1);
SLLI(gd, gd, 8);
OR(eb1, x1, gd);
} else {
ANDI(x1, eb1, ~0xff);
OR(eb1, x1, gd);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SB(gb1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MVxw(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SDxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8A:
INST_NAME("MOV Gb, Eb");
nextop = F8;
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb1 = xRAX+(gd&3);
}
gd = x4;
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
if(eb2) {
SRLI(x1, eb1, 8);
ANDI(x1, x1, 0xff);
} else {
ANDI(x1, eb1, 0xff);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LBU(x1, ed, fixedaddress);
}
if(gb2) {
MOV64x(x4, ~0xff00);
AND(gb1, gb1, x4);
SLLI(x1, x1, 8);
} else {
ANDI(gb1, gb1, ~0xff);
}
OR(gb1, gb1, x1);
break;
case 0x8B:
INST_NAME("MOV Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) {
MVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LDxw(gd, ed, fixedaddress);
}
break;
case 0x8C:
INST_NAME("MOV Ed, Seg");
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= seg
LHU(xRAX+(nextop&7)+(rex.b<<3), xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LHU(x3, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
SH(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
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
MV(gd, ed);
if(!rex.w || rex.is32bits) {
ZEROUP(gd); // truncate the higher 32bits as asked
}
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
LHU(x1, ed, fixedaddress);
ed = x1;
}
SW(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[(nextop&0x38)>>3]));
break;
case 0x8F:
INST_NAME("POP Ed");
nextop = F8;
if(MODREG) {
POP1z(xRAX+(nextop&7)+(rex.b<<3));
} else {
POP1z(x2); // so this can handle POP [ESP] and maybe some variant too
addr = geted(dyn, addr, ninst, nextop, &ed, x3, x1, &fixedaddress, rex, &lock, 1, 0);
if(ed==xRSP) {
SDz(x2, ed, fixedaddress);
} else {
// complicated to just allow a segfault that can be recovered correctly
ADDIz(xRSP, xRSP, rex.is32bits?-4:-8);
SDz(x2, ed, fixedaddress);
ADDIz(xRSP, xRSP, rex.is32bits?4:8);
}
}
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG EAX, Reg");
MVxw(x2, xRAX);
MVxw(xRAX, gd);
MVxw(gd, x2);
}
break;
case 0x98:
INST_NAME("CWDE");
if(rex.w) {
SEXT_W(xRAX, xRAX);
} else {
SLLI(xRAX, xRAX, 16);
SRAIW(xRAX, xRAX, 16);
ZEROUP(xRAX);
}
break;
case 0x99:
INST_NAME("CDQ");
if(rex.w) {
SRAI(xRDX, xRAX, 63);
} else {
SLLI(xRDX, xRAX, 32);
SRAI(xRDX, xRDX, 63);
ZEROUP(xRDX);
}
break;
case 0x9B:
INST_NAME("FWAIT");
break;
case 0x9C:
INST_NAME("PUSHF");
NOTEST(x1);
READFLAGS(X_ALL);
FLAGS_ADJUST_TO11(x3, xFlags, x2);
PUSH1z(x3);
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET);
POP1z(xFlags);
FLAGS_ADJUST_FROM11(xFlags, x2);
MOV32w(x1, 0x3F7FD7);
AND(xFlags, xFlags, x1);
ORI(xFlags, xFlags, 0x2);
SET_DFNONE();
if(box64_wine) { // should this be done all the time?
ANDI(x1, xFlags, 1 << F_TF);
CBZ_NEXT(x1);
MOV64x(xRIP, addr);
STORE_XEMU_CALL();
CALL(native_singlestep, -1);
ANDI(xFlags, xFlags, ~(1 << F_TF));
}
break;
case 0x9F:
INST_NAME("LAHF");
READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
ANDI(x1, xFlags, 0xFF);
SLLI(x1, x1, 8);
MOV64x(x2, 0xffffffffffff00ffLL);
AND(xRAX, xRAX, x2);
OR(xRAX, xRAX, x1);
break;
case 0xA0:
INST_NAME("MOV AL,Ob");
if(rex.is32bits) u64 = F32; else u64 = F64;
MOV64z(x1, u64);
LBU(x1, x1, 0);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
if(rex.is32bits) u64 = F32; else u64 = F64;
MOV64z(x1, u64);
LDxw(xRAX, x1, 0);
break;
case 0xA2:
INST_NAME("MOV Ob,AL");
if(rex.is32bits) u64 = F32; else u64 = F64;
MOV64z(x1, u64);
SB(xRAX, x1, 0);
SMWRITE();
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
if(rex.is32bits) u64 = F32; else u64 = F64;
MOV64z(x1, u64);
SDxw(xRAX, x1, 0);
SMWRITE();
break;
case 0xA4:
if(rep) {
INST_NAME("REP MOVSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LBU(x1, xRSI, 0);
SB(x1, xRDI, 0);
ADDI(xRSI, xRSI, 1);
ADDI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LBU(x1, xRSI, 0);
LBU(x1, xRDI, 0);
SUBI(xRSI, xRSI, 1);
SUBI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, x1, 1);
LBU(x1, xRSI, 0);
SB(x1, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
}
break;
case 0xA5:
if(rep) {
INST_NAME("REP MOVSD");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LDxw(x1, xRSI, 0);
ADDI(xRSI, xRSI, rex.w?8:4);
SDxw(x1, xRDI, 0);
ADDI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LDxw(x1, xRSI, 0);
SUBI(xRSI, xRSI, rex.w?8:4);
SDxw(x1, xRDI, 0);
SUBI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSD");
GETDIR(x3, x1, rex.w?8:4);
LDxw(x1, xRSI, 0);
SDxw(x1, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
}
break;
case 0xA6:
switch(rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LBU(x1, xRSI, 0);
ADDI(xRSI, xRSI, 1);
LBU(x2, xRDI, 0);
ADDI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNEZ_MARK(xRCX);
B_MARK3_nocond;
MARK2; // Part with DF==1
LBU(x1, xRSI, 0);
SUBI(xRSI, xRSI, 1);
LBU(x2, xRDI, 0);
SUBI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNEZ_MARK2(xRCX);
MARK3; // end
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
default:
INST_NAME("CMPSB");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, 1);
LBU(x1, xRSI, 0);
LBU(x2, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
}
break;
case 0xA8:
INST_NAME("TEST AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
ANDI(x1, xRAX, 0xff);
u8 = F8;
MOV32w(x2, u8);
emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xA9:
INST_NAME("TEST EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
break;
case 0xAA:
if(rep) {
INST_NAME("REP STOSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
SB(xRAX, xRDI, 0);
ADDI(xRDI, xRDI, 1);
ADDI(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
SB(xRAX, xRDI, 0);
ADDI(xRDI, xRDI, -1);
ADDI(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("STOSB");
GETDIR(x3, x1, 1);
SB(xRAX, xRDI, 0);
ADD(xRDI, xRDI, x3);
}
break;
case 0xAB:
if(rep) {
INST_NAME("REP STOSD");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
SDxw(xRAX, xRDI, 0);
ADDI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
SDxw(xRAX, xRDI, 0);
SUBI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("STOSD");
GETDIR(x3, x1, rex.w?8:4);
SDxw(xRAX, xRDI, 0);
ADD(xRDI, xRDI, x3);
}
break;
case 0xAE:
switch (rep) {
case 1:
case 2:
if (rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZ_NEXT(xRCX);
ANDI(x1, xRAX, 0xff);
ANDI(x2, xFlags, 1<<F_DF);
BNEZ_MARK2(x2);
MARK; // Part with DF==0
LBU(x2, xRDI, 0);
ADDI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNE_MARK(xRCX, xZR);
B_MARK3_nocond;
MARK2; // Part with DF==1
LBU(x2, xRDI, 0);
SUBI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNE_MARK2(xRCX, xZR);
MARK3; // end
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
default:
INST_NAME("SCASB");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, 1);
ANDI(x1, xRAX, 0xff);
LBU(x2, xRDI, 0);
ADD(xRDI, xRDI, x3);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
}
break;
case 0xAF:
switch (rep) {
case 1:
case 2:
if (rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZ_NEXT(xRCX);
if (rex.w) {MV(x1, xRAX);} else {AND(x1, xRAX, xMASK);}
ANDI(x2, xFlags, 1<<F_DF);
BNEZ_MARK2(x2);
MARK; // Part with DF==0
LDxw(x2, xRDI, 0);
ADDI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNE_MARK(xRCX, xZR);
B_MARK3_nocond;
MARK2; // Part with DF==1
LDxw(x2, xRDI, 0);
SUBI(xRDI, xRDI, rex.w?8:4);
SUBI(xRCX, xRCX, 1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNE_MARK2(xRCX, xZR);
MARK3; // end
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
break;
default:
INST_NAME("SCASD");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, rex.w?8:4);
AND(x1, xRAX, xMASK);
LDxw(x2, xRDI, 0);
ADD(xRDI, xRDI, x3);
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
break;
}
break;
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
INST_NAME("MOV xL, Ib");
u8 = F8;
if(rex.rex)
gb1 = xRAX+(opcode&7)+(rex.b<<3);
else
gb1 = xRAX+(opcode&3);
ANDI(gb1, gb1, ~0xff);
ORI(gb1, gb1, u8);
break;
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
INST_NAME("MOV xH, Ib");
u8 = F8;
if(rex.rex) {
gb1 = xRAX+(opcode&7)+(rex.b<<3);
ANDI(gb1, gb1, ~0xff);
ORI(gb1, gb1, u8);
} else {
MOV32w(x1, u8);
gb1 = xRAX+(opcode&3);
MOV64x(x2, 0xffffffffffff00ffLL);
AND(gb1, gb1, x2);
SLLI(x1, x1, 8);
OR(gb1, gb1, x1);
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
INST_NAME("MOV Reg, Id");
gd = xRAX+(opcode&7)+(rex.b<<3);
if(rex.w) {
u64 = F64;
MOV64x(gd, u64);
} else {
u32 = F32;
MOV32w(gd, u32);
}
break;
default:
DEFAULT;
}
return addr;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+496
View File
@@ -0,0 +1,496 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_64(dynarec_rv64_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);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0, x5);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x0F:
opcode = F8;
switch(opcode) {
case 0x11:
switch(rep) {
case 0:
INST_NAME("MOVUPS Ex,Gx");
nextop = F8;
GETGX();
GETEX(x2, 0);
if(!MODREG) {
grab_segdata(dyn, addr, ninst, x4, seg);
ADD(x4, x4, wback);
wback = x4;
}
LD(x3, gback, gdoffset+0);
LD(x5, gback, gdoffset+8);
SD(x3, wback, fixedaddress+0);
SD(x5, wback, fixedaddress+8);
if(!MODREG)
SMWRITE2();
break;
case 1:
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
d0 = sse_get_reg(dyn, ninst, x1, ed, 0);
FMVD(d0, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, x4, ed);
ed = x4;
FSD(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 2:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
FMVS(q0, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, x4, ed);
ed = x4;
FSW(v0, ed, fixedaddress);
SMWRITE2();
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0, x5);
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);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0, x5);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK(x5, 0);
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK(x5, 0);
break;
case 2: // ADC
INST_NAME("ADC Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK(x5, 0);
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK(x5, 0);
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK(x5, 0);
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
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);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x9);
WBACKO(x6);
break;
case 1: // OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
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);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
SD(x6, xEmu, offsetof(x64emu_t, scratch));
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x9);
LD(x6, xEmu, offsetof(x64emu_t, scratch));
WBACKO(x6);
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);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x9);
WBACKO(x6);
break;
case 4: // AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 5: // SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x9);
WBACKO(x6);
break;
case 6: // XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 7: // CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1, x5);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x88:
INST_NAME("MOV Seg:Eb, Gb");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb1 = xRAX+(gd&3);
}
gd = x5;
if(gb2) {
SRLI(x5, gb1, 8);
gb1 = x5;
}
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
ANDI(gd, gb1, 0xff);
if(eb2) {
MOV64x(x1, 0xffffffffffff00ffLL);
ANDI(x1, eb1, x1);
SLLI(gd, gd, 8);
OR(eb1, x1, gd);
} else {
ANDI(x1, eb1, ~0xff);
OR(eb1, x1, gd);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, ed, x4);
SB(gb1, x4, fixedaddress);
SMWRITE2();
}
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MVxw(xRAX+(nextop&7)+(rex.b<<3), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, ed, x4);
SDxw(gd, x4, fixedaddress);
SMWRITE2();
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MVxw(gd, xRAX+(nextop&7)+(rex.b<<3));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, ed, x4);
LDxw(gd, x4, fixedaddress);
}
break;
case 0xA1:
INST_NAME("MOV EAX,FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
// TODO: could be optimized.
MOV64z(x1, u64);
ADD(x1, x1, x4);
LDxw(xRAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV FS:Od,EAX");
grab_segdata(dyn, addr, ninst, x4, seg);
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
// TODO: could be optimized.
MOV64z(x1, u64);
ADD(x1, x1, x4);
SDxw(xRAX, x1, 0);
SMWRITE2();
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
if(MODREG) { // reg <= u8
u8 = F8;
if(!rex.rex) {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0;
}
if (eb2) {
// load a mask to x3 (ffffffffffff00ff)
LUI(x3, 0xffff0);
ORI(x3, x3, 0xff);
// apply mask
AND(eb1, eb1, x3);
if(u8) {
if((u8<<8)<2048) {
ADDI(x4, xZR, u8<<8);
} else {
ADDI(x4, xZR, u8);
SLLI(x4, x4, 8);
}
OR(eb1, eb1, x4);
}
} else {
ANDI(eb1, eb1, 0xf00); // mask ffffffffffffff00
ORI(eb1, eb1, u8);
}
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1);
u8 = F8;
if(u8) {
ADDI(x3, xZR, u8);
ed = x3;
} else
ed = xZR;
ADD(x4, wback, x4);
SB(ed, x4, fixedaddress);
SMWRITE2();
}
break;
case 0xC7:
INST_NAME("MOV Seg:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 4);
i64 = F32S;
if(i64) {
MOV64xw(x3, i64);
ed = x3;
} else
ed = xZR;
ADD(x4, wback, x4);
SDxw(ed, x4, fixedaddress);
SMWRITE2();
}
break;
default:
DEFAULT;
}
return addr;
}
+922
View File
@@ -0,0 +1,922 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int16_t i16;
uint16_t u16;
uint64_t u64;
int32_t i32;
int64_t j64;
uint8_t gd, ed;
uint8_t wback, wb1;
int64_t fixedaddress;
int unscaled;
int lock;
MAYUSE(u8);
MAYUSE(u16);
MAYUSE(u64);
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
switch(opcode) {
case 0x01:
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_add16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
GWBACK;
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1 , xRAX);
MOV32w(x2, i32);
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
LUI(x3, 0xffff0);
AND(xRAX, xRAX, x3);
OR(xRAX, xRAX, x1);
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
EWBACK;
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_or16(dyn, ninst, x1, x2, x4, x5);
GWBACK;
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1, xRAX);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
LUI(x3, 0xffff0);
AND(xRAX, xRAX, x3);
OR(xRAX, xRAX, x1);
break;
case 0x0F:
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
break;
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sbb16(dyn, ninst, x1, x2, x3, x4, x5);
GWBACK;
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_and16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_and16(dyn, ninst, x1, x2, x4, x5);
GWBACK;
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1, xRAX);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
LUI(x3, 0xffff0);
AND(xRAX, xRAX, x3);
OR(xRAX, xRAX, x1);
break;
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sub16(dyn, ninst, x2, x1, x4, x5, x6);
EWBACK;
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
GWBACK;
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1, xRAX);
MOV32w(x2, i32);
emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
LUI(x2, 0xffff0);
AND(xRAX, xRAX, x2);
OR(xRAX, xRAX, x1);
break;
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
GWBACK;
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1, xRAX);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4, x5);
LUI(x5, 0xffff0);
AND(xRAX, xRAX, x5);
OR(xRAX, xRAX, x1);
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
ZEXTH(x1, xRAX);
if(i32) {
MOV32w(x2, i32);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp16_0(dyn, ninst, x1, x3, x4);
}
break;
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_PENDING);
gd = xRAX + (opcode&7);
ZEXTH(x1, gd);
emit_inc16(dyn, ninst, x1, x2, x3, x4);
LUI(x3, 0xffff0);
AND(gd, gd, x3);
OR(gd, gd, x1);
ZEROUP(gd);
break;
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_PENDING);
gd = xRAX + (opcode&7);
ZEXTH(x1, gd);
emit_dec16(dyn, ninst, x1, x2, x3, x4, x5);
LUI(x3, 0xffff0);
AND(gd, gd, x3);
OR(gd, gd, x1);
ZEROUP(gd);
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);
break;
case 0x69:
case 0x6B:
if(opcode==0x69) {
INST_NAME("IMUL Gw,Ew,Iw");
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, (opcode==0x69)?2:1);
if(opcode==0x69) i32 = F16S; else i32 = F8S;
MOV32w(x2, i32);
MULW(x2, x2, x1);
ZEXTH(x2, x2);
UFLAG_RES(x2);
gd=x2;
GWBACK;
break;
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, rep, ok, need_epilog);
case 0x81:
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4, x6);
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_or16(dyn, ninst, x1, x5, 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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4, x6);
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4, x6);
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV64x(x5, i16);
emit_and16(dyn, ninst, x1, x5, 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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4, x6);
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4, x6);
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);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV64x(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
default:
DEFAULT;
}
break;
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
// we don't use GETGW above, so we need let gd & 0xffff.
LUI(x1, 0xffff0);
AND(ed, ed, x1);
ZEXTH(x2, gd);
OR(ed, ed, x2);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 0, 0);
SH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8B:
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD; // don't need GETGW neither
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
LUI(x1, 0xffff0);
AND(gd, gd, x1);
ZEXTH(x2, ed);
OR(gd, gd, x2);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LHU(x1, ed, fixedaddress);
LUI(x4, 0xffff0);
AND(gd, gd, x4);
OR(gd, gd, x1);
}
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
LUI(x4, 0xffff0);
// x2 <- rax
MV(x2, xRAX);
// rax[15:0] <- gd[15:0]
ZEXTH(x3, gd);
AND(xRAX, xRAX, x4);
OR(xRAX, xRAX, x3);
// gd[15:0] <- x2[15:0]
ZEXTH(x2, x2);
AND(gd, gd, x4);
OR(gd, gd, x2);
}
break;
case 0x98:
INST_NAME("CBW");
SLLI(x1, xRAX, 56);
SRAI(x1, x1, 56);
LUI(x2, 0xffff0);
AND(xRAX, xRAX, x2);
NOT(x2, x2);
AND(x1, x1, x2);
OR(xRAX, xRAX, x1);
break;
case 0xA5:
if(rep) {
INST_NAME("REP MOVSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LH(x1, xRSI, 0);
ADDI(xRSI, xRSI, 2);
SH(x1, xRDI, 0);
ADDI(xRDI, xRDI, 2);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LH(x1, xRSI, 0);
SUBI(xRSI, xRSI, 2);
SH(x1, xRDI, 0);
SUBI(xRDI, xRDI, 2);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSD");
GETDIR(x3, x1, 2);
LH(x1, xRSI, 0);
SH(x1, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
SLLIW(x1, xRAX, 16);
SRLIW(x1, x1, 16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xAB:
if(rep) {
INST_NAME("REP STOSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1<<F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
SH(xRAX, xRDI, 0);
ADDI(xRDI, xRDI, 2);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
SH(xRAX, xRDI, 0);
SUBI(xRDI, xRDI, 2);
SUBI(xRCX, xRCX, 1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("STOSW");
GETDIR(x3, x1, 2);
SH(xRAX, xRDI, 0);
ADD(xRDI, xRDI, x3);
}
break;
case 0xAF:
switch (rep) {
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZ_NEXT(xRCX);
GETDIR(x3, x1, rex.w?8:2);
if (rex.w) {
MARK;
LD(x2, xRDI, 0);
ADD(xRDI, xRDI, x3);
ADDI(xRCX, xRCX, -1);
if (rep==1) {BEQ_MARK3(xRAX, x2);} else {BNE_MARK3(xRAX, x2);}
BNE_MARK(xRCX, xZR);
MARK3;
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else {
ZEXTH(x1, xRAX);
MARK;
LHU(x2, xRDI, 0);
ADD(xRDI, xRDI, x3);
ADDI(xRCX, xRCX, -1);
if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
BNE_MARK(xRCX, xZR);
MARK3;
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
}
break;
default:
INST_NAME("SCASW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, rex.w?8:2);
if (rex.w) {
LD(x2, xRDI, 0);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else {
ZEXTH(x1, xRAX);
LHU(x2, xRDI, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
}
ADD(xRDI, xRDI, x3);
break;
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
INST_NAME("MOV Reg, Iw");
gd = xRAX+(opcode&7)+(rex.b<<3);
if(rex.w) {
u64 = F64;
MOV64x(gd, u64);
} else {
u16 = F16;
MOV64x(x1, ~0xffff);
AND(gd, gd, x1);
if(u16<2048) {
ORI(gd, gd, u16);
} else {
MOV32w(x1, u16);
OR(gd, gd, x1);
}
}
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rol16, x1, x3);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(ror16, x1, x3);
EWBACK;
break;
case 2:
INST_NAME("RCL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcl16, x1, x3);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcr16, x1, x3);
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
if(MODREG) {
SLLI(ed, ed, 48+(u8&0x1f));
SRLI(ed, ed, 48);
} else {
SLLI(ed, ed, u8&0x1f);
}
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
INST_NAME("SHR Ed, Ib");
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
SRLI(ed, ed, u8&0x1f);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
GETSEW(x1, 1);
u8 = F8;
UFLAG_IF {MOV32w(x2, (u8&0x1f));}
UFLAG_OP12(ed, x2)
SRAI(ed, ed, u8&0x1f);
if(MODREG) {
ZEXTH(ed, ed);
}
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ADDI(x1, xZR, -1);
SRLI(x1, x1, 48);
AND(ed, ed, x1);
u16 = F16;
MOV32w(x1, u16);
ORI(ed, ed, x1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 2);
u16 = F16;
MOV32w(x1, u16);
SH(x1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDI(x4, xRCX, 0x1f);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
SRL(ed, ed, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 4:
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDI(x4, xRCX, 0x1f);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
SLL(ed, ed, x4);
ZEXTH(ed, ed);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDI(x4, xRCX, 0x1f);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1, 0);
UFLAG_OP12(ed, x4);
SRA(ed, ed, x4);
ZEXTH(ed, ed);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
default:
DEFAULT;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ew");
GETEW(x1, 0);
NOT(ed, ed); // No flags affected
EWBACK;
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
ZEXTH(x2, xRAX);
SLLI(x3, xRDX, 48);
SRLI(x3, x3, 32);
OR(x2, x2, x3);
DIVUW(x3, x2, ed);
REMUW(x4, x2, ed);
MOV64x(x5, ~0xffff);
AND(xRAX, xRAX, x5);
AND(xRDX, xRDX, x5);
NOT(x5, x5);
AND(x3, x3, x5);
AND(x4, x4, x5);
OR(xRAX, xRAX, x3);
OR(xRDX, xRDX, x4);
break;
case 7:
INST_NAME("IDIV Ew");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
GETSEW(x1, 0);
ZEXTH(x2, xRAX);
SLLI(x3, xRDX, 48);
SRLI(x3, x3, 32);
OR(x2, x2, x3);
DIVW(x3, x2, ed);
REMW(x4, x2, ed);
MOV64x(x5, ~0xffff);
AND(xRAX, xRAX, x5);
AND(xRDX, xRDX, x5);
NOT(x5, x5);
AND(x3, x3, x5);
AND(x4, x4, x5);
OR(xRAX, xRAX, x3);
OR(xRDX, xRDX, x4);
break;
default:
DEFAULT;
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
File diff suppressed because it is too large. Load diff
+77
View File
@@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_6664(dynarec_rv64_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 = xRAX+(nextop&7)+(rex.b<<3);
if(rex.w) {
MV(gd, ed);
} else {
if(ed!=gd) {
LUI(x1, 0xffff0);
AND(gd, gd, x1);
ZEXTH(x1, ed);
OR(gd, gd, x1);
}
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD(x4, ed, x4);
if(rex.w) {
LD(gd, x4, fixedaddress);
} else {
LHU(x1, x4, fixedaddress);
SRLI(gd, gd, 16);
SLLI(gd, gd, 16);
OR(gd, gd, x1);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+129
View File
@@ -0,0 +1,129 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j64);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
GETREX();
switch(opcode) {
case 0x81:
case 0x83:
nextop = F8;
SMDMB();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
ZEXTH(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4, x2);
SRLI(ed, ed, 16);
SLLI(ed, ed, 16);
OR(ed, ed, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LR_W(x1, wback, 1, 1);
SRLIW(x3, x1, 16);
SLLIW(x3, x3, 16);
ADD(x4, x1, x5);
SLLIW(x4, x4, 16);
SRLIW(x4, x4, 16);
OR(x4, x4, x3);
SC_W(x3, x4, wback, 1, 1);
BNEZ_MARKLOCK(x3);
IFX(X_ALL|X_PEND) {
SLLIW(x1, x1, 16);
SRLIW(x1, x1, 16);
}
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LR_W(x1, wback, 1, 1);
SLLIW(x3, x1, 16);
SRLIW(x3, x3, 16);
SRLIW(x1, x1, 16);
ADD(x4, x1, x5);
SLLIW(x4, x4, 16);
OR(x4, x4, x3);
SC_W(x3, x4, wback, 1, 1);
BNEZ_MARK2(x3);
MARK3;
// final
IFX(X_ALL|X_PEND) {
emit_add16(dyn, ninst, x1, x5, x3, x4, x6);
}
}
break;
default:
DEFAULT;
}
SMDMB();
break;
default:
DEFAULT;
}
return addr;
}
+574
View File
@@ -0,0 +1,574 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_67(dynarec_rv64_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 0x01:
INST_NAME("ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x02:
INST_NAME("ADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_add8(dyn, ninst, x1, x2, x3, x4);
GBBACK(x4);
break;
case 0x03:
INST_NAME("ADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x05:
INST_NAME("ADD EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6);
break;
case 0x09:
INST_NAME("OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x0A:
INST_NAME("OR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_or8(dyn, ninst, x1, x2, x3, x4);
GBBACK(x4);
break;
case 0x0B:
INST_NAME("OR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0D:
INST_NAME("OR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x0F:
opcode=F8;
switch(opcode) {
case 0x2E:
// no special check...
case 0x2F:
switch (rep) {
case 0:
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGXSS(s0);
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
} else {
v0 = fpu_get_scratch(dyn);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
FLW(v0, ed, fixedaddress);
}
CLEAR_FLAGS();
// if isnan(s0) || isnan(v0)
IFX(X_ZF | X_PF | X_CF) {
FEQS(x3, s0, s0);
FEQS(x2, v0, v0);
AND(x2, x2, x3);
BNE_MARK(x2, xZR);
ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
B_NEXT_nocond;
}
MARK;
// else if isless(d0, v0)
IFX(X_CF) {
FLTS(x2, s0, v0);
BEQ_MARK2(x2, xZR);
ORI(xFlags, xFlags, 1<<F_CF);
B_NEXT_nocond;
}
MARK2;
// else if d0 == v0
IFX(X_ZF) {
FEQS(x2, s0, v0);
CBZ_NEXT(x2);
ORI(xFlags, xFlags, 1<<F_ZF);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x11:
INST_NAME("ADC Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
WBACK;
break;
case 0x13:
INST_NAME("ADC Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
break;
case 0x15:
INST_NAME("ADC EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x1, i64);
emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);
break;
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x1A:
INST_NAME("SBB Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5);
GBBACK(x4);
break;
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
break;
case 0x21:
INST_NAME("AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_and32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x22:
INST_NAME("AND Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_and8(dyn, ninst, x1, x2, x3, x4);
GBBACK(x4);
break;
case 0x23:
INST_NAME("AND Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_and32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x25:
INST_NAME("AND EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x29:
INST_NAME("SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5);
WBACK;
break;
case 0x2A:
INST_NAME("SUB Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_sub8(dyn, ninst, x1, x2, x3, x4, x5);
GBBACK(x5);
break;
case 0x2B:
INST_NAME("SUB Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x2D:
INST_NAME("SUB EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_sub32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6);
break;
case 0x31:
INST_NAME("XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
WBACK;
break;
case 0x32:
INST_NAME("XOR Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_xor8(dyn, ninst, x1, x2, x3, x4);
GBBACK(x4);
break;
case 0x33:
INST_NAME("XOR Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x35:
INST_NAME("XOR EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4);
break;
case 0x38:
INST_NAME("CMP Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x1, 0);
GETGB(x2);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x39:
INST_NAME("CMP Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
break;
case 0x3A:
INST_NAME("CMP Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x3B:
INST_NAME("CMP Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED32(0);
emit_cmp32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
break;
case 0x3C:
INST_NAME("CMP AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
u8 = F8;
ANDI(x1, xRAX, 0xff);
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;
case 0x3D:
INST_NAME("CMP EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
i64 = F32S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, 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);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, 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);
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);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, 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);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACK;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32((opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb1 = xRAX+(gd&3);
}
gd = x4;
if(gb2) {
SRLI(x4, gb1, 8);
gb1 = x4;
}
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
ANDI(gd, gb1, 0xff);
if(eb2) {
MOV64x(x1, 0xffffffffffff00ffLL);
AND(x1, eb1, x1);
SLLI(gd, gd, 8);
OR(eb1, x1, gd);
} else {
ANDI(x1, eb1, ~0xff);
OR(eb1, x1, gd);
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SB(gb1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MVxw(xRAX+(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, xRAX+(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);
if(ed!=gd) {
AND(gd, ed, xMASK);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+182
View File
@@ -0,0 +1,182 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t 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);
switch(nextop) {
case 0xC0 ... 0xC7:
case 0xC8 ... 0xCF:
case 0xD0 ... 0xD7:
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));
LHU(x3, xEmu, offsetof(x64emu_t, sw));
MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
AND(x3, x3, x1);
if(ST_IS_F(0)) {
FEQS(x5, v1, v1);
FEQS(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQS(x5, v1, v2);
BNEZ(x5, 28); // equal
FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
SLLI(x1, x3, 8);
J(20); // end
// undefined/NaN
LUI(x1, 1);
ADDI(x1, x1, 0b010100000000);
J(8); // end
// equal
LUI(x1, 1);
// end
} else {
FEQD(x5, v1, v1);
FEQD(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQD(x5, v1, v2);
BNEZ(x5, 28); // equal
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
SLLI(x1, x3, 8);
J(20); // end
// undefined/NaN
LUI(x1, 1);
ADDI(x1, x1, 0b010100000000);
J(8); // end
// equal
LUI(x1, 1);
// end
}
OR(x3, x3, x1);
SH(x3, xEmu, offsetof(x64emu_t, sw));
x87_do_pop(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(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
break;
case 0xE8 ... 0xEF:
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(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
break;
case 0xF8 ... 0xFF:
DEFAULT;
break;
default:
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);
FLW(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
} else {
FCVTDS(s0, s0);
FADDD(v1, v1, s0);
}
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);
FLW(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
} else {
FCVTDS(s0, s0);
FMULD(v1, v1, s0);
}
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);
FLW(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
} else {
FCVTDS(s0, s0);
FSUBD(v1, v1, s0);
}
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);
FLW(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
} else {
FCVTDS(s0, s0);
FDIVD(v1, v1, s0);
}
break;
default:
DEFAULT;
}
}
return addr;
}
+426
View File
@@ -0,0 +1,426 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t 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);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v2 = x87_do_push(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)) {
FMVS(v2, v1);
} else {
FMVD(v2, v1);
}
break;
case 0xC8:
INST_NAME("FXCH ST0");
break;
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
// should set C1 to 0
break;
case 0xD0:
INST_NAME("FNOP");
break;
case 0xD8:
INST_NAME("FSTPNCE ST0, ST0");
x87_do_pop(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FSTPNCE ST0, STx");
// copy the cache value for st0 to stx
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
FNEGS(v1, v1);
} else {
FNEGD(v1, v1);
}
break;
case 0xE1:
INST_NAME("FABS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
FABSS(v1, v1);
} else {
FABSD(v1, v1);
}
break;
case 0xE4:
INST_NAME("FTST");
DEFAULT
break;
case 0xE5:
INST_NAME("FXAM");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_refresh(dyn, ninst, x1, x2, 0);
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
break;
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
FMVWX(v1, x1);
} else {
MOV64x(x1, 0x3FF0000000000000);
FMVDX(v1, x1);
}
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, L2T);
break;
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, L2E);
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, PI);
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, LG2);
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, LN2);
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
FMVWX(v1, xZR);
} else {
FMVDX(v1, xZR);
}
break;
case 0xF0:
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_f2xm1, -1);
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);
CALL(native_fyl2x, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_ftan, -1);
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
FMVWX(v1, x1);
} else {
MOV64x(x1, 0x3FF0000000000000);
FMVDX(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);
CALL(native_fpatan, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xF4:
INST_NAME("FXTRACT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fxtract, -1);
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);
CALL(native_fprem1, -1);
break;
case 0xF6:
INST_NAME("FDECSTP");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
LW(x2, xEmu, offsetof(x64emu_t, top));
SUBI(x2, x2, 1);
ANDI(x2, x2, 7);
SW(x2, xEmu, offsetof(x64emu_t, top));
break;
case 0xF7:
INST_NAME("FINCSTP");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
LW(x2, xEmu, offsetof(x64emu_t, top));
ADDI(x2, x2, 1);
ANDI(x2, x2, 7);
SW(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);
CALL(native_fprem, -1);
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);
CALL(native_fyl2xp1, -1);
x87_do_pop(dyn, ninst, x3);
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
FSQRTS(v1, v1);
} else {
FSQRTD(v1, v1);
}
break;
case 0xFB:
INST_NAME("FSINCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fsincos, -1);
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)) {
FEQS(x2, v0, v0);
BNEZ_MARK(x2);
B_NEXT_nocond;
MARK; // v0 is not nan
FABSS(v1, v0);
MOV64x(x3, 1ULL << __FLT_MANT_DIG__);
FCVTSL(v2, x3, RD_RTZ);
FLTS(x3, v1, v2);
BNEZ_MARK2(x3);
B_NEXT_nocond;
MARK2;
FCVTLS(x3, v0, RD_DYN);
FCVTSL(v1, x3, RD_DYN);
FSGNJS(v0, v1, v0);
} else {
FEQD(x2, v0, v0);
BNEZ_MARK(x2);
B_NEXT_nocond;
MARK; // v0 is not nan
FABSD(v1, v0);
MOV64x(x3, 1ULL << __DBL_MANT_DIG__);
FCVTDL(v2, x3, RD_RTZ);
FLTD(x3, v1, v2);
BNEZ_MARK2(x3);
B_NEXT_nocond;
MARK2;
FCVTLD(x3, v0, RD_DYN);
FCVTDL(v1, x3, RD_DYN);
FSGNJD(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);
CALL(native_fscale, -1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fsin, -1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fcos, -1);
break;
case 0xD1:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst, x1, box64_dynarec_x87double?EXT_CACHE_ST_D:EXT_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLW(v1, ed, fixedaddress);
if(!ST_IS_F(0)) {
FCVTDS(v1, v1);
}
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch(dyn);
FCVTSD(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FSW(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if(!ST_IS_F(0)) {
FCVTSD(v1, v1);
}
FSW(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if(ed!=x1) {
MV(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_loadenv, -1);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
SH(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if(ed!=x1) {
MV(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_savenv, -1);
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;
LH(x1, xEmu, offsetof(x64emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
}
return addr;
}
+303
View File
@@ -0,0 +1,303 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t 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);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 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));
ANDI(x1, xFlags, 1<<F_CF);
CBNZ_NEXT(x1);
if(ST_IS_F(0)) {
FMVS(v1, v2);
} else {
FMVD(v1, v2); // F_CF==0
}
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 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));
ANDI(x1, xFlags, 1<<F_ZF);
CBNZ_NEXT(x1);
if(ST_IS_F(0)) {
FMVS(v1, v2);
} else {
FMVD(v1, v2); // F_ZF==0
}
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 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));
ANDI(x1, xFlags, (1<<F_CF)|(1<<F_ZF));
CBNZ_NEXT(x1);
if(ST_IS_F(0)) {
FMVS(v1, v2);
} else {
FMVD(v1, v2); // F_CF==0 & F_ZF==0
}
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 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));
ANDI(x1, xFlags, 1<<F_PF);
CBNZ_NEXT(x1);
if(ST_IS_F(0)) {
FMVS(v1, v2);
} else {
FMVD(v1, v2); // F_PF==0
}
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
break;
case 0xE2:
INST_NAME("FNCLEX");
LH(x2, xEmu, offsetof(x64emu_t, sw));
ANDI(x2, x2, ~(0xff)); // IE .. PE, SF, ES
MOV32w(x1, ~(1<<15)); // B
AND(x2, x2, x1);
SH(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(reset_fpu, -1);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
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));
IFX(F_ZF | F_PF | F_CF) {
if(ST_IS_F(0)) {
FEQS(x5, v1, v1);
FEQS(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQS(x5, v1, v2);
BNEZ(x5, 24); // equal
FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
OR(xFlags, xFlags, x3); // CF is the least significant bit
J(16); // end
// NaN
ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
J(8); // end
// equal
ORI(xFlags, xFlags, 1<<F_ZF);
// end
} else {
FEQD(x5, v1, v1);
FEQD(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQD(x5, v1, v2);
BNEZ(x5, 24); // equal
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
OR(xFlags, xFlags, x3); // CF is the least significant bit
J(16); // end
// NaN
ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
J(8); // end
// equal
ORI(xFlags, xFlags, 1<<F_ZF);
// end
}
}
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FCOMI ST0, STx");
DEFAULT;
break;
case 0xE0:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LW(x1, ed, fixedaddress);
FCVTDW(v1, x1, RD_RNE); // i32 -> double
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
DEFAULT;
break;
case 2:
INST_NAME("FIST Ed, ST0");
DEFAULT;
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v2 = fpu_get_scratch(dyn);
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // reset all bits
}
FCVTWD(x4, v1, RD_DYN);
x87_restoreround(dyn, ninst, u8);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, 1<<FR_NV);
BEQ_MARK2(x5, xZR);
MOV32w(x4, 0x80000000);
}
MARK2;
SW(x4, wback, fixedaddress);
x87_do_pop(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) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
// the FLD is immediatly followed by an FSTP
LD(x5, ed, fixedaddress+0);
LH(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(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);
SD(x5, ed, fixedaddress+0);
SH(x6, ed, fixedaddress+8);
} else {
if(box64_x87_no80bits) {
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
FLD(v1, ed, fixedaddress);
} else {
if(ed!=x1) {
MV(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(native_fld, -1);
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if(box64_x87_no80bits) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FSD(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);
if(ed!=x1) {
MV(x1, ed);
}
CALL(native_fstp, -1);
}
x87_do_pop(dyn, ninst, x3);
break;
default:
DEFAULT;
}
}
return addr;
}
+119
View File
@@ -0,0 +1,119 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
int64_t fixedaddress;
int unscaled;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FADD STx, ST0");
DEFAULT;
break;
case 0xC8 ... 0xCF:
INST_NAME("FMUL STx, ST0");
DEFAULT;
break;
case 0xD0 ... 0xD7:
INST_NAME("FCOM ST0, STx"); //yep
DEFAULT;
break;
case 0xD8 ... 0xDF:
INST_NAME("FCOMP ST0, STx");
DEFAULT;
break;
case 0xE0 ... 0xE7:
INST_NAME("FSUBR STx, ST0");
DEFAULT;
break;
break;
case 0xE8 ... 0xEF:
INST_NAME("FSUB STx, ST0");
DEFAULT;
break;
case 0xF0 ... 0xF7:
INST_NAME("FDIVR STx, ST0");
DEFAULT;
break;
case 0xF8 ... 0xFF:
INST_NAME("FDIV STx, ST0");
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD(v2, wback, fixedaddress);
LHU(x3, xEmu, offsetof(x64emu_t, sw));
MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
AND(x3, x3, x1);
FEQD(x5, v1, v1);
FEQD(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQD(x5, v1, v2);
BNEZ(x5, 28); // equal
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
SLLI(x1, x3, 8);
J(20); // end
// undefined/NaN
LUI(x1, 1);
ADDI(x1, x1, 0b010100000000);
J(8); // end
// equal
LUI(x1, 1);
// end
OR(x3, x3, x1);
SH(x3, xEmu, offsetof(x64emu_t, sw));
x87_do_pop(dyn, ninst, x3);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
default:
DEFAULT;
}
}
return addr;
}
+179
View File
@@ -0,0 +1,179 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed, wback;
int64_t fixedaddress;
int unscaled;
int v1, v2;
int s0;
int64_t j64;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j64);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
MOV32w(x1, nextop&7);
CALL(fpu_do_free, -1);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FST ST0, STx");
DEFAULT;
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FSTP ST0, STx");
// copy the cache value for st0 to stx
x87_get_st_empty(dyn, ninst, x1, x2, nextop&7, X87_ST(nextop&7));
x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FUCOM ST0, STx");
DEFAULT;
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMP ST0, STx");
DEFAULT;
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLD(v1, wback, fixedaddress);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FSD(v1, wback, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FSD(v1, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0);
LWU(x2, xEmu, offsetof(x64emu_t, top));
LHU(x3, xEmu, offsetof(x64emu_t, sw));
if(dyn->e.x87stack) {
// update top
ADDI(x2, x2, -dyn->e.x87stack);
ANDI(x2, x2, 7);
}
MOV32w(x5, ~0x3800);
AND(x3, x3, x5); // mask out TOP
SLLI(x2, x2, 11); // shift TOP to bit 11
OR(x3, x3, x2); // inject TOP
SH(x3, ed, fixedaddress); // store whole sw flags
break;
default:
DEFAULT;
}
}
return addr;
}
+177
View File
@@ -0,0 +1,177 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t wback;
int64_t fixedaddress;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FADDP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMULP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
// INST_NAME("FCOMP ST0, STx"); //yep
DEFAULT;
break;
case 0xD9:
// INST_NAME("FCOMPP ST0, STx");
DEFAULT;
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUBRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUBP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIVRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIVP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
return 0;
default:
switch((nextop>>3)&7) {
default:
DEFAULT;
}
}
return addr;
}
+244
View File
@@ -0,0 +1,244 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "emu/x87emu_private.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_helper.h"
#include "dynarec_rv64_functions.h"
uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed, wback, u8;
int v1, v2;
int s0;
int64_t j64;
int64_t fixedaddress;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j64);
switch(nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FFREEP STx");
DEFAULT;
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LHU(x2, xEmu, offsetof(x64emu_t, top));
LHU(x1, xEmu, offsetof(x64emu_t, sw));
MOV32w(x3, 0b1100011111111111); // mask
AND(x1, x1, x3);
SLLI(x2, x2, 11);
OR(x1, x1, x2); // inject top
SH(x1, xEmu, offsetof(x64emu_t, sw));
SRLI(xRAX, xRAX, 16);
SLLI(xRAX, xRAX, 16);
OR(xRAX, xRAX, x1);
break;
case 0xE8 ... 0xF7:
if (nextop < 0xF0) {
INST_NAME("FUCOMIP ST0, STx");
} else {
INST_NAME("FCOMIP ST0, STx");
}
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
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));
CLEAR_FLAGS();
IFX(F_ZF | F_PF | F_CF) {
if(ST_IS_F(0)) {
FEQS(x5, v1, v1);
FEQS(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQS(x5, v1, v2);
BNEZ(x5, 24); // equal
FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0
OR(xFlags, xFlags, x3); // CF is the least significant bit
J(16); // end
// NaN
ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
J(8); // end
// equal
ORI(xFlags, xFlags, 1<<F_ZF);
// end
} else {
FEQD(x5, v1, v1);
FEQD(x4, v2, v2);
AND(x5, x5, x4);
BEQZ(x5, 24); // undefined/NaN
FEQD(x5, v1, v2);
BNEZ(x5, 24); // equal
FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0
OR(xFlags, xFlags, x3); // CF is the least significant bit
J(16); // end
// NaN
ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF));
J(8); // end
// equal
ORI(xFlags, xFlags, 1<<F_ZF);
// end
}
}
x87_do_pop(dyn, ninst, x3);
break;
case 0xC8 ... 0xDF:
case 0xE1 ... 0xE7:
case 0xF8 ... 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
LH(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
FCVTSL(v1, x1, RD_RNE);
} else {
FCVTDL(v1, x1, RD_RNE);
}
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0);
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // reset all bits
}
FCVTWD(x4, v1, RD_RTZ);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, 1<<FR_NV);
BNEZ_MARK(x5);
SLLIW(x5, x4, 16);
SRAIW(x5, x5, 16);
BEQ_MARK2(x5, x4);
MARK;
MOV32w(x4, 0x8000);
}
MARK2;
SH(x4, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // reset all bits
}
FCVTWD(x4, v1, RD_DYN);
x87_restoreround(dyn, ninst, u8);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, 1<<FR_NV);
BNEZ_MARK(x5);
SLLIW(x5, x4, 16);
SRAIW(x5, x5, 16);
BEQ_MARK2(x5, x4);
MARK;
MOV32w(x4, 0x8000);
}
MARK2;
SH(x4, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
LD(x1, wback, fixedaddress);
if (rex.is32bits) {
// need to also feed the STll stuff...
ADDI(x4, xEmu, offsetof(x64emu_t, fpu_ll));
LWU(x5, xEmu, offsetof(x64emu_t, top));
int a = 0 - dyn->e.x87stack;
if(a) {
ADDIW(x5, x5, a);
ANDI(x5, x5, 0x7);
}
SLLI(x5, x5, 4); // fpu_ll is 2 i64
ADD(x5, x5, x4);
SD(x1, x5, 8); // ll
}
FCVTDL(v1, x1, RD_RTZ);
if(rex.is32bits) {
FSD(v1, x5, 0); // ref
}
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, NULL, 1, 0);
if(rex.is32bits) {
// need to check STll first...
ADDI(x4, xEmu, offsetof(x64emu_t, fpu_ll));
LWU(x5, xEmu, offsetof(x64emu_t, top));
int a = 0 - dyn->e.x87stack;
if(a) {
ADDIW(x5, x5, a);
ANDI(x5, x5, 0x7);
}
SLLI(x5, x5, 4); // fpu_ll is 2 i64
ADD(x5, x5, x4);
FMVXD(x3, v1);
LD(x6, x5, 0); // ref
BNE_MARK(x6, x3);
LD(x6, x5, 8); // ll
SD(x6, wback, fixedaddress);
B_MARK3_nocond;
MARK;
}
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // reset all bits
}
FCVTLD(x4, v1, RD_DYN);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, 1<<FR_NV);
BEQ_MARK2(x5, xZR);
MOV64x(x4, 0x8000000000000000LL);
}
MARK2;
SD(x4, wback, fixedaddress);
MARK3;
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst, x3);
break;
default:
DEFAULT;
break;
}
}
return addr;
}
+478
View File
@@ -0,0 +1,478 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "dynarec_rv64_helper.h"
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE();
}
XOR(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX(X_SF) {
SRLI(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_PEND) {
SB(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE();
}
XORI(s1, s1, c&0xff);
ANDI(s1, s1, 0xff);
IFX(X_SF) {
SRLI(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_PEND) {
SB(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE();
}
XOR(s1, s1, s2);
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w && s1!=s2) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_xor32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if(c>=-2048 && c<=2047) {
XORI(s1, s1, c);
} else {
MOV64xw(s3, c);
XOR(s1, s1, s3);
}
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE();
}
XOR(s1, s1, s2);
ZEXTH(s1, s1);
IFX(X_PEND) {
SH(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF | X_SF) {
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_SF) {
SRLI(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) {
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE();
}
OR(s1, s1, s2);
ZEXTH(s1, s1);
IFX(X_PEND) {
SD(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE();
}
OR(s1, s1, s2);
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_or32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if(c>=-2048 && c<=2047) {
ORI(s1, s1, c);
} else {
MOV64xw(s3, c);
OR(s1, s1, s3);
}
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE();
}
AND(s1, s1, s2);
IFX(X_PEND) {
SB(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE();
}
ANDI(s1, s1, c&0xff);
IFX(X_PEND) {
SD(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
void emit_and16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4) {
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, d_tst16);
} else IFX(X_ALL) {
SET_DFNONE();
}
AND(s1, s1, s2); // res = s1 & s2
IFX(X_PEND) {
SH(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else IFX(X_ALL) {
SET_DFNONE();
}
AND(s1, s1, s2); // res = s1 & s2
if (!rex.w) ZEROUP(s1);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, rex.w?63:31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_and32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if(c>=-2048 && c<=2047) {
ANDI(s1, s1, c);
} else {
MOV64xw(s3, c);
AND(s1, s1, s3); // res = s1 & s2
}
if (!rex.w && c<0 && c>=-2048) ZEROUP(s1);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, rex.w?63:31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
CLEAR_FLAGS();
IFX(X_PEND) {
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE();
}
OR(s1, s1, s2);
IFX(X_PEND) {
SB(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or8c(dynarec_rv64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4)
{
MOV32w(s2, c&0xff);
emit_or8(dyn, ninst, s1, s2, s3, s4);
}
File diff suppressed because it is too large. Load diff
Loaded 100 of 975 files, more files were not shown because too many files have changed in this diff. Show more