Compare commits

..
495 Commits
Author SHA1 Message Date
ptitSeb e42001b2bc Bumped version to v0.2.6 2023-12-15 19:26:45 +01:00
Lily 9818f5b6a3 Fix raspi5 building (#1142)
* Update CMakeLists.txt

* Update COMPILE.md

* Update COMPILE.md
2023-12-15 17:04:37 +01:00
ptitSeb 46e40fbb65 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-15 16:50:26 +01:00
ptitSeb c141dbbd82 That debian changelog was outdated a bit 2023-12-15 16:50:19 +01:00
ptitSeb 9d5d08fa6c Update README.md 2023-12-15 16:40:07 +01:00
ptitSeb 7b9aa5b91a [ARM64_DYNAREC] Added one ore special case of device unaligned memory access handling 2023-12-15 16:35:48 +01:00
ptitSeb 8c75f7659f Added 1 more vulkan extension 2023-12-15 13:31:31 +01:00
ptitSeb d8c40c1662 Limit the number of CPU Core repported to 64 when running wine (or proton) 2023-12-15 13:21:58 +01:00
ptitSeb 7c0180c3b9 Added lldb option to JITGDB 2023-12-15 13:18:59 +01:00
liuli 211fee2e4e [ARM64_DYNAREC] fix emit_shld16(c) (#1141)
0x1a46b618: 66 44 0F A4 F8 5B  SHLD Ew, Gw, Ib
0x7f53749bdc: 7 emitted opcodes, inst=2, barrier=0 state=3/1(1), set=3F/1, use=0, need=0/1, sm=0/0, pred=1, last_ip=0x1a46b610
        53003d41        UXTH w1, wEAX
        53003f22        UXTH w2, wR15
        2a024021        ORR w1, w1, w2, LSL 16
        fff57c24        247CF5FF ???
        3300009a        BFXIL wFlags, w4, 0, 1
        13811421        ROR w1, w1, 5
        b3403c2a        BFXIL xRAX, x1, 0, 16
??? rases SIGILL...

Change-Id: I8f4afe3a814f8ee012bfc467261b32a9585d354b
2023-12-15 08:20:05 +01:00
Martin Sundhaug 9b7b91651d Raspberry Pi 5 support (#1138)
* Basic RPi5 support

* Split RPi5 in 16k page-size variant and not

* Update COMPILE.md

Add documentation about 16K page support
2023-12-14 21:34:20 +01:00
Lily 6ecfe5e141 [LIBRARIES] Fixed lowercase libXrandr lib call (#1137)
for some apps like haxe apps and probably wine
2023-12-14 16:21:24 +01:00
ptitSeb e11291538c Added 1 more vulkan extension 2023-12-13 20:34:49 +01:00
ptitSeb 5b90d59877 [DYNAREC] Fixed a bug with latest dynarec changes 2023-12-13 15:55:15 +01:00
ptitSeb 85df885b90 Added 1 vulkan extension (for modern nvidia cards) 2023-12-13 15:29:46 +01:00
ptitSeb 4dd5b67bbf [DYNAREC] Update USage with latest callret info 2023-12-13 13:06:56 +01:00
ptitSeb 88575ebc5d [DYNAREC] Made callret default, improved callret efficiency, and dynarec speed on larger blocks 2023-12-13 13:05:38 +01:00
liuli d8a19e9832 fix emit_shr16 (#1135)
For the SHR instruction, the OF flag is set to the most-significant bit of the original operand.
2023-12-13 08:11:15 +01:00
ptitSeb 99a938ef37 [DYNAREC] New attempt to make callret optim stable and usable 2023-12-12 12:42:22 +01:00
ptitSeb b07ea3460e Added 1 wrapped symbol to libcups 2023-12-11 17:07:26 +01:00
ptitSeb f557a86ecc [DYNAREC] Rollback most callret changes for now, they are not good enough 2023-12-11 16:39:20 +01:00
ptitSeb a5f8dd0788 [INTERPRETER] Added 67 0F 29 opcode 2023-12-11 16:19:24 +01:00
ptitSeb effbd82d00 [DYNAREC] Try to improve stability of BOX64_DYNAREC_CALLRET=1 (not really support on RV64 yet) 2023-12-11 16:00:24 +01:00
Yang Liu 9d72c9db1b [DYNAREC_RV64] Added more opcodes for flatout.exe (#1134)
* [DYNAREC_RV64] Added more DA opcodes

* [DYNAREC_RV64] Added 0F E9 PSUBSW opcode

* [DYNAREC_RV64] Added 0F D9 PSUBUSW opcode

* [DYNAREC_RV64] Added more DD opcode

* [DYNAREC_RV64] Added more DE opcodes
2023-12-10 18:33:46 +01:00
Yang Liu 486df332dd [DYNAREC_RV64] Added more opcodes for flatout.exe (#1133)
* [DYNAREC_RV64] Added 0F 6B PACKSSDW opcode

* [DYNAREC_RV64] Added more 0F opcodes

* [DYNAREC_RV64] Added 67 63 MOVSXD opcode
2023-12-10 08:16:24 +01:00
ptitSeb 8806c8ba8b Added lib64 to loaded libs in pressur-vessel emulation 2023-12-09 22:00:37 +01:00
Yang Liu 0df1e38ded [DYNAREC_RV64] Added more opcodes for flatout.exe (#1132)
* [DYNAREC_RV64] Fixed printer imm format typo

* [DYNAREC_RV64] Added more DC opcodes

* [DYNAREC_RV64] Added 9E SAHF opcode

* [DYNAREC_RV64] Added 66 A1 MOV opcode

* [DYNAREC_RV64] Added 0F 72 /6 PSLLD opcode

* [DYNAREC_RV64] Added 0F 72 /2 PSRLD opcode

* [DYNAREC_RV64] Added 0F F5 PMADDWD opcode

* [DYNAREC_RV64] Added 0F 72 /4 PSRAD opcode

* [DYNAREC_RV64] Added 0F FE PADDD opcode

* [DYNAREC_RV64] Added 0F 73 opcodes

* Fixed a bunch of mistakes

* Fixed printer

* Fix fix fix

* Fixed printer again

* Added 0F DB PAND opcode

* Fixed 0F 6E MOVD opcode
2023-12-09 21:37:11 +01:00
ptitSeb 7344689ba6 Small fixes to a few pulse wrapped symbol signature 2023-12-09 19:04:14 +01:00
ptitSeb 0ddbb80ee3 Fixed a signal handler (helps wine stuffs) 2023-12-08 17:49:24 +01:00
ptitSeb 48667b7dda Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-08 16:02:50 +01:00
ptitSeb 5708bc6b49 [ARM64_DYNAREC] Fixed 66 A4/AC opcodes 2023-12-08 16:02:42 +01:00
Yang Liu 9481df50b1 [DYNAREC_RV64] Added more and more opcodes for flatout.exe (#1128)
* [DYNAREC_RV64] Added F0 87 LOCK XCHG opcode

* [DYNAREC_RV64] Added 66 (F2/F3) A7 CMPSW opcode

* [DYNAREC_RV64] Added more DC opcodes

* [DYNAREC_RV64] Added more D8 opcodes
2023-12-08 15:59:52 +01:00
Yang Liu 840c454c1c [DYNAREC_RV64] Added more opcodes for flatout.exe (#1126)
* [DYNAREC_RV64] Added DC C8..CF FMUL opcodes

* [DYNAREC_RV64] Added D8 /7 FDIVR opcode

* [DYNAREC_RV64] Added A7 CMPSD opcode

* [DYNAREC_RV64] Added more DC opcodes
2023-12-08 12:28:11 +01:00
ptitSeb 77143dc8cf Added a couple of wrapped gtk3/gdk3 function (for #1120) 2023-12-08 12:14:57 +01:00
ptitSeb e3e77a8234 Refactored wrapping of libpulse 2023-12-08 12:06:46 +01:00
ptitSeb c3e84e6daa More wrapped gtk3 functions 2023-12-08 10:32:48 +01:00
ptitSeb c3f71c43e9 Small fixes to new pulse additions 2023-12-08 10:32:36 +01:00
ptitSeb df2ad6b1ca Added some new wrapped function to pulseaudio 2023-12-07 22:39:46 +01:00
ptitSeb 1d462b7558 Many new (and some fixed) gtk3/gdk3 functions (for Cemu) 2023-12-07 22:25:56 +01:00
ptitSeb 0a8c3ddd71 [DYNAREC] Small change to signal handling and unexpected segfault 2023-12-07 22:15:29 +01:00
ptitSeb 6ab86657ff Fixes DynaCall when a uc_link has been setup before 2023-12-07 22:14:14 +01:00
ptitSeb aed66d81b3 [TRACE] Better trace for some specific jump 2023-12-07 22:13:33 +01:00
ptitSeb e355280232 Fixed some Callback signature for wrapped libpng16 2023-12-07 22:12:51 +01:00
Yang Liu 92fff0c903 [DYNAREC_RV64] Added unaligned support for some LOCK opcodes (#1123) 2023-12-07 16:24:23 +01:00
ptitSeb 06319911d4 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-07 13:42:06 +01:00
ptitSeb 98959e902b Better way to handle multiple 3E/26 and F2/F3 prefixes ([DYNAREC] too) 2023-12-07 13:41:59 +01:00
Yang Liu 1e996410f8 [DYNAREC_RV64] Use a temporary solution to get things to work (#1122) 2023-12-07 12:07:24 +01:00
Lily 548a8ac87b [DOCS] Updated TERMUX Building (#1121) 2023-12-07 09:39:52 +01:00
ptitSeb 44494df9d3 Added 1 more gdk3 function 2023-12-06 21:35:20 +01:00
ptitSeb 60c698d381 Added one more wrapped function to gtk3 2023-12-06 19:59:50 +01:00
ptitSeb df3e1ace61 [GTK3] Wrapped GtkFixed 2023-12-06 17:39:19 +01:00
ptitSeb 6def5118bb Fixed a warning 2023-12-06 17:38:54 +01:00
ptitSeb 7d3224e37f Fix for non-dynarec build 2023-12-06 17:38:29 +01:00
ptitSeb 28a1581bb6 [TRACE] Better trace for an issue inside a wrapper 2023-12-06 17:16:51 +01:00
ptitSeb 66b8e697ea [ARM64_DYNAREC] Made some opcode truer to what they should on some edge cases 2023-12-06 17:16:05 +01:00
ptitSeb c15f1c917a [INTERPRETER] Made some opcode truer to what they should on some edge cases 2023-12-06 17:15:26 +01:00
ptitSeb 5b72444a6d Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-06 15:43:36 +01:00
ptitSeb 94a37bb60a Added wrapped gtk_scrollable_get_type (for #1077) 2023-12-06 15:43:13 +01:00
Yang Liu 935113a53d [DYNAREC_RV64] Added more dasm support for thead extensions (#1118)
* More work on the imm format

* Added some thead dasm support
2023-12-06 12:21:38 +01:00
ptitSeb d39ed15517 Added mbstowcs_chk wrapped function 2023-12-06 10:44:33 +01:00
ptitSeb 1dce5ef39f [INTERPRETER] Trigger a trap exception when CC is encountered 2023-12-05 21:36:11 +01:00
ptitSeb 2c69b57617 [32BITS] Forgot 66 54 opcode 2023-12-05 21:35:40 +01:00
ptitSeb 06961d3db5 [INTERPRETER] Refactored 0F A4/A5 opcodes for better readability 2023-12-05 21:22:13 +01:00
ptitSeb bdf2922f5d [INTERPRETER] Added addling to divide by 0 exception 2023-12-05 21:21:34 +01:00
ptitSeb f52d13f86a [INTERPRETER] Call opcode also need getAlternate redirection 2023-12-05 15:28:45 +01:00
ptitSeb 1b7b361b30 Show TLS resize warning only if old size is not 0 2023-12-05 13:20:54 +01:00
ptitSeb 151c40441f Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-05 12:06:33 +01:00
ptitSeb e26363dc0f [DYNAREC] Removed unused code in strongmem emulation 2023-12-05 12:06:23 +01:00
ptitSeb 5dbc8bf383 [RCFILE] Added profile for Mini Motor Racing X 2023-12-05 12:05:20 +01:00
Yang Liu 27e6cf0e31 [DYNAREC_RV64] Refine printer and add support for Zb* extensions (#1115) 2023-12-05 11:50:26 +01:00
Lily 24f241a1cd [DOCS] Updated termux building instructions (#1113)
* [DOCS] Add a warning for termux builders (mostly due #1112)

* [DOCS] Added chroot or proot compiling
2023-12-04 18:24:45 +01:00
Creeper-xie a8febc8638 Changes to be committed: (#1110)
modified:   src/main.c
2023-12-04 12:26:08 +01:00
Lily c04dfb82bb [DOCS] Added missing library for #1108 (#1109)
* [DOCS] Added missing library for #1108

* [DOCS] Typo
2023-12-04 10:31:01 +01:00
ptitSeb 08d189683d [RCFILE] Refined some existing profile and add a buch of new one 2023-12-03 18:26:40 +01:00
ptitSeb b67975a820 [ARM64_DYNAREC] More work on LOCK prefixed opcodes (Atomic still disabled) 2023-12-03 18:26:11 +01:00
ptitSeb fa175e7d24 [ARM64] Documented most HWCAP flags 2023-12-03 18:25:11 +01:00
Lily c2221e5304 [TERMUX] Fix debian packaging (#1107)
* [TERMUX] Fix debian packaging

* How did I forget this
2023-12-03 18:18:05 +01:00
Lily 104b5ec6d6 [TERMUX] Fix make install (#1106) 2023-12-03 16:24:46 +01:00
ptitSeb 59b4780afa [ARM64_DYNAREC] XLAT is 64bits by default on 64bits mode 2023-12-03 11:20:47 +01:00
ptitSeb 899405456b [ARM64_DYNAREC] Added optionnal memory barrier to MOVS/STOS 2023-12-02 22:20:02 +01:00
ptitSeb 40a81173f3 [ARM64_DYNAREC] Restaured Memory Barrier on LOCK operation, and disable the use of Atomic extension for now (there is an issue somewhere) 2023-12-02 21:44:35 +01:00
ptitSeb 19a6608619 Added some more wrapped function to libdrm 2023-12-02 17:51:19 +01:00
Lily 558a52909d [TERMUX] Added faked wrapped termux-exec and simplified output (#1103)
* [TERMUX] Added faked wrapped termux-exec

* Remove This

* [MAIN] Little simplified output in box64
2023-12-02 16:37:35 +01:00
ptitSeb 76eb623de6 [ARM64_DYNAREC] Generalized the use of Flag Manipulation Extension (if present) 2023-12-02 15:16:51 +01:00
ptitSeb 9e45c05383 [ARM64_DYNAREC] Fixed add8 OF flag emitter when Flag Manipulation Ext is supported 2023-12-02 14:14:07 +01:00
ptitSeb c0a1529468 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-01 17:46:58 +01:00
ptitSeb f4a7a88167 Fixed some potentials segfault with wine apps (maybe other too) 2023-12-01 17:41:41 +01:00
Lily 44ecb62ce7 [DOCS] Termux Compiling (#1102)
* [DOCS] Termux Compiling

* [DOCS] Not needed this

* [DOCS] Added this back

I don't think I had to delete that sorry
2023-12-01 17:23:54 +01:00
ptitSeb 37a976831d [TERMUX] Hopefully this will fix it 2023-12-01 17:09:35 +01:00
ptitSeb dd1aeb7265 [TERMUX] Added 2 faked wrapped libs (symbols should be in libc already) 2023-12-01 14:57:28 +01:00
ptitSeb 777c62c056 [MALLOCHOOK] Small improvments to mallochook_2 2023-12-01 14:43:36 +01:00
ptitSeb 717cddcc3d Improved bridge name storage/retreival 2023-12-01 14:43:12 +01:00
ptitSeb d6f7f620fc [VULKAN] Better wrapping of vkCreateInstance 2023-12-01 13:48:35 +01:00
ptitSeb 1bd928a766 [ANDROID] Try to fix libbsd issues 2023-12-01 10:45:59 +01:00
Julian Groß e493b0775d Fix spelling in README.md (#1101) 2023-12-01 10:35:17 +01:00
ptitSeb a966fa34ae [ANDROID] Small change that might help on android? 2023-11-30 21:52:21 +01:00
ptitSeb 8cd27fca4d Added support for wrapped libbsd (needed for latest libstdc++ lib) 2023-11-30 21:37:55 +01:00
ptitSeb 3676ca15c8 [RCFILE] Added 2 ew profiles 2023-11-30 18:05:49 +01:00
ptitSeb 616f7d3def Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-30 17:40:53 +01:00
ptitSeb ec4c6ec7a1 [X64LIBS] Updated libstdc++ and libgcc_s 2023-11-30 17:40:46 +01:00
ptitSeb 941fa6d520 [ARM64_DYNAREC] Potential fixes for some arm64 emitter macros 2023-11-30 17:40:25 +01:00
Yang Liu ce5e561cf3 [DYNAREC_RV64] Added more opcodes for flatout.exe (#1100)
* [DYNAREC_RV64] Added DA E9 FUCOMPP opcode

* [DYNAREC_RV64] Added 66 0F B6 MOVZX opcode

* [DYNAREC_RV64] Added 0F E7 MOVNTQ opcode

* [DYNAREC_RV64] Added D8 /3 FCOMP opcode

* [DYANREC_RV64] Added D8 /2 FCOM opcode

* typo

* x2 is for ed
2023-11-29 15:50:43 +01:00
ptitSeb 8e5a00db76 [ELFLOADER] Use a fallback if allocated memory not at expected address for elf with vaddr 2023-11-29 10:51:27 +01:00
Yang Liu faaeffbd38 [DYNAREC_RV64] Added more opcodes for flatout.exe (#1099)
* [DYNAREC_RV64] Added 66 AD LODSW opcode

* [DYNAREC_RV64] Added AD LODSD opcode

* [DYNAREC_RV64] Added AC LODSB opcode
2023-11-28 19:39:24 +01:00
Yang Liu a070066b71 [DYNAREC][INTERPRETER] Rework on 6C/6D/6E/6F opcodes (#1098) 2023-11-28 19:34:14 +01:00
ptitSeb 4e92269ae1 [ELFLOADER] Some fixes to localy openned libs when symbols might collide with main binary 2023-11-28 18:51:08 +01:00
ptitSeb 994971b08f [ARM64_DYNAREC] Fixes some rare-case of flags not correctly propagated on forward-jump 2023-11-28 18:50:22 +01:00
ptitSeb 019c0fabe1 Use non-Android version of functions_list.txt on the repo 2023-11-28 18:49:25 +01:00
ptitSeb 8e5346be21 [AMR64_DYNAREC] A few optimisations on some F0 BTx opcodes 2023-11-28 18:48:55 +01:00
ptitSeb 5f9d1f62cf [ARM64_DYNAREC] Fixed BFI emitter 2023-11-28 18:06:25 +01:00
ptitSeb d7bdf862bf Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-28 17:11:26 +01:00
ptitSeb 6470442e08 [ARM64_DYNAREC] Added 67 8A opcode 2023-11-28 17:11:23 +01:00
Yang Liu 6157f53aae [DYNAREC_RV64] Added missing fallbacks in x87 opcodes (#1096) 2023-11-28 15:22:46 +01:00
Creeper-xie 3f2d4a5274 [ANDROID]Fix Termux installation path (#1095) 2023-11-28 09:14:40 +01:00
Lily ae83035380 [ANDROID] Fix Clang Compiling (#1094) 2023-11-28 08:56:34 +01:00
Yang Liu 4566ff6d24 [WRAPPERS] Added fallback glXSwapIntervalEXT function if not present (#1092)
* [WRAPPERS] Added fallback glXSwapIntervalEXT function if not present

* Fix glXSwapIntervalEXT signature
2023-11-27 20:28:10 +01:00
Lily cbceca3b35 [ANDROID] Use TERMUX Define Instead ANDROID (#1093) 2023-11-27 17:38:02 +01:00
Lily 436de1c4f5 [ANDROID] Fix Compiling (#1091)
* [ANDROID] Added missing wrappedandroidshmem def headers

* [ANDROID] Fix Compiling

* [CMAKE] Typo

* [CMAKE] TERMUX Define
2023-11-27 16:26:36 +01:00
ptitSeb 737d4a5506 [TRACE] Fixes some crash when setting a trace in a lib load later 2023-11-27 12:57:36 +01:00
ptitSeb e5b16e9ef1 Added a few wrapped libxcb and xcbrandr function (for Recursed) 2023-11-27 10:30:04 +01:00
Yang Liu ea64f8453f [DYNAREC_RV64] Fixed BTS BTR BTC again (#1090) 2023-11-27 08:27:38 +01:00
kaixindeken 507eb1c786 [DOCS] Add mold usage to COMPILE.md (#1089)
* Add mold usage to COMPILE.md

* add Mold usage to COMPILE.md
2023-11-27 08:17:36 +01:00
Lily 04f8ab3871 [ANDROID] Added missing wrappedandroidshmem def headers (#1088) 2023-11-27 08:16:22 +01:00
Yang Liu 6b390caef5 [DYNAREC_RV64] Fixed emit_ror32 (#1087) 2023-11-26 21:51:27 +01:00
Yang Liu 8cee527ad0 [SIGNAL] Fixed copyUCTXreg2Emu (#1086) 2023-11-26 21:50:43 +01:00
Yang Liu bdf7d47742 [CMAKE] Add WITH_MOLD option (#1085)
GNU ld is extremely slow on RISC-V. mold is a much faster drop in
replacement, but it does not support `-Ttext-segment`, so add
an option to allow use it.
2023-11-26 16:47:29 +01:00
Yang Liu 6ad9435b4d [DYNAREC_RV64] Fixed BTS BTR BTC for zbs extension (#1084) 2023-11-26 16:46:21 +01:00
ptitSeb e853892282 [ARM64_DYNAREC] Fixed some typo if x87_forget helper 2023-11-24 18:27:03 +01:00
Yang Liu 4969b8c252 [DYNAREC_RV64] Added more opcode for minipad2.exe (#1081)
* [DYNAREC_RV64] Added D1 /2 RCL opcode

* [DYNAREC_RV64] Added DA /6 FIDIV opcode

* [DYNAREC_RV64] Added DF /6 FBSTP opcode
2023-11-24 18:24:02 +01:00
ptitSeb 239ef8951d Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-23 23:27:14 +01:00
Yang Liu 494510e2a8 [DYNAREC_RV64] Fixed FCOMP opcode (#1080) 2023-11-23 23:10:52 +01:00
ptitSeb 6dd899df22 [ANDROID] This should fix Android build, again and again 2023-11-23 21:45:11 +01:00
ptitSeb 7c4b97961f [ANDROID] This should fix Android build, again 2023-11-23 20:19:18 +01:00
ptitSeb 5c0a82913f [ANDROID] This should fix Android build 2023-11-23 19:42:02 +01:00
ptitSeb d7e64d3f11 [RV64] This should fix RISCV64 build 2023-11-23 19:39:27 +01:00
ptitSeb ea8d725546 [INTERPRETER] LES/LDS are valid only if next byte has high bit not set 2023-11-23 18:21:21 +01:00
ptitSeb cfffbcc5be Clear errno when pctrl_arch has no error 2023-11-23 18:20:40 +01:00
ptitSeb ba80b40e9e [ARM64_DYNAREC] Some fixes and improvment to various opcodes 2023-11-23 18:19:59 +01:00
ptitSeb b0fe7ecf8c Small improvement on signal handling 2023-11-23 18:19:21 +01:00
ptitSeb 84a6cfd558 Small change (mostly cosmetics) for some wrapped libc functions 2023-11-23 18:18:39 +01:00
ptitSeb efbf692cca Fixed some wrapped aio_ functions signature of librt 2023-11-23 18:18:06 +01:00
ptitSeb f81057416b [ARM64_DYNAREC] Fixed 0F 38 CD opcode 2023-11-22 19:22:28 +01:00
ptitSeb 168675d380 Some small changes to cpuid and exposed BMI1 2023-11-22 11:05:41 +01:00
ptitSeb 6327477695 Fixed cpu name gathering 2023-11-22 09:59:14 +01:00
ptitSeb 4c7ac85ae8 [ARM64_DYNAREC] Added full support for SHA cpu extension, using SHA1/SHA2 extension if present 2023-11-21 18:01:41 +01:00
ptitSeb afe6fbe3b3 Added full support for the SHA cpu extension 2023-11-21 18:00:58 +01:00
ptitSeb 39568bff2f [ARM64_DYNAREC] Added D7 XLAT opcode 2023-11-20 12:31:22 +01:00
ptitSeb d3b44f1c84 [INTERPRETER] Fixed some rare issue with XLAT ocpode 2023-11-20 12:31:04 +01:00
ptitSeb 8e74746573 Better way to handle syscall array with c99 sparse array init 2023-11-20 12:30:36 +01:00
Yang Liu bb54f234bd [RV64_DYNAREC] Added 64 8F POP & 67 66 89 MOV opcodes (for minipad2.exe) (#1076)
* [RV64_DYNAREC] Added 64 8F POP opcode

* [RV64_DYNAREC] Added 67 66 89 MOV opcode
2023-11-20 11:07:58 +01:00
Yang Liu 572a84c19b [RV64_DYNAREC] Added FD STD, fixed FC CLD and F3 A4 REP MOVSB (for minipad2) (#1075)
* [RV64_DYNAREC] Added FD STD opcode

* [RV64_DYNAREC] Fixed F3 A4 REP MOVSB opcode
2023-11-20 11:06:49 +01:00
Yang Liu 8fe46092c0 [RV64_DYNAREC] Fixed zbb andn optimization (#1074) 2023-11-20 10:55:37 +01:00
Raezroth 02bad8bcd1 Change blokc size to 64kb (#1071)
This gives a slight performance increase to applications like Steam on devices with only 4GB ram
2023-11-18 09:14:05 +01:00
ptitSeb 54be0c0dec Saved defered flag status when processing signal / foreign function 2023-11-17 16:21:38 +01:00
Joe Speed 20df2789b5 ADLINK with Ampere (#1069)
Updated credit to say ADLINK with Ampere. It was a mutual effort.
2023-11-17 07:55:07 +01:00
ptitSeb a8f902885d [ARM64_DYNAREC] Optimized 66 0F A5 ocode 2023-11-16 16:30:21 +01:00
ptitSeb c17e37b6e0 [ARM64_DYNAREC] Optimized 66 0F A4 opcode 2023-11-16 15:10:56 +01:00
ptitSeb df25986597 [ARM64_DYNAREC] Optimized 0F A5 opcode 2023-11-16 13:20:01 +01:00
ptitSeb dc06ca51a6 [ARM64_DYNAREC] Improved 0F A4 opcode 2023-11-16 12:35:41 +01:00
ptitSeb d76ea27c54 [INTERPRETER] Fixed OF flags for shld opcodes 2023-11-16 11:24:12 +01:00
ptitSeb 90b606584d [ARM64_DYNAREC] Optimized 66 AD opcode 2023-11-16 11:17:10 +01:00
ptitSeb 19a24c2171 [ARM64_DYNAREC] Optimized 66 AC opcode 2023-11-16 11:00:09 +01:00
ptitSeb f7d75ca641 [ARM64_DYNAREC] Fixed shrd 32/64bits opcodes 2023-11-16 10:42:40 +01:00
ptitSeb 5baa083386 [ARM64_DYNAREC] Reworked shrd 32/64bits opcodes 2023-11-16 10:04:22 +01:00
ptitSeb 6f7cb088b0 [INTERPRETER] Reworked shrd OF flag computation 2023-11-16 10:02:59 +01:00
ptitSeb 8901d1c37d [ARM64_DYNAREC] Optimized F6 /6 /7 opcodes 2023-11-15 18:16:16 +01:00
ptitSeb ec9dedd75c [ARM64_DYNAREC] Uses SKIPTEST instead of NOTEST for 66 F7 /7 opcode 2023-11-15 18:15:49 +01:00
ptitSeb 3edf7ee978 [ARM64_DYNAREC] Small optims on some shift opcodes 2023-11-15 18:00:27 +01:00
ptitSeb 9e35b66510 [ELFLOADER] Small improvment to have correct R/W attribute set on elf memory 2023-11-15 15:20:33 +01:00
ptitSeb 713458ac81 Added syscall 266 (for #1066) 2023-11-15 14:13:06 +01:00
ptitSeb 90e2f04c34 Workaround to handle SIGMAX properly (should help #1056) 2023-11-15 10:17:12 +01:00
ptitSeb 9896b02bd6 Added 64/65 [64/65] 90 opcode ([ARM64_DYNAREC] Too) 2023-11-15 09:43:09 +01:00
ptitSeb d39dd45ae4 [TRACE] Small improvment to trace handling 2023-11-15 09:38:45 +01:00
ptitSeb d50ae52176 Fixed no DYNAREC build 2023-11-13 19:20:58 +01:00
ptitSeb 784be47702 [DYNAREC] Small improved trace on UD / INT type of opcodes 2023-11-13 18:53:58 +01:00
ptitSeb 4f1fa811d0 [INTERPRETER] Small cosmetic changes to some F0 prefixed opcodes 2023-11-13 18:53:17 +01:00
ptitSeb 201cd065a9 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-13 18:48:40 +01:00
ptitSeb d832ec8ab2 Better dependancies for fontconfig lib (should help #1063) 2023-11-13 18:48:33 +01:00
Yang Liu 0c6c01d86a [RV64_DYNAREC] [32BITS] Added more opcodes for minipad2.exe (#1062)
* [RV64_DYNAREC] Added 67 0F B7 MOVXZ opcode

* [RV64_DYNAREC][32BITS] Added 66 A3 MOV opcode

* [RV64_DYNAREC] Added 67 C7 MOV opcode

* [RV64_DYNAREC] [32BITS] Added 64 FF /6 PUSH opcode
2023-11-13 17:54:56 +01:00
ptitSeb 13612d4024 Prefixed the address space message by BOX64, it's cleaner 2023-11-13 13:27:28 +01:00
ptitSeb 9daf8d6493 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-13 12:53:16 +01:00
ptitSeb e071406829 [ELFLOADER] Small changes on elf memory managment 2023-11-13 12:53:09 +01:00
Yang Liu ff85b03e3f [RV64_DYNAREC] Added a few opcodes for minipad2.exe (#1061)
* [RV64_DYNAREC] Added 64/65 8E MOV opcode

* [RV64_DYNAREC] Added 67 0F B6 MOVXZ opcode

* [RV64_DYNAREC][32BITS] Added 67_32.c
2023-11-13 12:10:00 +01:00
ptitSeb 590429d104 [ARM64_DYNAREC] Optimized 16bits ROL/ROR opcodes 2023-11-13 12:01:57 +01:00
ptitSeb eb0b5bd3f8 [ARM64_DYNAREC] Optimized 16bits SHL/SHR/SAR opcodes 2023-11-13 11:26:05 +01:00
ptitSeb b15a902f6d [DYNAREC] Don't consume X_PEND if opcode MAY emit flags 2023-11-13 11:18:21 +01:00
ptitSeb 4468d63145 [ARM64_DYNAREC] Added emit_sar8 helper 2023-11-13 10:50:12 +01:00
ptitSeb aba5c428e9 [ARM64_DYNAREC] Add optionnal handling of no flag update for shift CL opcodes 2023-11-13 10:30:13 +01:00
ptitSeb 62966c2f64 [ELFLOADER] Some more fixes to elf memory manager 2023-11-13 10:15:46 +01:00
Yang Liu dfd2a4ef0e [COSIM] Fix GO_TRACE (#1059)
x1 is the second parameter when calling native functions in GO_TRACE, so we cannot use it as a scratch register for xthead optimization.
2023-11-12 16:10:58 +01:00
ptitSeb 7fcc6e010c [ARM64_DYNAREC] Some fixes to shift opcodes 2023-11-12 15:50:11 +01:00
Yang Liu 5d2ae4aa1e [ELFLOADER] Fixed align issue (may help #1057) (#1058) 2023-11-12 15:21:37 +01:00
ptitSeb 4318172edd Merge branch 'main' of https://github.com/ptitSeb/box64 2023-11-12 14:59:35 +01:00
ptitSeb 9201559b1d Small improvment in global hacking 2023-11-12 14:59:29 +01:00
ptitSeb 40f90dd8f3 [TRACE] Small improvment for push rbp trace 2023-11-12 14:58:36 +01:00
ptitSeb 308cc81a27 [ARM64_DYNAREC] More fixes on 8bits shift emiters 2023-11-12 12:06:26 +01:00
ptitSeb 7e8f8cf415 [ARM64_DYNAREC] Fixed sar8c usage 2023-11-12 11:20:53 +01:00
ptitSeb 62634c6e1e [ARM64_DYNAREC] Some more work on shift opcodes 2023-11-12 08:43:41 +01:00
ptitSeb 70e4bd4174 [INTERPRETER] Small adjustment on shl flag computation 2023-11-11 18:09:08 +01:00
ptitSeb 7e0e618222 [ARM64_DYNAREC] Added emit_sar8c 2023-11-11 18:01:02 +01:00
ptitSeb cf6f013909 [ARM64_DYNAREC] Added emit_shr8c and some mare adjustement to 8bits shifts 2023-11-11 17:47:26 +01:00
ptitSeb 2ed8557ea6 [ARM64_DYNAREC] Added emit_shr8 helper 2023-11-11 17:27:06 +01:00
ptitSeb da3373ae42 [ARM64_DYNAREC] improved D2 /4/6 opcodes 2023-11-11 17:12:40 +01:00
ptitSeb cd0173dae4 [ARM64_DYNAREC] Fixed 64/65 8E opcode 2023-11-11 16:43:26 +01:00
ptitSeb 02e7400ef0 [ARM64_DYNAREC] Reorganised D0/D2 opcodes and Added shl8c emitter use 2023-11-11 15:55:14 +01:00
ptitSeb 6d6f29b6e1 [ARM64_DYNAREC] Added shl8c emitter 2023-11-11 15:40:35 +01:00
ptitSeb 0260b3177e [ARM64_DYNAREC] Fixed OF flags for 8 bit addition when using FLAGM extension 2023-11-11 15:18:40 +01:00
ptitSeb b82d9d15d4 [ARM64_DYNAREC] More fixing and improving on shifting opcodes 2023-11-10 17:24:17 +01:00
ptitSeb 3bc0495eb2 [ARM64_DYNAREC] Added 64/65 8E opcode 2023-11-10 17:22:23 +01:00
ptitSeb 50c0b60c10 Cleaned up syscall and signed register access 2023-11-10 15:29:45 +01:00
ptitSeb c2680fd0a7 Added BOX64_FUTEX_WAITV, on by default expect for BAD_SIGNAL build 2023-11-10 15:05:39 +01:00
ptitSeb 85c74c6bf8 Fixed some edge-case with some of the shift opcodes 2023-11-10 11:02:54 +01:00
ptitSeb 93f665eb9c [INTERPRETER] Fixed a typo in 66 0F 2C opcode 2023-11-10 10:56:17 +01:00
ptitSeb 113c879d7a Allow unaligned lock xchg with rex.w 2023-11-09 23:16:17 +01:00
ptitSeb f13ee05c6a [RV64_DYNAREC] Fixed a nasty typo in add8c emitter 2023-11-09 22:02:30 +01:00
ptitSeb 90fd2ff6a3 [ARM64_DYNAREC] More accurate 0F BA opcodes on 64bits without rex.w 2023-11-09 10:56:40 +01:00
ptitSeb 3a40b9f3a3 More accurate 0F BA opcodes on 64bits without rex.w 2023-11-09 10:56:20 +01:00
ptitSeb d8805b6af7 Added wrapped curl_multi_poll function (for #1053) 2023-11-09 10:15:55 +01:00
ptitSeb 675336dee5 Use non-atomic operation on XCHG when unaligned 2023-11-08 22:58:59 +01:00
ptitSeb 3cd4ed8e63 [ELFLOADER] Take wine prereserve memory into account 2023-11-08 16:02:46 +01:00
ptitSeb 9c7208b1fa [RCFILE] Added Witcher 3 profile 2023-11-08 13:49:34 +01:00
ptitSeb 48af038643 Added 2 wrapped function to libfontconfig (for aesprites) 2023-11-08 11:08:48 +01:00
ptitSeb ca8ad5e554 Cosmetic change 2023-11-07 20:36:05 +01:00
ptitSeb ab146f5d23 [TRACE] Better trace for unknown offset in native elf 2023-11-07 20:35:31 +01:00
ptitSeb 13fdd31c67 Added wrapped __isoc23_strtoul (for #1052) 2023-11-07 20:34:27 +01:00
ptitSeb 28f69afe96 Refined ptrace hacks around POKEUSER/PEEKUSER (should help Wine Unity3D games) 2023-11-07 15:33:23 +01:00
ptitSeb 2827e9e253 [RCFILE] Disable FASTNAN, FASTROUND and CALLRET when using BOX64_DYNAREC_TEST in rcfile like in command line 2023-11-07 13:19:28 +01:00
ptitSeb 46ba6fc561 [ELFLOADER] Use alternate simpler method for memory managment when pagesize is not 4K (should help #1051) 2023-11-07 12:04:58 +01:00
ptitSeb b3997769c0 [ELFLOADER] Another fix for elfloader memory managment on pagesize not 4K (might help #1051) 2023-11-07 10:04:05 +01:00
ptitSeb 410f58b7c7 [ELFLOADER] Another fix for elfloader memory managment (might help #1051) 2023-11-07 09:52:23 +01:00
ptitSeb fbecdad199 [ARM64_DYNAREC] Fixed 66 0F 3A 21 opcode 2023-11-06 20:05:23 +01:00
ptitSeb 9e6e3160ff [ARM64_DYNAREC] Added F0 0F BA opcodes 2023-11-06 18:32:40 +01:00
ptitSeb ca8abae240 [ARM64_DYNAREC] Added 66 0F 3A 40 opcode (with tests) 2023-11-06 15:36:43 +01:00
ptitSeb 6f0d095364 Fixed some issue with some SSE4.2 string compare oprations (should help #1013) 2023-11-05 15:04:35 +01:00
ptitSeb cc661c7549 Added BOX64_INPROCESSGPU setting (helps Heroic 2.10 at least) 2023-11-05 14:23:54 +01:00
ptitSeb 6982846f50 Improved BOX64_MALLOC_HACK=2 setting 2023-11-05 13:28:17 +01:00
ptitSeb eb6ec17504 Some fixes to the BOX64_TRACE_FILE setting 2023-11-05 13:27:52 +01:00
ptitSeb 8c68e1108b [RCFILE] Added more trace when applying BOX64_TRACE_FILE setting 2023-11-05 13:22:11 +01:00
ptitSeb 9077fd7b51 Fixed some functions signature on gobject2 2023-11-05 13:21:30 +01:00
ptitSeb f8b88418ed [DYNAREC] Cancel dynablock creation on SEGBUS too 2023-11-05 13:21:02 +01:00
ptitSeb 9c12016859 Better way to track mapped memory 2023-11-05 13:17:50 +01:00
ptitSeb e6943c8a9d [TRACE] Show mmap size in hex 2023-11-05 13:17:37 +01:00
ptitSeb c6483b5cf8 Added some more gtk3/gdk3 wrapped functions 2023-11-04 18:43:38 +01:00
ptitSeb 60925658bb [RV64_DYNAREC] Fix test failling 2023-11-04 17:17:27 +01:00
ptitSeb 5ef9ea35d6 [ARM64_DYNAREC] Added 66 0F F2 38 F1 opcode 2023-11-04 16:06:17 +01:00
ptitSeb 901bb48877 Added 66 0F F2 38 F1 opcode, and fixed all 66 0F F2/F3 xx opcodes (should help #1013) 2023-11-04 16:03:28 +01:00
ptitSeb 9fc37e6418 [TRACE] Fixed a warning 2023-11-04 15:57:49 +01:00
ptitSeb b34cce3f75 Removed fake wrapped libunwind and use real x86_64 one (help wine exeception handling) 2023-11-04 15:15:44 +01:00
ptitSeb 787646b3cc [TRACE] Improved trace 2023-11-04 15:14:25 +01:00
ptitSeb f0d5e9d01e [ELFLOADER] More changes to elf memory managment 2023-11-04 09:09:55 +01:00
ptitSeb be05309e51 [ELFLOADER] Some more regression fixes on elf memory managment (for #1013) 2023-11-03 12:11:11 +01:00
ptitSeb 52811e2ec2 [ELFLOADER] Fixed loading of elf with huge alignment 2023-11-01 20:17:37 +01:00
ptitSeb 107738f0f2 [ELFLOADER] Last improvment to elfloader memory managment, should be good now 2023-11-01 18:14:08 +01:00
ptitSeb 936fa20928 [ELFLOADER] Small improvment in new elfloader memory manager 2023-10-31 16:36:54 +01:00
ptitSeb 362a3fde10 [ELFLOADER] Changed how memory is managed in elfloader 2023-10-31 15:38:31 +01:00
ptitSeb 5c13f8f10a [ARM64_DYNAREC] Added 66 0F 3A 60..63 opcodes 2023-10-30 19:00:44 +01:00
ptitSeb 20cf990bf7 Fixed a comment for 66 0F 3A 62 opcode 2023-10-30 19:00:20 +01:00
ptitSeb 00744bc0e5 [ARM64_DYNAREC] Added support for F2 0F 38 F0/F1 CRC32 opcodes 2023-10-30 16:39:06 +01:00
ptitSeb cb2a623faa Added full SSE 4.2 support 2023-10-30 16:38:15 +01:00
ptitSeb 7e80e7ba86 [RCFILE] Better profile for Heroic 2023-10-30 16:37:11 +01:00
ptitSeb c50c985c85 [ADLINK] Removed BOX64_RESERVE_HIGH, should not be usefull with latest improvment to mmap64 2023-10-29 17:08:00 +01:00
ptitSeb c3ee794d40 Small change on cpuid stuffs 2023-10-29 13:39:14 +01:00
ptitSeb c8502fa20c This might help Steam on Wine 2023-10-29 13:38:19 +01:00
ptitSeb a31c037165 Better trace for mmap operations 2023-10-28 11:54:31 +02:00
ptitSeb c71035530a More small improvment to wrapped mmap64 2023-10-28 10:16:55 +02:00
ptitSeb acaf23fcb8 [ARM64_DYNAREC] Better fix for x87 i64 promotion to Double 2023-10-27 17:54:50 +02:00
ptitSeb 15860f3245 [ARM64_DYNAREC] Fixed and improved i64 x87 optimisation 2023-10-27 17:38:16 +02:00
ptitSeb 8a1e4cdf30 [ARM64_DYNAREC] Ported fprem/fprem1 from box86 (fix camera issues in FlatOut / FlatOut 2) 2023-10-27 17:07:04 +02:00
ptitSeb e574dca373 [ARM64_DYNAREC] Small optim on Load/Unload x87 cache 2023-10-27 17:07:04 +02:00
ptitSeb 32fc932813 [ARM64_DYNAREC] Added LDR/STR SIMD printer 2023-10-27 17:07:04 +02:00
ptitSeb 8a471d4d11 This makes steamwebhelper (much) more stable 2023-10-27 17:07:04 +02:00
wannacu 81ca3cd06e [WRAPPER] Fixed my_execl (#1044)
* [WRAPPER] Fixed my_execl

* [ARM64_DYNAREC] Added 66 0F 17 and Fixed 66 0F 21
2023-10-27 10:43:06 +02:00
ptitSeb f8d65a831e Another fix to wrapped mmap (should fix #1031, hopefully not creating more regression) 2023-10-27 09:57:34 +02:00
ptitSeb a1ac21af75 [32BITS] Added a few 66 opcodes ([ARM64_DYNAREC] too) 2023-10-26 21:57:37 +02:00
ptitSeb d3d5e4e7bc [ARM64_DYNAREC] Fixes STUR print opcode 2023-10-26 21:48:00 +02:00
ptitSeb c11cd7f4af [ARM64_DYNAREC] More special handling of SEGBUS on device memory (for NVidia drivers) 2023-10-26 21:47:12 +02:00
Yang Liu 840f2dced7 [DYNAREC_RV64] Fixed x87 FCOMI opcodes (#1041) 2023-10-26 20:49:17 +02:00
Yang Liu f81d6cf262 [DYNAREC_RV64] Fixed opcode FLD tbyte (for #871) (#1040) 2023-10-26 19:03:41 +02:00
ptitSeb fe378c938a Added 1 more Vulkan extension 2023-10-26 11:33:30 +02:00
Yang Liu d9a4fed2f8 [WRAPPER] Fixed my_mmap64 on MAP_FIXED handling, helps wine 8.18 (#1039) 2023-10-26 09:48:28 +02:00
ptitSeb 2a4fe80399 Fixed wrapping of vkCreateDebugUtilsMessengerEXT 2023-10-25 22:37:37 +02:00
ptitSeb 8999713301 [ARM64_DYNAREC] Small optimisation on 66 0F 57 opcode 2023-10-25 22:37:12 +02:00
ptitSeb 0900cc2f59 [DYNAREC] Various improvment to x87 code and segment handling 2023-10-25 15:09:17 +02:00
Yang Liu 87bf751b11 [INTERP] Fix fpu_round (#1030)
* [INTERP] Fix fpu_round

* Should be working this time

* Handling wrappedlibm

* Format

* Fix loongarch

* Make it optional

* Fix android build
2023-10-25 14:14:11 +02:00
ptitSeb 12c40a5b80 [32BITS] Added 66 06/07 and 66 1E/1F opcodes ([ARM64_DYNAREC] too) 2023-10-24 16:59:40 +02:00
ptitSeb e9a2f9ff62 Added wrapped OpenCL (mostly complete, for wine) 2023-10-24 14:51:02 +02:00
ptitSeb 1fc382f74f [COSIM] Show if it's x86 or x64 code on difference warning 2023-10-24 13:39:11 +02:00
ptitSeb 65fc95b614 [ARM64_DYNAREC] Fixed some cases of 0F D3 opcode 2023-10-23 18:32:02 +02:00
ptitSeb 4354e8c861 [RV64_DYNAREC] Fixed an issue with MMX Cache transformation 2023-10-23 18:30:57 +02:00
ptitSeb f1014bbbb6 [ARM64_DYNAREC] Fixed an issue with MMX Cache transformation 2023-10-23 18:30:05 +02:00
ptitSeb 72f232e776 [ARM64_DYNAREC][32BITS] Added 67 64 A3 opcode 2023-10-23 16:58:42 +02:00
ptitSeb b7ebc35193 [32BITS] Added 67 64 A3 opcode 2023-10-23 16:49:33 +02:00
ptitSeb 671328aaf6 [ARM64_DYNAREC][32BITS] Added 67 64 FF /6 opcode 2023-10-23 16:44:13 +02:00
ptitSeb c7bd174d7c [32BITS] Added 67 64 FF /6 opcode 2023-10-23 16:43:35 +02:00
ptitSeb 54f8d05105 [ARM64_DYNAREC] Some fixes to x87 opcodes (helps 32bits games on WoW64) 2023-10-23 16:12:41 +02:00
ptitSeb 892f102e4a Merge branch 'main' of https://github.com/ptitSeb/box64 2023-10-23 16:08:56 +02:00
ptitSeb f9b54dab31 Added a workaround for unalinged 32bits xchg 2023-10-23 16:07:40 +02:00
ptitSeb b3daf55ec2 [ARM64_DYNAREC] Fixed 0F F4 opcode (for #1036) 2023-10-22 19:30:58 +02:00
ptitSeb 391cef8549 [ARM64_DYNAREC] Fixed an issue with refect_cache_mmx helper function 2023-10-22 19:26:47 +02:00
ptitSeb 59b51cccfc [ARM64] More unaligned improvments 2023-10-22 11:35:24 +02:00
ptitSeb a83091bc3b [ARM64_DYNAREC] More handling of SIGBUS on device memory (for Doomvk 2016 on NVidia) 2023-10-21 11:32:35 +02:00
ptitSeb 7372540fce Added some workaround for program that POKEUSER/PEEKUSER some drX value and expect the value to stick (for #930) 2023-10-20 17:33:34 +02:00
liuli ceaa4bcac6 fix emit_sar32c() ZF maybe set error. (#1034)
* fix emit_sar32c() ZF maybe set error.
2023-10-20 09:41:47 +02:00
ptitSeb 862f31ef1c [ARM64_DYNAREC] ifdef'd the new HW_CAP tests, to be able to build on older system (for #1033) 2023-10-19 18:33:07 +02:00
ptitSeb 6643bf8695 [RCFILE] Added a profile for ToTheMoon 2023-10-19 09:57:16 +02:00
ptitSeb 3c0297fbdf [ARM64_DYNAREC] One more extension detected (not used yet) 2023-10-18 19:05:56 +02:00
ptitSeb 479cdb4218 [ARM64_DYNAREC] More ARM64 extensions detection 2023-10-18 18:50:51 +02:00
ptitSeb 6389ccee8d [RV64_DYNAREC] More fixes to the build 2023-10-18 18:31:29 +02:00
ptitSeb d478f98a4c Merge branch 'main' of https://github.com/ptitSeb/box64 2023-10-18 18:27:33 +02:00
ptitSeb dba0058763 [RV64_DYNAREC] Try to fix the build 2023-10-18 18:27:22 +02:00
ptitSeb 10b4782efb [ARM64_DYNAREC] Added a use of FLAGM extension in add8 emitter 2023-10-18 18:14:41 +02:00
ptitSeb f82d8d647a Fix build issues 2023-10-18 18:01:29 +02:00
ptitSeb 1698c822a5 [DOCS] Added some infor about SAVE_MEM build option 2023-10-18 17:49:46 +02:00
ptitSeb c9177ec259 [ARM64_DYNAREC] Preparing handling of FLAGM and FLAGM2 extensions 2023-10-18 17:46:31 +02:00
ptitSeb 0481589615 [ARM64_DYNAREC] More changes to Strong memory model emulation 2023-10-18 17:18:50 +02:00
ptitSeb 6ef2b22a3c [ARM64_DYNAREC] Added support for BOX4_DYNAREC_ALIGNED_ATOMICS 2023-10-17 18:25:16 +02:00
ptitSeb da19b2008a [ARM64_DYNAREC] More fixes to F0 0F C7 opcode with Atomics extension 2023-10-17 18:17:35 +02:00
ptitSeb 5493ab345a Some more rollback on tls destructor (more work needed on threads cleanup handling) 2023-10-17 17:29:32 +02:00
ptitSeb 2589f7db14 [ARM64_DYNAREC] More fixes for Atomics extension 2023-10-17 15:50:42 +02:00
ptitSeb 2e283b9d6d [ARM64_DYNAREC] More fixes for Atomic extension n LOCK DEC opcodes 2023-10-17 14:52:34 +02:00
ptitSeb 3cf27bb46e [ARM64_DYNAREC] Fixed F0 0F B0 opcopde with Atomics extension 2023-10-17 14:05:16 +02:00
ptitSeb f67d0709b7 [ARM64_DYNAREC] Added code generation for Atomic ARM v8.1 extension for most lock prefix 2023-10-16 20:20:26 +02:00
ptitSeb 2e66d603d3 [ARM64_DYNAREC] Cosmetic changes to SM macros 2023-10-16 20:19:15 +02:00
ptitSeb d51560211c Rollback to previous way of handling tls key destructors 2023-10-16 12:40:22 +02:00
Yang Liu 1b620b31d5 [COSIM] Fix x87 testing (#1029) 2023-10-15 15:16:31 +02:00
Yang Liu b82b730bf9 [CI] Do not regenerate functions list when running in CI (#1028) 2023-10-15 15:06:42 +02:00
Yang Liu 9191c993b1 [DYNAREC] Fix x87cache issues (#1025)
* [DYNAREC][WIP] Fix x87cache issues

Co-authored-by [email protected]

* Check x87cache is full before push, is it working?

* Fixed a typo

* Update dynarec_arm64_helper.h

* Review

* Update test25
2023-10-14 18:49:30 +02:00
ptitSeb 1a2245043d Update README.md 2023-10-14 08:41:42 +02:00
ptitSeb 2df7b9f302 Update README.md 2023-10-14 08:39:38 +02:00
ptitSeb 202cbc62db Update README.md 2023-10-14 08:39:05 +02:00
ptitSeb 9209e57bd9 Various changes on pthread cancel and tls destructor, should be easier to maintain 2023-10-13 21:23:42 +02:00
ptitSeb 1e1ad7694b No actual need for emu when calling my_mmap and my_munmap 2023-10-13 21:20:34 +02:00
ptitSeb b920d37f4e And this one can be const too 2023-10-13 21:19:31 +02:00
ptitSeb 3cb2bc31a8 This struct can be const 2023-10-13 21:18:46 +02:00
ptitSeb be24eec9d0 [TRACE] Better trace for mmap error 2023-10-13 21:18:10 +02:00
ptitSeb 60fed04cb7 Use BOX64_RESERVE_HIGHMEM by default on ADLINK profile 2023-10-13 21:17:13 +02:00
Yang Liu 6c956013a6 [WRAPPER] Added missing function signature (#1024) 2023-10-13 13:43:22 +02:00
Sophon 59289ae8f9 Add a new vulkan extension: VK_KHR_maintenance5 (#1021)
Signed-off-by: Xilin Wu <[email protected]>
2023-10-12 17:35:05 +02:00
ptitSeb 8310e9762b [ARM64_DYNAREC] Fixes some border case 32bits potential issue with GETEDz helper macro 2023-10-12 10:54:44 +02:00
ptitSeb 99483d2913 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-10-11 22:26:34 +02:00
ptitSeb b77303931e [ARM64_DYNAREC] Small improvement to certain cases for 66 0F 70 opcode 2023-10-11 22:26:24 +02:00
Yang Liu 5863dc6c7c [RV64_DYNAREC] Fix a build warning (#1020)
```
warning: implicit declaration of function 'rv64_lock_get_b'
```
2023-10-11 17:14:33 +02:00
ptitSeb 2a3923a173 A bit more changes to cpuid bits and cpu identifications 2023-10-11 16:04:33 +02:00
ptitSeb 3e882f3fd9 [ARM64_DYNAREC] Fixed 66 0F 38 20..25/30..35 to only read needed amount of data instead of 128bits (fixes some border case issue) 2023-10-11 16:03:50 +02:00
ptitSeb 0499c38466 Added BOX64_SDL2_JGUID, a workaround for game using old SDL_GetJoystickGUIDInfo funciton on recent wrapped SDL2 (for #1018) 2023-10-11 12:15:05 +02:00
ptitSeb 3e18d5ea57 [ARM64_DYNAREC] Better place for memory barrier on jmp_next and iret_to_epilog 2023-10-11 12:01:21 +02:00
ptitSeb ae75a502f0 Added a few libgomp wrapped function (for #1019) 2023-10-11 10:05:00 +02:00
ptitSeb 6ac200f597 Small change on cpuid feature flags for leaf 0x80000001 2023-10-11 10:04:30 +02:00
ptitSeb d7f635586d Updated wrapping of SDL_GetJoystickGUIDInfo with latest version (will help #1018, probably other SDL2 program too) 2023-10-10 17:47:37 +02:00
ptitSeb e27156be58 Fixed signature for functions in wrapped libatomic (will help #1013) 2023-10-10 17:11:30 +02:00
ptitSeb cafe638d5a [ARM64] Fixed a SIGBUS handling for VSTR128 not detected correctly 2023-10-10 15:45:04 +02:00
ptitSeb 4d996f6273 [ARM64_DYNAREC] Added 66 0F 3A 21 opcode 2023-10-10 15:19:41 +02:00
ptitSeb 86dfd2840f Added wrapped libayatana-appindicator3 and libdbusmenu-glib (for #1013) 2023-10-10 14:18:35 +02:00
ptitSeb dd9c3a53bf Do not try to get nearest function name if pointer is to small 2023-10-10 14:16:56 +02:00
ptitSeb 57959a1e93 Fixed a nasty issue with wrapping of libpcre 2023-10-10 14:15:40 +02:00
ptitSeb 6cfd7a988b [RV64_DYNAREC] Small fixed single rex.w AF opcode 2023-10-10 11:54:08 +02:00
ptitSeb ef95ff3342 [ARM64_DYNAREC] Fixed single AF opcode 2023-10-10 11:53:28 +02:00
ptitSeb 773c17496e Fixed processor/core count in cpuid and proc/cpuinfo 2023-10-10 10:21:32 +02:00
ptitSeb 6118dafd94 Improved gstreamer wrapping 2023-10-09 20:45:10 +02:00
ptitSeb 8befcbfacf [ARM64] Fix SIGBUS workaround for STUR 2023-10-09 20:38:19 +02:00
ptitSeb b9ea4983f9 [ARM64_DYNAREC] Fixed 66 99 opcode 2023-10-09 11:13:53 +02:00
ptitSeb d8765f86dd [ARM64_DYNAREC] Added 66 99 opcode 2023-10-09 11:06:15 +02:00
ptitSeb 3d9744362f [ARM64_DYNAREC] Fixed most DA opcodes 2023-10-08 21:41:40 +02:00
ptitSeb b2162ba263 Another small improvment for signal when running unreadable memory 2023-10-08 19:01:57 +02:00
ptitSeb aba40a9360 Improved a bit running unreadable memory 2023-10-08 18:48:50 +02:00
ptitSeb 1a9e076685 [ARM64] More handling of unaligned access 2023-10-08 17:41:56 +02:00
ptitSeb 2d9a3c643a Added a few wrapped symbols to libwayland-client 2023-10-08 14:21:39 +02:00
ptitSeb 85d2a06f6f [ARM64] Some handling of unaligned write to device memory 2023-10-08 11:55:18 +02:00
ptitSeb 8a5719afe1 Added __isoc99_vswscanf wrapped function (for #1015) 2023-10-08 09:51:21 +02:00
André Zwing 2ec01c9b60 [ARM64_DYNAREC] Take dynarec64_DA into account (#1014) 2023-10-07 22:48:21 +02:00
ptitSeb 5fa02ef1e3 Improved cpu speed detection 2023-10-07 11:57:32 +02:00
ptitSeb cfe8f8f6e1 Added wrapped liblcms2 and libevent-2.1 used by TeamSpeak3 linux client (for #986) 2023-10-07 11:17:18 +02:00
ptitSeb 9d63f0ce9a Added wrapped threads_add_timeout_full to gdk2 and gdk3 (for #997) 2023-10-07 10:39:53 +02:00
ptitSeb afd8d305f3 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-10-07 10:25:56 +02:00
Sophon 83738a606d Added Snapdragon 8 Gen 2 profile (#1009)
Compilation works with GCC 12.1.0

Tested on AYN Odin 2 with mainline Linux 6.6.0-rc3-next-20230929

Signed-off-by: Xilin Wu <[email protected]>
2023-10-07 10:25:24 +02:00
Sophon 072311b256 Added Snapdragon 8 Gen 2 profile (#1009)
Compilation works with GCC 12.1.0

Tested on AYN Odin 2 with mainline Linux 6.6.0-rc3-next-20230929

Signed-off-by: Xilin Wu <[email protected]>
2023-10-05 08:09:17 +02:00
SeeSchloß c904a9af1c Add c32rtomb wrapped function for dfhack (fixes console, part of issue #939) (#1008) 2023-10-03 09:48:12 +02:00
KreitinnSoftware 7c042a566a [ANDROID] Fix Most Library Names (#1005)
* Add __sF, __assert2 Symbol and set PThread Symbols on libc

* [ANDROID] Fix Most Library Names
2023-10-02 18:55:14 +02:00
KreitinnSoftware 57b762eb29 Add __sF, __assert2 Symbol and set PThread Symbols on libc (#1004)
* Add __sF, __assert2 Symbol and set PThread Symbols on libc

* [ANDROID] Fix Most Library Names
2023-10-02 18:26:20 +02:00
SeeSchloß a4eb0cbd74 Add mbrtoc32 wrapped function for dfhack (fixes second part of issue #939) (#1003) 2023-10-02 08:15:14 +02:00
KreitinnSoftware e558912a36 [ANDROID] Remove PreInit Array Warning and Fix libdl name (#1001) 2023-10-01 19:25:03 +02:00
ptitSeb 00ea757e77 Use gold on ADLINK profile 2023-10-01 15:12:16 +02:00
ptitSeb 2f04934471 Cosmetic change 2023-10-01 15:08:19 +02:00
ptitSeb 1e6f492852 This steam-runtime-launcher-service process never exit and seems to be skipable when using box, so skip it 2023-10-01 15:07:56 +02:00
ptitSeb 582c7c762a [DYNAREC] Introduce a config that should save a bit of mmemory at runtime (ON for PIs and RK3399 only for now) 2023-10-01 15:03:44 +02:00
ptitSeb 3ad64aa6a4 [RV64_DYNAREC] Fix build 2023-10-01 08:53:52 +02:00
ptitSeb 1c680d3aaa [DYNAREC] Changed lock mecanism for memory protection 2023-10-01 08:38:57 +02:00
ptitSeb eed9ea35f9 [ANDROID] Fix build 2023-09-30 20:33:31 +02:00
ptitSeb a724725fdf [ANDROID] No mallochack on Android 2023-09-30 20:23:37 +02:00
ptitSeb 84a5929645 Added a few more wrapped function to libgssapi_krb5 (for wine) 2023-09-30 15:40:01 +02:00
ptitSeb cb85a8f5cb Use libdl whenever libc is used (for #984) 2023-09-28 18:53:01 +02:00
Yang Liu 23dd80ffd8 [RV64_DYNAREC] Added more support for XTheadMemPair extension (#995)
* Reformat

* [RV64_DYNAREC] Added more support for XTheadMemPair extension

* Align 'em up

* Fix spec typos
2023-09-27 10:33:25 +02:00
liuli 16393c499b Update dynarec_arm64_emit_math.c (#994)
UpdateFlags() using op1
2023-09-27 10:01:58 +02:00
Yang Liu 684160f178 [RV64_DYNAREC] Added more support for XTheadBs extension (#993)
* [RV64_DYNAREC] Added more support for XTheadBs extension

* Revert: FF0 is not CLZ
2023-09-26 21:45:33 +02:00
ptitSeb e3f193b382 Added a few missing GLES wrapped function to libGL 2023-09-26 21:33:19 +02:00
ptitSeb 37d9c4b480 Added 66 0F 3A 0D opcode ([ARM64_DYNAREC] Too) 2023-09-26 21:32:49 +02:00
ptitSeb b6633aa306 Ignore 2E CS prefix on LOCK opcodes (helps StardewValley on Ubuntu 20.04/AmpereAltra machine) 2023-09-26 02:28:51 +08:00
ptitSeb c8651fb1f3 Added wrapping of libicuuc66 and libicui18n66 (for when using ubuntu 20.04) 2023-09-26 02:23:45 +08:00
ptitSeb 83a5b0d223 Added missing updated on localized readme 2023-09-25 19:44:17 +08:00
ptitSeb d95ef48d22 Added ADLink AmpereAltra profile 2023-09-25 19:33:33 +08:00
SeeSchloß b59ce0b95b Add SDL_RenderWindowToLogical and SDL_SetSurfaceColorMod wrapped functions for #939 (#991) 2023-09-25 11:09:19 +02:00
Yang Liu c00cd1d627 [RV64_DYNAREC] Added more support for XTheadBb extension (#989)
* Reformat

* Use TH_FF0 for LZCNT

* Reformat

* Reformat

* Added MOVBE tests

* Reformat

* Added a new REVxw macro

* Refined test24

* Refined test24

* Fix bugs

* [INTERPRETER] Fixed MOVBE

* [DYNAREC_ARM64] Fix MOVBE
2023-09-24 22:20:21 +02:00
Yang Liu ab65641eae [CI] Run tests w/ and w/o DynaRec (#988) 2023-09-24 17:37:16 +02:00
Yang Liu 6c0781c157 [CI] Use qemu snapshots from archlinux archive (#987) 2023-09-24 08:54:59 +01:00
ptitSeb bf6c6498aa [DYNAREC] Use interpretor code for FPREM/FPREM1 instead of simplified version 2023-09-23 17:58:44 +02:00
Jai A P 4b6cec8452 Update README.md (#983) 2023-09-17 18:53:30 +01:00
ptitSeb b77da2635b Added 64/65 8E opcode (for #982) 2023-09-17 12:04:47 +02:00
ptitSeb 033ddf8cc8 Better handling of tls for elf loaded with dlopen (should fix a bunch of stuff) 2023-09-16 18:50:29 +02:00
ptitSeb 5b3c67c692 Small changes to wrapped libdl on last_error handling 2023-09-16 18:49:28 +02:00
ptitSeb 86aa8b8b2e Small change to fileno wrapped signature 2023-09-16 16:56:07 +02:00
ptitSeb 0329bbc55e [ARM64_DYNAREC] Added 64/65 01/21/29/31 opcodes 2023-09-16 16:55:29 +02:00
ptitSeb c9549e8ab6 [ARM64_DYNAREC] Added (F2/F3) AF opcode (for #975) 2023-09-16 13:57:08 +02:00
ptitSeb 5903f02086 Improvd steam/proton handling, and gstreamer initialization and a large bunch of gtk improvments 2023-09-16 13:49:39 +02:00
Yang Liu 28dcd34624 [RV64_DYNAREC] Added some support for XTheadBb extension (#977)
* [RV64_DYNAREC] Added XTheadBb instructions

* SRRIxw

* GETGB
2023-09-13 15:51:21 +02:00
Yang Liu 13b7398b3a [CI] Upgrade QEMU to 8.1.0 (#973) 2023-09-12 18:21:35 +02:00
Yang Liu 50cf9c0e67 [CI] Test RISCV with bit-manipulation extensions on (#972)
* [CI] Test RISCV with bit-manipulation extensions on

xthead extensions require qemu 8.1.0, therefore not available in CI

* fix ADDSL
2023-09-12 16:08:12 +02:00
ptitSeb 71ad38d742 Merge pull request #970 from ksco/xtheadba
[DYNAREC_RV64] Added support for xtheadba
2023-09-12 11:22:55 +02:00
Yang Liu c086a1ff24 Fixed CI and simplified 2023-09-12 08:54:18 +00:00
Yang Liu 75958f1f31 Use macro 2023-09-12 08:27:23 +00:00
Yang Liu be34e0221d [DYNAREC_RV64] Added support for xtheadba 2023-09-12 07:46:13 +00:00
ptitSeb 0913c94e46 Merge pull request #969 from ksco/thead
[RV64_DYNAREC] Added thead vendor extension detection
2023-09-11 13:17:01 +02:00
Yang Liu 910a0ef8e1 Fixed typo 2023-09-11 11:06:38 +00:00
Yang Liu 7b0e8b47a2 Try to fix memory instructions detection 2023-09-11 11:00:21 +00:00
Yang Liu 14e799ebe5 [RV64_DYNAREC] Added thead vendor extension detection 2023-09-11 10:16:40 +00:00
ptitSeb 5e52c735a6 Merge pull request #968 from shenmo7192/patch-1
Update README_CN.md
2023-09-11 10:33:53 +02:00
ptitSebandYang Liu 9eb5883f77 Update README_CN.md
Co-authored-by: Yang Liu <[email protected]>
2023-09-11 10:33:46 +02:00
ptitSebandYang Liu 7a783b867b Update README_CN.md
Co-authored-by: Yang Liu <[email protected]>
2023-09-11 10:33:40 +02:00
shenmo 83ec0bd751 fix: Fix wrong type set in Chinese
Personally I think it's OK for not being strictly obeyed as the view is not so bad~ ´༥`

Anyway, fixed
2023-09-11 16:16:19 +08:00
shenmo aacff4a9b6 Update README_CN.md 2023-09-11 16:07:06 +08:00
ptitSeb 7ab8ad8b10 Wrapped some more libdrm and libgbm functions 2023-09-10 12:16:57 +02:00
ptitSeb cf7ac30215 Added syscall 284 (for #965) 2023-09-09 21:25:06 +02:00
ptitSeb 547944ac88 [STEAM] Changed behaviour of simulated pressure-vessel 2023-09-09 19:06:03 +02:00
ptitSeb 99d7b46e48 Removed some debug leftover in libgstreamer 2023-09-09 18:49:15 +02:00
ptitSeb eca872c04d Added some more wrapped functions 2023-09-09 17:38:01 +02:00
ptitSeb 8947b735f9 Go back to use mmap for memory allocation, as some OS restric malloc'd memory to not being runnable (might help #939, #935 and #487, probably other) 2023-09-09 17:35:17 +02:00
ptitSeb e245dee90b [DYNAREC] Small improvment on multi-thread reliance for the jumptable 2023-09-09 16:26:50 +02:00
ptitSeb edba2a2e96 Improved default box64rc 2023-09-09 16:21:16 +02:00
ptitSeb 81e8ce4952 Added x86_64 version of libssl.so.1.1 and libcrypto.so.1.1 for conveniance 2023-09-09 15:17:48 +02:00
ptitSeb afd5d3a1e3 Added some __isoc23_XXX wrapped function as synonym to libc (for #943) 2023-09-09 14:41:23 +02:00
ptitSeb d1e8bcd7a5 Added syscall 282 (for #965) 2023-09-09 14:20:09 +02:00
ptitSeb 79c71bf5c1 [32BITS] Added D4 & D5 opcodes 2023-09-07 14:17:25 +02:00
ptitSeb 2c7daa388b Merge pull request #964 from wannacu/main
[ARM64_DYNAREC] Added some opcodes
2023-09-04 11:16:04 +02:00
wannacu cc351402a1 [ARM64_DYNAREC] Fixed (66) 0F 70 opcodes 2023-09-04 16:43:28 +08:00
wannacu 90a7602e5a [ARM64_DYNAREC] Added 66 0F 7D/D0 opcodes 2023-09-04 16:43:28 +08:00
wannacu 1e0b8e443b [ARM64_DYNAREC] Added 0F 1C/1D/1E opcodes 2023-09-04 16:43:28 +08:00
ptitSeb 96025a1977 [ARM64_DYNAREC] Fixed 0F 38 00 PSHUFB opcode (thanks @wannacu for the hint) 2023-09-04 09:29:55 +02:00
ptitSeb 6e1bcc03a6 Added 1 vk extension (for #963) 2023-09-03 14:05:17 +02:00
ptitSeb 728ec2e769 Added 1 wrapped function (for #229) 2023-09-02 16:58:35 +02:00
ptitSeb 25a064f3a8 Merge pull request #962 from ptitSeb/android
[ANDROID] Try to create an Android build, porting box86 Android build
2023-09-02 16:35:07 +02:00
ptitSeb 8a25b91ad2 [ANDROID] typo, typo, and typo 2023-09-02 16:22:58 +02:00
ptitSeb cacd7dd2eb [ANDROID] Don't run ctest on Android build 2023-09-02 15:57:56 +02:00
ptitSeb acf6825603 [ANDROID] fixing fix fix... 2023-09-02 15:43:18 +02:00
ptitSeb 1b8c48ee1d [ANDROID] f..ing fix, again 2023-09-02 15:34:42 +02:00
ptitSeb 6a6b75b7b4 [ANDROID] And yet again another build fix, some many missing declaration compared to linux 2023-09-02 15:27:08 +02:00
ptitSeb 491cbda0d3 [ANDROID] And yet again another build fix, slowly but surely loosing patience 2023-09-02 15:17:32 +02:00
ptitSeb aadd5e8786 Removed unused include in bridge.c 2023-09-02 15:11:16 +02:00
ptitSeb e155d43c4b [ANDROID] And again another attempt to fix the build 2023-09-02 15:04:00 +02:00
ptitSeb 683f5d64b9 [ANDROID] Oh, again another attempt to fix the build (and still my fault, typo, typo, typo) 2023-09-02 14:56:56 +02:00
ptitSeb d26469c6a4 [ANDROID] Oh, another attempt to fix the build (ok, my fault this time, fine) 2023-09-02 14:40:55 +02:00
ptitSeb 57d497c801 [ANDROID] And yet another attempt to fix the build, patience limit almost reached 2023-09-02 14:34:46 +02:00
ptitSeb eac105fe9e [ANDROID] And another attempt to fix the build, testing my patience it seems 2023-09-02 14:23:22 +02:00
ptitSeb 61c2a3ed7a [ANDOIRD] Yet another attempt to fix the build 2023-09-02 14:19:14 +02:00
ptitSeb 46031c008e [ANDOIRD] Another attempt to fix the build 2023-09-02 14:10:23 +02:00
ptitSeb d2aadd66bf [ANDROID] Try to fix build 2023-09-02 13:50:03 +02:00
ptitSeb 646770ff68 [ANDROID] More change to android/dynarec build 2023-09-02 12:45:59 +02:00
ptitSeb 90ad165359 [ANDROID] This should fix Dynarec build on Android 2023-09-02 12:21:39 +02:00
ptitSeb 30eae8f513 [ANDROID] Fix name of android compiler 2023-09-02 12:06:52 +02:00
ptitSeb 2d37575f3d [ANDROID] Try to create an Android build, porting box86 Android build 2023-09-02 11:56:20 +02:00
ptitSeb eb1e607b93 Correctly handle TF flags, with [DYNAREC] falling back to Interpretor when TF is on (should help #914) 2023-09-02 09:31:38 +02:00
ptitSeb 9d16aec99a Update USAGE.md on rcfiles 2023-08-31 20:30:40 +02:00
ptitSeb a95099696f Merge pull request #959 from wannacu/main
[ARM64_DYNAREC] Added some opcodes
2023-08-31 09:33:51 +02:00
wannacu be4791f826 [ARM64_DYNAREC] Added 0F 38 08/09/0A opcode 2023-08-31 13:41:36 +08:00
wannacu 41d5fa16a7 [ARM64_DYNAREC] Added 66 0F 38 37 opcode 2023-08-31 13:19:17 +08:00
wannacu d3635126b7 [ARM64_DYNAREC] Added 0F 38 01/02/03/05/06/07 opcodes 2023-08-31 13:18:36 +08:00
ptitSeb 7cba83231a Added 64 0F B7 opcode (for #958) 2023-08-30 21:53:29 +02:00
ptitSeb 7f4145d67f Added wrapping of libformw.so.6 (for #956) 2023-08-28 19:02:34 +02:00
ptitSeb 103c804c8e [ELFLOADER] This was missing from previous elfloader work 2023-08-27 17:16:22 +02:00
ptitSeb c7db4470e4 [ELFLOADER] Better handling of dlopen library without RTLD_GLOBAL flags 2023-08-27 11:38:00 +02:00
ptitSeb 2e55fc8c32 [ARM64_DYNAREC] Fixed some issue with some opcode handling 8bits values (fixed gogdl from Heroic issue, probably other program too) 2023-08-27 11:37:15 +02:00
ptitSeb 5d921acd7d [DYNAREC] Do not use dynarec in signal handling unless CUSTOM_MALLOC for Dynarec is defined (so off for now, to avoid random lockup on libcef and other complex programs) 2023-08-27 11:35:04 +02:00
ptitSeb aa051b662e Fixed detection and loading of program linked with glibc 2.34+ 2023-08-26 17:08:27 +02:00
ptitSeb 5fabd602ae Fixed signature of SDL1 AudioCallback (for #952) 2023-08-26 16:50:53 +02:00
ptitSeb 0393e15843 Merge pull request #951 from wannacu/main
Added (66) 0F 2A/2C/2D opcodes
2023-08-25 13:22:04 +02:00
wannacu 539fb8e214 [RV64_DYNAREC] Added (66) 0F 2A/2C/2D opcodes 2023-08-25 18:07:21 +08:00
wannacu 7b1fa28b85 [ARM64_DYNAREC] Added (66) 0F 2A/2C/2D opcodes 2023-08-25 16:43:11 +08:00
ptitSeb 30475f0eda Merge pull request #948 from Rhizomatica/main
Allow running at NULL, and trigger a segfault (backport from box86 5cdc1b9fa2238938e49176fcd937a1294c55a03d )
2023-08-23 12:09:57 +02:00
Rafael Diniz 19771b307c Allow running at NULL, and trigger a segfault (backport from box86 5cdc1b9fa2238938e49176fcd937a1294c55a03d 2023-08-22 23:37:26 +01:00
ptitSeb 7a992837a1 Merge pull request #941 from wannacu/main
[ARM64_DYNAREC] Added 0F F1/F3/F7 opcodes
2023-08-21 08:35:24 +02:00
ptitSeb 33d8fa7b23 Merge pull request #942 from liuli0217/main
Update my_posix_spawnp()
2023-08-21 08:32:05 +02:00
liuli 62d55296c0 Update my_posix_spawnp() 2023-08-21 05:07:43 +00:00
wannacu cd0aad731a [ARM64_DYNAREC] Added 0F F1/F3/F7 opcodes 2023-08-21 11:47:09 +08:00
ptitSeb 8e7afcc5fb Fixed potential issue with previous commit 2023-08-20 15:03:36 +02:00
ptitSeb a62618ee47 Cached Emulated symboled are fetched faster now 2023-08-20 13:53:26 +02:00
ptitSeb 4e9b7f27a9 Refactored how wrapped symbols are fetch and stored 2023-08-20 13:29:11 +02:00
ptitSeb 7d7ea4405c Start of a new dev. cycle 2023-08-20 13:23:57 +02:00
447 changed files with 32302 additions and 8737 deletions

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
---
BasedOnStyle: WebKit
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
ColumnLimit: 0
IndentWidth: 4
SortIncludes: false
MaxEmptyLinesToKeep: 2
IndentCaseLabels: true
AlignConsecutiveMacros: true
---
+3
View File
@@ -17,7 +17,10 @@ on:
- RK3399
- RK3588
- RPI4ARM64
- RPI5ARM64
- SD845
- SD888
- ADLINK
- TEGRAX1
- ARM64
build_type:
+28 -10
View File
@@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, ARM64]
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RPI5ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, SD888, ADLINK, ARM64, ANDROID]
type: [Release, Trace]
os: [ubuntu-latest]
include:
@@ -47,9 +47,17 @@ jobs:
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' && ${{ matrix.platform }} != 'RISCV' ]]; then
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-aarch64-linux-gnu cmake make python3
sudo apt-get -y install git cmake make python3
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX64_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV
echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DNOLOADADDR=1" >> $GITHUB_ENV
else
sudo apt-get -y install git gcc-aarch64-linux-gnu
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
fi
else
if [[ ${{ matrix.platform }} == 'X64' ]]; then
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
@@ -88,22 +96,32 @@ jobs:
${{ env.BOX64_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON\
-DCI=${{ matrix.platform != 'ANDROID' }}
make -j$(nproc) VERBOSE=1
- name: "Test Box64"
if: ${{ matrix.platform != 'TEGRAX1' }}
run: |
if [[ ${{ matrix.platform }} != 'X64' ]]; then
sudo apt-get -y install qemu-user
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then
mkdir qemu8.1.0
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-8.1.0-2-x86_64.pkg.tar.zst | tar -I zstd -C qemu8.1.0 -xf -
sudo cp qemu8.1.0/usr/bin/* /usr/bin/
fi
cd build
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
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,zba=true,zbb=true,zbc=true,zbs=true ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,xtheadba=true,xtheadba=true,xtheadbb=true,xtheadbs=true,xtheadcondmov=true,xtheadmemidx=true,xtheadmempair=true,xtheadfmemidx=true,xtheadmac=true,xtheadfmv=true ctest -j$(nproc) --rerun-failed --output-on-failure
elif [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then # AArch64
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
true
else
BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
ctest -j$(nproc) --rerun-failed --output-on-failure
fi
+218 -39
View File
@@ -7,6 +7,8 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RPI5ARM64 "Set to ON if targeting an RaspberryPi5 device with multiarch arm64 and armhf" ${RPI5ARM64})
option(RPI5ARM64PS16K "Set to ON if targeting an RaspberryPi5 device with multiarch arm64, armhf, and 16k pages" ${RPI5ARM64PS16K})
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(RK3588 "Set to ON if targeting an Rockchip RK3588(S) based device" ${RK3588})
@@ -15,19 +17,30 @@ option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(SD8G2 "Set to ON if targeting a Snapragon 8 Gen 2 based device" ${SD8G2})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
option(RV64 "Set to ON if targeting an RISC-V RV64GC based device" ${RV64})
option(PPC64LE "Set to ON if targeting an PowerPC 64 LE based device" ${PPC64LE})
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(TERMUX "Set to ON if targeting an Android device with Termux" ${TERMUX})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(SAVE_MEM "Set to ON to build dynarec with some slower memory saving optimisations" ${SAVE_MEM})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box64" OFF)
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
option(CI "Set to ON if running in CI" ${CI})
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
if(TERMUX)
set(TERMUX_PATH "/data/data/com.termux/files")
set(ANDROID ON CACHE BOOL "")
endif()
if(LARCH64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
@@ -48,19 +61,25 @@ if(PPC64LE)
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 SD888 OR LX2160A OR M1 OR ARM64)
if(RPI5ARM64PS16K)
set(RPI5ARM64 ON CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR M1 OR ARM64 OR ADLINK)
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 SD888 OR LX2160A)
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR ADLINK)
set(PAGE16K OFF CACHE BOOL "")
endif()
if(RK3399 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64)
set(SAVE_MEM ON CACHE BOOL "")
endif()
if(RK3588)
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
if(M1 OR LARCH64)
if(M1 OR LARCH64 OR RPI5ARM64PS16K)
set(PAGE16K ON CACHE BOOL "")
endif()
if(SW64)
@@ -68,6 +87,10 @@ if(SW64)
set(NOALIGN OFF CACHE BOOL "")
set(PAGE8K ON CACHE BOOL "")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
@@ -117,6 +140,11 @@ elseif(RPI4ARM64)
add_definitions(-DRPI4ARM64)
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
elseif(RPI5ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI5ARM64)
add_definitions(-pipe -march=armv8.2-a+crc+crypto+fp16+rcpc+dotprod -mtune=cortex-a76)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+crc+crypto+fp16+rcpc+dotprod -mtune=cortex-a76")
elseif(RK3326)
add_definitions(-DRK3326)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
@@ -148,8 +176,16 @@ elseif(SD845)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
elseif(SD888)
add_definitions(-DSD888)
add_definitions(-pipe -march=armv8.4-a+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.4-a+crypto")
add_definitions(-pipe -march=armv8.4-a+simd+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.4-a+simd+crypto")
elseif(SD8G2)
add_definitions(-DSD8G2)
add_definitions(-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2)
set(CMAKE_ASM_FLAGS "-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2")
elseif(ADLINK)
add_definitions(-DADLINK)
add_definitions(-pipe -mcpu=neoverse-n1 -fuse-ld=gold -fuse-linker-plugin)
set(CMAKE_ASM_FLAGS "-pipe -mcpu=neoverse-n1")
elseif(M1)
add_definitions(-DM1)
add_definitions(-pipe -march=armv8.5-a+simd+crypto)
@@ -174,13 +210,22 @@ elseif(ARM64)
#add_definitions(-pipe -march=native)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+simd")
elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
if(NOT ANDROID)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
endif()
if(ANDROID)
add_definitions(-DANDROID)
endif()
if(TERMUX)
add_definitions(-DTERMUX)
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
if(SAVE_MEM)
add_definitions(-DSAVE_MEM)
endif()
if(PAGE8K)
add_definitions(-DPAGE8K)
endif()
@@ -268,15 +313,16 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/mallochook.c"
"${BOX64_ROOT}/src/steam.c"
"${BOX64_ROOT}/src/dynarec/dynarec.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
"${BOX64_ROOT}/src/elfs/elfloader.c"
"${BOX64_ROOT}/src/elfs/elfparser.c"
"${BOX64_ROOT}/src/elfs/elfload_dump.c"
"${BOX64_ROOT}/src/emu/x64compstrings.c"
"${BOX64_ROOT}/src/emu/x64emu.c"
"${BOX64_ROOT}/src/emu/x64int3.c"
"${BOX64_ROOT}/src/emu/x87emu_private.c"
"${BOX64_ROOT}/src/emu/x64primop.c"
"${BOX64_ROOT}/src/emu/x64run_private.c"
"${BOX64_ROOT}/src/emu/x64shaext.c"
"${BOX64_ROOT}/src/emu/x64syscall.c"
"${BOX64_ROOT}/src/emu/x86syscall.c"
"${BOX64_ROOT}/src/emu/x64tls.c"
@@ -287,7 +333,6 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
"${BOX64_ROOT}/src/librarian/symbols.c"
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/obstack.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
@@ -305,6 +350,12 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/tools/wine_tools.c"
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
)
if(NOT ANDROID)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/obstack.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
)
endif()
set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64run.c"
@@ -312,6 +363,8 @@ set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64run64.c"
"${BOX64_ROOT}/src/emu/x64run66.c"
"${BOX64_ROOT}/src/emu/x64run660f.c"
"${BOX64_ROOT}/src/emu/x64run66f20f.c"
"${BOX64_ROOT}/src/emu/x64run66f30f.c"
"${BOX64_ROOT}/src/emu/x64run6664.c"
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
@@ -342,6 +395,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX64_ROOT}/src/wrapped/wrappedatomic.c"
"${BOX64_ROOT}/src/wrapped/wrappedatspi.c"
"${BOX64_ROOT}/src/wrapped/wrappedayatanaappindicator3.c"
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
"${BOX64_ROOT}/src/wrapped/wrappedcap.c"
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
@@ -352,6 +406,8 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX64_ROOT}/src/wrapped/wrappedevent21.c"
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped/wrappedfaudio.c"
"${BOX64_ROOT}/src/wrapped/wrappedflac.c"
@@ -373,19 +429,31 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedgomp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapi.c"
"${BOX64_ROOT}/src/wrapped/wrappedgssapikrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstallocators.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstaudio.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstcheck.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstcontroller.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstfft.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstnet.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstpbutils.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstreamer.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstriff.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstrtp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstrtsp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstsdp.c"
"${BOX64_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX64_ROOT}/src/wrapped/wrappedgstvideo.c"
"${BOX64_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtk3.c"
"${BOX64_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedkrb5.c"
"${BOX64_ROOT}/src/wrapped/wrappedlcms2.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcmusl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcrypt.c"
@@ -395,6 +463,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibfuse.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
@@ -477,6 +546,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappednss3.c"
"${BOX64_ROOT}/src/wrapped/wrappednssutil3.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedopencl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
@@ -525,11 +595,25 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
"${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc66.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n66.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(ANDROID)
list(APPEND WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedandroidshmem.c"
)
endif()
if(TERMUX)
list(APPEND WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappediconv.c"
"${BOX64_ROOT}/src/wrapped/wrappedtermuxexec.c"
"${BOX64_ROOT}/src/wrapped/wrappedandroidsupport.c"
)
endif()
# If BOX64_ROOT contains a ".c", the build breaks...
string(REPLACE ".c" "_private.h" MODROOT ${BOX64_ROOT})
@@ -544,16 +628,18 @@ endforeach()
set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/wrapped/generated/wrapper.h")
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
)
if(NOT CI)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
)
endif ()
#add_custom_command(
# OUTPUT "${BOX64_ROOT}/src/dynarec/last_run.txt"
@@ -601,9 +687,11 @@ if(ARM_DYNAREC)
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_65.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d8.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d9.c"
#"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_da.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_da.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_db.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dc.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_dd.c"
@@ -611,6 +699,8 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_df.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_660f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6664.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f20f.c"
@@ -649,9 +739,10 @@ if(RV64_DYNAREC)
#"${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_67_32.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c"
"${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"
@@ -659,6 +750,8 @@ if(RV64_DYNAREC)
"${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_66f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c"
@@ -725,7 +818,15 @@ add_dependencies(${BOX64} WRAPPERS)
if(STATICBUILD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-static -Wl,--no-as-needed -Wl,--whole-archive -Wl,--allow-multiple-definition -lm -ldl -lrt -lpthread -lresolv -lc -Wl,-defsym,_DYNAMIC=0 -pthread")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
if(ANDROID)
if(TERMUX)
target_link_libraries(${BOX64} c m dl android-sysv-semaphore)
else()
target_link_libraries(${BOX64} c m dl)
endif()
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
endif()
endif()
if(DYNAREC)
target_link_libraries(${BOX64} dynarec)
@@ -734,7 +835,7 @@ target_link_libraries(${BOX64} interpreter)
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--image-base=${BOX64_ELF_ADDRESS}")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
@@ -743,7 +844,7 @@ if(${CMAKE_VERSION} VERSION_LESS "3.13")
else()
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
else()
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
@@ -761,18 +862,42 @@ if(_x86_64 OR _aarch64)
endif()
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX64}
if(NOT TERMUX)
install(TARGETS ${BOX64}
RUNTIME DESTINATION bin)
else()
install(TARGETS ${BOX64}
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
endif()
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/)
if(NOT TERMUX)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
else()
#install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
endif()
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/)
if(NOT TERMUX)
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}/x64lib/libcrypto.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION /usr/lib/x86_64-linux-gnu/)
else()
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
endif()
endif()
endif()
@@ -790,7 +915,11 @@ set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION "Box64 - Linux Userspace x86_64 Emulator with a twist")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
if(NOT TERMUX)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
else()
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libandroid-sysv-semaphore")
endif()
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
file(STRINGS "${BOX64_ROOT}/src/box64version.h" TEMP_STRING REGEX "BOX64_MAJOR\\s*")
string(REGEX REPLACE "BOX64_MAJOR" "" TEMP_STRING ${TEMP_STRING})
@@ -804,9 +933,15 @@ string(REGEX MATCH "[0-9]" BOX64_REVISION ${TEMP_STRING})
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX64_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${BOX64_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${BOX64_REVISION})
if(NOT TERMUX)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
endif()
if(_aarch64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
if(TERMUX)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "aarch64")
else()
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
endif()
elseif(__riscv64)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "riscv64")
elseif(_x86_64)
@@ -815,7 +950,14 @@ else()
#probably wrong...
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
endif()
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
if(TERMUX)
set(CPACK_PACKAGING_INSTALL_PREFIX "${TERMUX_PATH}/usr")
endif()
if(NOT TERMUX)
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_${CMAKE_SYSTEM_NAME}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
else()
set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVISION}_Termux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
endif()
INCLUDE(CPack)
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
@@ -922,19 +1064,56 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(pshufb ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23 -D TEST_OUTPUT=tmpfile23.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87cache ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26 -D TEST_OUTPUT=tmpfile26.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(feround PROPERTIES ENVIRONMENT "BOX64_SYNC_ROUNDING=1")
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test27 -D TEST_OUTPUT=tmpfile27.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref27.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(shaext ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test28 -D TEST_OUTPUT=tmpfile28.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref28.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29 -D TEST_OUTPUT=tmpfile29.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
+13 -13
View File
@@ -37,8 +37,8 @@ Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault sig
Compiling/Installation
----
> Compilation instructions can be found [here](docs/COMPILE.md)\
> Instructions for installing Wine for Box64 can be found [here](docs/X64WINE.md)
> Compilation instructions can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md) \
> Instructions for installing Wine for Box64 can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
----
@@ -54,7 +54,7 @@ Notes about 32-bit platforms
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bit libraries. Box64 doesn't include any 64-bit <-> 32-bit translation.
So understand that box64 will only runs 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it imply on 64-bit OS).
So understand that box64 will only run 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it implies on a 64-bit OS).
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when the argument is "-m"
----
@@ -62,16 +62,16 @@ Note that many installer (mojo setup based) will fall back to "x86" when detecti
Notes about Box64 configuration
----
Box64 now have configurations files. There are 2 files loaded. `/etc/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
Note that the priority is: `~/.bashrc` > `/etc/box64.box64rc` > command line
So, your settings in `~/.bashrc` may override the setting from your command line...
Box64 now have configurations files. There are 2 files loaded. `/etc/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reason, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
Note that the priority is: `~/.box64rc` > `/etc/box64.box64rc` > command line
So, your settings in `~/.box64rc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games should just works, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, wich is not supported on many ARM integrated GPU.
Running Unity games should just work, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, which is not supported on many ARM integrated GPU.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
@@ -86,7 +86,7 @@ GTK libraries are now wrapped on box64, both gtk2 and gtk3.
Notes about Steam
----
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mendatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile tp use Steam.
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mandatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile to use Steam.
----
@@ -94,14 +94,14 @@ Notes about Wine
----
Wine64 is supported on box64. Proton too. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
Note that the new 32bits PE in 64bits process that the Wine time in currently implementing in Wine 7.+ is now supported, but the support is quite young so there might be some residual issues.
Note that the new 32-bit PE in 64-bit processes that the Wine team is currently implementing in Wine 7.+ is now supported, but the support is quite young so there might be some residual issues.
----
Notes about Vulkan
----
Box64 wraps Vulkan libraries, but note that it as mostly been tested with a AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
Box64 wraps Vulkan libraries, but note that it as mostly been tested with an AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
----
@@ -112,11 +112,11 @@ I want to thank everyone who has contributed to box64 development.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* 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/))
* For their hardware contribution: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/)
* For their continuous advertisements for the box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
And I also thank the many other people who participated even once in this project.
+4 -4
View File
@@ -14,7 +14,7 @@ Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux
由于 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 工作原理的一些信息。
Box64 集成了适用于 ARM64 和 RV64 平台的 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)。
@@ -54,7 +54,7 @@ LOGO 由 @grayduck 制作,感谢!
因为 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`。
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
----
@@ -77,7 +77,7 @@ box64 封装了 GTK,包括 gtk2 和 gtk3。
关于 Steam 的注意事项
----
请注意,Steam 是 32/64 位的混合体,所以还需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,但与大多数使用 libcef/chromium 的东西一样,它目前无法在 box64 上正常工作。所以,现在 box64 上暂时不能运行 Steam。
请注意,Steam 是 32/64 位混合的应用,所以你需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,它的 steamwebhelper 无法被关闭(即使是在最小模式)而且会吃掉大量的内存。对于内存小于 6 GB 的机型,你将会需要创建 swapfile 来运行 Steam。
----
@@ -105,7 +105,7 @@ Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过
* 代码贡献: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/)
* 硬件捐赠:[ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [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/))
我还要感谢很多人,即使他们只参与了一次本项目。
+1 -1
View File
@@ -111,7 +111,7 @@ Box64 використовує бібліотеки Vulkan, але зауваж
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
* За основний внесок у код RV64 Dynarec: ksco, xctan
* За внесок у апаратне забезпечення: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* За безперервну рекламу Box64: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/Команда [TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
І я також дякую багатьом іншим людям, які хоч раз брали участь у цьому проекті.
+57
View File
@@ -1,3 +1,60 @@
box64 (0.2.6) unstable; urgency=low
* X64Libs: Updated libstdc++ & libgcc_s
* X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine)
* Dynarec: More opcodes on ARM64 & RV64
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* Dynarec: ARM64: reworked shift and bit opcodes flags handling
* Dynarec: RV64: Many fixes, making Wow64 apps running
* Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU)
* Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it)
* Dynarec: ARM64: The CALLRET optimisation has been improved and is now default
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* CPU: Added full support for SHA extension
* ElfLoader: rework how elf memory is handled
* Emulation: Added some more syscalls
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines
* OS: Added profile to build for Android and Termux.
* OS: New option to use mold for a high speed link
* => More hadware support, more functions wrapped for an improve compatibity
* => More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation
* => Some work also to reduce the memory footprint
-- Sebastien Chevalier <[email protected]> Thu, 15 Dec 2023 17:30:33 -0100
box64 (0.2.4) unstable; urgency=low
* Added Dynarec for RISC-V
* Added partial 32 bits support (WoW64 works)
* Changed cpuid to display box64
* Fixed steam, again
* Improved hacked version for overridden malloc/free functions
* More wrapped libs
* More wrapped functions and syscalls
* Reduced memory footprint
* Added support for the BIND_NOW flags in ELF files
* Added RTLD_NOLOAD support
* Fixed some typos and general cleanup, again
* Added a cosimulation mode (to compare the behaviour of the dynarec with the interpreter)
* Added FASTNAN/FASTROUND handling for more opcodes
* Better float/double/long double handling
* Better dlopen/dlclose handling
* More games in the rc file
* Added BOX64_DYNAREC_MISSING to show only missing opcode, independantly of the log level
* Added BOX64_RESERVE_HIGH to reserve addresses above 47bits
* Improved multitreading support
* Ukrainian translation of the README
* => Dynarec now support RISC-V, large speedup on RISC-V 64, were games are now playable (like Stardew Valley on a Vision Five 2)
* => Improved compatibility with more fixes in elf handling, more wrapped libs and functiond, more fixed opcodes and refined profile
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
box64 (0.2.2) unstable; urgency=low
* Added a hacked version for overridden malloc/free functions, enabling libcef (and derivative) to work.
+28
View File
@@ -1,3 +1,31 @@
v0.2.6
======
* X64Libs: Updated libstdc++ & libgcc_s
* X64Libs: Use x86_64 vrsion of libunwind (it's needed by wine)
* Dynarec: More opcodes on ARM64 & RV64
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* Dynarec: ARM64: reworked shift and bit opcodes flags handling
* Dynarec: RV64: Many fixes, making Wow64 apps running
* Dynarec: ARM64: Added support for SSE4.2 (with CRC32 if supported by CPU)
* Dynarec: ARM64: Added support for SHA (with hardware support if CPU allows it)
* Dynarec: ARM64: The CALLRET optimisation has been improved and is now default
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* CPU: Added full support for SHA extension
* ElfLoader: rework how elf memory is handled
* Emulation: Added some more syscalls
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support ADLink Ampere Altra, Qualcomm 8Gen3, and Pi5 machines
* OS: Added profile to build for Android and Termux.
* OS: New option to use mold for a high speed link
=> More hadware support, more functions wrapped for an improve compatibity
=> More CPU extension, with ARM64 hardware support when possible, and improved CALLRET optimisation for an improved speed of emulation
=> Some work also to reduce the memory footprint
v0.2.4
======
* Added Dynarec for RISC-V
+49 -8
View File
@@ -27,9 +27,9 @@ 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
- You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588.
#### For instance, if you want to build box64 for Generic ARM64 Linux platforms, it would look like this:
#### 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
@@ -68,7 +68,6 @@ Still, this can be faster if your build is attended.
```
-D RPI3ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
make
```
#### for Raspberry Pi 4
@@ -79,6 +78,13 @@ Warning, you need a 64bit OS:
-D RPI4ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Raspberry Pi 5
If your Raspberry Pi OS use 16K pages use `RPI5ARM64PS16K` instead of `RPI5ARM64`:
```
-D RPI5ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for TEGRA X1
Using a 64bit OS:
@@ -96,7 +102,7 @@ Using a 64bit OS:
-D ODROIDN2=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Snapdragon 845
#### for Snapdragon
Using a 64bit OS:
@@ -104,6 +110,14 @@ Using a 64bit OS:
-D SD845=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
or
```
-D SD888=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
Depending how recent your Snapdragon is
#### for Phytium
Using a 64bit OS:
@@ -111,11 +125,11 @@ Using a 64bit OS:
-D PHYTIUM=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for a generic ARM64 machine
#### for ADLink machines
Using a 64bit OS:
```
-D ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
-D ADLINK=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for M1
@@ -158,6 +172,26 @@ Using a 64bit OS:
-D LX2160A=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Termux
You must have ARM64 Device for build box64.
##### in CHRoot/PRoot
```
-D ARM64=1 -DCMAKE_C_COMPILER=gcc -DBAD_SIGNAL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
##### in Termux (Native)
NOTE: BUILDING BOX64 IN TERMUX NATIVE IS EXPERIMENTAL AND DOESN'T GONNA RUN LINUX BINARIES IN NATIVE TERMUX BOX64!!!
You also needed have `libandroid-sysv-semaphore` and `libandroid-spawn` libraries:
```
-D TERMUX=1 -D -DCMAKE_C_COMPILER=clang CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for x86_64 Linux
```
-D LD80BITS=1 -D NOALIGN=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -166,7 +200,7 @@ If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -D NOLOA
----
### use ccmake
### Use ccmake
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
@@ -187,12 +221,19 @@ To have a trace enabled build (***the interpreter will be slightly slower***), a
#### To have ARM Dynarec
Dynarec is only available on ARM (for the meantime), Activate it by using `-DARM_DYNAREC=1`.
###### *Note: VFPv3 and NEON are required for Dynarec.*
#### To have a build using less memory
You can use `-DSAVE_MEM` to have a build that will try to save some memory. It's, for now, only increasing the jumptable from 4 level to 5 levels. The added granularity avoid wasting space, but the 1 level more to the jumptable means there is on read from memory more when jumping between blocks.
#### Not building from a git clone
If you are not building from a git clone (for example, downloading a release source code zip from github), you need to use `-DNOGIT=1` from cmake to be able to build (box64 uses git SHA1 to show last commit in version number).
#### Use faster linker
You need to add `-DWITH_MOLD=1` if GNU ld is extremely slow. Then run `mold -run make -j4` to build (make sure [Mold](https://github.com/rui314/mold) is installed).
----
Testing
+40 -11
View File
@@ -3,7 +3,10 @@ Usage
----
There are many environment variables to control Box64 behaviour.
Env. var with * can also be put inside box64rc files
Env. var with * can also be put inside box64rc files.
Box64 look for 2 places for rcfile: `/etc/box64.box64rc` and `~/.box64rc`
The second takes precedence to the first, on an APP level
(that means if an [MYAPP] my appears in both file, only the settings in `~/.box64rc` will be applied)
#### BOX64_LOG *
Controls the Verbosity level of the logs
@@ -49,7 +52,7 @@ Only on build with trace enabled. Trace allow the logging of all instruction exe
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
#### BOX64_TRACE_INIT *
Use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
Use BOX64_TRACE_INIT instead of BOX64_TRACE to start trace before the initialisation 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.
@@ -153,8 +156,9 @@ Define Box64's Dynarec max allowed forward value when building Block.
#### BOX64_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
* 1 : Enable some Memory Barrier when writting to 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 : All 1. plus a memory barrier on every write to memory using MOV
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
#### BOX64_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation
@@ -179,8 +183,8 @@ Handling of flags on CALL/RET opcodes
#### BOX64_DYNAREC_CALLRET *
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)
* 0 : Don't optimize CALL/RET, use Jump Table for boths
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (Default)
#### BOX64_DYNAREC_HOTPAGE *
Handling of HotPage (Page being both executed and written)
@@ -192,6 +196,11 @@ 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)
#### BOX64_DYNAREC_ALIGNED_ATOMICS *
Generated code for aligned atomics only
* 0 : The code generated can handle unaligned atomics (Default)
* 1 : Generated code only for aligned atomics (faster and less code generated, but will SEGBUS if LOCK prefix is unsed on unaligned data)
#### BOX64_DYNAREC_BLEEDING_EDGE *
Detect MonoBleedingEdge and apply conservative settings
* 0 : Don't detect MonoBleedingEdge
@@ -222,11 +231,21 @@ Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX64_SYNC_ROUNDING *
Box64 will sync rounding mode with fesetround/fegetround.
* 0 : Disable rounding mode syncing. (Default.)
* 1 : Enable rounding mode syncing.
#### BOX64_LIBCEF *
Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
#### BOX64_SDL2_JGUID *
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
* 0 : Don't use any workaround
* 1 : Use a workaround for program that use the private SDL_GetJoystickGUIDInfo function with 1 missing argument
#### BOX64_LIBGL *
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -282,12 +301,17 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX64_FUTEX_WAITV *
Use of the new fuext_waitc syscall
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
* 1 : let program use the syscall if the host system support it (Default for other build)
#### BOX64_BASH *
Define x86_64 bash to launch script
* yyyy
Will use yyyy as x86_64 bash to launch script. yyyy needs to be a full path to a valid x86_64 version of bash
#### BOX64_ENV
#### BOX64_ENV *
* XXX=yyyy
will add XXX=yyyy env. var.
@@ -295,6 +319,10 @@ Define x86_64 bash to launch script
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### 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)
#### BOX64_JITGDB *
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
@@ -305,6 +333,7 @@ Define x86_64 bash to launch script
* 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)
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
#### BOX64_NORCFILES
If the env var exist, no rc files (like /etc/box64.box64rc and ~/.box64rc) will be loaded
@@ -318,10 +347,10 @@ Those variables are only valid inside a rcfile:
* 0 : Nothing special
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
#### BOX64_INPROCESSGPU
* 0 : Nothing special
* 1 : Added "--in-process-gpu" to command line arguments (usefull for chrome based programs)
#### 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)
+20 -1
View File
@@ -55,6 +55,11 @@ F<~/.bashrc> may override the setting from your command line. Example:
When set to 1, add C<--no-sandbox> to command line arguments (useful for chrome
based programs).
=item B<BOX64_INPROCESSGPU=0|1>
When set to 1, add C<--in-process-gpu> 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.
@@ -146,7 +151,7 @@ Only on build with trace enabled. Trace allow the logging of all instruction exe
=item B<BOX64_TRACE_INIT>=I<0|1>
Use B<BOX64_TRACE_INIT> instead of B<BOX_TRACE> to start trace before the
Use B<BOX64_TRACE_INIT> instead of B<BOX64_TRACE> to start trace before the
initialization of libraries and the running program
* 0 : No trace. (Default.)
@@ -371,6 +376,13 @@ 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_SYNC_ROUNDING>=I<0|1>
Box64 will sync rounding mode with fesetround/fegetround.
* 0 : Disable rounding mode syncing. (Default.)
* 1 : Enable rounding mode syncing.
=item B<BOX64_LIBCEF>=I<0|1>
Detect libcef and apply malloc_hack settings
@@ -451,6 +463,13 @@ 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_FUTEX_WAITV>=I<0|1>
Use of the new fuext_waitc syscall
* 0 : Do not try to use it, return unsupported (default for BAD_SIGNAL build)
* 1 : let program use the syscall if the host system support it (Default for other build)
=item B<BOX64_BASH>=I<yyyy>
Define x86_64 bash to launch script. Will use yyyy as x86_64 bash to launch
+1
View File
@@ -402,6 +402,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("libGL", "libEGL") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
or match("libc", "androidshmem") \
or match("tcmallocminimal", "tbbmallocproxy"):
continue
+4 -1
View File
@@ -11,6 +11,9 @@ endif( NOT TEST_OUTPUT )
if( NOT TEST_REFERENCE )
message( FATAL_ERROR "Require TEST_REFERENCE to be defined" )
endif( NOT TEST_REFERENCE )
if(NOT DEFINED ENV{INTERPRETER})
set(ENV{INTERPRETER} "")
endif()
set(ENV{BOX64_LOG} 0)
set(ENV{BOX64_NOBANNER} 1)
@@ -24,7 +27,7 @@ endif( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
# run the test program, capture the stdout/stderr and the result var
execute_process(
COMMAND ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
COMMAND $ENV{INTERPRETER} ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
OUTPUT_FILE ${TEST_OUTPUT}
ERROR_VARIABLE TEST_ERROR
RESULT_VARIABLE TEST_RESULT
+3 -1
View File
@@ -68,6 +68,8 @@ void free_tlsdatasize(void* p)
tlsdatasize_t *data = (tlsdatasize_t*)p;
box_free(data->ptr);
box_free(p);
if(my_context)
pthread_setspecific(my_context->tlskey, NULL);
}
void x64Syscall(x64emu_t *emu);
@@ -278,6 +280,7 @@ void FreeBox64Context(box64context_t** context)
box64context_t* ctx = *context; // local copy to do the cleanning
//clean_current_emuthread(); // cleaning main thread seems a bad idea
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib, NULL);
if(ctx->maplib)
@@ -342,7 +345,6 @@ void FreeBox64Context(box64context_t** context)
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific(ctx->tlskey, NULL);
}
pthread_key_delete(ctx->tlskey);
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 2
#define BOX64_REVISION 4
#define BOX64_REVISION 6
#endif //__BOX64_VERSION_H_
+459 -140
View File
File diff suppressed because it is too large. Load diff
+333 -36
View File
@@ -92,24 +92,24 @@
// MOVZ
#define MOVZ_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b10<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
#define MOVZx(Rd, imm16) EMIT(MOVZ_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVZx_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVZw(Rd, imm16) EMIT(MOVZ_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVZw_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVZx(Rd, imm16) EMIT(MOVZ_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVZx_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVZw(Rd, imm16) EMIT(MOVZ_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVZw_LSL(Rd, imm16, shift) EMIT(MOVZ_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
// MOVN
#define MOVN_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b00<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
#define MOVNx(Rd, imm16) EMIT(MOVN_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVNx_LSL(Rd, imm16, shift) EMIT(MOVN_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVNw(Rd, imm16) EMIT(MOVN_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVNw_LSL(Rd, imm16, shift) EMIT(MOVN_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVNx(Rd, imm16) EMIT(MOVN_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVNx_LSL(Rd, imm16, shift) EMIT(MOVN_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVNw(Rd, imm16) EMIT(MOVN_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVNw_LSL(Rd, imm16, shift) EMIT(MOVN_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
// MOVK
#define MOVK_gen(sf, hw, imm16, Rd) ((sf)<<31 | 0b11<<29 | 0b100101<<23 | (hw)<<21 | (imm16)<<5 | (Rd))
#define MOVKx(Rd, imm16) EMIT(MOVK_gen(1, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVKx_LSL(Rd, imm16, shift) EMIT(MOVK_gen(1, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
#define MOVKx(Rd, imm16) EMIT(MOVK_gen(1, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVKx_LSL(Rd, imm16, shift) EMIT(MOVK_gen(1, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
// This macro will give a -Wsign-compare warning, probably bug #38341
#define MOV32w(Rd, imm32) \
@@ -200,6 +200,12 @@
#define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
// CCMP compare if cond is true, set nzcv if false
#define CCMP_reg(sf, Rm, cond, Rn, nzcv) ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
#define CCMPw(Wn, Wm, nzcv, cond) EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
// ADR
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
#define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd)))
@@ -240,6 +246,7 @@
#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 LDRB_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b010, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
@@ -427,6 +434,13 @@
// Data Memory Barrier
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#define DMB_SY() EMIT(DMB_gen(0b1111))
// Data Synchronization Barrier
#define DSB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#define DSB_ISHST() EMIT(DSB_gen(0b1010))
#define DSB_SY() EMIT(DSB_gen(0b1111))
// Break
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
@@ -593,12 +607,12 @@
#define BFMx(Rd, Rn, immr, imms) EMIT(BFM_gen(1, 0b01, 1, immr, imms, Rn, Rd))
#define BFMw(Rd, Rn, immr, imms) EMIT(BFM_gen(0, 0b01, 0, immr, imms, Rn, Rd))
#define BFMxw(Rd, Rn, immr, imms) EMIT(BFM_gen(rex.w, 0b01, rex.w, immr, imms, Rn, Rd))
#define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-lsb)%64)&0x3f, (width)-1)
#define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-lsb)%32)&0x1f, (width)-1)
#define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-(lsb))%64)&0x3f, (width)-1)
#define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-(lsb))%32)&0x1f, (width)-1)
#define BFIxw(Rd, Rn, lsb, width) if(rex.w) {BFIx(Rd, Rn, lsb, width);} else {BFIw(Rd, Rn, lsb, width);}
#define BFCx(Rd, lsb, width) BFMx(Rd, xZR, ((-lsb)%64)&0x3f, (width)-1)
#define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-lsb)%32)&0x1f, (width)-1)
#define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-lsb)%64)&0x3f):(((-lsb)%32)&0x1f), (width)-1)
#define BFCx(Rd, lsb, width) BFMx(Rd, xZR, ((-(lsb))%64)&0x3f, (width)-1)
#define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-(lsb))%32)&0x1f, (width)-1)
#define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-(lsb))%64)&0x3f):(((-(lsb))%32)&0x1f), (width)-1)
// Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched)
#define BFXILx(Rd, Rn, lsb, width) EMIT(BFM_gen(1, 0b01, 1, (lsb), (lsb)+(width)-1, Rn, Rd))
// Insert lsb:width part of Rn into low part of Rd (leaving rest of Rd untouched)
@@ -637,9 +651,9 @@
#define SBFMx(Rd, Rn, immr, imms) EMIT(SBFM_gen(1, 1, immr, imms, Rn, Rd))
#define SBFMw(Rd, Rn, immr, imms) EMIT(SBFM_gen(0, 0, immr, imms, Rn, Rd))
#define SBFMxw(Rd, Rn, immr, imms) EMIT(SBFM_gen(rex.w, rex.w, immr, imms, Rn, Rd))
#define SBFXx(Rd, Rn, lsb, width) SBFMx(Rd, Rn, lsb, lsb+width-1)
#define SBFXw(Rd, Rn, lsb, width) SBFMw(Rd, Rn, lsb, lsb+width-1)
#define SBFXxw(Rd, Rn, lsb, width) SBFMxw(Rd, Rn, lsb, lsb+width-1)
#define SBFXx(Rd, Rn, lsb, width) SBFMx(Rd, Rn, lsb, (lsb)+(width)-1)
#define SBFXw(Rd, Rn, lsb, width) SBFMw(Rd, Rn, lsb, (lsb)+(width)-1)
#define SBFXxw(Rd, Rn, lsb, width) SBFMxw(Rd, Rn, lsb, (lsb)+(width)-1)
#define SXTBx(Rd, Rn) SBFMx(Rd, Rn, 0, 7)
#define SXTBw(Rd, Rn) SBFMw(Rd, Rn, 0, 7)
#define SXTHx(Rd, Rn) SBFMx(Rd, Rn, 0, 15)
@@ -783,13 +797,13 @@
// imm16 must be 4-aligned
#define VLDR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b11, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
// (imm14) must be 3-aligned
#define VSTR32_U12(Dt, Rn, imm14) EMIT(VMEM_gen(0b10, 0b00, ((uint32_t)(imm14>>2))&0xfff, Rn, Dt))
#define VSTR32_U12(Dt, Rn, imm14) EMIT(VMEM_gen(0b10, 0b00, ((uint32_t)((imm14)>>2))&0xfff, Rn, Dt))
// (imm15) must be 3-aligned
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)((imm15)>>3))&0xfff, Rn, Dt))
// imm16 must be 4-aligned
#define VSTR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
// (imm13) must be 1-aligned
#define VSTR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm13>>1))&0xfff, Rn, Ht))
#define VSTR16_U12(Ht, Rn, imm13) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)((imm13)>>1))&0xfff, Rn, Ht))
#define VMEMUR_vector(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
// signed offset, no alignement!
@@ -951,6 +965,15 @@
#define VSRI_16(Vd, Vn, shift) EMIT(VSRI_vector(0, 0b0010 | ((shift)>>3)&1, (shift)&7, Vn, Vd))
#define VSRI_32(Vd, Vn, shift) EMIT(VSRI_vector(0, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
// Reverse elements in 64-bit doublewords (vector). This instruction reverses the order of 8-bit, 16-bit, or 32-bit elements in each doubleword
#define VREVx_vector(Q, U, size, o0, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | (o0)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VREV64_32(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b10, 0, Vn, Vd))
#define VREV64_16(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b01, 0, Vn, Vd))
#define VREV64_8(Vd, Vn) EMIT(VREVx_vector(0, 0, 0b00, 0, Vn, Vd))
#define VREV64Q_32(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b10, 0, Vn, Vd))
#define VREV64Q_16(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b01, 0, Vn, Vd))
#define VREV64Q_8(Vd, Vn) EMIT(VREVx_vector(1, 0, 0b00, 0, Vn, Vd))
// Integer MATH
#define ADDSUB_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10000<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VADDQ_8(Vd, Vn, Vm) EMIT(ADDSUB_vector(1, 0, 0b00, Vm, Vn, Vd))
@@ -1094,6 +1117,12 @@
#define FADDP_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11010<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFADDPQS(Vd, Vn, Vm) EMIT(FADDP_vector(1, 0, Vm, Vn, Vd))
#define VFADDPQD(Vd, Vn, Vm) EMIT(FADDP_vector(1, 1, Vm, Vn, Vd))
#define VFADDPS(Vd, Vn, Vm) EMIT(FADDP_vector(0, 0, Vm, Vn, Vd))
#define VFADDPD(Vd, Vn, Vm) EMIT(FADDP_vector(0, 1, Vm, Vn, Vd))
#define FADDP_scalar(sz, Rn, Rd) (0b01<<30 | 1<<29 | 0b11110<<24 | (sz)<<22 | 0b11000<<17 | 0b01101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define FADDPS(Sd, Sn) EMIT(FADDP_scalar(0, Sn, Sd))
#define FADDPD(Dd, Dn) EMIT(FADDP_scalar(1, Dn, Dd))
// NEG / ABS
#define FNEGABS_scalar(type, opc, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (opc)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
@@ -1360,22 +1389,12 @@
#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 VFRINTRS(Vd, Vn, mode) EMIT(FRINT_vector(0, 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))
#define FRINTID(Dd, Dn) EMIT(FRINTI_scalar(0b01, Dn, Dd))
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
#define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
// round toward 0 (truncate)
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
@@ -1490,7 +1509,6 @@
#define VTRNQ1_32(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b10, Vm, 0, Vn, Vd))
#define VTRNQ1_16(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b01, Vm, 0, Vn, Vd))
#define VTRNQ1_8(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b00, Vm, 0, Vn, Vd))
#define VSWP(Vd, Vn) VTRNQ1_64(Vd, Vn, Vn)
#define VTRNQ2_64(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b11, Vm, 1, Vn, Vd))
#define VTRNQ2_32(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b10, Vm, 1, Vn, Vd))
#define VTRNQ2_16(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b01, Vm, 1, Vn, Vd))
@@ -1599,6 +1617,15 @@
#define CMEQQ_0_16(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b01, Rn, Rd))
#define CMEQQ_0_32(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b10, Rn, Rd))
#define CMEQQ_0_64(Rd, Rn) EMIT(CMEQ_0_vector(1, 0b11, Rn, Rd))
// Greater Than 0
#define CMCond_0_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b0100<<13 | (op)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMGT_0_8(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b00, 0, Rn, Rd))
#define CMGT_0_16(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b01, 0, Rn, Rd))
#define CMGT_0_32(Rd, Rn) EMIT(CMCond_0_vector(0, 0, 0b10, 0, Rn, Rd))
#define CMGTQ_0_8(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b00, 0, Rn, Rd))
#define CMGTQ_0_16(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b01, 0, Rn, Rd))
#define CMGTQ_0_32(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b10, 0, Rn, Rd))
#define CMGTQ_0_64(Rd, Rn) EMIT(CMCond_0_vector(1, 0, 0b11, 0, Rn, Rd))
// Vector Float CMP
// EQual
@@ -1757,9 +1784,11 @@
// 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 MOVIQ_16(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((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_16(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
#define MOVI_32(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
#define MOVI_64(Rd, imm8) EMIT(MOVI_vector(0, 1, (((imm8)>>5)&0b111), 0b1110, ((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))
@@ -1919,4 +1948,272 @@
#define PMULL_128(Rd, Rn, Rm) EMIT(PMULL_gen(0, 0b11, Rm, Rn, Rd))
#define PMULL2_128(Rd, Rn, Rm) EMIT(PMULL_gen(1, 0b11, Rm, Rn, Rd))
// ATOMIC extension
#define ATOMIC_gen(size, A, R, Rs, opc, Rn, Rt) ((size)<<30 | 0b111<<27 | (A)<<23 | (R)<<22 | 1<<21 | (Rs)<<16 | (opc)<<12 | (Rn)<<5 | (Rt))
// Atomic ADD
#define LDADDxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b000, Rn, Rt))
#define LDADDAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b000, Rn, Rt))
#define LDADDALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b000, Rn, Rt))
#define LDADDLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, Rt))
#define STADDxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b000, Rn, 0b11111))
#define STADDLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b000, Rn, 0b11111))
#define LDADDB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b000, Rn, Rt))
#define LDADDAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b000, Rn, Rt))
#define LDADDALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b000, Rn, Rt))
#define LDADDLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b000, Rn, Rt))
#define STADDB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b000, Rn, 0b11111))
#define STADDLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b000, Rn, 0b11111))
#define LDADDH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b000, Rn, Rt))
#define LDADDAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b000, Rn, Rt))
#define LDADDALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b000, Rn, Rt))
#define LDADDLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b000, Rn, Rt))
#define STADDH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b000, Rn, 0b11111))
#define STADDLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b000, Rn, 0b11111))
// Atomic AND with complement (i.e. BIC)
#define LDCLRxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b001, Rn, Rt))
#define LDCLRAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b001, Rn, Rt))
#define LDCLRALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b001, Rn, Rt))
#define LDCLRLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b001, Rn, Rt))
#define STCLRxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b001, Rn, 0b11111))
#define STCLRLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b001, Rn, 0b11111))
#define LDCLRB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b001, Rn, Rt))
#define LDCLRAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b001, Rn, Rt))
#define LDCLRALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b001, Rn, Rt))
#define LDCLRLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b001, Rn, Rt))
#define STCLRB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b001, Rn, 0b11111))
#define STCLRLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b001, Rn, 0b11111))
#define LDCLRH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b001, Rn, Rt))
#define LDCLRAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b001, Rn, Rt))
#define LDCLRALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b001, Rn, Rt))
#define LDCLRLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b001, Rn, Rt))
#define STCLRH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b001, Rn, 0b11111))
#define STCLRLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b001, Rn, 0b11111))
// Atomic EOR
#define LDEORxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b010, Rn, Rt))
#define LDEORAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b010, Rn, Rt))
#define LDEORALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b010, Rn, Rt))
#define LDEORLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b010, Rn, Rt))
#define STEORxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b010, Rn, 0b11111))
#define STEORLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b010, Rn, 0b11111))
#define LDEORB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b010, Rn, Rt))
#define LDEORAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b010, Rn, Rt))
#define LDEORALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b010, Rn, Rt))
#define LDEORLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b010, Rn, Rt))
#define STEORB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b010, Rn, 0b11111))
#define STEORLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b010, Rn, 0b11111))
#define LDEORH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b010, Rn, Rt))
#define LDEORAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b010, Rn, Rt))
#define LDEORALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b010, Rn, Rt))
#define LDEORLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b010, Rn, Rt))
#define STEORH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b010, Rn, 0b11111))
#define STEORLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b010, Rn, 0b11111))
// Atomic OR
#define LDSETxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b011, Rn, Rt))
#define LDSETAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b011, Rn, Rt))
#define LDSETALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b011, Rn, Rt))
#define LDSETLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b011, Rn, Rt))
#define STSETxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b011, Rn, 0b11111))
#define STSETLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b011, Rn, 0b11111))
#define LDSETB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b011, Rn, Rt))
#define LDSETAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b011, Rn, Rt))
#define LDSETALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b011, Rn, Rt))
#define LDSETLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b011, Rn, Rt))
#define STSETB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b011, Rn, 0b11111))
#define STSETLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b011, Rn, 0b11111))
#define LDSETH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, Rt))
#define LDSETAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b011, Rn, Rt))
#define LDSETALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b011, Rn, Rt))
#define LDSETLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, Rt))
#define STSETH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, 0b11111))
#define STSETLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, 0b11111))
// Atomic Signel Max
#define LDSMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b100, Rn, Rt))
#define LDSMAXLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b100, Rn, Rt))
#define STSMAXxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, 0b11111))
#define STSMAXLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b100, Rn, 0b11111))
#define LDSMAXB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b100, Rn, Rt))
#define LDSMAXLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b100, Rn, Rt))
#define STSMAXB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b100, Rn, 0b11111))
#define STSMAXLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b100, Rn, 0b11111))
#define LDSMAXH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b100, Rn, Rt))
#define LDSMAXLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b100, Rn, Rt))
#define STSMAXH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b100, Rn, 0b11111))
#define STSMAXLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b100, Rn, 0b11111))
// Atomic Signed Min
#define LDSMINxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b101, Rn, Rt))
#define LDSMINAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b101, Rn, Rt))
#define LDSMINALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b101, Rn, Rt))
#define LDSMINLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b101, Rn, Rt))
#define STSMINxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b101, Rn, 0b11111))
#define STSMINLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b101, Rn, 0b11111))
#define LDSMINB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b101, Rn, Rt))
#define LDSMINAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b101, Rn, Rt))
#define LDSMINALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b101, Rn, Rt))
#define LDSMINLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b101, Rn, Rt))
#define STSMINB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b101, Rn, 0b11111))
#define STSMINLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b101, Rn, 0b11111))
#define LDSMINH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b101, Rn, Rt))
#define LDSMINAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b101, Rn, Rt))
#define LDSMINALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b101, Rn, Rt))
#define LDSMINLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b101, Rn, Rt))
#define STSMINH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b101, Rn, 0b11111))
#define STSMINLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b101, Rn, 0b11111))
// Atomic Unsigned Max
#define LDUMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b110, Rn, Rt))
#define LDUMAXLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b110, Rn, Rt))
#define STUMAXxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b110, Rn, 0b11111))
#define STUMAXLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b110, Rn, 0b11111))
#define LDUMAXB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b110, Rn, Rt))
#define LDUMAXLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b110, Rn, Rt))
#define STUMAXB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b110, Rn, 0b11111))
#define STUMAXLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b110, Rn, 0b11111))
#define LDUMAXH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b110, Rn, Rt))
#define LDUMAXALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b110, Rn, Rt))
#define LDUMAXLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b110, Rn, Rt))
#define STUMAXH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b110, Rn, 0b11111))
#define STUMAXLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b110, Rn, 0b11111))
// Atomic Unsigned Min
#define LDUMINxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b111, Rn, Rt))
#define LDUMINAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b111, Rn, Rt))
#define LDUMINALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b111, Rn, Rt))
#define LDUMINLxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b111, Rn, Rt))
#define STUMINxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b111, Rn, 0b11111))
#define STUMINLxw(Rs, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 1, Rs, 0b111, Rn, 0b11111))
#define LDUMINB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b111, Rn, Rt))
#define LDUMINAB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 0, Rs, 0b111, Rn, Rt))
#define LDUMINALB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 1, 1, Rs, 0b111, Rn, Rt))
#define LDUMINLB(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b111, Rn, Rt))
#define STUMINB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 0, Rs, 0b111, Rn, 0b11111))
#define STUMINLB(Rs, Rn) EMIT(ATOMIC_gen(0b00, 0, 1, Rs, 0b111, Rn, 0b11111))
#define LDUMINH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b111, Rn, Rt))
#define LDUMINAH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 0, Rs, 0b111, Rn, Rt))
#define LDUMINALH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 1, 1, Rs, 0b111, Rn, Rt))
#define LDUMINLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b111, Rn, Rt))
#define STUMINH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b111, Rn, 0b11111))
#define STUMINLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b111, Rn, 0b11111))
// SWAPxx(Xs, Xt, Xn) : [Xn] => Xt, Xs => [Xn]
#define SWAP_gen(size, A, R, Rs, Rn, Rt) ((size)<<30 | 0b111<<27 | (A)<<23 | (R)<<22 | 1<<21 | (Rs)<<16 | 1<<15 | (Rn)<<5 | (Rt))
#define SWPxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 0, 0, Rs, Rn, Rt))
#define SWPAxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 1, 0, Rs, Rn, Rt))
#define SWPALxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 1, 1, Rs, Rn, Rt))
#define SWPLxw(Rs, Rt, Rn) EMIT(SWAP_gen(0b10+rex.w, 0, 1, Rs, Rn, Rt))
#define SWPB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 0, 0, Rs, Rn, Rt))
#define SWPAB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 1, 0, Rs, Rn, Rt))
#define SWPALB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 1, 1, Rs, Rn, Rt))
#define SWPLB(Rs, Rt, Rn) EMIT(SWAP_gen(0b00, 0, 1, Rs, Rn, Rt))
#define SWPH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 0, 0, Rs, Rn, Rt))
#define SWPAH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 1, 0, Rs, Rn, Rt))
#define SWPALH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 1, 1, Rs, Rn, Rt))
#define SWPLH(Rs, Rt, Rn) EMIT(SWAP_gen(0b01, 0, 1, Rs, Rn, Rt))
#define CAS_gen(size, L, Rs, O0, Rn, Rt) ((size)<<30 | 0b001000<<24 | 1<<23 | (L)<<22 | 1<<21 | (Rs)<<16 | (O0)<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
// Compare and Swap compare Rs with [Rn], write Rt is same, return old [Rn] in Rs
#define CASxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 0, Rs, 0, Rn, Rt))
#define CASAxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 1, Rs, 0, Rn, Rt))
#define CASALxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 1, Rs, 1, Rn, Rt))
#define CASLxw(Rs, Rt, Rn) EMIT(CAS_gen(0b10+rex.w, 0, Rs, 1, Rn, Rt))
#define CASB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 0, Rs, 0, Rn, Rt))
#define CASAB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 1, Rs, 0, Rn, Rt))
#define CASALB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 1, Rs, 1, Rn, Rt))
#define CASLB(Rs, Rt, Rn) EMIT(CAS_gen(0b00, 0, Rs, 1, Rn, Rt))
#define CASH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 0, Rs, 0, Rn, Rt))
#define CASAH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 1, Rs, 0, Rn, Rt))
#define CASALH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 1, Rs, 1, Rn, Rt))
#define CASLH(Rs, Rt, Rn) EMIT(CAS_gen(0b01, 0, Rs, 1, Rn, Rt))
#define CASP_gen(size, L, Rs, O0, Rn, Rt) ((size)<<30 | 0b001000<<24 | 0<<23 | (L)<<22 | 1<<21 | (Rs)<<16 | (O0)<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
// Compare and Swap with pair, Rs, Rs+1 and Rt,Rt+1 with [Rt]
#define CASPxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 0, Rs, 0, Rn, Rt))
#define CASPAxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 1, Rs, 0, Rn, Rt))
#define CASPALxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 1, Rs, 1, Rn, Rt))
#define CASPLxw(Rs, Rt, Rn) EMIT(CASP_gen(0b00+rex.w, 0, Rs, 1, Rn, Rt))
// FLAGM extension
// Invert Carry Flag
#define CFINV() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
#define RMIF_gen(imm6, Rn, mask) (0b10111010000<<21 | (imm6)<<15 | 0b00001<<10 | (Rn)<<5 | (mask))
// Rotate right reg and use as NZCV
#define RMIF(Xn, shift, mask) EMIT(RMIF_gen(shift, Xn, mask))
#define SETF_gen(sz, Rn) (0b00111010000<<21 | (sz)<<14 | 0b0010<<10 | (Rn)<<5 | 0b1101)
// Set NZVc with 8bit value of reg: N=bit7, Z=[0..7]==0, V=bit8 eor bit7, C unchanged
#define SETF8(Wn) EMIT(SETF_gen(0, Wn))
// Set NZVc with 16bit value of reg: N=bit15, Z=[0..15]==0, V=bit16 eor bit15, C unchanged
#define SETF16(Wn) EMIT(SETF_gen(1, Wn))
// FLAGM2 extension
// NZCV -> N=0 Z=C|V C=C&!V V=0
#define AXFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
// NZCV -> N=!C&!Z Z=Z&C C=C|Z V=!C&Z
#define XAFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
// FRINTTS extension
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
// CRC32 extension
#define CRC32C_gen(sf, Rm, sz, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b010<<13 | 1<<12 | (sz)<<10 | (Rn)<<5 | (Rd))
#define CRC32CB(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b00, Wn, Wd))
#define CRC32CH(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b01, Wn, Wd))
#define CRC32CW(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b10, Wn, Wd))
#define CRC32CX(Wd, Wn, Xm) EMIT(CRC32C_gen(1, Xm, 0b11, Wn, Wd))
#define CRC32Cxw(Wd, Wn, Rm) EMIT(CRC32C_gen(rex.w, Rm, 0b10|rex.w, Wn, Wd))
// SHA1 extension
#define SHA1H_gen(Rn, Rd) (0b01011110<<24 | 0b10100<<17 | 0b10<<10 | (Rn)<<5 | (Rd))
// SHA1 fixed rotate (ROL 30 of 32bits value)
#define SHA1H(Sd, Sn) EMIT(SHA1H_gen(Sn, Sd))
#define SHA1SU1_gen(Rn, Rd) (0b01011110<<24 | 0b10100<<17 | 0b00001<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// SHA1 schedule update 1
#define SHA1SU1(Vd, Vn) EMIT(SHA1SU1_gen(Vn, Vd))
#define SHA1C_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | (Rn)<<5 | (Rd))
// SHA1 hash update (choose)
#define SHA1C(Qd, Sn, Vm) EMIT(SHA1C_gen(Vm, Sn, Qd))
#define SHA1M_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b010<<12 | (Rn)<<5 | (Rd))
// SHA1 hash update (majority)
#define SHA1M(Qd, Sn, Vm) EMIT(SHA1M_gen(Vm, Sn, Qd))
#define SHA1P_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b001<<12 | (Rn)<<5 | (Rd))
// SHA1 hash update (parity)
#define SHA1P(Qd, Sn, Vm) EMIT(SHA1P_gen(Vm, Sn, Qd))
#define SHA256SU0_gen(Rn,Rd) (0b01011110<<24 | 0b10100<<17 | 0b00010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
//SHA256 schedule update 0
#define SHA256SU0(Vd, Vn) EMIT(SHA256SU0_gen(Vn, Vd))
#define SHA256SU1_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b110<<12 | (Rn)<<5 | (Rd))
//SHA256 schedule update 1
#define SHA256SU1(Vd, Vn, Vm) EMIT(SHA256SU1_gen(Vm, Vn, Vd))
#define SHA256H_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b100<<12 | (Rn)<<5 | (Rd))
//SHA256 hash update (part 1)
#define SHA256H(Vd, Vn, Vm) EMIT(SHA256H_gen(Vm, Vn, Vd))
#define SHA256H2_gen(Rm, Rn, Rd) (0b01011110<<24 | (Rm)<<16 | 0b101<<12 | (Rn)<<5 | (Rd))
//SHA256 hash update (part 2)
#define SHA256H2(Vd, Vn, Vm) EMIT(SHA256H2_gen(Vm, Vn, Vd))
#endif //__ARM64_EMITTER_H__
+21
View File
@@ -29,6 +29,10 @@
.global arm64_lock_incif0
.global arm64_lock_decifnot0
.global arm64_lock_store
.global arm64_lock_store_dd
.global arm64_lock_get_b
.global arm64_lock_get_d
.global arm64_lock_get_dd
arm64_lock_read_b:
dmb ish
@@ -254,3 +258,20 @@ arm64_lock_store:
str w1, [x0]
dmb ish
ret
arm64_lock_store_dd:
str x1, [x0]
dmb ish
ret
arm64_lock_get_b:
ldaxrb w0, [x0]
ret
arm64_lock_get_d:
ldaxr w0, [x0]
ret
arm64_lock_get_dd:
ldaxr x0, [x0]
ret
+12
View File
@@ -69,4 +69,16 @@ extern int arm64_lock_decifnot0(void*p);
// atomic store (with memory barrier)
extern void arm64_lock_store(void*p, uint32_t v);
// atomic store (with memory barrier)
extern void arm64_lock_store_dd(void*p, uint64_t v);
// atomic get (with memory barrier)
extern uint8_t arm64_lock_get_b(void*p);
// atomic get (with memory barrier)
extern uint32_t arm64_lock_get_d(void*p);
// atomic get (with memory barrier)
extern void* arm64_lock_get_dd(void*p);
#endif //__ARM64_LOCK__H__
+219 -9
View File
@@ -16,7 +16,7 @@ static const char* conds[] = {"cEQ", "cNE", "cCS", "cCC", "cMI", "cPL", "cVS", "
#define abs(A) (((A)<0)?(-(A)):(A))
typedef struct arm64_print_s {
int N, S, U, L, Q;
int N, S, U, L, Q, A, R;
int t, n, m, d, t2, a;
int f, c, o, h, p;
int i, r, s;
@@ -60,6 +60,8 @@ int isMask(uint32_t opcode, const char* mask, arm64_print_t *a)
case 'N': a->N = (a->N<<1) | v; break;
case 'S': a->S = (a->S<<1) | v; break;
case 'U': a->U = (a->U<<1) | v; break;
case 'A': a->A = (a->A<<1) | v; break;
case 'R': a->R = (a->R<<1) | v; break;
case 'L': a->L = (a->L<<1) | v; break;
case 'Q': a->Q = (a->Q<<1) | v; break;
case 't': a->t = (a->t<<1) | v; break;
@@ -182,22 +184,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
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));
snprintf(buff, sizeof(buff), "LDURH %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));
snprintf(buff, sizeof(buff), "LDURSB %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));
snprintf(buff, sizeof(buff), "LDURSH %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));
snprintf(buff, sizeof(buff), "LDURSW %s, [%s, %s0x%x]", Xt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x111000000iiiiiiiii00nnnnnttttt", &a)) {
@@ -213,7 +215,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
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));
snprintf(buff, sizeof(buff), "STURH %s, [%s, %s0x%x]", Wt[Rt], XtSp[Rn], (offset<0)?"-":"", abs(offset));
return buff;
}
if(isMask(opcode, "1x11100101iiiiiiiiiiiinnnnnttttt", &a)) {
@@ -795,6 +797,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "CSEL %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]);
return buff;
}
if(isMask(opcode, "f1111010010mmmmmcccc00nnnnn0iiii", &a)) {
snprintf(buff, sizeof(buff), "CCMP %s, %s, %s 0x%x", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond], imm);
return buff;
}
// MISC Bits
if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
@@ -950,6 +957,22 @@ 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;
}
// CMP zero
if(isMask(opcode, "0QU01110ff100000100o10nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Z[] = {"GT", "GE", "EQ", "LE"};
const char* Vd = Y[((sf)<<1) | a.Q];
const char* Cond = Z[(a.o << 1 | a.U)];
snprintf(buff, sizeof(buff), "VCM%s V%d.%s, V%d.%s, #0", Cond, Rd, Vd, Rn, Vd);
return buff;
}
// CMPLT zero
if(isMask(opcode, "0Q001110ff100000101010nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[((sf)<<1) | a.Q];
snprintf(buff, sizeof(buff), "VCMLT V%d.%s, V%d.%s, #0", Rd, Vd, Rn, Vd);
return buff;
}
// MIN/MAX
if(isMask(opcode, "0QU01110ff1mmmmm0110o1nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -965,11 +988,21 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
return buff;
}
// MOV immediate (not)shifted 16bits & 32bits
// MOV immediate notshifted 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);
int sh = 0;
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<sh);
return buff;
}
// MOV immediate shifted 16bits
if(isMask(opcode, "0Q00111100000iii101001iiiiiddddd", &a)) {
const char* Y[] = {"4H", "8H"};
const char* Vd = Y[a.Q];
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<8);
return buff;
}
@@ -1034,7 +1067,30 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
if(!offset)
snprintf(buff, sizeof(buff), "%s %c%d, [%s]", op?"STR":"LDR", s, Rt, XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %d]", op?"STR":"LDR", s, Rt, XtSp[Rn], offset);
snprintf(buff, sizeof(buff), "%s %c%d, [%s, 0x%x]", op?"STR":"LDR", s, Rt, XtSp[Rn], offset);
return buff;
}
if(isMask(opcode, "ss111100cc1mmmmmoooS10nnnnnttttt", &a)) {
char s = '?';
int size=imms;
int op=0;
if(size==0 && opc==1) {s='B';}
else if(size==1 && opc==1) {s='H';}
else if(size==2 && opc==1) {s='S';}
else if(size==3 && opc==1) {s='D';}
else if(size==0 && opc==3) {s='Q'; size = 4;}
else if(size==0 && opc==0) {s='B'; op=1;}
else if(size==1 && opc==0) {s='H'; op=1;}
else if(size==2 && opc==0) {s='S'; op=1;}
else if(size==3 && opc==0) {s='D'; op=1;}
else if(size==0 && opc==2) {s='Q'; op=1; size = 4;}
const char* extend[] = {"?0", "?1", "UXTW", "LSL", "?4", "?5", "SXTW", "SXTX"};
int amount = size*a.S;
if(option==3 && !amount)
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %s]", op?"STR":"LDR", s, Rt, XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm]);
else
snprintf(buff, sizeof(buff), "%s %c%d, [%s, %s, %s %d]", op?"STR":"LDR", s, Rt, XtSp[Rn], ((option&1)==0)?Wt[Rm]:Xt[Rm], extend[option], amount);
return buff;
}
@@ -1094,6 +1150,20 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// FADDP
if(isMask(opcode, "0Q1011100f1mmmmm110101nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFADDP %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
return buff;
}
if(isMask(opcode, "011111100f110000110110nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "FADDP %c%d, %c%d, %c%d", s, Rd, s, Rn, s, Rm);
return buff;
}
// SQRT
if(isMask(opcode, "0Q1011101f100001111110nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
@@ -1302,6 +1372,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "FCVT%sS %s, %c%d", roundings[a.c], sf?Xt[Rd]:Wt[Rd], s, Rn);
return buff;
}
if(isMask(opcode, "0QU01110of100001101o10nnnnnddddd", &a)) {
const char* Y[] = {"2S", "4S", "??", "2D"};
const char* Z[] = {"S", "S", "??", "D"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* roundings[] = {"N", "M", "P", "Z"};
snprintf(buff, sizeof(buff), "VFCVT%s%s%s%s V%d.%s, V%d.%s", roundings[option], a.U?"U":"S", a.Q?"Q":"", Z[(sf<<1)|a.Q], Rd, Vd, Rn, Vd);
return buff;
}
// FMOV
if(isMask(opcode, "00011110pp100000010000nnnnnddddd", &a)) {
@@ -1548,7 +1626,139 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
return buff;
}
// DSB ISH/ISHST
if(isMask(opcode, "11010101000000110011nnnn10011111", &a)) {
snprintf(buff, sizeof(buff), "DSB %s", (Rn==0b1011)?"ISH":((Rn==0b1010)?"ISHST":"???"));
return buff;
}
// CASxw
if(isMask(opcode, "1f0010001L1ssssso11111nnnnnttttt", &a)) {
snprintf(buff, sizeof(buff), "CAS%s%s %s, %s, [%s]", a.o?"A":"", a.L?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
return buff;
}
// CAS B/H
if(isMask(opcode, "0f0010001L1ssssso11111nnnnnttttt", &a)) {
snprintf(buff, sizeof(buff), "CAS%s%s%s %s, %s, [%s]", a.o?"A":"", a.L?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
return buff;
}
// CASPxw
if(isMask(opcode, "0f0010000L1ssssso11111nnnnnttttt", &a)) {
snprintf(buff, sizeof(buff), "CASP%s%s %s,%s, %s,%s, [%s]", a.o?"A":"", a.L?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rs+1]:Wt[Rs+1], sf?Xt[Rt]:Wt[Rt], sf?Xt[Rt+1]:Wt[Rt+1], XtSp[Rn]);
return buff;
}
// SWPxw
if(isMask(opcode, "1f111000AR1sssss100000nnnnnttttt", &a)) {
snprintf(buff, sizeof(buff), "SWP%s%s %s, %s, [%s]", a.A?"A":"", a.R?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
return buff;
}
// SWPxw
if(isMask(opcode, "0f111000AR1sssss100000nnnnnttttt", &a)) {
snprintf(buff, sizeof(buff), "CAS%s%s%s %s, %s, [%s]", a.A?"A":"", a.R?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
return buff;
}
// LDXXXxw
if(isMask(opcode, "1f111000AR1sssss0ooo00nnnnnttttt", &a)) {
const char* ops[] = { "ADD", "CLR", "EOR", "SET", "SMAX, SMIN", "UMAX", "UMIN" };
if((Rt == 0b11111) && !a.A) {
snprintf(buff, sizeof(buff), "ST%s%s %s, [%s]", ops[a.o], a.R?"L":"", sf?Xt[Rs]:Wt[Rs], XtSp[Rn]);
} else {
snprintf(buff, sizeof(buff), "LD%s%s%s %s, %s, [%s]", ops[a.o], a.A?"A":"", a.R?"L":"", sf?Xt[Rs]:Wt[Rs], sf?Xt[Rt]:Wt[Rt], XtSp[Rn]);
}
return buff;
}
// LDXXX B/H
if(isMask(opcode, "0f111000AR1sssss0ooo00nnnnnttttt", &a)) {
const char* ops[] = { "ADD", "CLR", "EOR", "SET", "SMAX, SMIN", "UMAX", "UMIN" };
if((Rt == 0b11111) && !a.A) {
snprintf(buff, sizeof(buff), "ST%s%s%s %s, [%s]", ops[a.o], a.R?"L":"", sf?"H":"B", Xt[Rs], XtSp[Rn]);
} else {
snprintf(buff, sizeof(buff), "LD%s%s%s%s %s, %s, [%s]", ops[a.o], a.A?"A":"", a.R?"L":"", sf?"H":"B", Xt[Rs], Xt[Rt], XtSp[Rn]);
}
return buff;
}
// AXFLAG
if(isMask(opcode, "11010101000000000100000001011111", &a)) {
snprintf(buff, sizeof(buff), "AXFLAG");
return buff;
}
// XAFLAG
if(isMask(opcode, "11010101000000000100000000111111", &a)) {
snprintf(buff, sizeof(buff), "XAFLAG");
return buff;
}
// CFINV
if(isMask(opcode, "11010101000000000100000000011111", &a)) {
snprintf(buff, sizeof(buff), "CFINV");
return buff;
}
// RMIF
if(isMask(opcode, "10111010000iiiiii00001nnnnn0oooo", &a)) {
snprintf(buff, sizeof(buff), "RMIF %s, #%d, #0x%x", Xt[Rn], imm, opc);
return buff;
}
// SETF
if(isMask(opcode, "00111010000000000f0010nnnnn01101", &a)) {
snprintf(buff, sizeof(buff), "SETF%d %s", 8<<sf, Xt[Rn]);
return buff;
}
// REV64
if(isMask(opcode, "0Q001110ff100000000010nnnnnddddd", &a)) {
const char* T[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "??"};
int sz = sf;
const char* Vn = T[(sz<<1)|a.Q];
const char* Vd = T[(sz<<1)|a.Q];
snprintf(buff, sizeof(buff), "REV64 V%d.%s, V%d.%s",Rd, Vd, Rn, Vn);
return buff;
}
//TRNx
if(isMask(opcode, "0Q001110ff0mmmmm0o1010nnnnnddddd", &a)) {
const char* T[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
int sz = sf;
const char* Vn = T[(sz<<1)|a.Q];
const char* Vm = T[(sz<<1)|a.Q];
const char* Vd = T[(sz<<1)|a.Q];
snprintf(buff, sizeof(buff), "TRN%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vn, Rm, Vm);
return buff;
}
//SHA1 stuffs
if(isMask(opcode, "0101111000101000000010nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA1H S%d, S%d", Rd, Rn);
return buff;
}
if(isMask(opcode, "0101111000101000000110nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA1SU1 V%d.4S, V%d.4S", Rd, Rn);
return buff;
}
if(isMask(opcode, "01011110000mmmmm000000nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA1C Q%d, S%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
if(isMask(opcode, "01011110000mmmmm001000nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA1M Q%d, S%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
if(isMask(opcode, "01011110000mmmmm000100nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA1P Q%d, S%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
//SHA256 stuffs
if(isMask(opcode, "0101111000101000001010nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA256SU0 V%d.4S, V%d.4S", Rd, Rn);
return buff;
}
if(isMask(opcode, "01011110000mmmmm011000nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA256SU1 V%d.4S, V%d.4S, V%d.4S", Rd, Rn, Rm);
return buff;
}
if(isMask(opcode, "01011110000mmmmm010000nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA256H Q%d, Q%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
if(isMask(opcode, "01011110000mmmmm010100nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "SHA256H2 Q%d, Q%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
return buff;
File diff suppressed because it is too large. Load diff
+592 -99
View File
@@ -17,6 +17,7 @@
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
@@ -302,7 +303,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMWRITE2();
}
break;
case 0x2A:
INST_NAME("CVTPI2PS Gx,Em");
nextop = F8;
GETGX(v0, 1);
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn);
u8 = sse_setround(dyn, ninst, x1, x2, x3);
SCVTFS(d0, q1);
x87_restoreround(dyn, ninst, u8);
VMOVeD(v0, 0, d0, 0);
break;
case 0x2B:
INST_NAME("MOVNTPS Ex,Gx");
nextop = F8;
@@ -317,7 +328,69 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VST128(v0, ed, fixedaddress);
}
break;
case 0x2C:
INST_NAME("CVTTPS2PI Gm,Ex");
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if (box64_dynarec_fastround) {
VFCVTZSS(q0, v1);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
if (i) {
VMOVeS(d0, 0, v1, i);
FRINTZS(d0, d0);
} else {
FRINTZS(d0, v1);
}
FCVTZSwS(x1, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
MOVw_REG(x1, x2);
VMOVQSfrom(q0, i, x1);
}
}
break;
case 0x2D:
INST_NAME("CVTPS2PI Gm, Ex");
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if (box64_dynarec_fastround) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIS(q0, v1);
x87_restoreround(dyn, ninst, u8);
VFCVTZSS(q0, q0);
} 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(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
if (i) {
VMOVeS(d0, 0, v1, i);
FRINTIS(d0, d0);
} else {
FRINTIS(d0, v1);
}
FCVTZSwS(x1, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
MOVw_REG(x1, x2);
VMOVQSfrom(q0, i, x1);
}
x87_restoreround(dyn, ninst, u8);
}
break;
case 0x2E:
// no special check...
case 0x2F:
@@ -349,11 +422,34 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGM(q0);
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn);
MOVI_8(d0, 0b10001111);
MOVI_8(d0, 0b10000111);
VAND(d0, d0, q1); // mask the index
VTBL1_8(q0, q0, d0);
break;
case 0x01:
INST_NAME("PHADDW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
VADDP_16(q0, q0, q1);
break;
case 0x2:
INST_NAME("PHADDD Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
VADDP_32(q0, q0, q1);
break;
case 0x03:
INST_NAME("PHADDSW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VUZP1_16(v0, q0, q1);
VUZP2_16(q0, q0, q1);
SQADD_16(q0, q0, v0);
break;
case 0x04:
INST_NAME("PMADDUBSW Gm,Em");
nextop = F8;
@@ -367,7 +463,75 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SADDLPQ_16(v1, v0);
SQXTN_16(q0, v1);
break;
case 0x05:
INST_NAME("PHSUBW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VUZP1_16(v0, q0, q1);
VUZP2_16(q0, q0, q1);
VSUB_16(q0, v0, q0);
break;
case 0x06:
INST_NAME("PHSUBD Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VUZP1_32(v0, q0, q1);
VUZP2_32(q0, q0, q1);
VSUB_32(q0, v0, q0);
break;
case 0x07:
INST_NAME("PHSUBSW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
VUZP1_16(v0, q0, q1);
VUZP2_16(q0, q0, q1);
SQSUB_16(q0, v0, q0);
break;
case 0x08:
INST_NAME("PSIGNB Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
CMGT_0_8(v0, q1);
VAND(v0, v0, q0);
CMLT_0_8(v1, q1);
VMUL_8(q0, q0, v1);
VORR(q0, q0, v0);
break;
case 0x09:
INST_NAME("PSIGNW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
CMGT_0_16(v0, q1);
VAND(v0, v0, q0);
CMLT_0_16(v1, q1);
VMUL_16(q0, q0, v1);
VORR(q0, q0, v0);
break;
case 0x0A:
INST_NAME("PSIGND Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
CMGT_0_32(v0, q1);
VAND(v0, v0, q0);
CMLT_0_32(v1, q1);
VMUL_32(q0, q0, v1);
VORR(q0, q0, v0);
break;
case 0x0B:
INST_NAME("PMULHRSW Gm,Em");
nextop = F8;
@@ -375,6 +539,199 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(q1, 0);
SQRDMULH_16(q0, q0, q1);
break;
case 0x1C:
INST_NAME("PABSB Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
ABS_8(q0, q1);
break;
case 0x1D:
INST_NAME("PABSW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
ABS_16(q0, q1);
break;
case 0x1E:
INST_NAME("PABSD Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
ABS_32(q0, q1);
break;
case 0xC8:
INST_NAME("SHA1NEXTE Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
VEORQ(v0, v0, v0);
if(arm64_sha1) {
v1 = fpu_get_scratch(dyn);
VMOVeS(v1, 0, q0, 3);
SHA1H(v1, v1);
VMOVeS(v0, 3, v1, 0);
} else {
VMOVSto(x1, q0, 3);
RORw(x1, x1, 2); // i.e. ROL 30
VMOVQSfrom(v0, 3, x1);
}
VADDQ_32(q0, v0, q1);
break;
case 0xC9:
INST_NAME("SHA1MSG1 Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
VEXTQ_8(v0, q1, q0, 8);
VEORQ(q0, q0, v0);
break;
case 0xCA:
INST_NAME("SHA1MSG2 Gx, Ex");
nextop = F8;
if(arm64_sha1) {
GETGX(q0, 1);
GETEX(q1, 0, 0);
VEXTQ_8(q0, q0, q0, 8);
VREV64Q_32(q0, q0);
if(MODREG) {
if(q0==q1)
v0 = q0;
else {
v0 = fpu_get_scratch(dyn);
VEXTQ_8(v0, q1, q1, 8);
VREV64Q_32(v0, v0);
}
} else {
v0 = q1;
VEXTQ_8(v0, q1, q1, 8);
VREV64Q_32(v0, v0);
}
SHA1SU1(q0, v0);
VEXTQ_8(q0, q0, q0, 8);
VREV64Q_32(q0, q0);
} else {
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x2) {
MOVx_REG(x2, wback);
}
}
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
CALL(sha1msg2, -1);
}
break;
case 0xCB:
INST_NAME("SHA256RNDS2 Gx, Ex (, XMM0)");
nextop = F8;
if(arm64_sha2) {
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = sse_get_reg(dyn, ninst, x1, 0, 0);
v0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
if(MODREG) {
v1 = fpu_get_scratch(dyn);
} else
v1 = q1;
VREV64Q_32(q0, q0);
VREV64Q_32(v1, q1);
VZIP1Q_64(v0, v1, q0);
VZIP2Q_64(v1, v1, q0);
SHA256H(v1, v0, d0);
VREV64Q_32(d1, q1);
VZIP2Q_64(d1, d1, q0);
SHA256H2(v0, d1, d0);
VZIP2Q_64(q0, v0, v1);
VREV64Q_32(q0, q0);
} else {
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x2) {
MOVx_REG(x2, wback);
}
}
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
sse_reflect_reg(dyn, ninst, 0);
CALL(sha256rnds2, -1);
}
break;
case 0xCC:
INST_NAME("SHA256MSG1 Gx, Ex");
nextop = F8;
if(arm64_sha2) {
GETGX(q0, 1);
GETEX(q1, 0, 0);
SHA256SU0(q0, q1);
} else {
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x2) {
MOVx_REG(x2, wback);
}
}
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
CALL(sha256msg1, -1);
}
break;
case 0xCD:
INST_NAME("SHA256MSG2 Gx, Ex");
nextop = F8;
if(arm64_sha2) {
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VEORQ(v1, v1, v1);
VMOVQ(v0, q0);
SHA256SU1(v0, v1, q1); // low v0 are ok and also need to be feed again SHA256SU1 to get the high part
VTRNQ1_64(d0, v0, v0); // duplicate low to hi
VEXTQ_8(q0, q0, q0, 8); // invert low/high now
SHA256SU1(q0, v1, d0); // low is destination high
VEXTQ_8(q0, d0, q0, 8);
} else {
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x2) {
MOVx_REG(x2, wback);
}
}
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
CALL(sha256msg2, -1);
}
break;
case 0xF0:
INST_NAME("MOVBE Gd, Ed");
@@ -427,6 +784,81 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VEXT_8(q0, q1, q0, u8);
}
break;
case 0xCC:
INST_NAME("SHA1RNDS4 Gx, Ex, Ib");
nextop = F8;
if(arm64_sha1) {
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8&3;
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn);
VEXTQ_8(v0, q0, q0, 8);
VREV64Q_32(v0, v0);
VEORQ(d1, d1, d1);
if(MODREG) {
if(q0==q1)
v1 = v0;
else
v1 = fpu_get_scratch(dyn);
} else
v1 = q1;
if(v1!=v0) {
VEXTQ_8(v1, q1, q1, 8);
VREV64Q_32(v1, v1);
}
switch(u8) {
case 0:
MOV32w(x1, 0x5A827999);
VDUPQS(d0, x1);
VADDQ_32(v1, v1, d0);
SHA1C(v0, d1, v1);
break;
case 1:
MOV32w(x1, 0x6ED9EBA1);
VDUPQS(d0, x1);
VADDQ_32(v1, v1, d0);
SHA1P(v0, d1, v1);
break;
case 2:
MOV32w(x1, 0X8F1BBCDC);
VDUPQS(d0, x1);
VADDQ_32(v1, v1, d0);
SHA1M(v0, d1, v1);
break;
case 3:
MOV32w(x1, 0xCA62C1D6);
VDUPQS(d0, x1);
VADDQ_32(v1, v1, d0);
SHA1P(v0, d1, v1);
break;
}
VREV64Q_32(v0, v0);
VEXTQ_8(q0, v0, v0, 8);
break;
} else {
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(wback!=x2) {
MOVx_REG(x2, wback);
}
}
u8 = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
MOV32w(x3, u8);
CALL(sha1rnds4, -1);
}
break;
default:
DEFAULT;
}
@@ -787,33 +1219,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VMOVeS(v0, 1, v1, 0);
}
} else if(u8==0x00) {
// dumplicate lower 16bits to all spot
if(v0!=v1) {
VMOVeH(v0, 0, v1, 0);
}
VMOVeH(v0, 1, v1, 0);
VMOVeS(v0, 1, v1, 0);
// duplicate lower 16bits to all spot
VDUP_16(v0, v1, 0);
} else if(u8==0x55) {
// dumplicate 16bits slot 1 to all spot
if(v0!=v1) {
VMOVeH(v0, 1, v1, 1);
}
VMOVeH(v0, 0, v1, 1);
VMOVeS(v0, 1, v1, 0);
// duplicate 16bits slot 1 to all spot
VDUP_16(v0, v1, 1);
} else if(u8==0xAA) {
// dumplicate 16bits slot 2 to all spot
if(v0!=v1) {
VMOVeH(v0, 2, v1, 2);
}
VMOVeH(v0, 3, v1, 2);
VMOVeS(v0, 0, v1, 1);
// duplicate 16bits slot 2 to all spot
VDUP_16(v0, v1, 2);
} else if(u8==0xFF) {
// dumplicate 16bits slot 3 to all spot
if(v0!=v1) {
VMOVeH(v0, 3, v1, 3);
}
VMOVeH(v0, 2, v1, 3);
VMOVeS(v0, 0, v1, 1);
// duplicate 16bits slot 3 to all spot
VDUP_16(v0, v1, 3);
} else if(v0!=v1) {
VMOVeH(v0, 0, v1, (u8>>(0*2))&3);
VMOVeH(v0, 1, v1, (u8>>(1*2))&3);
@@ -1133,13 +1549,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
UXTBw(x3, xRCX);
SETFLAGS(X_ALL, SF_SET);
GETEDW(x4, x1, 0);
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
GETGD;
MOVxw_REG(x2, gd);
CALL_(rex.w?((void*)shld64):((void*)shld32), ed, x4);
GETED(0);
if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}
UFLAG_IF {
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
B_NEXT(cEQ);
} else {
if(rex.w) {
ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
}
emit_shld32(dyn, ninst, rex, ed, gd, x3, x5, x4);
WBACK;
break;
@@ -1166,17 +1596,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDSx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDSw_mask(x4, x4, 0, 0); //mask=1
IFX(X_CF) {
LSRxw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
EORxw_REG(x4, ed, x4);
CSELxw(ed, ed, x4, cNE);
ORRxw_REG(ed, ed, x4);
if(wback) {
STRxw_U12(ed, wback, fixedaddress);
SMWRITE();
@@ -1195,13 +1621,27 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ed, Gd, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
UXTBw(x3, xRCX);
GETEDW(x4, x1, 0);
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
GETGD;
MOVxw_REG(x2, gd);
CALL_(rex.w?((void*)shrd64):((void*)shrd32), ed, x4);
GETED(0);
if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}
UFLAG_IF {
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
B_NEXT(cEQ);
} else {
if(rex.w) {
ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
}
emit_shrd32(dyn, ninst, rex, ed, gd, x3, x5, x4);
WBACK;
break;
@@ -1279,7 +1719,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
@@ -1288,9 +1728,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {
SMULH(x3, gd, ed);
MULx(gd, gd, ed);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
IFX(X_PEND) {
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x4, d_imul64);
} else IFX(X_CF|X_OF) {
SET_DFNONE(x4);
}
IFX(X_CF|X_OF) {
ASRx(x4, gd, 63);
CMPSx_REG(x3, x4);
CSETw(x3, cNE);
BFIw(xFlags, x3, F_CF, 1);
BFIw(xFlags, x3, F_OF, 1);
}
} else {
MULxw(gd, gd, ed);
}
@@ -1298,10 +1749,29 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// 32bits imul
UFLAG_IF {
SMULL(gd, gd, ed);
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
IFX(X_PEND) {
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x4, d_imul32);
} else IFX(X_CF|X_OF) {
SET_DFNONE(x4);
}
IFX(X_CF|X_OF) {
ASRx(x3, gd, 31);
ASRw(x4, gd, 31);
CMPSw_REG(x3, x4);
CSETw(x3, cNE);
BFIw(xFlags, x3, F_CF, 1);
BFIw(xFlags, x3, F_OF, 1);
}
if(box64_dynarec_test) {
// to avoid noise during test
BFCw(xFlags, F_AF, 1);
BFCw(xFlags, F_PF, 1);
BFCw(xFlags, F_ZF, 1);
BFCw(xFlags, F_SF, 1);
}
MOVw_REG(gd, gd);
} else {
MULxw(gd, gd, ed);
@@ -1332,13 +1802,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDw_mask(x4, x4, 0, 0); //mask=1
IFX(X_CF) {
LSRxw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
BICxw_REG(ed, ed, x4);
@@ -1417,15 +1884,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
MOV32w(x4, 1);
ORRxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
case 6:
INST_NAME("BTR Ed, Ib");
@@ -1442,15 +1909,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
MOV32w(x4, 1);
BICxw_REG_LSL(ed, ed, x4, u8);
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
BFCxw(ed, u8, 1);
if(wback) {
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
case 7:
INST_NAME("BTC Ed, Ib");
@@ -1467,14 +1933,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
u8 = F8;
u8&=(rex.w?0x3f:0x1f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
if(wback) {
STxw(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
default:
DEFAULT;
@@ -1503,13 +1970,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ANDw_mask(x2, gd, 0, 0b00100); //mask=0x00000001f
}
LSRxw_REG(x4, ed, x2);
if(rex.w) {
ANDx_mask(x4, x4, 1, 0, 0); //mask=1
} else {
ANDw_mask(x4, x4, 0, 0); //mask=1
IFX(X_CF) {
LSRxw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
}
BFIw(xFlags, x4, F_CF, 1);
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
EORxw_REG(ed, ed, x4);
@@ -1780,12 +2244,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
if(MODREG)
q0 = fpu_get_scratch(dyn);
else
q0 = d1;
NEG_64(q0, d1);
USHL_R_64(d0, d0, q0);
v0 = fpu_get_scratch(dyn);
//MOVI_64(v0, 64); not 64!
MOV32w(x1, 64);
VMOVQDfrom(v0, 0, x1);
UMIN_32(v0, v0, d1); // limit to 0 .. +64 values (will force 32bits upper part to 0)
NEG_64(v0, v0);
USHL_R_64(d0, d0, v0);
break;
case 0xD4:
INST_NAME("PADDQ Gm,Em");
@@ -1975,7 +2440,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VEOR(q0, q0, q1);
}
break;
case 0xF1:
INST_NAME("PSLLW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
v0 = fpu_get_scratch(dyn);
VMOVHto(x1, d1, 0);
VDUPH(v0, x1);
USHL_16(d0, d0, v0);
break;
case 0xF2:
INST_NAME("PSLLD Gm,Em");
nextop = F8;
@@ -1987,11 +2461,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SQXTN_32(v0, v0); // 2*q1 in 32bits now
SSHL_32(d0, d0, v0);
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
case 0xF3:
INST_NAME("PSLLQ Gm,Em");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
GETGM(d0);
GETEM(d1, 0);
USHL_R_64(d0, d0, d1);
break;
case 0xF4:
INST_NAME("PMULUDQ Gm,Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VUMULL_32(v0, v0, v1);
break;
case 0xF5:
@@ -2016,7 +2497,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UADDLVQ_16(d1, d0);
VMOVeD(q0, 0, d1, 0);
break;
case 0xF7:
INST_NAME("MASKMOVQ Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VSSHR_8(d1, q1, 7); // d1 = byte slection mask
VLDR64_U12(d0, xRDI, 0);
VBIC(d0, d0, d1); // d0 = clear masked byte
VAND(d1, q0, d1); // d1 = masked Gm
VORR(d0, d0, d1);
VSTR64_U12(d0, xRDI, 0);
break;
case 0xF8:
INST_NAME("PSUBB Gm, Em");
nextop = F8;
@@ -2038,14 +2532,6 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(v1, 0);
VSUB_32(v0, v0, v1);
break;
case 0xFC:
INST_NAME("PADDB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VADD_8(v0, v0, v1);
break;
case 0xFB:
INST_NAME("PSUBQ Gm, Em");
nextop = F8;
@@ -2053,6 +2539,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(v1, 0);
SUB_64(v0, v0, v1);
break;
case 0xFC:
INST_NAME("PADDB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VADD_8(v0, v0, v1);
break;
case 0xFD:
INST_NAME("PADDW Gm, Em");
nextop = F8;
+84 -7
View File
@@ -58,6 +58,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x01:
INST_NAME("ADD Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, ed, gd, x3, x5);
WBACKO(x4);
break;
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -223,8 +233,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
MOVw_REG(gd, gd);
UFLAG_DF(x3, d_imul32);
} else {
MULxw(gd, gd, ed);
}
@@ -268,6 +278,28 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x21:
INST_NAME("AND Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_and32(dyn, ninst, rex, ed, gd, x3, x5);
WBACKO(x4);
break;
case 0x29:
INST_NAME("SUB Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x5);
WBACKO(x4);
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -278,6 +310,17 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x31:
INST_NAME("XOR Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, ed, gd, x3, x5);
WBACKO(x4);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -337,10 +380,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
}
break;
case 0x64:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
break;
case 0x67:
if(rex.is32bits)
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, seg, ok, need_epilog);
else {
DEFAULT;
}
break;
case 0x80:
nextop = F8;
@@ -514,7 +569,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
gd = (nextop&0x38)>>3;
gb1 = xRAX+(gd&3);
gb2 = ((gd&4)>>2);
gb2 = ((gd&4)<<1);
}
if(MODREG) {
if(rex.rex) {
@@ -538,7 +593,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRB_REG(x4, wback, x4);
ed = x4;
}
BFIx(gb1, ed, gb2*8, 8);
BFIx(gb1, ed, gb2, 8);
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
@@ -584,7 +639,22 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
u8 = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
LDRH_REG(x1, wback, x4);
ed = x1;
}
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0x8F:
INST_NAME("POP FS:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
@@ -604,6 +674,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA1:
INST_NAME("MOV EAX,FS:Od");
@@ -902,7 +975,6 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
GETEDO(x6, 0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -916,11 +988,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
GETEDO(x6, 0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -934,6 +1006,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
break;
case 6:
INST_NAME("DIV Ed");
@@ -1048,6 +1121,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEDOz(x6, 0);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
@@ -1055,12 +1129,15 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
GETIP_(addr);
if(box64_dynarec_callret) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
+298 -132
View File
@@ -15,6 +15,7 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
@@ -42,7 +43,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(j64);
MAYUSE(lock);
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x66)) // ignoring CS:, SS: or multiple 0x66
while((opcode==0x2E) || (opcode==0x36) || (opcode==0x26) || (opcode==0x66)) // ignoring CS:, SS:, ES: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
@@ -82,6 +83,25 @@ 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 0x06:
if(rex.is32bits) {
INST_NAME("PUSH ES");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
PUSH1_32(x1);
} else {
DEFAULT;
}
break;
case 0x07:
if(rex.is32bits) {
INST_NAME("POP ES");
POP1_32(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_ES]));
} else {
DEFAULT;
}
break;
case 0x09:
INST_NAME("OR Ew, Gw");
@@ -112,7 +132,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x0F:
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
switch(rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
}
break;
case 0x11:
INST_NAME("ADC Ew, Gw");
@@ -175,6 +199,25 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
break;
case 0x1E:
if(rex.is32bits) {
INST_NAME("PUSH DS");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
PUSH1_32(x1);
} else {
DEFAULT;
}
break;
case 0x1F:
if(rex.is32bits) {
INST_NAME("POP DS");
POP1_32(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
} else {
DEFAULT;
}
break;
case 0x21:
INST_NAME("AND Ew, Gw");
@@ -330,7 +373,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(rex.is32bits) {
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07);
if (gd == xRSP) {
if (gd==xRSP) {
MOVw_REG(x1, xRSP);
PUSH1_16(x1);
} else {
@@ -415,7 +458,6 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
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);
@@ -423,6 +465,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_RES(x2);
gd=x2;
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0x70:
@@ -548,19 +591,36 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
GETGD;
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);
MARKLOCK;
LDAXRH(x1, ed);
STLXRH(x3, gd, ed);
CBNZx_MARKLOCK(x3);
B_MARK2_nocond;
MARK;
LDRH_U12(x1, ed, 0);
STRH_U12(gd, ed, 0);
MARK2;
SMDMB();
if(!ALIGNED_ATOMICH) {
TSTx_mask(ed, 1, 0, 0); // mask=1
B_MARK(cNE);
}
if(arm64_atomics) {
SWPALH(gd, x1, ed);
SMDMB();
if(!ALIGNED_ATOMICH) {
B_MARK2_nocond;
}
} else {
MARKLOCK;
LDAXRH(x1, ed);
STLXRH(x3, gd, ed);
CBNZx_MARKLOCK(x3);
SMDMB();
if(!ALIGNED_ATOMICH) {
B_MARK2_nocond;
}
}
if(!ALIGNED_ATOMICH) {
MARK;
LDRH_U12(x1, ed, 0);
LDAXRB(x3, ed);
STLXRB(x3, gd, ed);
CBNZx_MARK(x3);
STRH_U12(gd, ed, 0);
SMDMB();
MARK2;
}
BFIx(gd, x1, 0, 16);
}
break;
@@ -600,7 +660,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV EW, Seg");
nextop=F8;
u8 = (nextop&0x38)>>3;
LDRw_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
LDRH_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
@@ -610,6 +670,22 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
u8 = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDH(x1, wback, fixedaddress);
ed = x1;
}
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0x90:
case 0x91:
case 0x92:
@@ -634,7 +710,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTBw(x1, xRAX);
BFIx(xRAX, x1, 0, 16);
break;
case 0x99:
INST_NAME("CWD");
SXTHw(x1, xRAX);
BFXILx(xRDX, x1, 16, 16);
break;
case 0x9C:
INST_NAME("PUSHF");
READFLAGS(X_ALL);
@@ -665,7 +745,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
else
u64 = F64;
MOV64z(x1, u64);
SMREAD();
if(isLockAddress(u64)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDRH_U12(x2, x1, 0);
BFIx(xRAX, x2, 0, 16);
break;
@@ -677,8 +758,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
else
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
STRH_U12(xRAX, x1, 0);
SMWRITE();
SMWRITELOCK(lock);
break;
case 0xA5:
@@ -864,23 +946,29 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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;
if(geted_ib(dyn, addr, ninst, nextop)&15) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1, 1);
u8 = F8;
emit_rol16c(dyn, ninst, x1, u8&15, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(ror16, x1, x3);
EWBACK;
if(geted_ib(dyn, addr, ninst, nextop)&15) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1, 1);
u8 = F8;
emit_ror16c(dyn, ninst, x1, u8&15, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 2:
INST_NAME("RCL Ew, Ib");
@@ -907,42 +995,42 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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)
LSLw_IMM(ed, ed, u8&0x1f);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8)&0x1f;
emit_shl16c(dyn, ninst, x1, u8, x5, x4);
EWBACK;
} else {
FAKEED;
F8;
}
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)
LSRw_IMM(ed, ed, u8&0x1f);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8)&0x1f;
emit_shr16c(dyn, ninst, x1, u8, x5, x4);
EWBACK;
} else {
FAKEED;
F8;
}
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)
ASRw(ed, ed, (u8&0x1f));
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEW(x1, 0);
u8 = (F8)&0x1f;
emit_sar16c(dyn, ninst, x1, u8, x5, x4);
EWBACK;
} else {
FAKEED;
F8;
}
break;
}
break;
@@ -965,108 +1053,186 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
if(opcode==0xD1) {
INST_NAME("ROL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
ANDw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROL Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
CALL_(rol16, x1, x3);
emit_rol16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 1:
if(opcode==0xD1) {
INST_NAME("ROR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROR Ew, CL");
ANDw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
CALL_(ror16, x1, x3);
emit_ror16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 2:
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
INST_NAME("RCL Ew, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
MOV32w(x2, 1);
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
EWBACK;
break;
case 3:
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
INST_NAME("RCR Ew, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDw_mask(x2, xRCX, 0, 0b00100);}
MOV32w(x2, 1);
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
EWBACK;
break;
case 4:
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHL Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
LSLw_REG(ed, ed, x4);
emit_shl16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
LSRw_REG(ed, ed, x4);
emit_shr16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOV32w(x4, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SAR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEW(x1, 0);
UFLAG_OP12(ed, x4)
ASRw_REG(ed, ed, x4);
emit_sar16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
}
break;
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
MOV32w(x4, 16);
SUBx_REG(x2, x4, x2);
GETEW(x1, 0);
ORRw_REG_LSL(ed, ed, ed, 16);
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPSw_U12(x2, 15);
B_MARK(cNE);
ADDxw_REG_LSR(x3, ed, ed, 15);
BFIw(xFlags, x3, F_OF, 1);
MARK;
BFIw(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
GETEW(x1, 0);
ORRw_REG_LSL(ed, ed, ed, 16);
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPSw_U12(x2, 1);
B_MARK(cNE);
LSRxw(x2, ed, 14); // x2 = d>>14
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFIw(xFlags, x2, F_OF, 1);
MARK;
BFXILw(xFlags, ed, 15, 1);
UFLAG_DF(x2, d_none);
}
break;
case 2:
INST_NAME("RCL Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4);
EWBACK;
break;
case 5:
INST_NAME("SHR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4);
EWBACK;
break;
case 7:
INST_NAME("SAR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
@@ -1102,24 +1268,24 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
INST_NAME("MUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_mul16);
GETEW(x1, 0);
UXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_mul16);
break;
case 5:
INST_NAME("IMUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 0);
SXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_imul16);
break;
case 6:
INST_NAME("DIV Ew");
@@ -1134,7 +1300,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);
SKIPTEST(x1);
SETFLAGS(X_ALL, SF_SET);
GETSEW(x1, 0);
UXTHw(x2, xRAX);
+504 -109
View File
@@ -20,10 +20,11 @@
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
@@ -48,6 +49,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MAYUSE(j64);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
static const int8_t round_round[] = { 0, 2, 1, 3};
#endif
@@ -169,7 +172,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
FAKEED;
break;
case 0x28:
INST_NAME("MOVAPD Gx,Ex");
nextop = F8;
@@ -201,7 +204,92 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SMWRITE2();
}
break;
case 0x2A:
INST_NAME("CVTPI2PD Gx,Em");
nextop = F8;
GETGX(v0, 1);
GETEM(q1, 0);
SXTL_32(v0, q1);
SCVTQFD(v0, v0);
break;
case 0x2B:
INST_NAME("MOVNTPD Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
}
break;
case 0x2C:
INST_NAME("CVTTPD2PI Gm,Ex");
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if(box64_dynarec_fastround) {
VFCVTZSQD(q0, v1);
SQXTN_32(q0, q0);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
if (i) {
VMOVeD(d0, 0, v1, i);
FRINTZD(d0, d0);
} else {
FRINTZD(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, x2);
VMOVQSfrom(q0, i, x1);
}
}
break;
case 0x2D:
INST_NAME("CVTPD2PI Gm,Ex");
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if(box64_dynarec_fastround) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIDQ(q0, v1);
FCVTXN(q0, q0);
x87_restoreround(dyn, ninst, u8);
VFCVTZSS(q0, q0);
} 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(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
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, x2);
VMOVQSfrom(q0, i, x1);
}
x87_restoreround(dyn, ninst, u8);
}
break;
case 0x2E:
// no special check...
case 0x2F:
@@ -241,7 +329,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q1, 0, 0);
VADDPQ_32(q0, q0, q1);
break;
case 0x03:
INST_NAME("PHADDSW Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
VUZP1Q_16(v0, q0, q1);
VUZP2Q_16(q0, q0, q1);
SQADDQ_16(q0, q0, v0);
break;
case 0x04:
INST_NAME("PMADDUBSW Gx,Ex");
nextop = F8;
@@ -443,14 +540,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x20:
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
break;
case 0x21:
INST_NAME("PMOVSXBD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX32(q1, 0, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
SXTL_16(q0, q0); //16bits->32bits
@@ -458,7 +555,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x22:
INST_NAME("PMOVSXBQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX16(q1, 0, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
SXTL_16(q0, q0); //16bits->32bits
@@ -467,14 +564,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x23:
INST_NAME("PMOVSXWD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
SXTL_16(q0, q1); // 16bits->32bits
break;
case 0x24:
INST_NAME("PMOVSXWQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX32(q1, 0, 0);
GETGX_empty(q0);
SXTL_16(q0, q1); // 16bits->32bits
SXTL_32(q0, q0); // 32bits->64bits
@@ -482,7 +579,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x25:
INST_NAME("PMOVSXDQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
SXTL_32(q0, q1); // 32bits->64bits
break;
@@ -539,14 +636,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x30:
INST_NAME("PMOVZXBW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
UXTL_8(q0, q1); // 8bits->16bits
break;
case 0x31:
INST_NAME("PMOVZXBD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX32(q1, 0, 0);
GETGX_empty(q0);
UXTL_8(q0, q1); // 8bits->16bits
UXTL_16(q0, q0); //16bits->32bits
@@ -554,7 +651,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x32:
INST_NAME("PMOVZXBQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX16(q1, 0, 0);
GETGX_empty(q0);
UXTL_8(q0, q1); // 8bits->16bits
UXTL_16(q0, q0); //16bits->32bits
@@ -563,14 +660,14 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x33:
INST_NAME("PMOVZXWD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
UXTL_16(q0, q1); // 16bits->32bits
break;
case 0x34:
INST_NAME("PMOVZXWQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX32(q1, 0, 0);
GETGX_empty(q0);
UXTL_16(q0, q1); // 16bits->32bits
UXTL_32(q0, q0); // 32bits->64bits
@@ -578,11 +675,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x35:
INST_NAME("PMOVZXDQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETEX64(q1, 0, 0);
GETGX_empty(q0);
UXTL_32(q0, q1); // 32bits->64bits
break;
case 0x37:
INST_NAME("PCMPGTQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
VCMGTQ_64(q0, q0, q1);
break;
case 0x38:
INST_NAME("PMINSB Gx, Ex"); // SSE4 opcode!
nextop = F8;
@@ -757,7 +861,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0);
LDH(x1, ed, fixedaddress);
REV16x(x1, x1);
BFIx(gd, x1, 0, 16);
@@ -773,7 +877,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, x1, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, (1<<2)-1, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, 0);
REV16x(x1, gd);
STH(x1, ed, fixedaddress);
}
@@ -863,7 +967,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeS(q0, i, q1, i);
}
break;
case 0x0D:
INST_NAME("PBLENDPD Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8&0b11;
if(u8==0b01) {
VMOVeD(q0, 0, q1, 0);
} else if(u8==0b10) {
VMOVeD(q0, 1, q1, 1);
} else if(u8==0b11) {
VMOVQ(q0, q1);
}
break;
case 0x0E:
INST_NAME("PBLENDW Gx, Ex, Ib");
nextop = F8;
@@ -907,7 +1024,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q1, 0, 1);
u8 = F8;
if(u8>31) {
VEORQ(q0, q0, q0);
VEORQ(q0, q0, q0);
} else if(u8>15) {
d0 = fpu_get_scratch(dyn);
VEORQ(d0, d0, d0);
@@ -970,7 +1087,22 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SMWRITE2();
}
break;
case 0x17:
INST_NAME("EXTRACTPS Ew, Gx, Ib");
nextop = F8;
GETGX(q0, 0);
if (MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8&0b11;
MOVx_REG(ed, xZR);
VMOVSto(ed, q0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0xfff<<2, 3, rex, NULL, 0, 1);
u8 = F8&0b11;
VMOVSto(x1, q0, u8);
STW(x1, wback, fixedaddress);
}
break;
case 0x20:
INST_NAME("PINSRB Gx, ED, Ib");
nextop = F8;
@@ -979,7 +1111,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
u8 = F8;
VMOVQBfrom(q0, (u8&15), ed);
break;
case 0x21:
INST_NAME("INSERTPS Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
d0 = fpu_get_scratch(dyn);
VMOVQ(d0, q0);
if (MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
u8 = F8;
VMOVeS(q0, (u8>>4)&3, q1, (u8>>6)&3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
u8 = F8;
LDW(x2, wback, fixedaddress);
VMOVQSfrom(q0, (u8>>4)&3, x2);
}
uint8_t zmask = u8 & 0xf;
for (uint8_t i=0; i<4; i++) {
if (zmask & (1<<i)) {
VMOVQSfrom(q0, i, wZR);
}
}
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
nextop = F8;
@@ -993,6 +1148,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x40:
INST_NAME("DPPS Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
v0 = fpu_get_scratch(dyn);
VFMULQS(v0, q0, q1);
// mask some, duplicate all, mask some
for(int i=0; i<4; ++i)
if(!(u8&(1<<(4+i)))) {
VMOVQSfrom(v0, i, xZR);
}
VFADDPQS(v0, v0, v0);
FADDPS(v0, v0);
VDUPQ_32(q0, v0, 0);
for(int i=0; i<4; ++i)
if(!(u8&(1<<i))) {
VMOVQSfrom(q0, i, xZR);
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
@@ -1021,7 +1198,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); //p = NULL
@@ -1038,6 +1215,181 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x60:
INST_NAME("PCMPESTRM Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd]));
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
}
MOVx_REG(x2, xRDX);
MOVx_REG(x4, xRAX);
u8 = F8;
MOV32w(x5, u8);
CALL(sse42_compare_string_explicit_len, x1);
q0 = sse_get_reg_empty(dyn, ninst, x2, gd);
q1 = fpu_get_scratch(dyn);
if(u8&0b1000000) {
switch(u8&1) {
case 0b00:
VDUPQB(q0, x1); // load the low 8bits of the mask
LSRw_IMM(x1, x1, 8);
VDUPQB(q1, x1); // load the high 8bits of the mask
VEXTQ_8(q0, q0, q1, 8); // low and hig bits mask
TABLE64(x2, (uintptr_t)&mask_string8);
VLDR64_U12(q1, x2, 0); // load shift
VDUPQ_64(q1, q1, 0);
USHLQ_8(q0, q0, q1); // extract 1 bit
MOVIQ_8(q1, 0x80); // load mask
VANDQ(q0, q0, q1);
VSSHRQ_8(q0, q0, 7); // saturate the mask
break;
case 0b01:
VDUPQH(q0, x1); // load the 8bits of the mask
TABLE64(x2, (uintptr_t)&mask_string16);
VLDR64_U12(q1, x2, 0); // load shift
UXTL_8(q1, q1); // extend mask to 16bits
USHLQ_16(q0, q0, q1); // extract 1 bit
MOVIQ_16(q1, 0x80, 1); // load mask
VANDQ(q0, q0, q1);
VSSHRQ_16(q0, q0, 15); // saturate the mask
}
} else {
VEORQ(q0, q0, q0);
VMOVQHfrom(q0, 0, x1);
}
break;
case 0x61:
INST_NAME("PCMPESTRI Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
nextop = F8;
GETG;
sse_reflect_reg(dyn, ninst, gd);
ADDx_U12(x3, xEmu, offsetof(x64emu_t, xmm[gd]));
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
}
MOVx_REG(x2, xRDX);
MOVx_REG(x4, xRAX);
u8 = F8;
MOV32w(x5, u8);
CALL(sse42_compare_string_explicit_len, x1);
CBNZw_MARK(x1);
MOV32w(xRCX, (u8&1)?8:16);
B_NEXT_nocond;
MARK;
if(u8&0b1000000) {
CLZw(xRCX, x1);
MOV32w(x2, 31);
SUBw_REG(xRCX, x2, xRCX);
} else {
RBITxw(xRCX, x1);
CLZw(xRCX, xRCX);
}
break;
case 0x62:
INST_NAME("PCMPISTRM Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd]));
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
}
u8 = F8;
MOV32w(x3, u8);
CALL(sse42_compare_string_implicit_len, x1);
q0 = sse_get_reg_empty(dyn, ninst, x2, gd);
q1 = fpu_get_scratch(dyn);
if(u8&0b1000000) {
switch(u8&1) {
case 0b00:
VDUPQB(q0, x1); // load the low 8bits of the mask
LSRw_IMM(x1, x1, 8);
VDUPQB(q1, x1); // load the high 8bits of the mask
VEXTQ_8(q0, q0, q1, 8); // low and hig bits mask
TABLE64(x2, (uintptr_t)&mask_string8);
VLDR64_U12(q1, x2, 0); // load shift
VDUPQ_64(q1, q1, 0);
USHLQ_8(q0, q0, q1); // extract 1 bit
MOVIQ_8(q1, 0x80); // load mask
VANDQ(q0, q0, q1);
VSSHRQ_8(q0, q0, 7); // saturate the mask
break;
case 0b01:
VDUPQH(q0, x1); // load the 8bits of the mask
TABLE64(x2, (uintptr_t)&mask_string16);
VLDR64_U12(q1, x2, 0); // load shift
UXTL_8(q1, q1); // extend mask to 16bits
USHLQ_16(q0, q0, q1); // extract 1 bit
MOVIQ_16(q1, 0x80, 1); // load mask
VANDQ(q0, q0, q1);
VSSHRQ_16(q0, q0, 15); // saturate the mask
}
} else {
VEORQ(q0, q0, q0);
VMOVQHfrom(q0, 0, x1);
}
break;
case 0x63:
INST_NAME("PCMPISTRI Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
nextop = F8;
GETG;
sse_reflect_reg(dyn, ninst, gd);
ADDx_U12(x2, xEmu, offsetof(x64emu_t, xmm[gd]));
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_reflect_reg(dyn, ninst, ed);
ADDx_U12(x1, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
}
u8 = F8;
MOV32w(x3, u8);
CALL(sse42_compare_string_implicit_len, x1);
CBNZw_MARK(x1);
MOV32w(xRCX, (u8&1)?8:16);
B_NEXT_nocond;
MARK;
if(u8&0b1000000) {
CLZw(xRCX, x1);
MOV32w(x2, 31);
SUBw_REG(xRCX, x2, xRCX);
} else {
RBITxw(xRCX, x1);
CLZw(xRCX, xRCX);
}
break;
case 0xDF:
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
nextop = F8;
@@ -1045,7 +1397,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); //p = NULL
@@ -1095,7 +1447,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
LSRx(x1, x1, 63);
LSRx(gd, gd, 63);
BFIx(gd, x1, 1, 1);
break;
break;
case 0x51:
INST_NAME("SQRTPD Gx, Ex");
nextop = F8;
@@ -1115,7 +1467,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFSQRTQD(q1, q0);
}
break;
case 0x54:
INST_NAME("ANDPD Gx, Ex");
nextop = F8;
@@ -1140,9 +1492,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x57:
INST_NAME("XORPD Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VEORQ(v0, v0, q0);
GETG;
if(MODREG && ((nextop&7)+(rex.b<<3)==gd)) {
// special case for XORPD Gx, Gx
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VEORQ(q0, q0, q0);
} else {
q0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(q1, 0, 0);
VEORQ(q0, q0, q1);
}
break;
case 0x58:
INST_NAME("ADDPD Gx, Ex");
@@ -1470,32 +1829,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
} else if(u8==0x00) {
// duplicate lower 32bits to all spot
if(v0!=v1) {
VMOVeS(v0, 0, v1, 0);
}
VMOVeS(v0, 1, v1, 0);
VMOVeD(v0, 1, v0, 0);
VDUPQ_32(v0, v1, 0);
} else if(u8==0x55) {
// duplicate slot 1 to all spot
if(v0!=v1) {
VMOVeS(v0, 1, v1, 1);
}
VMOVeS(v0, 0, v1, 1);
VMOVeD(v0, 1, v0, 0);
VDUPQ_32(v0, v1, 1);
} else if(u8==0xAA) {
// duplicate slot 2 to all spot
if(v0!=v1) {
VMOVeS(v0, 2, v1, 2);
}
VMOVeS(v0, 3, v1, 2);
VMOVeD(v0, 0, v0, 1);
VDUPQ_32(v0, v1, 2);
} else if(u8==0xFF) {
// duplicate slot 3 to all spot
if(v0!=v1) {
VMOVeS(v0, 3, v1, 3);
}
VMOVeS(v0, 2, v1, 3);
VMOVeD(v0, 0, v0, 1);
VDUPQ_32(v0, v1, 3);
} else if(u8==0x44) {
// duplicate slot 0/1 to all spot
VDUPQ_64(v0, v1, 0);
} else if(u8==0xEE) {
// duplicate slot 2/3 to all spot
VDUPQ_64(v0, v1, 1);
} else if(u8==0xB1) {
// invert 0/1 and 2/3
VREV64Q_32(v0, v1);
} else if(v0!=v1) {
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
@@ -1736,7 +2088,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x7D:
INST_NAME("HSUBPD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch(dyn);
VUZP1Q_64(v0, q0, q1);
VUZP2Q_64(q0, q0, q1);
VFSUBQD(q0, v0, q0);
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
@@ -1796,24 +2157,31 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIw(xFlags, x1, F_CF, 1);
break;
case 0xA4:
INST_NAME("SHLD Ew, Gw, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEW(x1, 1);
GETGW(x2);
u8 = F8;
emit_shld16c(dyn, ninst, ed, gd, u8, x4, x5);
EWBACK;
break;
case 0xA5:
nextop = F8;
if(opcode==0xA4) {
INST_NAME("SHLD Ew, Gw, Ib");
} else {
INST_NAME("SHLD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xA4)?1:0);
INST_NAME("SHLD Ew, Gw, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
GETGW(x2);
if(opcode==0xA4) {
u8 = F8;
MOV32w(x3, u8);
GETEW(x1, 0);
UFLAG_IF {
ANDSw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
}
CALL_(shld16, x1, wback);
EWBACKW(x1);
emit_shld16(dyn, ninst, ed, gd, x4, x5, x6);
EWBACK;
break;
case 0xAB:
@@ -1834,48 +2202,55 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = x4;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDSw_mask(x1, x1, 0, 0); //mask=1
B_NEXT(cNE);
IFX(X_CF) {
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
}
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
LSLw_REG(x1, x1, x2);
ORRx_REG(ed, ed, x1);
if(wback) {
STRH_U12(ed, wback, fixedaddress);
}
break;
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ew, Gw, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 1);
GETGW(x2);
u8 = F8;
emit_shrd16c(dyn, ninst, ed, gd, u8, x4, x5);
EWBACK;
break;
case 0xAD:
nextop = F8;
if(opcode==0xAC) {
INST_NAME("SHRD Ew, Gw, Ib");
} else {
INST_NAME("SHRD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xAC)?1:0);
INST_NAME("SHRD Ew, Gw, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
GETGW(x2);
if(opcode==0xAC) {
u8 = F8;
MOV32w(x3, u8);
GETEW(x1, 0);
UFLAG_IF {
ANDSw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
}
CALL_(shrd16, x1, wback);
EWBACKW(x1);
emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6);
EWBACK;
break;
case 0xAF:
INST_NAME("IMUL Gw,Ew");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETSEW(x1, 0);
GETSGW(x2);
MULw(x2, x2, x1);
UFLAG_RES(x2);
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0xB3:
@@ -1899,8 +2274,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDSw_mask(x1, x1, 0, 0); //mask=1
B_NEXT(cEQ);
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
BICx_REG(ed, ed, x1);
@@ -1916,7 +2289,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0; \
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
@@ -1967,12 +2340,12 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBNZ_MARK3(xFlags, 0); // bit already set, jump to next instruction
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
MOV32w(x4, 1);
ORRxw_REG_LSL(ed, ed, x4, u8);
BFIxw(ed, x4, u8, 1);
EWBACK(x1);
MARK3;
break;
case 6:
INST_NAME("BTR Ew, Ib");
@@ -1981,12 +2354,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
TBZ_MARK3(xFlags, 0); // bit already clear, jump to next instruction
MOV32w(x4, 1);
BICxw_REG_LSL(ed, ed, x4, u8);
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
BFCxw(ed, u8, 1);
EWBACK(x1);
MARK3;
break;
case 7:
INST_NAME("BTC Ew, Ib");
@@ -1995,7 +2367,9 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
MOV32w(x4, 1);
EORxw_REG_LSL(ed, ed, x4, u8);
EWBACK(x1);
@@ -2023,9 +2397,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = x4;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDw_mask(x1, x1, 0, 0); //mask=1
IFX(X_CF) {
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
}
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORx_REG(ed, ed, x1);
@@ -2091,6 +2466,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16);
break;
case 0xC1:
INST_NAME("XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
BFIx(xRAX+((nextop&0x38)>>3)+(rex.r<<3), ed, 0, 16);
emit_add16(dyn, ninst, ed, gd, x4, x5);
EWBACK;
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex, Ib");
nextop = F8;
@@ -2102,21 +2487,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0: VFCMEQQD(v0, v0, v1); break; // Equal
case 1: VFCMGTQD(v0, v1, v0); break; // Less than
case 2: VFCMGEQD(v0, v1, v0); break; // Less or equal
case 3: VFCMEQQD(v0, v0, v0);
case 3: VFCMEQQD(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQD(q0, v1, v1);
q0 = fpu_get_scratch(dyn);
VFCMEQQD(q0, v1, v1);
VANDQ(v0, v0, q0);
}
VMVNQ(v0, v0);
VMVNQ(v0, v0);
break; // NaN (NaN is not equal to himself)
case 4: VFCMEQQD(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: VFCMGTQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 6: VFCMGEQD(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
case 7: VFCMEQQD(v0, v0, v0);
case 7: VFCMEQQD(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
VFCMEQQD(q0, v1, v1);
q0 = fpu_get_scratch(dyn);
VFCMEQQD(q0, v1, v1);
VANDQ(v0, v0, q0);
}
break; // not NaN
@@ -2206,6 +2591,16 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VDUPQ_16(v0, v0, 0); // only the low 8bits will be used anyway
USHLQ_16(q0, q0, v0); // SHR x8
break;
case 0xD0:
INST_NAME("ADDSUBPD Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn);
VFSUBQD(v0, q0, q1);
VFADDQD(q0, q0, q1);
VMOVeD(q0, 0, v0, 0);
break;
case 0xD2:
INST_NAME("PSRLD Gx,Ex");
nextop = F8;
@@ -2283,7 +2678,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
UADDLV_8(q1, q1); // accumalte
VMOVBto(x1, q1, 0);
BFIx(gd, x1, 8, 8);
break;
break;
case 0xD8:
INST_NAME("PSUBUSB Gx, Ex");
nextop = F8;
+200 -103
View File
@@ -53,7 +53,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
SMDMB();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
@@ -61,13 +60,22 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, x6, 0, 16);
} else {
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);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
UFLAG_IF {
LDSETALH(x5, x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
} else {
STSETLH(x5, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
SMDMB();
break;
case 0x0F:
@@ -79,7 +87,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
UXTHw(x6, xRAX);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -90,34 +97,43 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, gd, 0, 16);
} else {
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);
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK3(cNE);
}
// Aligned version
MARKLOCK;
LDAXRH(x1, wback);
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRH(x4, gd, wback);
CBNZx_MARKLOCK(x4);
// done
B_MARK_nocond;
// Unaligned version
MARK3;
LDRH_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRB(x4, gd, wback);
CBNZx_MARK3(x4);
STRH_U12(gd, wback, 0);
if(arm64_atomics) {
MOVw_REG(x1, x6);
CASALH(x1, gd, wback);
} else {
MARKLOCK;
LDAXRH(x1, wback);
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRH(x4, gd, wback);
CBNZx_MARKLOCK(x4);
// done
}
if(!ALIGNED_ATOMICH) {
B_MARK_nocond;
// Unaligned version
MARK3;
LDRH_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
STLXRB(x4, gd, wback);
CBNZx_MARK3(x4);
STRH_U12(gd, wback, 0);
}
}
SMDMB();
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
BFIx(xRAX, x1, 0, 16);
SMDMB();
break;
case 0xC1:
@@ -126,7 +142,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
UXTHx(x5, gd);
SMDMB();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
BFIx(gd, ed, 0, 16);
@@ -134,18 +149,22 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, x5, 0, 16);
} else {
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);
STLXRH(x3, x4, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
LDADDALH(x5, x1, wback);
} else {
MARKLOCK;
LDAXRH(x1, wback);
ADDxw_REG(x4, x1, x5);
STLXRH(x3, x4, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
IFX(X_ALL|X_PEND) {
MOVxw_REG(x2, x1);
emit_add16(dyn, ninst, x2, x5, x3, x4);
}
BFIx(gd, x1, 0, 16);
}
SMDMB();
break;
default:
@@ -158,7 +177,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
SMDMB();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
@@ -171,13 +189,12 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
SMDMB();
break;
case 0x81:
case 0x83:
nextop = F8;
SMDMB();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -197,22 +214,35 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
}
if(arm64_atomics) {
LDADDALH(x5, x1, wback);
UFLAG_IF {
emit_add16(dyn, ninst, x1, x5, x3, x4);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICH) {
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
SMDMB();
}
}
break;
case 1: //OR
@@ -229,11 +259,21 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
UFLAG_IF {
LDSETALH(x5, x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
} else {
STSETLH(x5, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
break;
case 2: //ADC
@@ -256,6 +296,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
break;
case 3: //SBB
@@ -278,6 +319,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
break;
case 4: //AND
@@ -293,12 +335,24 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
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;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
MOV32w(x5, ~i32);
UFLAG_IF {
LDCLRALH(x5, x1, wback);
MVNw_REG(x5, x5);
emit_and16(dyn, ninst, x1, x5, x3, x4);
} else {
STCLRLH(x5, wback);
}
} else {
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
}
break;
case 5: //SUB
@@ -315,22 +369,38 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
}
if(arm64_atomics) {
NEGw_REG(x4, x5);
UFLAG_IF {
LDADDALH(x4, x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
} else {
STADDLH(x4, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICH) {
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
SMDMB();
}
}
break;
case 6: //XOR
@@ -347,11 +417,21 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
UFLAG_IF {
LDEORALH(x5, x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
} else {
STEORLH(x5, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
}
break;
case 7: //CMP
@@ -369,7 +449,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
}
SMDMB();
break;
case 0xFF:
@@ -379,7 +458,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0: // INC Ew
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SMDMB();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
@@ -387,18 +465,27 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, x6, 0, 16);
} else {
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);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
MOV32w(x3, 1);
UFLAG_IF {
LDADDALH(x3, x1, wback);
emit_inc16(dyn, ninst, x1, x3, x4);
} else {
STADDLH(x3, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_inc16(dyn, ninst, x1, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
SMDMB();
break;
case 1: //DEC Ew
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SMDMB();
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
@@ -406,13 +493,23 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(ed, x6, 0, 16);
} else {
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);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
if(arm64_atomics) {
MOV32w(x3, -1);
UFLAG_IF {
LDADDALH(x3, x1, wback);
emit_dec16(dyn, ninst, x1, x3, x4);
} else {
STADDLH(x3, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_dec16(dyn, ninst, x1, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
SMDMB();
break;
default:
DEFAULT;
+93
View File
@@ -0,0 +1,93 @@
#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 "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
static const int8_t round_round[] = { 0, 2, 1, 3};
#endif
switch(opcode) {
case 0x38: // SSE 4.x
opcode = F8;
switch(opcode) {
case 0xF1:
INST_NAME("CRC32 Gd, Ew");
nextop = F8;
GETEW(x1, 0);
GETGD;
if(arm64_crc32) {
CRC32CH(gd, gd, ed);
} else {
MOV32w(x2, 0x82f63b78);
for(int j=0; j<2; ++j) {
UBFXxw(x3, ed, 8*j, 8);
EORw_REG(gd, gd, x3);
for(int i=0; i<8; ++i) {
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
TBZ((i&1)?x4:gd, 0, 4+4);
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
}
}
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+64
View File
@@ -0,0 +1,64 @@
#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 "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
static const int8_t mask_string8[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
static const int8_t mask_string16[] = { 15, 14, 13, 12, 11, 10, 9, 8 };
static const int8_t round_round[] = { 0, 2, 1, 3};
#endif
switch(opcode) {
default:
DEFAULT;
}
return addr;
}
+39 -6
View File
@@ -276,7 +276,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0; \
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
@@ -761,12 +761,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
gb2 = 0;
gb1 = xRAX + gd;
} else {
gb2 = ((gd&4)>>2);
gb2 = ((gd&4)<<1);
gb1 = xRAX+(gd&3);
}
if(gb2) {
gd = x4;
UBFXw(gd, gb1, gb2*8, 8);
UBFXw(gd, gb1, gb2, 8);
} else {
gd = gb1; // no need to extract
}
@@ -798,7 +798,40 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMWRITELOCK(lock);
}
break;
case 0x8A:
INST_NAME("MOV Gb, Eb");
nextop = F8;
if(rex.rex) {
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gb2=0;
} else {
gd = (nextop&0x38)>>3;
gb1 = xRAX+(gd&3);
gb2 = ((gd&4)<<1);
}
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
if(wb2) {
UBFXw(x4, wback, wb2*8, 8);
ed = x4;
} else {
ed = wback;
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
SMREADLOCK(lock);
LDB(x4, wback, fixedaddress);
ed = x4;
}
BFIx(gb1, ed, gb2, 8);
break;
case 0x8B:
INST_NAME("MOV Gd, Ed");
nextop=F8;
@@ -1008,7 +1041,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -1022,11 +1054,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -1040,6 +1072,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
break;
case 6:
INST_NAME("DIV Ed");
+103
View File
@@ -0,0 +1,103 @@
#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 "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(!rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0xA3:
INST_NAME("MOV Seg:[Od], EAX");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg);
if(i32<4096 && !(i32&3)) {
STRw_U12(xRAX, x4, i32);
} else if(i32<256) {
STURw_I9(xRAX, x4, i32);
} else {
MOV32w(x1, i32);
STRw_REG(xRAX, x4, x1);
}
break;
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0, 0, 0);
LDRw_REG(x3, ed, x4);
PUSH1_32(x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+72
View File
@@ -0,0 +1,72 @@
#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 "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(!rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 64:
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
default:
DEFAULT;
}
return addr;
}
+3 -3
View File
@@ -108,7 +108,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -178,7 +178,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FDIVD(v1, v2, v1);
}
break;
default:
switch((nextop>>3)&7) {
case 0:
@@ -234,7 +234,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
+99 -23
View File
@@ -51,7 +51,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v2 = x87_do_push(dyn, ninst, x1, X87_ST(nextop&7));
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, X87_ST(nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
if(ST_IS_F(0)) {
FMOVS(v2, v1);
@@ -84,7 +84,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xD8:
INST_NAME("FSTPNCE ST0, ST0");
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
@@ -98,7 +98,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FCHS");
@@ -138,7 +138,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
} else {
@@ -147,82 +147,123 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
FTABLE64(v1, L2T);
break;
case 0xEA:
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
FTABLE64(v1, L2E);
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
FTABLE64(v1, PI);
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
FTABLE64(v1, LG2);
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
FTABLE64(v1, LN2);
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
VEOR(v1, v1, v1);
break;
case 0xF0:
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_f2xm1, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xF1:
INST_NAME("FYL2X");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fyl2x, -1);
x87_do_pop(dyn, ninst, x3);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_ftan, -1);
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
x87_unstackcount(dyn, ninst, x1, i1);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
u8 = F8;
u8 = F8;
} else {
FMOVD_8(v1, 0b01110000);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
} else {
FMOVD_8(v1, 0b01110000);
}
}
break;
case 0xF3:
INST_NAME("FPATAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fpatan, -1);
x87_do_pop(dyn, ninst, x3);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF4:
INST_NAME("FXTRACT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fxtract, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xF5:
INST_NAME("FPREM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
#if 0
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fprem1, -1);
x87_unstackcount(dyn, ninst, x1, i1);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
FDIVD(s0, v1, v2);
FRINTRRD(s0, s0, 0b00); // Nearest == TieToEven?
FCVTZSxD(x4, s0);
FMULD(s0, s0, v2);
FSUBD(v1, v1, s0);
LDRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
// set C2 = 0
BFCw(x1, 10, 1);
// set C1 = Q0
BFIw(x1, x4, 9, 1);
// set C3 = Q1
LSRx_IMM(x4, x4, 1);
BFIw(x1, x4, 14, 1);
// Set C0 = Q2
LSRx(x4, x4, 1);
BFIw(x1, x4, 8, 1);
STRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
#endif
break;
case 0xF6:
INST_NAME("FDECSTP");
@@ -242,18 +283,45 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF8:
INST_NAME("FPREM");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fprem, -1);
x87_unstackcount(dyn, ninst, x1, i1);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
FDIVD(s0, v1, v2);
FRINTZD(s0, s0);
FCVTZSxD(x4, s0);
FMULD(s0, s0, v2);
FSUBD(v1, v1, s0);
LDRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
// set C2 = 0
BFCw(x1, 10, 1);
// set C1 = Q0
BFIw(x1, x4, 9, 1);
// set C3 = Q1
LSRx_IMM(x4, x4, 1);
BFIw(x1, x4, 14, 1);
// Set C0 = Q2
LSRx(x4, x4, 1);
BFIw(x1, x4, 8, 1);
STRw_U12(x1, xEmu, offsetof(x64emu_t, sw));
#endif
break;
case 0xF9:
INST_NAME("FYL2XP1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fyl2xp1, -1);
x87_do_pop(dyn, ninst, x3);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xFA:
INST_NAME("FSQRT");
@@ -267,9 +335,11 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xFB:
INST_NAME("FSINCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fsincos, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFC:
INST_NAME("FRNDINT");
@@ -292,21 +362,27 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xFD:
INST_NAME("FSCALE");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fscale, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fsin, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fcos, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
@@ -322,12 +398,12 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
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)) {
@@ -354,7 +430,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCVT_S_D(v1, v1);
}
VST32(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
+239
View File
@@ -0,0 +1,239 @@
#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 "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
int64_t j64;
uint8_t ed;
uint8_t wback;
int v1, v2;
int d0;
int s0;
int64_t fixedaddress;
int unscaled;
MAYUSE(s0);
MAYUSE(d0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(j64);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FCMOVB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTw_mask(xFlags, 0, 0); //mask=1<<F_CF
if(ST_IS_F(0)) {
FCSELS(v1, v2, v1, cNE); // F_CF==1
} else {
FCSELD(v1, v2, v1, cNE); // F_CF==1
}
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FCMOVE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTw_mask(xFlags, 0b011010, 0); //mask=1<<F_ZF
if(ST_IS_F(0)) {
FCSELS(v1, v2, v1, cNE);
} else {
FCSELD(v1, v2, v1, cNE); // F_ZF==0
}
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCMOVBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
MOV32w(x1, (1<<F_CF)|(1<<F_ZF));
TSTw_REG(xFlags, x1);
if(ST_IS_F(0)) {
FCSELS(v1, v2, v1, cNE);
} else {
FCSELD(v1, v2, v1, cNE); // 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("FCMOVU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
TSTw_mask(xFlags, 0b011110, 0); //mask=1<<F_PF
if(ST_IS_F(0)) {
FCSELS(v1, v2, v1, cNE);
} else {
FCSELD(v1, v2, v1, cNE); // F_PF==0
}
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFD:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, 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, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v2, v1);
break;
}
}
return addr;
}
+8 -8
View File
@@ -156,7 +156,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
FCOMI(x1, x2);
break;
case 0xF0:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
@@ -188,7 +188,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
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
@@ -218,7 +218,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ed, ST0");
@@ -273,7 +273,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FLD tbyte");
@@ -296,13 +296,13 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRH_U12(x6, ed, 8);
} else {
if(box64_x87_no80bits) {
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
VLDR64_U12(v1, ed, fixedaddress);
} else {
if(ed!=x1) {
MOVx_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
CALL(native_fld, -1);
}
}
@@ -344,7 +344,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CMPSw_REG(x3, x4);
B_MARK2(cNE);
// NaN and Infinite
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
TSTx_mask(x1, 1, 0, 0b110011); //0x000fffffffffffffL
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
ORRx_mask(x4, xZR, 1, 0b10, 0b01); //0xc000000000000000
@@ -372,7 +372,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRH_U12(x3, wback, 8);
#endif
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+3 -3
View File
@@ -106,7 +106,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -158,7 +158,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FDIVD(v1, v2, v1);
}
break;
break;
case 0xF8:
case 0xF9:
case 0xFA:
@@ -211,7 +211,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
+34 -29
View File
@@ -74,7 +74,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
@@ -88,7 +88,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -126,7 +126,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
@@ -160,34 +160,38 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x3, NEON_CACHE_ST_D);
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);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
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!
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
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
STx(x5, ed, fixedaddress);
MARK3;
#endif
x87_do_pop(dyn, ninst, x3);
if(ST_IS_I64(0)) {
VST64(v1, ed, fixedaddress);
} else {
s0 = fpu_get_scratch(dyn);
#if 0
// those are ARM 8.5 opcode!
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
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
STx(x5, ed, fixedaddress);
MARK3;
#endif
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FST double");
@@ -200,9 +204,9 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
case 4:
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
@@ -210,7 +214,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_frstor, -1);
break;
case 6:
case 6:
INST_NAME("FSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
@@ -220,7 +224,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
//fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
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));
@@ -234,6 +238,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, xEmu, offsetof(x64emu_t, sw));
STH(x3, ed, fixedaddress); // store whole sw flags
break;
default:
+11 -11
View File
@@ -53,7 +53,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FADDD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
@@ -71,7 +71,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FMULD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
@@ -90,7 +90,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
INST_NAME("FCOMPP ST0, STx");
@@ -102,8 +102,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -121,7 +121,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FSUBD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE8:
case 0xE9:
@@ -139,7 +139,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FSUBD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
@@ -157,8 +157,8 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FDIVD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF8:
case 0xF9:
case 0xFA:
@@ -175,7 +175,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FDIVD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD8:
case 0xDA:
@@ -233,7 +233,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, word[ED]");
+21 -10
View File
@@ -34,6 +34,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int64_t j64;
int64_t fixedaddress;
int unscaled;
int i1;
MAYUSE(s0);
MAYUSE(v2);
@@ -51,12 +52,20 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC7:
INST_NAME("FFREEP STx");
// not handling Tag...
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
if(dyn->n.x87stack) {
if(dyn->n.x87stack>0) {
SUBw_U12(x2, x2, dyn->n.x87stack);
} else {
ADDw_U12(x2, x2, -dyn->n.x87stack);
}
ANDw_mask(x2, x2, 0, 2); //mask=7
}
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
BFIw(x1, x2, 11, 3); // inject top
STRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
@@ -81,7 +90,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
@@ -102,7 +111,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCMPD(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
@@ -151,7 +160,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
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)) {
@@ -196,7 +205,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ew, ST0");
@@ -275,19 +284,19 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
x87_do_push_empty(dyn, ninst, x1);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
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_I64);
X87_PUSH_OR_FAIL(v1, 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)) {
@@ -315,11 +324,13 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 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);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7:
INST_NAME("FISTP i64, ST0");
@@ -375,7 +386,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#endif
x87_restoreround(dyn, ninst, u8);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+6 -54
View File
@@ -230,15 +230,7 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -261,15 +253,7 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -292,15 +276,7 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -323,15 +299,7 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -423,15 +391,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -500,15 +460,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
+16 -114
View File
@@ -303,15 +303,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -329,7 +321,7 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
SET_DFNONE(s3);
}
IFX(X_AF | X_OF) {
if(X_PEND) {} else {MOV32w(s4, c&0xff);}
IFX(X_PEND) {} else {MOV32w(s4, c&0xff);}
ORRw_REG(s3, s1, s4); // s3 = op1 | op2
ANDw_REG(s4, s1, s4); // s4 = op1 & op2
}
@@ -355,15 +347,7 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -407,15 +391,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -465,15 +441,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -516,15 +484,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STRw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -634,15 +594,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -792,16 +744,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -838,15 +781,7 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_ZF) {
TSTw_mask(s1, 0, 0b001111); // mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -906,7 +841,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_dec8);
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
SET_DFNONE(s3);
@@ -1162,15 +1097,7 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
LSRw(s3, s1, 8);
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -1224,15 +1151,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
LSRw(s3, s1, 16);
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -1474,15 +1393,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 7); //mask=0xff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -1537,15 +1448,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -1732,10 +1635,9 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_AF|X_OF) {
MOVw_REG(s3, s1);
}
NEGw_REG(s1, s1);
IFX(X_ZF) {
NEGSw_REG(s1, s1);
} else {
NEGw_REG(s1, s1);
ANDSw_mask(s1, s1, 0, 7); // mask 0xff
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
File diff suppressed because it is too large. Load diff
+6 -44
View File
@@ -111,22 +111,11 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
} else {
SET_DFNONE(s3);
}
IFX(X_ZF) {
SUBSw_REG(s5, s1, s2); // res = s1 - s2
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s5, 15);
BFIw(xFlags, s4, F_SF, 1);
}
COMP_ZFSF(s5, 16)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVNw_REG(s4, s1); // s4 = ~d
@@ -170,15 +159,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 15); //mask=0xffff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s1, 15);
BFIw(xFlags, s4, F_SF, 1);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -194,22 +175,11 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
} else {
SET_DFNONE(s4);
}
IFX(X_ZF) {
SUBSw_REG(s5, s1, s2); // res = s1 - s2
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s5, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s5, 8)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
ORNw_REG(s4, s2, s1); // s4 = ~d | s
@@ -251,15 +221,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, 0, 0b000111); //mask=000000ff
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
File diff suppressed because it is too large. Load diff
+48 -22
View File
@@ -28,7 +28,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t wback;
uint8_t wback, wb1, wb2;
uint8_t u8;
uint64_t u64, j64;
int v0, v1;
@@ -159,30 +159,41 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch(opcode) {
case 0xF0:
INST_NAME("(unsupported) CRC32 Gd, Eb)");
INST_NAME("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;
GETEB(x1, 0);
GETGD;
if(arm64_crc32) {
CRC32CB(gd, gd, ed);
} else {
EORw_REG(gd, gd, ed);
MOV32w(x2, 0x82f63b78);
for(int i=0; i<8; ++i) {
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
TBZ((i&1)?x4:gd, 0, 4+4);
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
}
}
break;
case 0xF1:
INST_NAME("(unsupported) CRC32 Gd, Ed)");
INST_NAME("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;
GETED(0);
GETGD;
if(arm64_crc32) {
CRC32Cxw(gd, gd, ed);
} else {
MOV32w(x2, 0x82f63b78);
for(int j=0; j<4*(1+rex.w); ++j) {
UBFXxw(x3, ed, 8*j, 8);
EORw_REG(gd, gd, x3);
for(int i=0; i<8; ++i) {
LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);
TBZ((i&1)?x4:gd, 0, 4+4);
EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);
}
}
}
break;
default:
@@ -376,7 +387,22 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
VFADDPQS(v0, v0, v1);
break;
case 0x7D:
INST_NAME("HSUBPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
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, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
VLD128(v1, ed, fixedaddress);
}
d0 = fpu_get_scratch(dyn);
VUZP1Q_32(d0, v0, v1);
VUZP2Q_32(v0, v0, v1);
VFSUBQS(v0, d0, v0);
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
+20 -12
View File
@@ -30,7 +30,6 @@
#define XMM8 16
#define X870 8
#define EMM0 8
#define SCRATCH0 24
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn)
@@ -96,6 +95,15 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
}
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a)
{
if(a==NEON_CACHE_ST_I64) {
neoncache_promote_double(dyn, ninst, st);
return NEON_CACHE_ST_D;
}
return a;
}
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
{
if (dyn->insts[ninst].n.swapped) {
@@ -139,7 +147,7 @@ int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
&& dyn->insts[ninst].n.neoncache[i].n==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)
@@ -150,7 +158,7 @@ int neoncache_get_st_f_i64(dynarec_arm_t* dyn, int ninst, int a)
&& 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)
@@ -158,7 +166,7 @@ int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
&& dyn->insts[ninst].n.neoncache[i].n==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)
@@ -166,7 +174,7 @@ int neoncache_get_st_f_i64_noback(dynarec_arm_t* dyn, int ninst, int a)
&& 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)
@@ -174,7 +182,7 @@ int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
&& dyn->n.neoncache[i].n==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)
@@ -182,7 +190,7 @@ int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a)
&& 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)
@@ -190,7 +198,7 @@ static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int
if(a == dyn->insts[ninst].n.combined1 || a == dyn->insts[ninst].n.combined2) {
if(a == dyn->insts[ninst].n.combined1) {
a = dyn->insts[ninst].n.combined2;
} else
} else
a = dyn->insts[ninst].n.combined1;
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);
@@ -314,7 +322,7 @@ static int isCacheEmpty(dynarec_native_t* dyn, int ninst) {
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_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))
@@ -339,7 +347,7 @@ 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_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))
@@ -377,7 +385,7 @@ void neoncacheUnwind(neoncache_t* cache)
{
if(cache->swapped) {
// unswap
int a = -1;
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 || cache->neoncache[j].t == NEON_CACHE_ST_I64)) {
@@ -580,4 +588,4 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
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));
}
}
@@ -3,6 +3,8 @@
#include "../dynarec_native_functions.h"
#define SCRATCH0 24
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
// Reset scratch regs counter
@@ -35,6 +37,9 @@ int neoncache_get_current_st_f_i64(dynarec_arm_t* dyn, int a);
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*
// Do not allow i64 type
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
// FPU Cache transformation (for loops) // Specific, need to be written by backend
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
+122 -37
View File
@@ -32,6 +32,8 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
if(rex.is32bits)
return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
@@ -69,7 +71,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
} else {
switch(lock) {
case 1: addLockAddress(tmp); break;
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV64x(ret, tmp);
@@ -106,7 +108,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
ADDx_REG(ret, ret, xRIP);
}
switch(lock) {
case 1: addLockAddress(addr+delta+tmp); break;
case 1: addLockAddress(addr+delta+tmp); if(fixaddress) *fixaddress=addr+delta+tmp; break;
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
} else {
@@ -126,7 +128,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask)) || (unscaled && (i64>-256) && (i64<256))) {
*fixaddress = i64;
if(unscaled && (i64>-256) && (i64<256))
if(unscaled && i64 && (i64>-256) && (i64<256))
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
@@ -221,7 +223,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
}
} else {
switch(lock) {
case 1: addLockAddress((int32_t)tmp); break;
case 1: addLockAddress((int32_t)tmp); if(fixaddress) *fixaddress=(int32_t)tmp; break;
case 2: if(isLockAddress((int32_t)tmp)) *l=1; break;
}
MOV32w(ret, tmp);
@@ -237,7 +239,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
uint64_t tmp = F32;
MOV32w(ret, tmp);
switch(lock) {
case 1: addLockAddress(tmp); break;
case 1: addLockAddress(tmp); if(fixaddress) *fixaddress=tmp; break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
} else {
@@ -256,11 +258,11 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
}
if(nextop&0x80)
i32 = F32S;
else
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))
if(unscaled && i32 && (i32>-256) && (i32<256))
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
@@ -567,6 +569,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Jump to next\n");
SMEND();
if(reg) {
if(reg!=xRIP) {
MOVx_REG(xRIP, reg);
@@ -575,6 +578,10 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
uintptr_t tbl = getJumpTable64();
MAYUSE(tbl);
TABLE64(x3, tbl);
#ifdef JMPTABL_SHIFT4
UBFXx(x2, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
LDRx_REG_LSL3(x3, x3, x2);
#endif
UBFXx(x2, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
LDRx_REG_LSL3(x3, x3, x2);
UBFXx(x2, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
@@ -598,7 +605,6 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
#ifdef HAVE_TRACE
//MOVx(x3, 15); no access to PC reg
#endif
SMEND();
BLR(x2); // save LR...
}
@@ -612,16 +618,21 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
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, 6*4);
ADDx_U12(xSP, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
BLR(x2);
// not the correct return address, regular jump
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
SUBx_U12(xSP, xSavedSP, 0);
}
uintptr_t tbl = getJumpTable64();
NOTEST(x2);
MOV64x(x2, tbl);
#ifdef JMPTABL_SHIFT4
UBFXx(x3, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
LDRx_REG_LSL3(x2, x2, x3);
#endif
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
@@ -650,16 +661,21 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
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, 6*4);
ADDx_U12(xSP, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
BLR(x2);
// not the correct return address, regular jump
SUBx_U12(xSP, xSavedSP, 0);
}
uintptr_t tbl = getJumpTable64();
NOTEST(x2);
MOV64x(x2, tbl);
#ifdef JMPTABL_SHIFT4
UBFXx(x3, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
LDRx_REG_LSL3(x2, x2, x3);
#endif
UBFXx(x3, xRIP, JMPTABL_START3, JMPTABL_SHIFT3);
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START2, JMPTABL_SHIFT2);
@@ -677,6 +693,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
//#warning TODO: is64bits
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
SMEND();
// POP IP
NOTEST(x2);
if(is64bits) {
@@ -711,7 +728,6 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
MOVx_REG(xRSP, x3);
// Ret....
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
SMEND();
BR(x2);
CLEARIP();
}
@@ -852,11 +868,11 @@ static void x87_reset(dynarec_arm_t* dyn)
dyn->n.neoncache[i].v = 0;
}
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
{
MAYUSE(scratch);
if(!dyn->n.x87stack)
return;
return 0;
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, scratch);
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->n.x87stack);
@@ -879,10 +895,45 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
ANDw_mask(scratch, scratch, 0, 2); //mask=7
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
// reset x87stack, but not the stack count of neoncache
int ret = dyn->n.x87stack;
dyn->n.x87stack = 0;
dyn->n.stack_next -= dyn->n.stack;
dyn->n.stack = 0;
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
return ret;
}
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count)
{
MAYUSE(scratch);
if(!count)
return;
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, scratch);
MESSAGE(LOG_DUMP, "\tUnsynch x87 Stackcount (%d)\n", count);
int a = -count;
// Add x87stack to emu fpu_stack
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDw_U12(scratch, scratch, a);
} else {
SUBw_U12(scratch, scratch, -a);
}
STRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
if(a>0) {
SUBw_U12(scratch, scratch, a);
} else {
ADDw_U12(scratch, scratch, -a);
}
ANDw_mask(scratch, scratch, 0, 2); //mask=7
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
// reset x87stack, but not the stack count of neoncache
dyn->n.x87stack = count;
dyn->n.stack = count;
dyn->n.stack_next += dyn->n.stack;
MESSAGE(LOG_DUMP, "\t------x87 Unstackcount\n");
}
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b)
@@ -1098,7 +1149,11 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
if(dyn->n.x87cache[i]!=-1) {
ADDw_U12(s3, s2, dyn->n.x87cache[i]);
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3);
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[i])>=0) {
FCVT_D_S(SCRATCH0, dyn->n.x87reg[i]);
VSTR64_REG_LSL3(SCRATCH0, s1, s3);
} else
VSTR64_REG_LSL3(dyn->n.x87reg[i], s1, s3);
}
}
@@ -1135,6 +1190,8 @@ int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
#if STEP == 1
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_I64 && (dyn->n.neoncache[dyn->n.x87reg[i]].t==NEON_CACHE_ST_F))
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
@@ -1232,7 +1289,6 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
x87_stackcount(dyn, ninst, s1);
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->n.x87cache[i] == st)
@@ -1240,8 +1296,9 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(ret==-1) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
const int reg = dyn->n.x87reg[ret];
#if STEP == 1
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)
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F || dyn->n.neoncache[reg].t==NEON_CACHE_ST_I64)
neoncache_promote_double(dyn, ninst, st);
#endif
// prepare offset to fpu => s1
@@ -1249,15 +1306,28 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// Get top
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// Update
if(st) {
ADDw_U12(s2, s2, st);
int ast = st - dyn->n.x87stack;
if(ast) {
if(ast>0) {
ADDw_U12(s2, s2, ast);
} else {
SUBw_U12(s2, s2, -ast);
}
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
}
VSTR64_REG_LSL3(dyn->n.x87reg[ret], s1, s2);
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
FCVT_D_S(31, reg);
VSTR64_REG_LSL3(31, s1, s2);
} else if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_I64) {
SCVTFDD(31, reg);
VSTR64_REG_LSL3(31, s1, s2);
} else {
VSTR64_REG_LSL3(reg, s1, s2);
}
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
// and forget that cache
fpu_free_reg(dyn, dyn->n.x87reg[ret]);
dyn->n.neoncache[dyn->n.x87reg[ret]].v = 0;
fpu_free_reg(dyn, reg);
dyn->n.neoncache[reg].v = 0;
dyn->n.x87cache[ret] = -1;
dyn->n.x87reg[ret] = -1;
}
@@ -1438,7 +1508,7 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
for (int i=0; i<8; ++i)
if(dyn->n.mmxcache[i]!=-1) {
VLDR64_U12(dyn->n.mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
VSTR64_U12(dyn->n.mmxcache[i], xEmu, offsetof(x64emu_t, mmx[i]));
}
}
@@ -1541,6 +1611,17 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
}
}
void sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a)
{
if(dyn->n.ssecache[a].v==-1)
return;
if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) {
VSTR128_U12(dyn->n.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
/*dyn->n.neoncache[dyn->n.ssecache[a].reg].t = NEON_CACHE_XMMR;
dyn->n.ssecache[a].write = 0;*/
}
}
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
int start = not07?8:0;
@@ -1573,6 +1654,8 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
for (int i=start; i<16; ++i)
if(dyn->n.ssecache[i].v!=-1) {
VLDR128_U12(dyn->n.ssecache[i].reg, xEmu, offsetof(x64emu_t, xmm[i]));
/*dyn->n.ssecache[i].write = 0; // OPTIM: it's sync, so not write anymore
dyn->n.neoncache[dyn->n.ssecache[i].reg].t = NEON_CACHE_XMMR;*/
}
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
}
@@ -1697,7 +1780,7 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
break;
case NEON_CACHE_MM:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
VLDR64_U12(i, xEmu, offsetof(x64emu_t, mmx[i]));
VLDR64_U12(i, xEmu, offsetof(x64emu_t, mmx[n]));
break;
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_F:
@@ -1717,9 +1800,11 @@ static void loadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, int
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + i)&7
}
*s3_top += a;
*s2_val = 0;
ADDx_REG_LSL(s2, xEmu, s3, 3);
VLDR64_U12(i, s2, offsetof(x64emu_t, x87));
if(*s2_val!=1) {
*s2_val = 1;
ADDx_U12(s2, xEmu, offsetof(x64emu_t, x87));
}
VLDR64_REG_LSL3(i, s2, s3);
if(t==NEON_CACHE_ST_F) {
FCVT_S_D(i, i);
}
@@ -1769,14 +1854,16 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + i)&7
}
*s3_top += a;
ADDx_REG_LSL(s2, xEmu, s3, 3);
*s2_val = 0;
if(*s2_val!=1) {
*s2_val = 1;
ADDx_U12(s2, xEmu, offsetof(x64emu_t, x87));
}
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));
VSTR64_REG_LSL3(i, s2, s3);
break;
case NEON_CACHE_NONE:
case NEON_CACHE_SCR:
@@ -1945,7 +2032,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = 0;
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
@@ -1963,12 +2050,10 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
else
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
else if (dyn->insts[jmp].f_entry.dfnone !=dyn->f.dfnone)
go = 1;
break;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
go = 1;
if(go) {
if(dyn->f.pending!=SF_PENDING) {
LDRw_U12(s1, xEmu, offsetof(x64emu_t, df));
@@ -2016,7 +2101,7 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
LSRw(s3, s3, 5);
MOV64x(s4, (uintptr_t)GetParityTab());
TABLE64(s4, (uintptr_t)GetParityTab());
LDRw_REG_LSL2(s4, s4, s3);
ANDw_mask(s3, s1, 0, 0b000100); //0x1f
LSRw_REG(s4, s4, s3);
@@ -2086,4 +2171,4 @@ void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
}
}
+162 -22
View File
@@ -33,28 +33,31 @@
#define PKip(a) *(uint8_t*)(ip+a)
// Strong mem emulation helpers
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
// Sequence of Write will trigger a DMB on "last" write if strongmem is 1
#define SMREAD_MIN 2
#define SMWRITE_MIN 1
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
// Opcode will read
#define SMREAD() if(!dyn->smread && box64_dynarec_strongmem>1) {SMDMB();}
#define SMREAD() if((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box64_dynarec_strongmem>1)) {SMDMB();}
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
// Opcode might read (depend on nextop)
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
// Opcode has wrote
#define SMWRITE() dyn->smwrite=1
// Opcode has wrote (strongmem>1 only)
#define SMWRITE2() if(box64_dynarec_strongmem>1) dyn->smwrite=1
#define SMWRITE2() if(box64_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
#define SMWRITELOCK(lock) if(lock || (box64_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
// Opcode might have wrote (depend on nextop)
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
// Start of sequence
#define SMSTART() SMEND()
// End of sequence
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
#define SMDMB() if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -66,7 +69,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
SMREAD() \
SMREAD(); \
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; \
@@ -85,7 +88,7 @@
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(3-rex.is32bits), rex.is32bits?3:7, rex, NULL, 0, D); \
LDz(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -422,6 +425,9 @@
VLD64(a, ed, fixedaddress); \
}
// Get Ex as 64bits, not a quad (warning, x1 get used)
#define GETEX64(a, w, D) GETEXSD(a, w, D)
// Get Ex as a single, not a quad (warning, x1 get used)
#define GETEXSS(a, w, D) \
if(MODREG) { \
@@ -433,6 +439,20 @@
VLD32(a, ed, fixedaddress); \
}
// Get Ex as 32bits, not a quad (warning, x1 get used)
#define GETEX32(a, w, D) GETEXSS(a, w, D)
// Get Ex as 16bits, not a quad (warning, x1 get used)
#define GETEX16(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, D); \
VLD16(a, ed, fixedaddress); \
}
// Get GM, might use x1, x2 and x3
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
@@ -464,6 +484,9 @@
TSTw_mask(xFlags, 0b010110, 0); \
CNEGx(r, r, cNE)
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&((1<<(2+rex.w)-1)))) || box64_dynarec_aligned_atomics)
#define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || box64_dynarec_aligned_atomics)
// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL(F, ret) call_c(dyn, ninst, F, x7, ret, 1, 0)
@@ -742,8 +765,39 @@
LDP_REGS(R12, R13); \
LDP_REGS(R14, R15)
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
if (dyn->n.stack == +8) { \
*ok = 0; \
break; \
} \
var = x87_do_push(dyn, ninst, scratch, t);
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
if (dyn->n.stack == +8) { \
*ok = 0; \
break; \
} \
x87_do_push_empty(dyn, ninst, scratch);
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
if (dyn->n.stack == -8) { \
*ok = 0; \
break; \
} \
x87_do_pop(dyn, ninst, scratch);
#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_DF(S, N) \
if((N)!=d_none) { \
MOVZw(S, (N)); \
STRw_U12(S, xEmu, offsetof(x64emu_t, df)); \
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after&X_PEND)) { \
CALL_(UpdateFlags, -1, 0); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone=0; \
} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
@@ -784,7 +838,7 @@
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
#define JUMP(A, C) SMEND()
#endif
#ifndef BARRIER
#define BARRIER(A)
@@ -792,6 +846,9 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#ifndef SET_HASCALLRET
#define SET_HASCALLRET()
#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, xEmu, offsetof(x64emu_t, op2));}
@@ -874,6 +931,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_65 STEPNAME(dynarec64_65)
#define dynarec64_66 STEPNAME(dynarec64_66)
#define dynarec64_67 STEPNAME(dynarec64_67)
#define dynarec64_67_32 STEPNAME(dynarec64_67_32)
#define dynarec64_6764_32 STEPNAME(dynarec64_6764_32)
#define dynarec64_D8 STEPNAME(dynarec64_D8)
#define dynarec64_D9 STEPNAME(dynarec64_D9)
#define dynarec64_DA STEPNAME(dynarec64_DA)
@@ -884,6 +943,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_DF STEPNAME(dynarec64_DF)
#define dynarec64_F0 STEPNAME(dynarec64_F0)
#define dynarec64_660F STEPNAME(dynarec64_660F)
#define dynarec64_66F20F STEPNAME(dynarec64_66F20F)
#define dynarec64_66F30F STEPNAME(dynarec64_66F30F)
#define dynarec64_6664 STEPNAME(dynarec64_6664)
#define dynarec64_66F0 STEPNAME(dynarec64_66F0)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
@@ -965,16 +1026,38 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define emit_shr32 STEPNAME(emit_shr32)
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_shl8 STEPNAME(emit_shl8)
#define emit_shl8c STEPNAME(emit_shl8c)
#define emit_shr8 STEPNAME(emit_shr8)
#define emit_shr8c STEPNAME(emit_shr8c)
#define emit_sar8 STEPNAME(emit_sar8)
#define emit_sar8c STEPNAME(emit_sar8c)
#define emit_shl16 STEPNAME(emit_shl16)
#define emit_shl16c STEPNAME(emit_shl16c)
#define emit_shr16 STEPNAME(emit_shr16)
#define emit_shr16c STEPNAME(emit_shr16c)
#define emit_sar16 STEPNAME(emit_sar16)
#define emit_sar16c STEPNAME(emit_sar16c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_rol8c STEPNAME(emit_rol8c)
#define emit_ror8c STEPNAME(emit_ror8c)
#define emit_rol16c STEPNAME(emit_rol16c)
#define emit_ror16c STEPNAME(emit_ror16c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_shld32 STEPNAME(emit_shld32)
#define emit_shrd16c STEPNAME(emit_shrd16c)
#define emit_shrd16 STEPNAME(emit_shrd16)
#define emit_shld16c STEPNAME(emit_shld16c)
#define emit_shld16 STEPNAME(emit_shld16)
#define emit_pf STEPNAME(emit_pf)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
#define x87_do_pop STEPNAME(x87_do_pop)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
#define x87_do_pop STEPNAME(x87_do_pop)
#define x87_get_current_cache STEPNAME(x87_get_current_cache)
#define x87_get_cache STEPNAME(x87_get_cache)
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
@@ -984,6 +1067,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_unstackcount STEPNAME(x87_unstackcount)
#define x87_swapreg STEPNAME(x87_swapreg)
#define x87_setround STEPNAME(x87_setround)
#define x87_restoreround STEPNAME(x87_restoreround)
@@ -994,6 +1078,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_purge07cache STEPNAME(sse_purge07cache)
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
@@ -1092,16 +1177,40 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
// x87 helper
// cache of the local stack counter, to avoid update at every call
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// cache of the local stack counter, to avoid update at every call, return old internal stack counter
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// revert local stack counter to previous version (return from x87_stackcount)
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count);
// fpu push. Return the Dd value to be used
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
@@ -1154,8 +1263,8 @@ int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
#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)
#define X87_ST0 neoncache_no_i64(dyn, ninst, 0, neoncache_get_current_st(dyn, ninst, 0))
#define X87_ST(A) neoncache_no_i64(dyn, ninst, 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)
@@ -1183,7 +1292,8 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
// purge the XMM0..XMM7 cache (before function call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
// Push current value to the cache
void sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn);
@@ -1208,16 +1318,20 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
@@ -1354,4 +1468,30 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
opcode = F8; \
}
#define COMP_ZFSF(s1, A) \
IFX(X_ZF|X_SF) { \
if(arm64_flagm) { \
SETF##A(s1); \
IFX(X_ZF) { \
CSETw(s3, cEQ); \
BFIw(xFlags, s3, F_ZF, 1); \
} \
IFX(X_SF) { \
CSETw(s3, cMI); \
BFIw(xFlags, s3, F_SF, 1); \
} \
} else { \
IFX(X_ZF) { \
ANDSw_mask(s1, s1, 0, (A)-1); \
CSETw(s3, cEQ); \
BFIw(xFlags, s3, F_ZF, 1); \
} \
IFX(X_SF) { \
LSRw(s3, s1, (A)-1); \
BFIw(xFlags, s3, F_SF, 1); \
} \
} \
}
#endif //__DYNAREC_ARM64_HELPER_H__
+3 -2
View File
@@ -16,9 +16,10 @@
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x64.barrier = A
#define BARRIER_NEXT(A) dyn->insts[ninst].x64.barrier_next = A
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
+6 -1
View File
@@ -102,6 +102,9 @@ typedef struct dynarec_arm_s {
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
int* jmps; // variable array of jump instructions
int jmp_sz;
int jmp_cap;
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
@@ -119,6 +122,8 @@ typedef struct dynarec_arm_s {
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
@@ -126,7 +131,7 @@ int Table64(dynarec_arm_t *dyn, uint64_t val, int pass); // add a value to tabl
void CreateJmpNext(void* addr, void* next);
#define GO_TRACE(A, B) \
#define GO_TRACE(A, B, s0) \
GETIP(addr); \
MOVx_REG(x1, xRIP); \
STORE_XEMU_CALL(xRIP); \
+12 -7
View File
@@ -41,10 +41,10 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
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);
// remove jumptable without waiting
setJumpTableDefault64(db->x64_addr);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
// remove jumptable
setJumpTableDefault64(db->x64_addr);
db->done = 0;
db->gone = 1;
if(need_lock)
@@ -74,10 +74,10 @@ void FreeDynablock(dynablock_t* db, int need_lock)
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size-1, db->gone);
// remove jumptable without waiting
setJumpTableDefault64(db->x64_addr);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
// remove jumptable
setJumpTableDefault64(db->x64_addr);
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
@@ -171,11 +171,16 @@ dynablock_t *AddNewDynablock(uintptr_t addr)
}
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
static __thread JUMPBUFF dynarec_jmpbuf;
#ifdef ANDROID
#define DYN_JMPBUF dynarec_jmpbuf
#else
#define DYN_JMPBUF &dynarec_jmpbuf
#endif
void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
longjmp(DYN_JMPBUF, 1);
}
/*
@@ -208,7 +213,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
// fill the block
block->x64_addr = (void*)addr;
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
if(sigsetjmp(DYN_JMPBUF, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, canceling\n", (void*)addr);
FreeDynablock(block, 0);
if(need_lock)
+36 -4
View File
@@ -81,16 +81,38 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
uint64_t old_rsi = R_RSI;
uint64_t old_rbp = R_RBP;
uint64_t old_rip = R_RIP;
// save defered flags
deferred_flags_t old_df = emu->df;
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
multiuint_t old_op1_sav= emu->op1_sav;
multiuint_t old_res_sav= emu->res_sav;
deferred_flags_t old_df_sav= emu->df_sav;
// uc_link
x64_ucontext_t* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
// restore defered flags
emu->df = old_df;
emu->op1 = old_op1;
emu->op2 = old_op2;
emu->res = old_res;
emu->op1_sav = old_op1_sav;
emu->res_sav = old_res_sav;
emu->df_sav = old_df_sav;
// and the old registers
R_RBX = old_rbx;
R_RDI = old_rdi;
R_RSI = old_rsi;
@@ -100,19 +122,25 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
}
int my_setcontext(x64emu_t* emu, void* ucp);
void DynaRun(x64emu_t* emu)
{
// prepare setjump for signal handling
struct __jmp_buf_tag jmpbuf[1] = {0};
JUMPBUFF jmpbuf[1] = {0};
int skip = 0;
struct __jmp_buf_tag *old_jmpbuf = emu->jmpbuf;
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
emu->flags.jmpbuf_ready = 0;
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
emu->flags.jmpbuf_ready = 1;
if((skip=sigsetjmp(emu->jmpbuf, 1))) {
#ifdef ANDROID
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
#else
if((skip=sigsetjmp(emu->jmpbuf, 1)))
#endif
{
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
#ifdef DYNAREC
if(box64_dynarec_test) {
@@ -134,7 +162,7 @@ void DynaRun(x64emu_t* emu)
else {
int is32bits = (emu->segs[_CS]==0x23);
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
if(!block || !block->block || !block->done) {
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
@@ -153,6 +181,10 @@ void DynaRun(x64emu_t* emu)
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
}
if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
+67 -24
View File
@@ -94,6 +94,21 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
}
return best;
}
void add_jump(dynarec_native_t *dyn, int ninst) {
// add slots
if(dyn->jmp_sz == dyn->jmp_cap) {
dyn->jmp_cap += 64;
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
}
dyn->jmps[dyn->jmp_sz++] = ninst;
}
int get_first_jump(dynarec_native_t *dyn, int next) {
for(int i=0; i<dyn->jmp_sz; ++i)
if(dyn->insts[dyn->jmps[i]].x64.jmp == next)
return i;
return -2;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
{
@@ -356,11 +371,11 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
dyn->insts[ninst].x64.gen_flags |= X_PEND;
dyn->insts[ninst].x64.need_after = need;
need = dyn->insts[ninst].x64.need_after&~dyn->insts[ninst].x64.gen_flags;
if(dyn->insts[ninst].x64.may_set)
need |= dyn->insts[ninst].x64.gen_flags; // forward the flags
// Consume X_PEND if relevant
if((need&X_PEND) && (dyn->insts[ninst].x64.set_flags&SF_PENDING))
need &=~X_PEND;
else if((need&X_PEND) && (dyn->insts[ninst].x64.set_flags&SF_PENDING))
need &=~X_PEND; // Consume X_PEND if relevant
need |= dyn->insts[ninst].x64.use_flags;
if(dyn->insts[ninst].x64.need_before == need)
return ninst - 1;
@@ -392,6 +407,7 @@ void CancelBlock64(int need_lock)
current_helper = NULL;
if(helper) {
dynaFree(helper->next);
dynaFree(helper->jmps);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart))
@@ -471,10 +487,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
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, alternate, is32bits);
// no need for next anymore
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);
@@ -493,26 +505,57 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
uintptr_t j = helper.insts[i].x64.jmp;
if(j<start || j>=end || 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 {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x64.addr==j)
k=i2;
for(int ii=0; ii<helper.jmp_sz; ++ii) {
int i = helper.jmps[ii];
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 {
// find jump address instruction
int k=-1;
int search = ((j>=helper.insts[0].x64.addr) && j<helper.insts[0].x64.addr+helper.isize)?1:0;
int imin = 0;
int imax = helper.size-1;
int i2 = helper.size/2;
// dichotomy search
while(search) {
if(helper.insts[i2].x64.addr == j) {
k = i2;
search = 0;
} else if(helper.insts[i2].x64.addr>j) {
imax = i2;
i2 = (imax+imin)/2;
} else {
imin = i2;
i2 = (imax+imin)/2;
}
if(search && (imax-imin)<2) {
search = 0;
if(helper.insts[imin].x64.addr==j)
k = imin;
else if(helper.insts[imax].x64.addr==j)
k = imax;
}
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
helper.insts[i].x64.jmp_insts = k;
}
/*for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x64.addr==j)
k=i2;
}*/
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
helper.insts[i].x64.jmp_insts = k;
}
}
// no need for next and jmps anymore
dynaFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
dynaFree(helper.jmps);
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// fill predecessors with the jump address
fillPredecessors(&helper);
+60 -29
View File
@@ -66,12 +66,24 @@ void native_fxtract(x64emu_t* emu)
}
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);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
void native_fyl2xp1(x64emu_t* emu)
{
@@ -174,6 +186,17 @@ void native_singlestep(x64emu_t* emu)
emit_signal(emu, SIGTRAP, (void*)R_RIP, 1);
}
void native_int3(x64emu_t* emu)
{
emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
}
void native_div0(x64emu_t* emu)
{
emu->test.test = 0;
emit_div0(emu, (void*)R_RIP, 0);
}
void native_fsave(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -200,13 +223,24 @@ void native_frstor(x64emu_t* emu, uint8_t* ed)
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);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
@@ -371,9 +405,8 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
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) {*/
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
@@ -382,22 +415,14 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
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
if(dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
return 1;
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[ninst].f_exit.pending==SF_PENDING || dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
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;
}
@@ -451,6 +476,12 @@ uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
return addr;
}
// return Ib on a mod/rm opcode without emiting anything
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
addr = fakeed(dyn, addr, ninst, nextop);
return F8;
}
#undef F8
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
+4
View File
@@ -46,7 +46,9 @@ 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);
void native_int3(x64emu_t* emu);
void native_int(x64emu_t* emu, int num);
void native_div0(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
@@ -57,6 +59,8 @@ 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);
// return Ib on a mod/rm opcode without emiting anything
uint8_t geted_ib(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);
+29 -21
View File
@@ -77,6 +77,11 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->last_ip = 0; // reset IP if some jump are coming here
fpu_propagate_stack(dyn, ninst);
NEW_INST;
#if STEP == 0
if(ninst && dyn->insts[ninst-1].x64.barrier_next) {
BARRIER(dyn->insts[ninst-1].x64.barrier_next);
}
#endif
if(!ninst) {
GOTEST(x1, x2);
}
@@ -88,17 +93,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(box64_dynarec_test) {
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(x64test_init, 1);
GO_TRACE(x64test_init, 1, x5);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
#ifdef HAVE_TRACE
else if(my_context->dec && box64_dynarec_trace) {
if((trace_end == 0)
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(PrintTrace, 1);
GO_TRACE(PrintTrace, 1, x5);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
@@ -107,12 +112,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
rep = 0;
uint8_t pk = PK(0);
while((pk==0xF2) || (pk==0xF3)) {
rep = pk-0xF1;
++addr;
pk = PK(0);
}
while(pk==0x3E || pk==0x26) { //Branch Taken Hint ignored, same for ES: prefix
while((pk==0xF2) || (pk==0xF3) || (pk==0x3E) || (pk==0x26)) {
switch(pk) {
case 0xF2: rep = 1; break;
case 0xF3: rep = 2; break;
case 0x3E:
case 0x26: /* ignored */ break;
}
++addr;
pk = PK(0);
}
@@ -177,7 +183,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog) {
// we made it!
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to);
if(dyn->insts[dyn->forward_ninst].x64.has_callret && !dyn->insts[dyn->forward_ninst].x64.has_next)
dyn->insts[dyn->forward_ninst].x64.has_next = 1; // this block actually continue
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
@@ -200,18 +208,18 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
reset_n = -2;
for(int ii=0; ii<ninst; ++ii)
if(dyn->insts[ii].x64.jmp == next) {
reset_n = ii;
ii=ninst;
}
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);
if(dyn->insts[ninst].x64.has_callret && !dyn->insts[ninst].x64.has_next) {
dyn->insts[ninst].x64.has_next = 1; // this block actually continue
} else {
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
// and pred table is not ready yet
reset_n = get_first_jump(dyn, next);
}
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %s%p -> %p (ninst=%d, jump from %d)\n", dyn, dyn->insts[ninst].x64.has_callret?"(opt. call) ":"", (void*)addr, (void*)next, ninst, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
if(dyn->forward) {
@@ -232,7 +240,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
#endif
if(ok<0) {
ok = 0; need_epilog=1;
ok = 0; need_epilog=1;
#if STEP == 0
if(ninst) {
--ninst;
@@ -256,7 +264,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
++ninst;
#if STEP == 0
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
|| (addr>=box64_nodynarec_start && addr<box64_nodynarec_end)))
#else
if(ok && (ninst==dyn->size))
+2
View File
@@ -33,6 +33,8 @@ typedef struct instruction_x64_s {
uint8_t jmp_cond; // 1 of conditionnal jump
uint8_t has_next; // does this opcode can continue to the next?
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t barrier_next; // next instruction needs a barrier
uint8_t has_callret; // this instruction have an optimised call setup
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
+8
View File
@@ -28,6 +28,10 @@
#define native_lock_incif0(A) arm64_lock_incif0(A)
#define native_lock_decifnot0(A) arm64_lock_decifnot0(A)
#define native_lock_store(A, B) arm64_lock_store(A, B)
#define native_lock_store_dd(A, B) arm64_lock_store_dd(A, B)
#define native_lock_get_b(A) arm64_lock_get_b(A)
#define native_lock_get_d(A) arm64_lock_get_d(A)
#define native_lock_get_dd(A) arm64_lock_get_dd(A)
#elif defined(RV64)
#include "rv64/rv64_lock.h"
@@ -50,6 +54,7 @@
#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_store_dd(A, B) rv64_lock_store_dd(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)
@@ -68,6 +73,9 @@
// 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);
#define native_lock_get_b(A) rv64_lock_get_b(A)
#define native_lock_get_d(A) rv64_lock_get_d(A)
#define native_lock_get_dd(A) rv64_lock_get_dd(A)
#else
#error Unsupported architecture
+1 -1
View File
@@ -213,7 +213,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
ANDI(x1, xRAX, 0xff);
emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
ANDI(xRAX, xRAX, -256);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x1);
break;
case 0x15:
+29 -1
View File
@@ -172,7 +172,10 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
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);
if(rex.is32bits)
addr = dynarec64_67_32(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
else
addr = dynarec64_67(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x68:
INST_NAME("PUSH Id");
@@ -260,6 +263,31 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0x6C:
case 0x6D:
INST_NAME(opcode == 0x6C ? "INSB" : "INSD");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(x3);
CALL(native_priv, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0x6E:
case 0x6F:
INST_NAME(opcode == 0x6C ? "OUTSB" : "OUTSD");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL(x3);
CALL(native_priv, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
i8 = F8S; \
+81 -9
View File
@@ -418,7 +418,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
LHU(x1, ed, fixedaddress);
ed = x1;
}
SW(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
SH(ed, xEmu, offsetof(x64emu_t, segs[(nextop&0x38)>>3]));
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[(nextop&0x38)>>3]));
break;
case 0x8F:
@@ -499,15 +499,24 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
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));
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
case 0x9E:
INST_NAME("SAHF");
SETFLAGS(X_CF | X_PF | X_AF | X_ZF | X_SF, SF_SUBSET);
ADDI(x1, xZR, ~0b11010101);
AND(xFlags, xFlags, x1);
NOT(x1, x1);
SRLI(x2, xRAX, 8);
AND(x1, x1, x2);
OR(xFlags, xFlags, x1);
SET_DFNONE();
break;
case 0x9F:
INST_NAME("LAHF");
READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
READFLAGS(X_CF | X_PF | X_AF | X_ZF | X_SF);
ANDI(x1, xFlags, 0xFF);
SLLI(x1, x1, 8);
MOV64x(x2, 0xffffffffffff00ffLL);
@@ -558,7 +567,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
B_NEXT_nocond;
MARK2; // Part with DF==1
LBU(x1, xRSI, 0);
LBU(x1, xRDI, 0);
SB(x1, xRDI, 0);
SUBI(xRSI, xRSI, 1);
SUBI(xRDI, xRDI, 1);
SUBI(xRCX, xRCX, 1);
@@ -646,6 +655,48 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
}
break;
case 0xA7:
switch (rep) {
case 1:
case 2:
if (rep == 1) { INST_NAME("REPNZ CMPSD"); } else { INST_NAME("REPZ CMPSD"); }
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
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); }
BNEZ_MARK(xRCX);
B_MARK3_nocond;
MARK2; // Part with DF==1
LDxw(x1, xRSI, 0);
SUBI(xRSI, xRSI, rex.w ? 8 : 4);
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); }
BNEZ_MARK2(xRCX);
MARK3; // end
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
break;
default:
INST_NAME("CMPSD");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, rex.w ? 8 : 4);
LDxw(x1, xRSI, 0);
LDxw(x2, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
break;
}
break;
case 0xA8:
INST_NAME("TEST AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -711,6 +762,28 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
ADD(xRDI, xRDI, x3);
}
break;
case 0xAC:
if (rep) {
DEFAULT;
} else {
INST_NAME("LODSB");
GETDIR(x1, x2, 1);
LBU(x2, xRSI, 0);
ADD(xRSI, xRSI, x1);
ANDI(xRAX, xRAX, ~0xff);
OR(xRAX, xRAX, x2);
}
break;
case 0xAD:
if (rep) {
DEFAULT;
} else {
INST_NAME("LODSD");
GETDIR(x1, x2, rex.w ? 8 : 4);
LDxw(xRAX, xRSI, 0);
ADD(xRSI, xRSI, x1);
}
break;
case 0xAE:
switch (rep) {
case 1:
@@ -780,10 +853,9 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
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);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
break;
}
break;
+25 -10
View File
@@ -319,7 +319,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
addr+=8+8;
} else {
GETIP(ip+1); // read the 0xCC
STORE_XEMU_CALL();
STORE_XEMU_CALL(x3);
ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
CALL_S(x64Int3, -1);
LOAD_XEMU_CALL();
@@ -360,7 +360,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
NOTEST(x1);
SMEND();
GETIP(addr);
STORE_XEMU_CALL();
STORE_XEMU_CALL(x3);
CALL_S(x86Syscall, -1);
LOAD_XEMU_CALL();
TABLE64(x3, addr); // expected return address
@@ -368,13 +368,13 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
LW(x1, xEmu, offsetof(x64emu_t, quit));
BEQ_NEXT(x1, xZR);
MARK;
LOAD_XEMU_REM();
LOAD_XEMU_REM(x3);
jump_to_epilog(dyn, 0, xRIP, ninst);
} else {
INST_NAME("INT n");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
GETIP(ip);
STORE_XEMU_CALL();
STORE_XEMU_CALL(x3);
CALL(native_priv, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
@@ -503,6 +503,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
WBACK;
if(!wback && !rex.w) ZEROUP(ed);
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
GETEDW(x4, x1, 0);
CALL_(rex.w ? ((void*)rcl64) : ((void*)rcl32), ed, x4);
WBACK;
break;
case 3:
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
@@ -604,7 +614,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xD9:
addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDA:
addr = dynarec64_DA(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDB:
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
@@ -723,7 +735,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
dyn->last_ip = addr;
} else {
GETIP_(dyn->insts[ninst].natcall); // read the 0xCC already
STORE_XEMU_CALL();
STORE_XEMU_CALL(x3);
ADDI(x1, xEmu, (uint32_t)offsetof(x64emu_t, ip)); // setup addr as &emu->ip
CALL_S(x64Int3, -1);
LOAD_XEMU_CALL();
@@ -755,7 +767,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
// regular call
//BARRIER_NEXT(1);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
} else {
@@ -1076,7 +1087,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0xFC:
INST_NAME("CLD");
ANDI(xFlags, xFlags, ~(1<<F_CF));
ANDI(xFlags, xFlags, ~(1 << F_DF));
break;
case 0xFD:
INST_NAME("STD");
ORI(xFlags, xFlags, 1 << F_DF);
break;
case 0xFE:
nextop = F8;
@@ -1168,12 +1183,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("JMP FAR Ed");
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
SMREAD()
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
LDxw(x1, wback, 0);
ed = x1;
LHU(x3, wback, rex.w?8:4);
SW(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[_CS]));
jump_to_epilog(dyn, 0, ed, ninst);
*need_epilog = 0;
File diff suppressed because it is too large. Load diff
+52 -1
View File
@@ -393,7 +393,44 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LDxw(gd, x4, fixedaddress);
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
u8 = (nextop&0x38) >> 3;
if ((nextop&0xC0) == 0xC0) {
ed = xRAX+(nextop&7) + (rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
ADD(x4, wback, x4);
LHU(x1, x4, 0);
ed = x1;
}
SH(ed, xEmu, offsetof(x64emu_t, segs[u8]));
SW(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
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(x3); // so this can handle POP [ESP] and maybe some variant too
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
if (ed == xRSP) {
ADD(x4, ed, x4);
SDz(x3, x4, 0);
} else {
// complicated to just allow a segfault that can be recovered correctly
ADDIz(xRSP, xRSP, rex.is32bits ? -4 : -8);
ADD(x4, ed, x4);
SDz(x3, x4, 0);
ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8);
}
}
break;
case 0xA1:
INST_NAME("MOV EAX,FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg);
@@ -489,6 +526,20 @@ uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SMWRITE2();
}
break;
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH Ed");
GETEDOz(x6, 0, x3);
PUSH1z(ed);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
+85 -3
View File
@@ -15,6 +15,7 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
@@ -115,7 +116,11 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
OR(xRAX, xRAX, x1);
break;
case 0x0F:
addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
switch(rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
}
break;
case 0x11:
INST_NAME("ADC Ew, Gw");
@@ -539,7 +544,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
OR(ed, ed, x2);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -602,6 +607,29 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
AND(x1, x1, x2);
OR(xRAX, xRAX, x1);
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
if (rex.is32bits) u64 = F32; else u64 = F64;
MOV64z(x1, u64);
if (isLockAddress(u64)) lock = 1; else lock = 0;
SMREADLOCK(lock);
LHU(x2, x1, 0);
LUI(x3, 0xffff0);
AND(xRAX, xRAX, x3);
OR(xRAX, xRAX, x2);
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
if(rex.is32bits)
u64 = F32;
else
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
SH(xRAX, x1, 0);
SMWRITELOCK(lock);
break;
case 0xA5:
if(rep) {
INST_NAME("REP MOVSW");
@@ -633,6 +661,48 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADD(xRDI, xRDI, x3);
}
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);
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LHU(x1, xRSI, 0);
ADDI(xRSI, xRSI, 2);
LHU(x2, xRDI, 0);
ADDI(xRDI, xRDI, 2);
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
LHU(x1, xRSI, 0);
SUBI(xRSI, xRSI, 2);
LHU(x2, xRDI, 0);
SUBI(xRDI, xRDI, 2);
SUBI(xRCX, xRCX, 1);
if (rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); }
BNEZ_MARK2(xRCX);
MARK3; // end
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
default:
INST_NAME("CMPSW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, x1, 2);
LHU(x1, xRSI, 0);
LHU(x2, xRDI, 0);
ADD(xRSI, xRSI, x3);
ADD(xRDI, xRDI, x3);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -667,7 +737,19 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADD(xRDI, xRDI, x3);
}
break;
case 0xAD:
if (rep) {
DEFAULT;
} else {
INST_NAME("LODSW");
GETDIR(x1, x2, 2);
LHU(x2, xRSI, 0);
ADD(xRSI, xRSI, x1);
LUI(x1, 0xffff0);
AND(xRAX, xRAX, x1);
OR(xRAX, xRAX, x2);
}
break;
case 0xAF:
switch (rep) {
case 1:
File diff suppressed because it is too large. Load diff
+58
View File
@@ -0,0 +1,58 @@
#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"
uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8, s8;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2, gback;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress, gdoffset;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ };
switch (opcode) {
default:
DEFAULT;
}
return addr;
}
+58
View File
@@ -0,0 +1,58 @@
#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"
uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8, s8;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2, gback;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress, gdoffset;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j64);
static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ };
switch (opcode) {
default:
DEFAULT;
}
return addr;
}
+103
View File
@@ -180,6 +180,44 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0xB6:
INST_NAME("MOVXZ 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
}
if (eb2) {
SRLI(gd, eb1, 8);
ANDI(gd, gd, 0xff);
} else {
ANDI(gd, eb1, 0xff);
}
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
LBU(gd, ed, fixedaddress);
}
break;
case 0xB7:
INST_NAME("MOVZX Gd, Ew");
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX + (nextop & 7) + (rex.b << 3);
ZEXTH(gd, ed);
} else {
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
LHU(gd, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
@@ -410,6 +448,54 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else
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
ADDIW(gd, xRAX + (nextop & 7) + (rex.b << 3), 0);
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 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 = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
LWU(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) {
LUI(x1, 0xffff0);
AND(ed, ed, x1);
ZEXTH(x2, gd);
OR(ed, ed, x2);
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
@@ -567,6 +653,23 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
}
break;
case 0xC7:
INST_NAME("MOV Ed, Id");
nextop = F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX + (nextop & 7) + (rex.b << 3);
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
i64 = F32S;
MOV64xw(x3, i64);
SDxw(x3, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
#define GO(Z) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
+59
View File
@@ -0,0 +1,59 @@
#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_32(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;
if(!rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
default:
DEFAULT;
}
return addr;
}
+103 -48
View File
@@ -43,56 +43,45 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch(nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
break;
case 0xC8 ... 0xCF:
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
break;
case 0xD0 ... 0xD7:
INST_NAME("FCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
break;
case 0xD8 ... 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
LHU(x3, xEmu, offsetof(x64emu_t, sw));
MOV32w(x1, 0b1110100011111111); // mask off c0,c1,c2,c3
AND(x3, x3, x1);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
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
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} 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
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
OR(x3, x3, x1);
SH(x3, xEmu, offsetof(x64emu_t, sw));
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0 ... 0xE7:
INST_NAME("FSUB ST0, STx");
@@ -105,11 +94,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0xE8 ... 0xEF:
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
break;
case 0xF0 ... 0xF7:
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
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 {
@@ -117,7 +114,14 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
break;
case 0xF8 ... 0xFF:
DEFAULT;
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
break;
default:
@@ -148,6 +152,33 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FMULD(v1, v1, s0);
}
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLW(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FCOMS(v1, s0, x1, x6, x3, x4, x5);
} else {
FCVTDS(s0, s0);
FCOMD(v1, s0, x1, x6, x3, x4, x5);
}
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLW(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FCOMS(v1, s0, x1, x6, x3, x4, x5);
} else {
FCVTDS(s0, s0);
FCOMD(v1, s0, x1, x6, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
@@ -161,6 +192,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FSUBD(v1, v1, s0);
}
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLW(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FSUBS(v1, s0, v1);
} else {
FCVTDS(s0, s0);
FSUBD(v1, s0, v1);
}
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
@@ -174,8 +218,19 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FDIVD(v1, v1, s0);
}
break;
default:
DEFAULT;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
FLW(s0, ed, fixedaddress);
if (ST_IS_F(0)) {
FDIVS(v1, s0, v1);
} else {
FCVTDS(s0, s0);
FDIVD(v1, s0, v1);
}
break;
}
}
return addr;
+20 -20
View File
@@ -54,7 +54,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v2 = x87_do_push(dyn, ninst, x1, X87_ST(nextop&7));
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, X87_ST(nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
if(ST_IS_F(0)) {
FMVS(v2, v1);
@@ -87,7 +87,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xD8:
INST_NAME("FSTPNCE ST0, ST0");
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
@@ -101,7 +101,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FCHS");
@@ -135,7 +135,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
FMVWX(v1, x1);
@@ -146,32 +146,32 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
FTABLE64(v1, L2T);
break;
case 0xEA:
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, 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);
X87_PUSH_OR_FAIL(v1, 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);
X87_PUSH_OR_FAIL(v1, 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);
X87_PUSH_OR_FAIL(v1, 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);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
FMVWX(v1, xZR);
} else {
@@ -191,14 +191,14 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fyl2x, -1);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_ftan, -1);
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32w(x1, 0x3f800000);
FMVWX(v1, x1);
@@ -213,12 +213,12 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fpatan, -1);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF4:
INST_NAME("FXTRACT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fxtract, -1);
break;
@@ -258,7 +258,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fyl2xp1, -1);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xFA:
INST_NAME("FSQRT");
@@ -272,7 +272,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xFB:
INST_NAME("FSINCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fsincos, -1);
break;
@@ -349,12 +349,12 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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);
X87_PUSH_OR_FAIL(v1, 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)) {
@@ -381,7 +381,7 @@ uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FCVTSD(v1, v1);
}
FSW(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
+164
View File
@@ -0,0 +1,164 @@
#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_DA(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 = F8;
int64_t j64;
uint8_t ed;
uint8_t wback;
int v1, v2;
int d0;
int s0;
int64_t fixedaddress;
int unscaled;
MAYUSE(s0);
MAYUSE(d0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(j64);
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FCMOVB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
ANDI(x1, xFlags, 1 << F_CF);
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMVS(v1, v2);
else
FMVD(v1, v2);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FCMOVE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
ANDI(x1, xFlags, 1 << F_ZF);
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMVS(v1, v2);
else
FMVD(v1, v2);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCMOVBE ST0, STx");
READFLAGS(X_CF | X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
ANDI(x1, xFlags, (1 << F_CF) | (1 << F_ZF));
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMVS(v1, v2);
else
FMVD(v1, v2);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCMOVU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
ANDI(x1, xFlags, (1 << F_PF));
CBZ_NEXT(x1);
if (ST_IS_F(0))
FMVS(v1, v2);
else
FMVD(v1, v2);
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, 1, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFD:
DEFAULT;
break;
default:
switch ((nextop >> 3) & 7) {
case 6:
INST_NAME("FIDIV ST0, 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, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LW(x1, ed, fixedaddress);
FCVTDW(v2, x1, RD_RNE);
FDIVD(v1, v1, v2);
break;
default:
DEFAULT;
break;
}
}
return addr;
}
+8 -8
View File
@@ -153,7 +153,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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) {
IFX(X_ZF | X_PF | X_CF) {
if(ST_IS_F(0)) {
FEQS(x5, v1, v1);
FEQS(x4, v2, v2);
@@ -189,7 +189,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
}
break;
case 0xF0:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
@@ -213,7 +213,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, 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
@@ -245,7 +245,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
MARK2;
SW(x4, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FLD tbyte");
@@ -268,13 +268,13 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SH(x6, ed, fixedaddress+8);
} else {
if(box64_x87_no80bits) {
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, EXT_CACHE_ST_D);
FLD(v1, ed, fixedaddress);
} else {
if(ed!=x1) {
MV(x1, ed);
ADDI(x1, ed, fixedaddress);
}
x87_do_push_empty(dyn, ninst, x3);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
CALL(native_fld, -1);
}
}
@@ -293,7 +293,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
CALL(native_fstp, -1);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+107 -35
View File
@@ -39,69 +39,135 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch(nextop) {
case 0xC0 ... 0xC7:
INST_NAME("FADD STx, ST0");
DEFAULT;
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);
}
break;
case 0xC8 ... 0xCF:
INST_NAME("FMUL STx, ST0");
DEFAULT;
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);
}
break;
case 0xD0 ... 0xD7:
INST_NAME("FCOM ST0, STx"); //yep
DEFAULT;
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
break;
case 0xD8 ... 0xDF:
INST_NAME("FCOMP ST0, STx");
DEFAULT;
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0 ... 0xE7:
INST_NAME("FSUBR STx, ST0");
DEFAULT;
break;
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);
}
break;
case 0xE8 ... 0xEF:
INST_NAME("FSUB STx, ST0");
DEFAULT;
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);
}
break;
case 0xF0 ... 0xF7:
INST_NAME("FDIVR STx, ST0");
DEFAULT;
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);
}
break;
case 0xF8 ... 0xFF:
INST_NAME("FDIV STx, ST0");
DEFAULT;
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);
}
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD 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);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FMUL 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);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FCOM 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);
FCOMD(v1, v2, x1, x6, x3, x4, x5);
break;
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);
FCOMD(v1, v2, x1, x6, x3, x4, x5);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, 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);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FSUBR 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);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
@@ -111,8 +177,14 @@ uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FLD(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
default:
DEFAULT;
case 7:
INST_NAME("FDIVR 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, v2, v1);
break;
}
}
return addr;
+26 -7
View File
@@ -64,11 +64,17 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xD6:
case 0xD7:
INST_NAME("FST ST0, STx");
DEFAULT;
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)) {
FMVS(v2, v1);
} else {
FMVD(v2, v1);
}
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
@@ -82,7 +88,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -93,7 +99,13 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xE6:
case 0xE7:
INST_NAME("FUCOM ST0, STx");
DEFAULT;
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
break;
case 0xE8:
case 0xE9:
@@ -104,7 +116,14 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xEE:
case 0xEF:
INST_NAME("FUCOMP ST0, STx");
DEFAULT;
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
@@ -137,7 +156,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, 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;
@@ -152,7 +171,7 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7:
INST_NAME("FNSTSW m2byte");
+28 -12
View File
@@ -52,7 +52,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FADDD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
@@ -70,7 +70,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FMULD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
@@ -80,12 +80,27 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xD5:
case 0xD6:
case 0xD7:
// INST_NAME("FCOMP ST0, STx"); //yep
DEFAULT;
INST_NAME("FCOMP ST0, STx"); // yep
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
// INST_NAME("FCOMPP ST0, STx");
DEFAULT;
INST_NAME("FCOMPP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
FCOMS(v1, v2, x1, x2, x3, x4, x5);
} else {
FCOMD(v1, v2, x1, x2, x3, x4, x5);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -103,7 +118,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FSUBD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE8:
case 0xE9:
@@ -121,7 +136,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FSUBD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
@@ -139,8 +154,8 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FDIVD(v1, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
break;
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF8:
case 0xF9:
case 0xFA:
@@ -157,7 +172,7 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
FDIVD(v1, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD8:
case 0xDA:
@@ -166,7 +181,8 @@ uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xDD:
case 0xDE:
case 0xDF:
return 0;
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
default:
+16 -8
View File
@@ -46,7 +46,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xE0:
INST_NAME("FNSTSW AX");
LHU(x2, xEmu, offsetof(x64emu_t, top));
LWU(x2, xEmu, offsetof(x64emu_t, top));
LHU(x1, xEmu, offsetof(x64emu_t, sw));
MOV32w(x3, 0b1100011111111111); // mask
AND(x1, x1, x3);
@@ -68,7 +68,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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) {
IFX(X_ZF | X_PF | X_CF) {
if(ST_IS_F(0)) {
FEQS(x5, v1, v1);
FEQS(x4, v2, v2);
@@ -103,7 +103,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
// end
}
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8 ... 0xDF:
case 0xE1 ... 0xE7:
@@ -115,7 +115,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, 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)) {
@@ -144,7 +144,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
MARK2;
SH(x4, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
@@ -168,11 +168,11 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
MARK2;
SH(x4, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, 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) {
@@ -193,6 +193,14 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FSD(v1, x5, 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, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL(fpu_fbst, -1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, EXT_CACHE_ST_D);
@@ -233,7 +241,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SD(x4, wback, fixedaddress);
MARK3;
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+18 -18
View File
@@ -63,7 +63,7 @@ void emit_add32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s5, s1); // s5 = ~res
AND(s3, s5, s3); // s3 = ~res & (op1 | op2)
@@ -160,7 +160,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
@@ -218,7 +218,7 @@ void emit_add16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s5, s1); // s5 = ~res
AND(s3, s5, s3); // s3 = ~res & (op1 | op2)
@@ -280,7 +280,7 @@ void emit_add8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_AF|X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s4, s1); // s4 = ~res
AND(s3, s4, s3); // s3 = ~res & (op1 | op2)
@@ -336,7 +336,7 @@ void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
SET_DFNONE();
}
IFX(X_AF | X_OF) {
if(X_PEND) {} else {MOV32w(s4, c&0xff);}
IFX(X_PEND) {} else {MOV32w(s4, c&0xff);}
OR(s3, s1, s4); // s3 = op1 | op2
AND(s4, s1, s4); // s4 = op1 & op2
}
@@ -344,7 +344,7 @@ void emit_add8c(dynarec_rv64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
IFX(X_AF|X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
@@ -596,7 +596,7 @@ void emit_inc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
@@ -709,7 +709,7 @@ void emit_inc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
@@ -825,7 +825,7 @@ void emit_inc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s3); // s3 = ~res & (op1 | op2)
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s3); // s3 = ~res & (op1 | op2)
@@ -968,8 +968,8 @@ void emit_adc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
SET_DFNONE();
}
IFX(X_AF | X_OF) {
OR(s4, s1, s2); // s3 = op1 | op2
AND(s5, s1, s2); // s4 = op1 & op2
OR(s4, s1, s2); // s4 = op1 | op2
AND(s5, s1, s2); // s5 = op1 & op2
}
ADD(s1, s1, s2);
@@ -982,7 +982,7 @@ void emit_adc8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
@@ -1304,8 +1304,8 @@ void emit_adc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
SET_DFNONE();
}
IFX(X_AF | X_OF) {
OR(s4, s1, s2); // s3 = op1 | op2
AND(s5, s1, s2); // s4 = op1 & op2
OR(s4, s1, s2); // s4 = op1 | op2
AND(s5, s1, s2); // s5 = op1 & op2
}
ADD(s1, s1, s2);
@@ -1318,7 +1318,7 @@ void emit_adc16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
@@ -1386,8 +1386,8 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
}
IFX(X_AF | X_OF) {
OR(s4, s1, s2); // s3 = op1 | op2
AND(s5, s1, s2); // s4 = op1 & op2
OR(s4, s1, s2); // s4 = op1 | op2
AND(s5, s1, s2); // s5 = op1 & op2
}
ADDxw(s1, s1, s2);
@@ -1404,7 +1404,7 @@ void emit_adc32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX(X_AF | X_OF) {
if(rv64_zbb) {
ANDN(s3, s1, s4); // s3 = ~res & (op1 | op2)
ANDN(s3, s4, s1); // s3 = ~res & (op1 | op2)
} else {
NOT(s2, s1); // s2 = ~res
AND(s3, s2, s4); // s3 = ~res & (op1 | op2)
+8 -4
View File
@@ -385,8 +385,8 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
SRLI(s3, s1, rex.w?63:31);
AND(xFlags, xFlags, s3);
SRLIxw(s3, s1, rex.w?63:31);
OR(xFlags, xFlags, s3);
}
IFX(X_OF) {
ADDI(s3, xZR, 1);
@@ -421,6 +421,8 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
if(rv64_zbb) {
RORIxw(s1, s1, (rex.w?64:32)-c);
} else if (rv64_xtheadbb) {
TH_SRRIxw(s1, s1, (rex.w?64:32)-c);
} else {
SLLIxw(s3, s1, c);
SRLIxw(s1, s1, (rex.w?64:32)-c);
@@ -466,6 +468,8 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
if(rv64_zbb) {
RORIxw(s1, s1, c);
} else if (rv64_xtheadbb) {
TH_SRRIxw(s1, s1, c);
} else {
SRLIxw(s3, s1, c);
SLLIxw(s1, s1, (rex.w?64:32)-c);
@@ -475,8 +479,8 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
SRLI(s3, s1, rex.w?63:31);
AND(xFlags, xFlags, s3);
SRLIxw(s3, s1, rex.w?63:31);
OR(xFlags, xFlags, s3);
}
IFX(X_OF) {
if(c==1) {
+81 -9
View File
@@ -49,8 +49,9 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETREX();
// TODO: Take care of unligned memory access for all the LOCK ones.
// https://github.com/ptitSeb/box64/pull/604
// TODO: Add support for unligned memory access for all the LOCK ones.
// TODO: Add support for BOX4_DYNAREC_ALIGNED_ATOMICS.
switch(opcode) {
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
@@ -214,13 +215,29 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
LRxw(x1, wback, 1, 1);
SUBxw(x3, x1, xRAX);
BNE_MARK(x3, xZR);
BNEZ_MARK(x3);
// EAX == Ed
SCxw(x4, gd, wback, 1, 1);
BNEZ_MARKLOCK(x4);
B_MARK_nocond;
MARK3;
// Unaligned
ANDI(x5, wback, -(1 << (rex.w + 2)));
MARK2; // Use MARK2 as a "MARKLOCK" since we're running out of marks.
LDxw(x6, wback, 0);
LRxw(x1, x5, 1, 1);
SUBxw(x3, x6, xRAX);
BNEZ_MARK(x3);
// EAX == Ed
SCxw(x4, x1, x5, 1, 1);
BNEZ_MARK2(x4);
SDxw(gd, wback, 0);
MARK;
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);}
MVxw(xRAX, x1);
@@ -371,7 +388,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MARKLOCK;
LR_W(x5, wback, 1, 1);
ANDI(x4, x5, 0xff); // x4 = Ed.b[0]
ANDI(x5, x5, -256); // x5 = clear Ed.b[0]
ANDI(x5, x5, ~0xff); // x5 = clear Ed.b[0]
ADDW(x6, x4, x2);
ANDI(x9, xFlags, 1 << F_CF);
ADDW(x6, x6, x9); // x6 = adc
@@ -533,20 +550,40 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if (i64 < -2048 || i64 >= 2048)
MOV64xw(x4, i64);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
LRxw(x1, wback, 1, 1);
if(i64>=-2048 && i64<2048)
if (i64 >= -2048 && i64 < 2048)
ADDIxw(x4, x1, i64);
else {
MOV64xw(x4, i64);
else
ADDxw(x4, x1, x4);
}
SCxw(x3, x4, wback, 1, 1);
BNEZ_MARKLOCK(x3);
IFX(X_ALL|X_PEND)
B_MARK_nocond;
MARK3;
// Unaligned
ANDI(x5, wback, -(1 << (rex.w + 2)));
MARK2; // Use MARK2 as a "MARKLOCK" since we're running out of marks.
LDxw(x6, wback, 0);
LRxw(x1, x5, 1, 1);
if (i64 >= -2048 && i64 < 2048)
ADDIxw(x4, x6, i64);
else
ADDxw(x4, x6, x4);
SCxw(x3, x1, x5, 1, 1);
BNEZ_MARK2(x3);
SDxw(x4, wback, 0);
MARK;
IFX (X_ALL | X_PEND)
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
SMDMB();
}
break;
case 1: // OR
@@ -640,6 +677,41 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
SMDMB();
break;
case 0x87:
INST_NAME("LOCK XCHG Ed, Gd");
nextop = F8;
if (MODREG) {
GETGD;
GETED(0);
MV(x1, gd);
MV(gd, ed);
MV(ed, x1);
} else {
SMDMB();
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
LRxw(x1, wback, 1, 1);
SCxw(x4, gd, wback, 1, 1);
BNEZ_MARKLOCK(x4);
B_MARK_nocond;
MARK3;
// Unaligned
ANDI(x5, wback, -(1 << (rex.w + 2)));
MARK2; // Use MARK2 as a "MARKLOCK" since we're running out of marks.
LDxw(x1, wback, 0);
LRxw(x3, x5, 1, 1);
SCxw(x4, x3, x5, 1, 1);
BNEZ_MARK2(x4);
SDxw(gd, wback, 0);
MARK;
MVxw(gd, x1);
SMDMB();
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7)
-27
View File
@@ -146,33 +146,6 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
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();
CALL(native_ud, -1);
LOAD_XEMU_CALL();
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();
CALL(native_ud, -1);
LOAD_XEMU_CALL();
jump_to_epilog(dyn, 0, xRIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
default:
DEFAULT;
}
+113 -106
View File
@@ -24,7 +24,8 @@
uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
@@ -46,14 +47,14 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
MAYUSE(v1);
MAYUSE(j64);
switch(opcode) {
switch (opcode) {
case 0x10:
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
if (MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 1);
q0 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1);
FMVS(v0, q0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd, 1);
@@ -61,8 +62,8 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
FLW(v0, ed, fixedaddress);
// reset upper part
SW(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+4);
SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8);
SW(xZR, xEmu, offsetof(x64emu_t, xmm[gd]) + 4);
SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd]) + 8);
}
break;
case 0x11:
@@ -70,8 +71,8 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
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);
if (MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1);
FMVS(q0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
@@ -88,12 +89,12 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
// GX->ud[1] = GX->ud[0] = EX->ud[0];
// GX->ud[3] = GX->ud[2] = EX->ud[2];
LD(x3, wback, fixedaddress+0);
SD(x3, gback, gdoffset+0);
SD(x3, gback, gdoffset+4);
LD(x3, wback, fixedaddress+8);
SD(x3, gback, gdoffset+8);
SD(x3, gback, gdoffset+12);
LD(x3, wback, fixedaddress + 0);
SD(x3, gback, gdoffset + 0);
SD(x3, gback, gdoffset + 4);
LD(x3, wback, fixedaddress + 8);
SD(x3, gback, gdoffset + 8);
SD(x3, gback, gdoffset + 12);
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
@@ -106,7 +107,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGXSS(v0);
GETED(0);
if(rex.w) {
if (rex.w) {
FCVTSL(v0, ed, RD_RNE);
} else {
FCVTSW(v0, ed, RD_RNE);
@@ -118,17 +119,17 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGD;
GETEXSS(d0, 0);
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // // reset all bits
if (!box64_dynarec_fastround) {
FSFLAGSI(0); // // reset all bits
}
FCVTSxw(gd, d0, RD_RTZ);
if(!rex.w)
if (!rex.w)
ZEROUP(gd);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1<<FR_NV)|(1<<FR_OF));
if (!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF));
CBZ_NEXT(x5);
if(rex.w) {
if (rex.w) {
MOV64x(gd, 0x8000000000000000LL);
} else {
MOV32w(gd, 0x80000000);
@@ -140,19 +141,19 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGD;
GETEXSS(d0, 0);
if(!box64_dynarec_fastround) {
FSFLAGSI(0); // // reset all bits
if (!box64_dynarec_fastround) {
FSFLAGSI(0); // // reset all bits
}
u8 = sse_setround(dyn, ninst, x5, x6);
FCVTSxw(gd, d0, RD_DYN);
x87_restoreround(dyn, ninst, u8);
if(!rex.w)
if (!rex.w)
ZEROUP(gd);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1<<FR_NV)|(1<<FR_OF));
if (!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF));
CBZ_NEXT(x5);
if(rex.w) {
if (rex.w) {
MOV64x(gd, 0x8000000000000000LL);
} else {
MOV32w(gd, 0x80000000);
@@ -257,31 +258,31 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
int32_t idx;
idx = 4+((u8>>(0*2))&3);
LHU(x3, wback, fixedaddress+idx*2);
idx = 4+((u8>>(1*2))&3);
LHU(x4, wback, fixedaddress+idx*2);
idx = 4+((u8>>(2*2))&3);
LHU(x5, wback, fixedaddress+idx*2);
idx = 4+((u8>>(3*2))&3);
LHU(x6, wback, fixedaddress+idx*2);
idx = 4 + ((u8 >> (0 * 2)) & 3);
LHU(x3, wback, fixedaddress + idx * 2);
idx = 4 + ((u8 >> (1 * 2)) & 3);
LHU(x4, wback, fixedaddress + idx * 2);
idx = 4 + ((u8 >> (2 * 2)) & 3);
LHU(x5, wback, fixedaddress + idx * 2);
idx = 4 + ((u8 >> (3 * 2)) & 3);
LHU(x6, wback, fixedaddress + idx * 2);
SH(x3, gback, gdoffset+(4+0)*2);
SH(x4, gback, gdoffset+(4+1)*2);
SH(x5, gback, gdoffset+(4+2)*2);
SH(x6, gback, gdoffset+(4+3)*2);
SH(x3, gback, gdoffset + (4 + 0) * 2);
SH(x4, gback, gdoffset + (4 + 1) * 2);
SH(x5, gback, gdoffset + (4 + 2) * 2);
SH(x6, gback, gdoffset + (4 + 3) * 2);
if (!(MODREG && (gd==ed))) {
LD(x3, wback, fixedaddress+0);
SD(x3, gback, gdoffset+0);
if (!(MODREG && (gd == ed))) {
LD(x3, wback, fixedaddress + 0);
SD(x3, gback, gdoffset + 0);
}
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
// Will load Gx as SD. Is that a good choice?
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
GETGXSD_empty(v0);
FMVD(v0, v1);
} else {
@@ -290,7 +291,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
FLD(v0, ed, fixedaddress);
}
SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8);
SD(xZR, xEmu, offsetof(x64emu_t, xmm[gd]) + 8);
break;
case 0x7F:
INST_NAME("MOVDQU Ex,Gx");
@@ -298,7 +299,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX();
GETEX(x2, 0);
SSE_LOOP_MV_Q2(x3);
if(!MODREG) SMWRITE2();
if (!MODREG) SMWRITE2();
break;
case 0x5B:
@@ -307,19 +308,19 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX();
GETEX(x2, 0);
v0 = fpu_get_scratch(dyn);
for(int i=0; i<4; ++i) {
if(!box64_dynarec_fastround) {
for (int i = 0; i < 4; ++i) {
if (!box64_dynarec_fastround) {
FSFLAGSI(0); // reset all bits
}
FLW(v0, wback, fixedaddress+i*4);
FLW(v0, wback, fixedaddress + i * 4);
FCVTWS(x3, v0, RD_RTZ);
if(!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1<<FR_NV)|(1<<FR_OF));
if (!box64_dynarec_fastround) {
FRFLAGS(x5); // get back FPSR to check the IOC bit
ANDI(x5, x5, (1 << FR_NV) | (1 << FR_OF));
BEQZ(x5, 8);
MOV32w(x3, 0x80000000);
}
SW(x3, gback, gdoffset+i*4);
SW(x3, gback, gdoffset + i * 4);
}
break;
case 0xB8:
@@ -329,17 +330,17 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETED(0);
GETGD;
if(!rex.w && MODREG) {
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ed = x4;
}
CLEAR_FLAGS();
BNE_MARK(ed, xZR);
ORI(xFlags, xFlags, 1<<F_ZF);
ORI(xFlags, xFlags, 1 << F_ZF);
MOV32w(gd, 0);
B_NEXT_nocond;
MARK;
if(rv64_zbb) {
if (rv64_zbb) {
CPOPxw(gd, ed);
} else {
TABLE64(x1, 0x5555555555555555uLL);
@@ -371,75 +372,75 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETED(0);
GETGD;
if(!rex.w && MODREG) {
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ed = x4;
}
ANDI(xFlags, xFlags, ~((1<<F_ZF) | (1<<F_CF)));
ANDI(xFlags, xFlags, ~((1 << F_ZF) | (1 << F_CF)));
BNE_MARK(ed, xZR);
ORI(xFlags, xFlags, 1<<F_CF);
MOV32w(gd, rex.w?64:32);
ORI(xFlags, xFlags, 1 << F_CF);
MOV32w(gd, rex.w ? 64 : 32);
B_NEXT_nocond;
MARK;
if(rv64_zbb) {
if (rv64_zbb) {
CTZxw(gd, ed);
} else {
NEG(x2, ed);
AND(x2, x2, ed);
TABLE64(x3, 0x03f79d71b4ca8b09ULL);
MUL(x2, x2, x3);
SRLI(x2, x2, 64-6);
SRLI(x2, x2, 64 - 6);
TABLE64(x1, (uintptr_t)&deBruijn64tab);
ADD(x1, x1, x2);
LBU(gd, x1, 0);
}
BNE(gd, xZR, 4+4);
ORI(xFlags, xFlags, 1<<F_ZF);
BNE(gd, xZR, 4 + 4);
ORI(xFlags, xFlags, 1 << F_ZF);
break;
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
SETFLAGS(X_ZF|X_CF, SF_SUBSET);
SETFLAGS(X_ZF | X_CF, SF_SUBSET);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
if(!rex.w && MODREG) {
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ed = x4;
}
BNE_MARK(ed, xZR);
MOV32w(gd, rex.w?64:32);
ANDI(xFlags, xFlags, ~(1<<F_ZF));
ORI(xFlags, xFlags, 1<<F_CF);
MOV32w(gd, rex.w ? 64 : 32);
ANDI(xFlags, xFlags, ~(1 << F_ZF));
ORI(xFlags, xFlags, 1 << F_CF);
B_NEXT_nocond;
MARK;
if(rv64_zbb) {
if (rv64_zbb) {
CLZxw(gd, ed);
} else {
if(ed!=gd)
if (ed != gd)
u8 = gd;
else
u8 = x1;
ADDI(u8, xZR, rex.w?63:31);
if(rex.w) {
ADDI(u8, xZR, rex.w ? 63 : 31);
if (rex.w) {
MV(x2, ed);
SRLI(x3, x2, 32);
BEQZ(x3, 4+2*4);
BEQZ(x3, 4 + 2 * 4);
SUBI(u8, u8, 32);
MV(x2, x3);
} else {
AND(x2, ed, xMASK);
}
SRLI(x3, x2, 16);
BEQZ(x3, 4+2*4);
BEQZ(x3, 4 + 2 * 4);
SUBI(u8, u8, 16);
MV(x2, x3);
SRLI(x3, x2, 8);
BEQZ(x3, 4+2*4);
BEQZ(x3, 4 + 2 * 4);
SUBI(u8, u8, 8);
MV(x2, x3);
SRLI(x3, x2, 4);
BEQZ(x3, 4+2*4);
BEQZ(x3, 4 + 2 * 4);
SUBI(u8, u8, 4);
MV(x2, x3);
ANDI(x2, x2, 0b1111);
@@ -449,9 +450,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
SUB(gd, u8, x2);
MARK2;
}
ANDI(xFlags, xFlags, ~((1<<F_ZF) | (1<<F_CF)));
BNE(gd, xZR, 4+4);
ORI(xFlags, xFlags, 1<<F_ZF);
ANDI(xFlags, xFlags, ~((1 << F_ZF) | (1 << F_CF)));
BNE(gd, xZR, 4 + 4);
ORI(xFlags, xFlags, 1 << F_ZF);
break;
case 0xC2:
@@ -460,9 +461,9 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGXSS(d0);
GETEXSS(d1, 1);
u8 = F8;
if ((u8&7) == 0) { // Equal
if ((u8 & 7) == 0) { // Equal
FEQS(x2, d0, d1);
} else if ((u8&7) == 4) { // Not Equal or unordered
} else if ((u8 & 7) == 4) { // Not Equal or unordered
FEQS(x2, d0, d1);
XORI(x2, x2, 1);
} else {
@@ -471,27 +472,33 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FEQS(x2, d1, d1);
AND(x2, x2, x3);
switch(u8&7) {
case 1: BEQ_MARK(x2, xZR); FLTS(x2, d0, d1); break; // Less than
case 2: BEQ_MARK(x2, xZR); FLES(x2, d0, d1); break; // Less or equal
case 3: XORI(x2, x2, 1); break; // NaN
case 5: { // Greater or equal or unordered
BEQ_MARK2(x2, xZR);
FLES(x2, d1, d0);
B_MARK_nocond;
break;
}
case 6: { // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
BEQ_MARK2(x2, xZR);
FLTS(x2, d1, d0);
B_MARK_nocond;
break;
}
case 7: break; // Not NaN
switch (u8 & 7) {
case 1:
BEQ_MARK(x2, xZR);
FLTS(x2, d0, d1);
break; // Less than
case 2:
BEQ_MARK(x2, xZR);
FLES(x2, d0, d1);
break; // Less or equal
case 3: XORI(x2, x2, 1); break; // NaN
case 5: { // Greater or equal or unordered
BEQ_MARK2(x2, xZR);
FLES(x2, d1, d0);
B_MARK_nocond;
break;
}
case 6: { // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
BEQ_MARK2(x2, xZR);
FLTS(x2, d1, d0);
B_MARK_nocond;
break;
}
case 7: break; // Not NaN
}
MARK2;
if ((u8&7) == 5 || (u8&7) == 6) {
if ((u8 & 7) == 5 || (u8 & 7) == 6) {
MOV32w(x2, 1);
}
MARK;
@@ -507,12 +514,12 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEX(x2, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
LW(x3, wback, fixedaddress+0);
LW(x4, wback, fixedaddress+4);
LW(x3, wback, fixedaddress + 0);
LW(x4, wback, fixedaddress + 4);
FCVTDW(q0, x3, RD_RTZ);
FCVTDW(q1, x4, RD_RTZ);
FSD(q0, gback, gdoffset+0);
FSD(q1, gback, gdoffset+8);
FSD(q0, gback, gdoffset + 0);
FSD(q1, gback, gdoffset + 8);
break;
default:
+3 -3
View File
@@ -58,7 +58,7 @@ void fpu_free_reg(dynarec_rv64_t* dyn, int reg)
int idx = EXTIDX(reg);
// TODO: check upper limit?
dyn->e.fpuused[idx] = 0;
if(dyn->e.extcache[reg].t!=EXT_CACHE_ST_F && dyn->e.extcache[reg].t!=EXT_CACHE_ST_D)
if(dyn->e.extcache[idx].t!=EXT_CACHE_ST_F && dyn->e.extcache[idx].t!=EXT_CACHE_ST_D)
dyn->e.extcache[idx].v = 0;
}
// Get an MMX double reg
@@ -494,7 +494,7 @@ const char* getCacheName(int t, int n)
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
{
static const char* fnames[] = {
"ft0"," ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
"ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
"fs0", "fs1",
"fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7",
"fs2", "fs3", "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11",
@@ -561,4 +561,4 @@ void print_newinst(dynarec_native_t* dyn, int ninst)
ninst, dyn->block, dyn->native_size,
(box64_dynarec_dump>1)?"\e[m":""
);
}
}
+14 -55
View File
@@ -56,16 +56,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if (sib_reg!=4) {
if(tmp && ((tmp<-2048) || (tmp>maxval) || !i12)) {
MOV64x(scratch, tmp);
if((sib>>6)) {
if(rv64_zba) {
SHxADD(ret, xRAX+sib_reg, sib>>6, scratch);
} else {
SLLI(ret, xRAX+sib_reg, (sib>>6));
ADD(ret, ret, scratch);
}
} else {
ADD(ret, xRAX+sib_reg, scratch);
}
ADDSL(ret, scratch, xRAX+sib_reg, sib>>6, ret);
} else {
if(sib>>6) {
SLLI(ret, xRAX+sib_reg, (sib>>6));
@@ -82,16 +73,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
} else {
if (sib_reg!=4) {
if(sib>>6) {
if(rv64_zba) {
SHxADD(ret, xRAX+sib_reg, sib>>6, xRAX+sib_reg2);
} else {
SLLI(scratch, xRAX+sib_reg, (sib>>6));
ADD(ret, xRAX+sib_reg2, scratch);
}
} else {
ADD(ret, xRAX+sib_reg2, xRAX+sib_reg);
}
ADDSL(ret, xRAX+sib_reg2, xRAX+sib_reg, sib>>6, scratch);
} else {
ret = xRAX+sib_reg2;
}
@@ -146,16 +128,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
*fixaddress = i64;
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sib>>6) {
if(rv64_zba) {
SHxADD(ret, xRAX+sib_reg, sib>>6, xRAX+sib_reg2);
} else {
SLLI(scratch, xRAX+sib_reg, (sib>>6));
ADD(ret, xRAX+sib_reg2, scratch);
}
} else {
ADD(ret, xRAX+sib_reg2, xRAX+sib_reg);
}
ADDSL(ret, xRAX+sib_reg2, xRAX+sib_reg, sib>>6, scratch);
} else {
ret = xRAX+sib_reg2;
}
@@ -165,16 +138,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if(i64>=-2048 && i64<=2047) {
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sib>>6) {
if(rv64_zba) {
SHxADD(scratch, xRAX+sib_reg, sib>>6, xRAX+sib_reg2);
} else {
SLLI(scratch, xRAX+sib_reg, (sib>>6));
ADD(scratch, xRAX+sib_reg2, scratch);
}
} else {
ADD(scratch, xRAX+sib_reg2, xRAX+sib_reg);
}
ADDSL(scratch, xRAX+sib_reg2, xRAX+sib_reg, sib>>6, scratch);
} else {
scratch = xRAX+sib_reg2;
}
@@ -186,16 +150,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if((nextop&7)==4) {
if (sib_reg!=4) {
ADD(scratch, scratch, xRAX+sib_reg2);
if(sib>>6) {
if(rv64_zba) {
SHxADD(ret, xRAX+sib_reg, sib>>6, scratch);
} else {
SLLI(ret, xRAX+sib_reg, (sib>>6));
ADD(ret, scratch, ret);
}
} else {
ADD(ret, scratch, xRAX+sib_reg);
}
ADDSL(ret, scratch, xRAX+sib_reg, sib>>6, ret);
} else {
PASS3(int tmp = xRAX+sib_reg2);
ADD(ret, tmp, scratch);
@@ -507,7 +462,9 @@ void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
SMEND();
BR(x2);
}
#ifdef JMPTABLE_SHIFT4
#error TODO!
#endif
void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst)
{
MAYUSE(dyn); MAYUSE(ninst);
@@ -1718,9 +1675,9 @@ static void swapCache(dynarec_rv64_t* dyn, int ninst, int i, int j, extcache_t *
// SWAP
ext_cache_t tmp;
MESSAGE(LOG_DUMP, "\t - Swapping %d <-> %d\n", i, j);
// There is no VSWP in Arm64 NEON to swap 2 register contents!
// There is no swap instruction in RV64 to swap 2 float registers!
// so use a scratch...
#define SCRATCH 0
#define SCRATCH 2
if(i_single)
FMVS(SCRATCH, reg_i);
else
@@ -1770,7 +1727,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int
break;
case EXT_CACHE_MM:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
FLD(reg, xEmu, offsetof(x64emu_t, mmx[i]));
FLD(reg, xEmu, offsetof(x64emu_t, mmx[n]));
break;
case EXT_CACHE_ST_D:
case EXT_CACHE_ST_F:
@@ -1926,7 +1883,9 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in
s3_top = 0;
stack_cnt = cache_i2.stack;
}
extcache_t cache = dyn->e;
// FIXME: why we can't just use dyn->e here? debug that!
extcache_t cache = dyn->insts[ninst].e;
int s1_val = 0;
int s2_val = 0;
// unload every uneeded cache
File diff suppressed because it is too large. Load diff
+3 -2
View File
@@ -16,9 +16,10 @@
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x64.barrier = A
#define BARRIER_NEXT(A) dyn->insts[ninst].x64.barrier_next = A
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
+10 -5
View File
@@ -79,8 +79,8 @@ typedef struct instruction_rv64_s {
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, markf2;
uintptr_t mark[3];
uintptr_t markf[2];
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
@@ -112,6 +112,9 @@ typedef struct dynarec_rv64_s {
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
int* jmps; // variable array of jump instructions
int jmp_sz;
int jmp_cap;
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
@@ -132,6 +135,8 @@ typedef struct dynarec_rv64_s {
void add_next(dynarec_rv64_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr);
void add_jump(dynarec_rv64_t *dyn, int ninst);
int get_first_jump(dynarec_rv64_t *dyn, int next);
int is_nops(dynarec_rv64_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_rv64_t *dyn, uintptr_t addr, int n);
@@ -139,12 +144,12 @@ int Table64(dynarec_rv64_t *dyn, uint64_t val, int pass); // add a value to tab
void CreateJmpNext(void* addr, void* next);
#define GO_TRACE(A, B) \
#define GO_TRACE(A, B, s0) \
GETIP(addr); \
MV(A1, xRIP); \
STORE_XEMU_CALL(); \
STORE_XEMU_CALL(s0); \
MOV64x(A2, B); \
CALL(A, -1); \
LOAD_XEMU_CALL()
#endif //__DYNAREC_RV64_PRIVATE_H_
#endif //__DYNAREC_RV64_PRIVATE_H_
File diff suppressed because it is too large. Load diff
+25 -1
View File
@@ -17,9 +17,13 @@
.global rv64_lock_incif0
.global rv64_lock_decifnot0
.global rv64_lock_store
.global rv64_lock_store_dd
.global rv64_lock_cas_d
.global rv64_lock_cas_dd
.global rv64_lock_cas_dq
.global rv64_lock_get_b
.global rv64_lock_get_d
.global rv64_lock_get_dd
rv64_lock_xchg_dd:
// address is a0, value is a1, return old value in a0
@@ -202,6 +206,11 @@ rv64_lock_store:
fence rw, rw
ret
rv64_lock_store_dd:
sd a1, 0(a0)
fence rw, rw
ret
rv64_lock_cas_d:
lr.w t0, (a0)
bne t0, a1, 1f
@@ -229,4 +238,19 @@ rv64_lock_cas_dq:
ret
1:
li a0, 1
ret
ret
rv64_lock_get_b:
fence rw, rw
lb a0, 0(a0)
ret
rv64_lock_get_d:
fence rw, rw
lw a0, 0(a0)
ret
rv64_lock_get_dd:
fence rw, rw
ld a0, 0(a0)
ret
+12
View File
@@ -44,9 +44,21 @@ extern int rv64_lock_decifnot0(void*p);
// atomic store (with memory barrier)
extern void rv64_lock_store(void*p, uint32_t v);
// atomic store (with memory barrier)
extern void rv64_lock_store_dd(void*p, uint64_t v);
// (mostly) Atomically store val1 and val2 at [p] if old [p] is ref. Return 0 if OK, 1 is not. p needs to be aligned
extern int rv64_lock_cas_dq(void* p, uint64_t ref, uint64_t val1, uint64_t val2);
// atomic get (with memory barrier)
extern uint32_t rv64_lock_get_b(void* p);
// atomic get (with memory barrier)
extern uint32_t rv64_lock_get_d(void* p);
// atomic get (with memory barrier)
extern void* rv64_lock_get_dd(void* p);
// Not defined in assembler but in dynarec_rv64_functions
uint8_t extract_byte(uint32_t val, void* address);
uint32_t insert_byte(uint32_t val, uint8_t b, void* address);
File diff suppressed because it is too large. Load diff
+3 -1
View File
@@ -45,7 +45,9 @@ const char* DumpSection(Elf64_Shdr *s, char* SST) {
GO(SHT_GNU_ATTRIBUTES);
GO(SHT_GNU_HASH);
GO(SHT_GNU_LIBLIST);
GO(SHT_CHECKSUM);
#ifndef TERMUX
GO(SHT_CHECKSUM);
#endif
GO(SHT_LOSUNW);
//GO(SHT_SUNW_move);
GO(SHT_SUNW_COMDAT);
+220 -232
View File
@@ -38,6 +38,7 @@
#endif
#include "../emu/x64emu_private.h"
#include "../emu/x64run_private.h"
#include "../tools/bridge_private.h"
#include "x64tls.h"
void* my__IO_2_1_stderr_ = NULL;
@@ -69,6 +70,9 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
h->globaldefver = NewDefaultVersion();
h->weakdefver = NewDefaultVersion();
h->refcnt = 1;
h->file = f;
h->fileno = fileno(f);
return h;
}
@@ -100,6 +104,8 @@ void FreeElfHeader(elfheader_t** head)
box_free(h->name);
box_free(h->path);
if(h->file)
fclose(h->file);
box_free(h);
*head = NULL;
@@ -169,201 +175,174 @@ const char* ElfPath(elfheader_t* head)
return NULL;
return head->path;
}
int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
#define ALIGN(p) (((p)+box64_pagesize-1)&~(box64_pagesize-1))
int AllocLoadElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
loadProtectionFromMap();
int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
head->multiblock_n = 0; // count PHEntrie with LOAD
uintptr_t max_align = (box64_pagesize-1);
for (size_t i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
if(max_align < head->PHEntries[i].p_align-1)
max_align = head->PHEntries[i].p_align-1;
++head->multiblock_n;
}
if(!head->vaddr && box64_load_addr) {
offs = (uintptr_t)find47bitBlockNearHint((void*)box64_load_addr, head->memsz);
box64_load_addr += head->memsz;
offs = (uintptr_t)find47bitBlockNearHint((void*)((box64_load_addr+max_align)&~max_align), head->memsz, max_align);
box64_load_addr = offs + head->memsz;
box64_load_addr = (box64_load_addr+0x10ffffffLL)&~0xffffffLL;
}
int log_level = box64_load_addr?LOG_INFO:LOG_DEBUG;
if(!offs)
offs = head->vaddr;
if(head->vaddr) {
head->multiblock_n = 0; // count PHEntrie with LOAD
for (size_t i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
++head->multiblock_n;
head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
// and now, create all individual blocks
head->memory = (char*)0xffffffffffffffff;
int n = 0;
for (size_t i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
Elf64_Phdr * e = &head->PHEntries[i];
uintptr_t bstart = e->p_vaddr;
uint64_t bsize = e->p_memsz;
uintptr_t balign = e->p_align;
if (balign) balign = balign-1; else balign = 1;
if(balign<4095) balign = 4095;
uintptr_t bend = (bstart + bsize + balign)&(~balign);
bstart &= ~balign;
int ok = 0;
for (int j=0; !ok && j<n; ++j) {
uintptr_t start = head->multiblock_offs[j];
uintptr_t end = head->multiblock_offs[j] + head->multiblock_size[j];
start &= ~balign;
if( (head->e_type == ET_DYN) ||
(((bstart>=start) && (bstart<=end+0x1000)) || ((bend>=start) && (bend<=end)) || ((bstart<start) && (bend>end))))
{
// merge
ok = 1;
if(bstart<start)
head->multiblock_offs[j] = bstart;
head->multiblock_size[j] = ((bend>end)?bend:end) - head->multiblock_offs[j];
--head->multiblock_n;
}
}
if(!ok) {
head->multiblock_offs[n] = bstart;
head->multiblock_size[n] = bend - head->multiblock_offs[n];
++n;
}
}
head->multiblock_n = n; // might be less in fact
for (int i=0; i<head->multiblock_n; ++i) {
printf_log(log_level, "Allocating 0x%lx memory @%p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i]
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
, -1, 0);
if(p==MAP_FAILED) {
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
return 1;
}
if(head->multiblock_offs[i] &&( p!=(void*)head->multiblock_offs[i])) {
if((head->e_type!=ET_DYN)) {
printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name, p);
return 1;
} else {
printf_log(LOG_INFO, "Allocated memory is not at hinted %p but %p (size %lx) \"%s\"\n", (void*)head->multiblock_offs[i], p, head->multiblock_size[i], head->name);
// need to adjust vaddr!
for (size_t j=0; j<head->numPHEntries; ++j)
if(head->PHEntries[j].p_type == PT_LOAD) {
Elf64_Phdr * e = &head->PHEntries[j];
if(e->p_vaddr>=head->multiblock_offs[j] && e->p_vaddr<(head->multiblock_offs[j]+head->multiblock_size[j])) {
e->p_vaddr = e->p_vaddr - head->multiblock_offs[j] + (uintptr_t)p;
if(!head->delta) head->delta = (intptr_t)p - (intptr_t)head->multiblock_offs[j];
}
}
}
}
setProtection((uintptr_t)p, head->multiblock_size[i], PROT_READ | PROT_WRITE | PROT_EXEC);
head->multiblock[i] = p;
if(p<(void*)head->memory)
head->memory = (char*)p;
}
} else {
// vaddr is 0, load everything has a One block
uintptr_t old_offs = offs;
if(!offs /*&& box64_wine*/)
offs = (uintptr_t)find47bitBlock(head->memsz); // limit to 47bits...
printf_log(log_level, "Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
void* p = mmap((void*)offs, head->memsz
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
, -1, 0);
if(offs &&!old_offs && p!=MAP_FAILED && offs!=(uintptr_t)p) {
// try again
munmap(p, head->memsz);
loadProtectionFromMap();
offs = (uintptr_t)find47bitBlock(head->memsz);
printf_log(log_level, "New, try. Allocating 0x%zx memory @%p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
p = mmap((void*)offs, head->memsz
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
, -1, 0);
}
if(p==MAP_FAILED) {
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
return 1;
}
if(offs && (p!=(void*)offs) && (head->e_type!=ET_DYN)) {
printf_log(LOG_NONE, "Error, memory map (@%p 0x%zx/0x%zx) for elf \"%s\" allocated @%p\n", (void*)offs, head->memsz, head->align, head->name, p);
return 1;
}
setProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
head->memory = p;
memset(p, 0, head->memsz);
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
printf_log(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta);
head->multiblock_n = 1;
head->multiblock_size = (uint64_t*)box_calloc(head->multiblock_n, sizeof(uint64_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size[0] = head->memsz;
head->multiblock_offs[0] = (uintptr_t)p;
head->multiblock[0] = p;
if(!offs && !head->vaddr)
offs = (uintptr_t)find47bitBlockElf(head->memsz, mainbin, max_align); // limit to 47bits...
#if defined(PAGE8K) || defined(PAGE16K) || defined(PAGE64K)
// Will not try anything smart on pagesize != 4k....
void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
#else // PAGE4K
// prereserve the whole elf image, without populating
void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
if(image!=MAP_FAILED && head->vaddr && image!=(void*)offs && (((uintptr_t)image)&max_align)) {
munmap(image, head->memsz);
image = mmap64(find47bitBlockElf(head->memsz, mainbin, max_align), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
}
#endif
if(image!=MAP_FAILED && !head->vaddr && image!=(void*)offs) {
printf_log(LOG_INFO, "Mmap64 for (@%p 0x%zx) for elf \"%s\" returned %p instead\n", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image);
offs = (uintptr_t)image;
}
if(image==MAP_FAILED || image!=(void*)(head->vaddr?head->vaddr:offs)) {
printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name);
if(image==MAP_FAILED) {
printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
} else {
printf_log(LOG_NONE, " got %p\n", image);
}
if(image==MAP_FAILED)
return 1;
offs = (uintptr_t)image-head->vaddr;
}
printf_log(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
head->delta = offs;
printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
head->image = image;
#if defined(PAGE8K) || defined(PAGE16K) || defined(PAGE64K)
setProtection_elf((uintptr_t)image, head->memsz, PROT_READ|PROT_WRITE|PROT_EXEC);
#else
setProtection_elf((uintptr_t)image, head->memsz, 0);
#endif
head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
head->tlsbase = AddTLSPartition(context, head->tlssize);
return 0;
}
void FreeElfMemory(elfheader_t* head)
{
if(head->multiblock_n) {
for(int i=0; i<head->multiblock_n; ++i) {
#ifdef DYNAREC
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
if(box64_dynarec) {
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
}
#endif
munmap(head->multiblock[i], head->multiblock_size[i]);
}
box_free(head->multiblock);
box_free(head->multiblock_size);
box_free(head->multiblock_offs);
}
}
int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
{
// and now, create all individual blocks
head->memory = (char*)0xffffffffffffffff;
int n = 0;
for (size_t i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
Elf64_Phdr * e = &head->PHEntries[i];
char* dest = (char*)e->p_paddr + head->delta;
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz);
void* p = (void*)-1;
if(e->p_memsz==e->p_filesz && !(e->p_align&(box64_pagesize-1))) {
printf_log(LOG_DEBUG, "MMap block #%zu @%p offset=%p (0x%zx/0x%zx, flags:0x%x)\n", i, dest, (void*)e->p_offset, e->p_filesz, e->p_memsz, e->p_flags);
p = mmap(dest, e->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fileno(f), e->p_offset);
}
if(p!=dest) {
printf_log(LOG_DEBUG, "Loading block #%zu %p (0x%zx/0x%zx)\n",i, dest, e->p_filesz, e->p_memsz);
fseeko64(f, e->p_offset, SEEK_SET);
head->multiblocks[n].flags = e->p_flags;
head->multiblocks[n].offs = e->p_offset;
head->multiblocks[n].paddr = e->p_paddr + offs;
head->multiblocks[n].size = e->p_filesz;
head->multiblocks[n].align = e->p_align;
uint8_t prot = ((e->p_flags & PF_R)?PROT_READ:0)|((e->p_flags & PF_W)?PROT_WRITE:0)|((e->p_flags & PF_X)?PROT_EXEC:0);
#if defined(PAGE8K) || defined(PAGE16K) || defined(PAGE64K)
head->multiblocks[n].p = NULL;
if(e->p_filesz) {
if(fread(dest, e->p_filesz, 1, f)!=1) {
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%zu (size=%zd)\n", i, e->p_filesz);
fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET);
if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) {
printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, head->name);
return 1;
}
}
#else //PAGE4K
// check if alignment is correct
uintptr_t balign = head->multiblocks[n].align-1;
if(balign<(box64_pagesize-1)) balign = (box64_pagesize-1);
head->multiblocks[n].asize = ALIGN(e->p_memsz+(e->p_paddr&balign));
int try_mmap = 1;
if(e->p_paddr&balign)
try_mmap = 0;
if(e->p_offset&(box64_pagesize-1))
try_mmap = 0;
if(e->p_memsz-e->p_filesz>(box64_pagesize-1))
try_mmap = 0;
if(!e->p_filesz)
try_mmap = 0;
if(try_mmap) {
printf_log(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name);
void* p = mmap64(
(void*)head->multiblocks[n].paddr,
head->multiblocks[n].size,
prot,
MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED,
head->fileno,
e->p_offset
);
if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) {
try_mmap = 0;
printf_log(log_level, "Mapping failed, using regular mmap+read");
} else {
setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot);
head->multiblocks[n].p = p;
}
}
if(!try_mmap) {
uintptr_t paddr = head->multiblocks[n].paddr&~balign;
size_t asize = head->multiblocks[n].asize;
printf_log(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
void* p = mmap64(
(void*)paddr,
asize,
prot|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
-1,
0
);
if(p==MAP_FAILED || p!=(void*)paddr) {
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name);
if(p==MAP_FAILED) {
printf_log(LOG_NONE, " error=%d/%s\n", errno, strerror(errno));
} else {
printf_log(LOG_NONE, " got %p\n", p);
}
return 1;
}
setProtection_elf((uintptr_t)p, asize, prot);
head->multiblocks[n].p = p;
if(e->p_filesz) {
fseeko64(head->file, head->multiblocks[n].offs, SEEK_SET);
if(fread((void*)head->multiblocks[n].paddr, head->multiblocks[n].size, 1, head->file)!=1) {
printf_log(LOG_NONE, "Cannot read elf block (@%p 0x%zx/0x%zx) for elf \"%s\"\n", (void*)head->multiblocks[n].offs, head->multiblocks[n].asize, balign, head->name);
return 1;
}
}
if(!(prot&PROT_WRITE))
mprotect((void*)paddr, asize, prot);
}
#endif //PAGE4K
#ifdef DYNAREC
if(box64_dynarec && (e->p_flags & PF_X)) {
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
addDBFromAddressRange((uintptr_t)dest, e->p_memsz);
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", head->multiblocks[n].p, (void*)head->multiblocks[n].asize);
addDBFromAddressRange((uintptr_t)head->multiblocks[n].p, head->multiblocks[n].asize);
}
#endif
// zero'd difference between filesz and memsz
/*if(e->p_filesz != e->p_memsz)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation
if((uintptr_t)head->memory>(uintptr_t)head->multiblocks[n].p)
head->memory = (char*)head->multiblocks[n].p;
++n;
}
if(head->PHEntries[i].p_type == PT_TLS) {
Elf64_Phdr * e = &head->PHEntries[i];
char* dest = (char*)(context->tlsdata+context->tlssize+head->tlsbase);
printf_log(LOG_DEBUG, "Loading TLS block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
if(e->p_filesz) {
fseeko64(f, e->p_offset, SEEK_SET);
if(fread(dest, e->p_filesz, 1, f)!=1) {
fseeko64(head->file, e->p_offset, SEEK_SET);
if(fread(dest, e->p_filesz, 1, head->file)!=1) {
printf_log(LOG_NONE, "Fail to read PT_TLS part #%zu (size=%zd)\n", i, e->p_filesz);
return 1;
}
@@ -373,9 +352,34 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
}
}
// can close the elf file now!
fclose(head->file);
head->file = NULL;
head->fileno = -1;
return 0;
}
void FreeElfMemory(elfheader_t* head)
{
if(head->multiblock_n) {
#ifdef DYNAREC
for(int i=0; i<head->multiblock_n; ++i) {
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
if(box64_dynarec)
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1);
freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize);
}
#endif
box_free(head->multiblocks);
}
// we only need to free the overall mmap, no need to free individual part as they are inside the big one
if(head->image && head->memsz)
munmap(head->image, head->memsz);
freeProtection((uintptr_t)head->image, head->memsz);
}
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
{
if(!verneeded || !head)
@@ -393,39 +397,6 @@ int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verne
return 1;
}
int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head)
{
(void)context;
for (size_t i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf64_Phdr * e = &head->PHEntries[i];
char* dest = (char*)e->p_paddr + head->delta;
printf_log(LOG_DEBUG, "Re-loading block #%zu @%p (0x%zx/0x%zx)\n", i, dest, e->p_filesz, e->p_memsz);
int ret = fseeko64(f, e->p_offset, SEEK_SET);
if(ret==-1) {printf_log(LOG_NONE, "Fail to (re)seek PT_LOAD part #%zu (offset=%ld, errno=%d/%s)\n", i, e->p_offset, errno, strerror(errno)); return 1;}
#ifdef DYNAREC
cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
#endif
uint32_t page_offset = (uintptr_t)dest & (box64_pagesize - 1);
mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
if(e->p_filesz) {
ssize_t r = -1;
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
printf_log(LOG_NONE, "Fail to (re)read PT_LOAD part #%zu (dest=%p, size=%zd, return=%zd, feof=%d/ferror=%d/%s)\n", i, dest, e->p_filesz, r, feof(f), ferror(f), strerror(ferror(f)));
return 1;
}
}
// zero'd difference between filesz and memsz
if(e->p_filesz != e->p_memsz)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);
}
}
// TLS data are just a copy, no need to re-load it
return 0;
}
int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t** p, size_t size, int version, const char* vername)
{
if(!h)
@@ -471,7 +442,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
const char* weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
if(bind==STB_LOCAL) {
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
@@ -494,14 +465,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
if(!offs && !end) {
if(!offs && !end && local_maplib)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
if(!offs && !end)
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
if(!offs && !end) {
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
@@ -539,10 +510,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
offs = globoffs;
end = globend;
}
}*/
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
printf_log(LOG_NONE, "%s: Global Symbol %s (ver=%d/%s) not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, version, vername?vername:"(none)", p, *(void**)p, head->name);
@@ -676,7 +647,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
weakdefver = old_weakdefver;
} else {
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
old_weakdefver = weakdefver = (bind==STB_WEAK || !globdefver)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
}
if(bind==STB_LOCAL) {
if(!symname || !symname[0]) {
@@ -715,9 +686,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
offs = old_offs;
end = old_end;
} else {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
}
@@ -787,10 +759,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
offs = globoffs;
end = globend;
}
}*/
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start") && strcmp(symname, "collector_func_load"))
printf_log((bind==STB_WEAK)?LOG_INFO:LOG_NONE, "%s: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", (bind==STB_WEAK)?"Warning":"Error", symname, p, *(void**)p, head->name);
@@ -1060,6 +1032,10 @@ uintptr_t GetLastByte(elfheader_t* h)
return (uintptr_t)h->memory/* + h->delta*/ + h->memsz;
}
#ifndef STB_GNU_UNIQUE
#define STB_GNU_UNIQUE 10
#endif
void checkHookedSymbols(elfheader_t* h); // in mallochook.c
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
{
@@ -1273,8 +1249,8 @@ void RefreshElfTLS(elfheader_t* h)
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
tlsdatasize_t* ptr;
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL) {
if (pthread_getspecific(my_context->tlskey)) {
tlsdatasize_t* ptr = getTLSData(my_context);
// refresh in tlsdata too
dest = (char*)(ptr->data+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%lx\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
@@ -1328,16 +1304,15 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
// reset Segs Cache
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
uintptr_t p = h->initentry + h->delta;
box64context_t* context = GetEmuContext(emu);
// Refresh no-file part of TLS in case default value changed
RefreshElfTLS(h);
// check if in deferredInit
if(context->deferredInit) {
if(context->deferredInitSz==context->deferredInitCap) {
context->deferredInitCap += 4;
context->deferredInitList = (elfheader_t**)box_realloc(context->deferredInitList, context->deferredInitCap*sizeof(elfheader_t*));
if(my_context->deferredInit) {
if(my_context->deferredInitSz==my_context->deferredInitCap) {
my_context->deferredInitCap += 4;
my_context->deferredInitList = (elfheader_t**)box_realloc(my_context->deferredInitList, my_context->deferredInitCap*sizeof(elfheader_t*));
}
context->deferredInitList[context->deferredInitSz++] = h;
my_context->deferredInitList[my_context->deferredInitSz++] = h;
return;
}
h->init_done = 1;
@@ -1349,14 +1324,14 @@ void RunElfInit(elfheader_t* h, x64emu_t *emu)
}
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
if(h->initentry)
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
RunFunctionWithEmu(emu, 0, p, 3, my_context->argc, my_context->argv, my_context->envv);
printf_dump(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
// and check init array now
Elf64_Addr *addr = (Elf64_Addr*)(h->initarray + h->delta);
for (size_t i=0; i<h->initarray_sz; ++i) {
if(addr[i]) {
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
}
}
@@ -1391,6 +1366,10 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
if(!h || h->fini_done || !h->init_done)
return;
h->fini_done = 1;
#ifdef ANDROID
// TODO: Fix .fini_array on Android
printf_log(LOG_DEBUG, "Android does not support Fini for %s\n", ElfName(h));
#else
// first check fini array
Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
for (int i=h->finiarray_sz-1; i>=0; --i) {
@@ -1405,6 +1384,7 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
}
h->init_done = 0; // can be re-inited again...
return;
#endif
}
uintptr_t GetElfInit(elfheader_t* h)
@@ -1418,7 +1398,7 @@ uintptr_t GetElfFini(elfheader_t* h)
void* GetBaseAddress(elfheader_t* h)
{
return h->memory;
return h->image;
}
void* GetElfDelta(elfheader_t* h)
@@ -1435,13 +1415,20 @@ int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
{
if(!h)
return 0;
#if defined(PAGE8K) || defined(PAGE16K) || defined(PAGE64K)
uintptr_t base = (uintptr_t)h->image;
uintptr_t end = base+h->memsz;
if(base && addr>=base && addr<=end)
return 1;
#else //PAGE4K
for(int i=0; i<h->multiblock_n; ++i) {
uintptr_t base = h->multiblock_offs[i];
uintptr_t end = h->multiblock_offs[i] + h->multiblock_size[i] - 1;
if(addr>=base && addr<=end)
uintptr_t base = (uintptr_t)h->multiblocks[i].p;
uintptr_t end = (uintptr_t)h->multiblocks[i].p + h->multiblocks[i].asize - 1;
if(base && addr>=base && addr<=end)
return 1;
}
#endif //PAGE4K
return 0;
}
elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr)
@@ -1461,22 +1448,23 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
const char* ret = NULL;
uintptr_t s = 0;
uint64_t size = 0;
#ifdef HAVE_TRACE
if((uintptr_t)p<0x10000)
return ret;
if(!h) {
if(getProtection((uintptr_t)p)&(PROT_READ)) {
if(*(uint8_t*)(p)==0xCC && *(uint8_t*)(p+1)=='S' && *(uint8_t*)(p+2)=='C') {
ret = getBridgeName(*(void**)(p+3+8));
uintptr_t adj_p = ((uintptr_t)p)&~(sizeof(onebridge_t));
if(*(uint8_t*)(adj_p)==0xCC && *(uint8_t*)(adj_p+1)=='S' && *(uint8_t*)(adj_p+2)=='C') {
ret = getBridgeName((void*)adj_p);
if(ret) {
if(start)
*start = (uintptr_t)p;
*start = (uintptr_t)adj_p;
if(sz)
*sz = 32;
*sz = sizeof(onebridge_t);
}
}
}
return ret;
}
#endif
if(!h || h->fini_done)
return ret;
+17 -5
View File
@@ -9,7 +9,17 @@ typedef struct kh_defaultversion_s kh_defaultversion_t;
#include <elf.h>
#include "elfloader.h"
struct elfheader_s {
typedef struct multiblock_s {
void* p;
uintptr_t offs;
uintptr_t paddr;
uintptr_t align;
uint64_t size;
uint64_t asize;
uint8_t flags;
} multiblock_t;
typedef struct elfheader_s {
char* name;
char* path; // Resolved path to file
char* soname; // soname of the elf
@@ -39,6 +49,7 @@ struct elfheader_s {
uint32_t flags;
intptr_t delta; // should be 0
void* image;
uintptr_t entrypoint;
uintptr_t initentry;
@@ -90,20 +101,21 @@ struct elfheader_s {
int malloc_hook_2; // this elf hook malloc, hacking it
char* memory; // char* and not void* to allow math on memory pointer
void** multiblock;
uintptr_t* multiblock_offs;
uint64_t* multiblock_size;
multiblock_t* multiblocks;
int multiblock_n;
library_t *lib; // attached lib (exept on main elf)
needed_libs_t* needed;
FILE* file;
int fileno;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
};
} elfheader_t;
#define R_X86_64_NONE 0 /* No reloc */
#define R_X86_64_64 1 /* Direct 64 bit */
+20 -3
View File
@@ -247,8 +247,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#ifndef ANDROID
if(val)
printf_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#endif
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
@@ -466,4 +468,19 @@ const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
}
}
return NULL;
}
}
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
{
if(!libname || !ver)
return 0;
int n = GetNeededVersionCnt(h, libname);
if(!n)
return 0;
for(int i=0; i<n; ++i) {
const char* vername = GetNeededVersionString(h, libname, i);
if(vername && !strcmp(ver, vername))
return 1;
}
return 0;
}
+120
View File
@@ -0,0 +1,120 @@
#include <stdint.h>
#include "box64stack.h"
#include "x64emu.h"
#include "x64run_private.h"
#include "x64emu_private.h"
#include "x64compstrings.h"
static int overrideIfDataInvalid(sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, int j, int i, int imm8)
{
int valid1 = (i<lreg);
int valid2 = (j<lmem);
if(!valid1 && !valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01: return 0;
case 0b10:
case 0b11: return 1;
}
if(!valid1 && valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01:
case 0b10: return 0;
case 0b11: return 1;
}
if(valid1 && !valid2)
return 0;
switch((imm8>>2)&3) {
case 0b01: // range
switch (imm8&3) {
case 0b00: // ub
return (i&1)?((reg->ub[i]>=mem->ub[j])):((reg->ub[i]<=mem->ub[j]));
case 0b01: // uw
return (i&1)?((reg->uw[i]>=mem->uw[j])):((reg->uw[i]<=mem->uw[j]));
case 0b10: // sb
return (i&1)?((reg->sb[i]>=mem->sb[j])):((reg->sb[i]<=mem->sb[j]));
case 0b11: // sw
return (i&1)?((reg->sw[i]>=mem->sw[j])):((reg->sw[i]<=mem->sw[j]));
}
break;
default: // the others
switch (imm8&1) {
case 0: // byte
return (reg->ub[i] == mem->ub[j]);
case 1: // word
return (reg->uw[i] == mem->uw[j]);
}
}
}
uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, uint8_t imm8)
{
// get number of packed byte/word
int n_packed = (imm8&1)?8:16;
if(lreg<0) lreg = -lreg;
if(lmem<0) lmem = -lmem;
if(lreg>n_packed) lreg = n_packed;
if(lmem>n_packed) lmem = n_packed;
// aggregate to intres1
uint32_t intres1 = 0;
switch((imm8>>2)&3) {
case 0b00: //Equal any
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8)<<j;
}
break;
case 0b01: // Range
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; i+=2) {
intres1 |= (overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8) & overrideIfDataInvalid(mem, lmem, reg, lreg, j, i+1, imm8))<<j;
}
break;
case 0b10: // Equal each
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, i, i, imm8)<<i;
}
break;
case 0b11: // Equal ordered
intres1 = (1<<n_packed)-1;
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed-j; ++i) {
int k = i+j;
intres1 &= (((1<<n_packed)-1)^(1<<j)) | overrideIfDataInvalid(mem, lmem, reg, lreg, k, i, imm8)<<j;
}
break;
}
// build intres2
uint32_t intres2 = intres1;
switch((imm8>>4)&3) {
case 0b01: intres2 ^= ((1<<n_packed)-1); break;
case 0b11: intres2 ^= ((1<<lmem)-1); break;
}
// and now set the flags
RESET_FLAGS(emu);
CONDITIONAL_SET_FLAG(intres2, F_CF);
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_PF);
return intres2;
}
uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* mem, sse_regs_t* reg, uint8_t imm8)
{
int lmem = 0;
int lreg = 0;
// get lmem and lreg
if(imm8&1) {
while(lmem<8 && mem->uw[lmem]) ++lmem;
while(lreg<8 && reg->uw[lreg]) ++lreg;
} else {
while(lmem<16 && mem->ub[lmem]) ++lmem;
while(lreg<16 && reg->ub[lreg]) ++lreg;
}
return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8);
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef __X64_CMPSTRINGS_H__
#define __X64_CMPSTRINGS_H__
#include <stdint.h>
#include "regs.h"
typedef struct x64emu_s x64emu_t;
uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* a, int la, sse_regs_t* b, int lb, uint8_t imm8);
uint32_t sse42_compare_string_implicit_len(x64emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8);
#endif //__X64_CMPSTRINGS_H__
Loaded 100 of 447 files, more files were not shown because too many files have changed in this diff. Show more