Compare commits

...
510 Commits
Author SHA1 Message Date
ptitSeb 2b300bd199 Bumped version to v0.3.4 2025-03-10 17:01:37 +01:00
ptitSeb 9c69ebd717 [RV64_DYNAREC] Added 66 F0 81/83 /4 opcode 2025-03-10 14:55:23 +01:00
ptitSeb ea01b56422 [RV64_DYNAREC] Reduce the number of false-positive for dynarec missing opcode 2025-03-10 14:41:40 +01:00
ptitSeb 216cf51d4a [RV64_DYNAREC] Added 66 F0 81/83 /1 opcode 2025-03-10 14:33:40 +01:00
ptitSeb 1476b502a2 [RV64_DYNAREC] Small change in F0 0F C7 opcode 2025-03-10 14:21:18 +01:00
ptitSeb bc53ae8925 [RCFIEL] Add/Adjust more game profiles 2025-03-10 12:18:24 +01:00
ptitSeb 9cef52a1fc [DYNAREC] Reduced lifetime of hotpage when using DIRTY=1 2025-03-10 12:16:05 +01:00
ptitSeb 5ed60d99a8 [DYNAREC] Don't continue a dynablock if entering an hotpage 2025-03-10 12:15:30 +01:00
Yang Liu d7c7a716fe [RV64_DYNAREC] Optimized PMOVZX and PMOVSX opcodes for vector 1.0 (#2430) 2025-03-10 09:54:20 +01:00
ptitSeb 41bee35634 [DYNAREC] Fixed some potential issue with NEVERCLEAN on memory mapping tracking 2025-03-09 11:19:52 +01:00
ptitSeb e764029cae [LA64_DYNAREC] This should fix the build 2025-03-09 07:58:50 +01:00
ptitSeb b110623103 [ARM64_DYNAREC] Improced arch_build helpers function to only compute build steps 1 time per dynablock 2025-03-08 22:38:22 +01:00
ptitSeb 35c1f97115 [ARM64_DYNAREC] Removed obsolete comment 2025-03-08 20:59:08 +01:00
ptitSeb e8a7bef5a0 [ARM64_DYNAREC] Fixed a potential issue with AVX.0F 50 opcode 2025-03-08 20:58:04 +01:00
ptitSeb c2f73e6de0 [ARM64_DYNAREC] Fixed a few potential issue with some AVX opcodes 2025-03-08 20:57:21 +01:00
ptitSeb 0724f52d5f [ARM64_DYNAREC] Fixed inlined ClearCache, re-enabling it 2025-03-08 20:33:32 +01:00
ptitSeb 61a605a2dc [ARM64_DYNAREC] Disabled inlined ClearCache as it seems not 100% efficient 2025-03-08 20:30:52 +01:00
ptitSeb 7a058c9194 [RCFILE] More game profile plus adjustment to existing ones 2025-03-08 16:03:13 +01:00
ptitSeb 99971e94c0 [TRACE] Improved a bit a few traces 2025-03-08 13:46:28 +01:00
ptitSeb 445d885090 [RCFILE] Added a game profile 2025-03-08 10:43:29 +01:00
ptitSeb fc02f0d140 [BOX32][WRAPPER] Fixed some gnutls wrapped functions (help NFS Payback from Steam) 2025-03-08 10:43:12 +01:00
ptitSeb c2d02977f8 Added F0 F7 /2 opcode ([ARM64_DYNAREC] too) 2025-03-07 20:13:41 +01:00
Yang Liu 946c999e25 [RV64_DYNAREC] Rollback some falsy optimization in the xtheadvector path (#2426) 2025-03-07 16:36:53 +01:00
ptitSeb c8b6f80f99 Removed isDBFromAddressRange and added that function to cleanDBFromAddressRange as it was used only 1 time and followed by that function anyway 2025-03-07 13:45:41 +01:00
ptitSeb 9444ce0b89 Use getProtection_fast for check_exec test, as it can be used a lot on interpreter mode 2025-03-07 11:24:27 +01:00
ptitSeb 401d2ae0b9 [WRAPPER] Do not reference epoll_pwait2 directly, to fix issues with Android and old glibc based system (also for #2425) 2025-03-07 10:59:44 +01:00
ptitSeb 8dde796103 [ARM64_DYNAREC] Small change to AVX.66.0F 7F opcode 2025-03-06 20:04:22 +01:00
ptitSeb 7ba0e7a055 [DOC] Fixed default for strongmem in docs 2025-03-06 20:03:08 +01:00
Leslie Zhai eb039c0449 Fix undefined reference to `epoll_pwait2' for LA64 ABI 1.0 (#2422) 2025-03-06 08:08:09 +01:00
ptitSeb 0c0f5263e1 [ARM64_DYNAREC] Added unaligned path for AVX.F3.0F 7F opcode 2025-03-05 11:50:35 +01:00
ptitSeb ad70febaac [ANDROID] Fixed wrapping of epoll_pwait2 to epoll_pwait timeout parameter 2025-03-04 22:44:18 +01:00
ptitSeb 39583c6da4 [ANDROID] Fix build, as epoll_pwait2 doesn't seems to exist 2025-03-04 14:36:25 +01:00
ptitSeb 1bf4851cf6 [WRAPPER] Added epoll_pwait2 wrapped function 2025-03-04 14:11:42 +01:00
liuli 2129e98b0e [WRAPPER] add gnutls_fips140_set_mode (#2417)
Change-Id: I8e9db9b5bbc16459154f30c4c29a4b1ec77c416a
2025-03-04 10:41:22 +01:00
Yang Liu b015f33376 [RV64_DYNAREC] Minor optimizations to sign mask extraction instructions for vector (#2416) 2025-03-04 08:07:45 +01:00
Yang Liu 2636e7e8b5 [RCFILE] Added range gdbjit support (#2414) 2025-03-03 10:08:50 +01:00
Yang Liu b0e726d953 [RCFILE] Fixed load addr parse issue (#2413) 2025-03-03 10:07:00 +01:00
Yang Liu eb40c49132 [CORE] Limited some syscalls for Android build (#2412) 2025-03-03 10:05:58 +01:00
ptitSeb 5dadc513db [WRAPPER] Updated auto-generated files 2025-02-26 17:56:29 +01:00
alexvorxx 4120dc10bd Fixed Box32 for Winlator Glibc (#2404)
* 1

* 2

* 3

* 4

* Fix

* 5

* 6

* 7

* 8

* revert 8

* 9
2025-02-26 17:47:42 +01:00
ptitSeb 48f51bd5fe [BOX32][WRAPPER] Use a temp xcb when converting an unknown xcb_connection instead of adding it 2025-02-25 11:46:37 +01:00
Yang Liu 940317949a [RV64_DYNAREC] Fixed some minor typos (#2406) 2025-02-23 20:29:49 +01:00
Yang Liu f9b6ea48e9 [RV64_DYNAREC] Fixed swapCache scratch register usage (#2405) 2025-02-23 19:29:59 +01:00
Hugh Cole-Baker 3567c6da2b [DEBIAN] fix typo and add box64-bash in shlibdeps excludes (#2403) 2025-02-22 22:23:51 +01:00
ptitSeb f3fe72b541 [RCFILE] Added 1 more game profile 2025-02-21 20:47:00 +01:00
ptitSeb 14966e48a6 [ARM64_DYNAREC] Fixed potential issue with SUBSET with a DF still present 2025-02-21 20:43:48 +01:00
ptitSeb 91b282235b [BOX32][ANDROID][TERMUX] revert previous commit and added a new test for shmat wrapped function (still for #2227) 2025-02-21 15:42:21 +01:00
ptitSeb 63c3e4fcf5 [INTERP] Fixed ror/rol flags on cputype=0 2025-02-21 15:28:31 +01:00
ptitSeb c740590bcd [BOX32][ANDROID][TERMUX] Use simple wrapper for shmat function on Android/Termux (for #2227) 2025-02-21 12:13:43 +01:00
ptitSeb e868c89233 [INTERP] Work on UD flags 2025-02-21 11:40:15 +01:00
Yang Liu c517d7196d [RV64_DYNAREC] Added more opcodes (#2400)
* [RV64_DYNAREC] Added more 66 0F 38 opcodes for vector

* [RV64_DYNAREC] Added more opcodes
2025-02-21 10:50:08 +01:00
Yang Liu cb42b3b00f [RV64_DYNAREC] Added more MMX opcodes for vector and fixes too (#2399)
* [RV64_DYNAREC] Fixed fallback to scalar messge

* [RV64_DYNAREC] Added more MMX opcodes for vector and fixes too
2025-02-21 09:03:19 +01:00
Yang Liu 61362b06ec Made some tweaks to banner and help message (#2397)
* Made some tweaks to banner and help message

* more tweaks

* fix nobanner
2025-02-20 18:55:37 +01:00
Yang Liu bb8559933f Made error logs prefix has red color (#2396) 2025-02-20 15:25:14 +01:00
ptitSeb c2cb333261 [ARM64_DYNAREC] More work on UD flags 2025-02-20 13:47:04 +01:00
ptitSeb b7e4cc4f50 [ARM64_DYNAREC] Fixed a typo in flag computation for PCMPESTRI and BZHI opcodes 2025-02-20 13:29:50 +01:00
Yang Liu a4908f1407 [ARM64_DYNAREC] Fixed a regression in LOCK XADD opcode (#2394) 2025-02-20 12:24:34 +01:00
ptitSeb a252e87fa9 [BOX32][INTERP] Added some support for BOUND opcode ([ARM64_DYNAREC] too) 2025-02-20 10:45:11 +01:00
ptitSeb ee3ee539e0 [BOX32][WRAPPING] Do not convert stream private field of FT_FaceRec structure 2025-02-19 20:31:28 +01:00
Yang Liu c4b79374fe [RCFILE] Added support for perfile dynarec dump (#2393) 2025-02-19 15:54:40 +01:00
Yang Liu 5dfa27ea58 [DYNAREC] Minor optimizations to SHL/SHR Ed, CL fastpath (#2392)
* [DYNAREC] Minor optimizations to SHL/SHR Ed, CL fastpath

* Fixed build

* Partially revert some fake optimizations
2025-02-19 15:04:20 +01:00
Yang Liu 49cba432c2 [CORE] Rework on function hookMangoHud (#2387) 2025-02-18 20:59:02 +01:00
Yang Liu 39a9cf903f [CORE] Display Box64 version info in mangohud (#2386)
* [CORE] Display Box64 version info in mangohud

* check for config files
2025-02-18 20:00:31 +01:00
ptitSeb 611ac3933c [LA64][WRAPPING][BOX32] Added alt name for libnsl 2025-02-18 18:12:38 +01:00
xctan fdd1509ee5 [WRAPPER] Display Box64 version in Vulkan driver info (#2385) 2025-02-18 17:33:55 +01:00
Yang Liu 52a9443f53 [RV64_DYNAREC] Fixed a regression introduced recently ([LA64_DYNAREC] too) (#2384) 2025-02-18 15:46:32 +01:00
Yang Liu 0d1488b016 Fixed dlsym_error logs prefix (#2383) 2025-02-18 10:41:48 +01:00
Yang Liu fb4662cb28 [RV64_DYNAREC] Small changes to SET_DFNONE to make it safer ([LA64_DYNAREC] too) (#2382) 2025-02-18 10:40:03 +01:00
Yang Liu 32a747979a [RV64_DYNAREC] Optimized REP MOVSB (#2381) 2025-02-18 09:26:33 +01:00
ptitSeb 362a92c158 [RCFILE] Added a setting to Talos2 2025-02-17 22:19:19 +01:00
Luke Short c27b659bce [BUNDLE] Add script to bundle x86 libraries (#2380)
This manages both x86_64 and x86 libraries. It helps with improving
emulation in all of the Box projects.
2025-02-17 21:32:12 +01:00
ptitSeb 049cbd3783 [ARM64_DYNAREC] More work on UD flags 2025-02-17 17:46:03 +01:00
Yang Liu 8b5b5aa3a7 [INTERP] Added more nops ([DYNAREC] too) (#2378) 2025-02-17 17:38:11 +01:00
Yang Liu f85b9ac664 [INTERP] Added more nops ([DYNAREC] too) (#2377) 2025-02-17 17:06:47 +01:00
Yang Liu ee5a41e21e [INTERP] Added 0F 19 NOP opcode ([DYNAREC] too) (#2376) 2025-02-17 16:29:42 +01:00
ptitSeb d49fc43791 [ARM64_DYNAREC] Continue work on UD flags 2025-02-17 14:18:49 +01:00
Yang Liu 9ec7930eb1 [INTERP] Added 66 0F 19 NOP opcode ([DYNAREC] too) (#2375) 2025-02-17 14:14:10 +01:00
Yang Liu 26dd597a1b [LA64_DYNAREC] Added more opcodes (#2374) 2025-02-17 13:49:12 +01:00
Yang Liu 040f8d9a9f [DYNAREC] Print decoded instruction mnemonics for missing opcodes if trace enabled (#2373) 2025-02-17 13:46:07 +01:00
wannacu f107321d06 [ARM64_DYNAREC] Added more AVX opcodes (#2372)
* [ARM64_DYNAREC] Fixed AVX.F2.0F 12 opcode

* [ARM64_DYNAREC] Added more AVX opcodes
2025-02-17 13:42:43 +01:00
Yang Liu 64313d5aa6 [LA64_DYNAREC] Minor optims and fixes to some opcodes (#2371) 2025-02-17 09:16:15 +01:00
Yang Liuandphorcys 71845a11bb [LA64_DYNAREC] Added more SSE4 opcodes (#2370)
Co-authored-by: phorcys <[email protected]>
2025-02-17 08:13:49 +01:00
Yang Liu e3adda8ff9 [LA64_DYNAREC] Added more opcodes (#2366)
* [LA64_DYNAREC] Added more opcodes

* fix
2025-02-17 08:13:18 +01:00
ptitSeb 85e79a8224 [ARM64_DYNAREC] Improved safeflags=2 2025-02-16 14:41:08 +01:00
ptitSeb 9ef3e080fa [ARM64_DYNAREC] More work on UD flags 2025-02-15 13:54:50 +01:00
ptitSeb 4b5f63dc6d [RCFILE] Added 1 more game profile 2025-02-15 09:47:59 +01:00
Lily 730e9d215c [BOX64RC] Add Zenless Zone Zero Config (#2363) 2025-02-15 08:57:29 +01:00
wannacu efa1cbd49a [ARM64_DYNAREC] Add some opcodes (#2358)
* [ARM64_DYNAREC] Added 66 0F 3A 41 opcode

* [ARM64_DYNAREC] Added AVX.66.0F38 DB opcode

* [ARM64_DYNAREC] Added AVX.66.0F3A DF opcode

* [ARM64_DYNAREC] Added AVX.F2.0F38 F5 opcode

* [ARM64_DYNAREC] Added 66 F3 0F BC,B8 opcode
2025-02-14 14:29:43 +01:00
ptitSeb 91798194d5 [ARM64_DYNAREC] Fixed some issue with DF handling on mayset instructions 2025-02-13 22:12:59 +01:00
Yang Liu d550f9384c [COSIM] Print decoded instruction mnemonics if trace enabled (#2357) 2025-02-13 19:08:53 +01:00
Yang Liu d59d531f14 [RV64_DYNAREC] Fixed F3 0F 11,12 opcodes for vector (#2356) 2025-02-13 18:48:33 +01:00
Yang Liu c9369c5ea1 [RV64_DYNAREC] Added a fastpath to SHL/SHR CL opcodes (#2355) 2025-02-13 17:43:59 +01:00
Yang Liu 05fd25d3bb [RV64_DYNAREC] Minor optimization to CMOV opcodes (#2354) 2025-02-13 16:58:15 +01:00
Yang Liu 2b75a0de55 [RV64_DYNAREC] Minor fixes and improvements to CMP opcodes (#2353)
* [RV64_DYNAREC] Minor fixes and improvements to CMP opcodes

* review
2025-02-13 13:51:16 +01:00
ptitSeb 59e1da5f74 [ARM64_DYNAREC] The check on REP MOVSB overlapping memory is done with saflags=1 now 2025-02-13 13:10:24 +01:00
wannacu 639466d45a [ARM64_DYNAREC] Added some BMI.0F38 opcodes (#2347)
* [ARM64_DYNAREC] Fixed BMI.0F38 F5 ocpode

* [ARM64_DYNAREC] Added BMI.0F38 F3 /2,/3 ocpode

* Added BMI.0F38 F7 opcode

* Fixed emitter mistake about CSINVxw
2025-02-13 13:07:36 +01:00
Yang Liu 95bdaf6eca [RV64_DYNAREC] Minor fixes and improvements to TEST opcodes (#2352) 2025-02-13 11:38:19 +01:00
ptitSeb 9dc10bdc47 [ARM64_DYNAREC] Small optims to AVX.66.0F38 16/18/19/36 opcodes 2025-02-13 10:20:40 +01:00
ptitSeb bf212a7b52 [ARM64_DYNAREC] Fixed LD1R and CBN/CBNZ printer 2025-02-13 10:07:36 +01:00
ptitSeb 40d83ad882 [ARM64_DYNAREC] Fixed regression introduced with b8cc8594f6 2025-02-13 09:29:09 +01:00
ptitSeb baa9efeaa6 [RCFILE] Added 2 more game profiles 2025-02-12 19:28:06 +01:00
ptitSeb 0c17b55e28 [ARM64_DYNAREC] Fixed some issue with DF and mayset opcodes 2025-02-12 19:27:39 +01:00
ptitSeb e2f4ab7700 [COSIM] Added commented way to dumps regs whe printing a difference 2025-02-12 19:26:44 +01:00
ptitSeb 84982ff86f Limit to 11 the number of cpuid invalid parameter message 2025-02-12 19:25:59 +01:00
ptitSeb cfd17e59ac [ARM64_DYNAREC] Removed obsolete comment 2025-02-12 19:25:02 +01:00
ptitSeb af0b0c6c9d [ARM64_DYNAREC] Improved some 66 F0 opcode, especially unaligned path 2025-02-12 19:24:27 +01:00
ptitSeb 0e588e444f [RCFILE] Added 2 game profiles 2025-02-12 16:26:44 +01:00
ptitSeb f575a7846e [ARM64_DYNAREC] Improved many LOCK prefixed opcodes, espcialy unaligned path 2025-02-12 15:17:01 +01:00
ptitSeb c7ff0f658b [ARM64_DYNAREC] More work on flag 2025-02-12 11:04:46 +01:00
ye-yeshun b8cc8594f6 fix VPMASKMOV and VMASKMOVP (#2342)
* fix: 0x2C: 'VMASKMOVPS Gx, Vx, Ex'

Log: VMASKMOVPS读取内存时, 如果某些mask位是0则不进行读写避免访问越界

Signed-off-by: YeshunYe <[email protected]>
Change-Id: I197fc356edcac202b5a329c50c334d0166532e93

* fix: 0x2D: 'VMASKMOVPD Gx, Vx, Ex'

Log: VMASKMOVPD读取内存时, 如果某些mask位是0则不进行读写避免访问越界

Signed-off-by: YeshunYe <[email protected]>
Change-Id: Ie11d93971aa92b141540a37bfdae0b3b060e3aea

* fix: 0x2E: 'VMASKMOVPS Ex, Gx, Vx'

Log: VMASKMOVPS写入内存时, 如果某些mask位是0则不进行读写避免访问越界

Signed-off-by: YeshunYe <[email protected]>
Change-Id: Ide5cb36dc03fc56480fdd45e7d96daed8557d849

* fix: 0x2F: 'VMASKMOVPD Ex, Gx, Vx'

Log: VMASKMOVPD写入内存时, 如果某些mask位是0则不进行读写避免访问越界

Signed-off-by: YeshunYe <[email protected]>
Change-Id: I037de8568e9d2d29597fdf08f991d54e3cb2f6d9

* fix: 0x8E: 'VPMASKMOVD/Q Ex, Vx, Gx'

Log: VPMASKMOVD/Q写入内存时, 如果某些mask位是0则不进行读写避免访问越界

Signed-off-by: YeshunYe <[email protected]>
Change-Id: I0dc98a29ed933d953e137e777bc296149d94b10b

* tests: add test for VPMASKMOV and VMASKMOVP

Log:

Signed-off-by: YeshunYe <[email protected]>

---------

Signed-off-by: YeshunYe <[email protected]>
2025-02-12 10:32:57 +01:00
ptitSeb 6197b70a9a [RCFILE] Improved support for windows setup 2025-02-12 09:20:04 +01:00
ptitSeb 60396f58c0 [ARM64_DYNAREC] Fixed F0 0F B1 ocpode (emit_cmp32 can only be used once per opcode, because of the df flags handling) 2025-02-11 22:52:52 +01:00
wannacu ee83ef4c01 [ARM64_DYNAREC] Fixed wrong COUNT operand in VPSLL{W,D,Q} (#2344) 2025-02-11 13:26:24 +01:00
Yang Liu 4b7e116aa7 [LA64_DYNAREC] Added F3 0F 52 RSQRTSS opcode (#2343) 2025-02-11 10:53:33 +01:00
ptitSeb 785d3ed5ab [ARM64_DYNAREC] Added code on safeflags=2 to check if SI/DI memory overlap on fast rep movsb opcode 2025-02-11 09:59:45 +01:00
Yang Liu 33d1727925 [LA64_DYNAREC] Added F2 0F 7D HSUBPS opcode (#2341) 2025-02-11 08:12:50 +01:00
ptitSeb a50d34e4ba [ARM64_DYNAREC] Some changes on shift opcode and OF handling, and added some new profiles 2025-02-10 15:36:43 +01:00
ptitSeb 7e0c4dcee5 [ARM64_DYNAREC] Mostly cosmetic change on (I)DIV 8bits opcode 2025-02-10 15:10:39 +01:00
Yang Liu f5174d12aa [LA64_DYNAREC] Added preliminary optimization for REP MOVSB (#2340) 2025-02-10 11:44:35 +01:00
Yang Liu 2cb25c095a [LA64_DYNAREC] Added more opcodes (#2339) 2025-02-10 08:35:38 +01:00
ptitSeb d0039c65b4 [DYNAREC] Fixed inst_size building that could be wrong when dynablock was stopped for unknown opcode or other various reason 2025-02-09 20:46:46 +01:00
Yang Liu 099bd148cb [LA64_DYNREC] Added more opcodes (#2338) 2025-02-09 16:41:58 +01:00
Yang Liu 20885702b9 [DYNAREC] Fixed diff logging prefix of pass2&3 (#2337) 2025-02-09 14:32:28 +01:00
Yang Liu 751582df05 [LA64_DYNAREC] Fixed newly added 66 0F BA /4 BT opcode (#2336) 2025-02-09 14:24:12 +01:00
ptitSeb 5212de0d66 [ARM64_DYNAREC] Fixed a potential segfault when signal happens while running Interpreter 2025-02-09 09:55:00 +01:00
Yang Liu 056bb38607 [LA64_DYNAREC] Added more opcodes (#2333) 2025-02-08 19:18:12 +01:00
Yang Liu 1a01adb2ef [ARM64_DYNAREC] Minor simplifications with the usage of GETEX (#2332) 2025-02-08 19:16:22 +01:00
Yang Liu 797731e9e2 [RV64_DYNAREC] Minor fixes and improvements on various opcodes (#2331) 2025-02-08 19:14:36 +01:00
Yang Liu 3e2c698710 [LA64_DYNAREC] Added more opcodes (#2330) 2025-02-08 18:01:53 +01:00
Yang Liu 58b24c85a2 [LA64_DYNAREC] Added more opcodes (#2328) 2025-02-08 15:45:21 +01:00
Yang Liu 28ebc1a0b7 [RV64_DYNAREC] Added aligned optim case for REP MOVSB (#2327)
* [RV64_DYNAREC] Added aligned optim case for REP MOVSB

* fixed a typo
2025-02-08 11:30:02 +01:00
ptitSeb 65487dac51 [ARM64_DYNAREC] Optimized unaligned path for REP MOVSB 2025-02-08 10:51:39 +01:00
Yang Liu 592af6db3b [ARM64_DYNAREC] Added more aligned optim cases for REP MOVSB (#2326) 2025-02-08 09:04:50 +01:00
ptitSeb 997140f500 [RCFILE] Fixed ROLLING_LOG when setup in a profile only 2025-02-07 18:55:43 +01:00
Yang Liu 16f0adec6f [LA64_DYNAREC] Added more opcodes (#2324) 2025-02-07 17:01:08 +01:00
Yang Liu ba6ff73c69 [LA64_DYNAREC] Added more opcodes (#2323) 2025-02-07 13:28:02 +01:00
Yang Liu 2bf78ea18c [LA64_DYNAREC] Added more 66 0F 38 opcodes (#2322) 2025-02-07 12:32:05 +01:00
Yang Liu fc6efb220b [LA64_DYNAREC] Fixed F3 0F MOVSLDUP opcode (#2321) 2025-02-07 12:30:04 +01:00
ptitSeb 523bfbdf3b [RCFILE] Added a new profile 2025-02-07 12:20:37 +01:00
ptitSeb 46ad2261e7 [ARM64_DYNAREC] Optimized REP MOVSB 2025-02-07 12:13:21 +01:00
Yang Liu 6c60ad4695 [RV64_DYNAREC] Small optim to 64 A1/A3 opcodes (#2320) 2025-02-07 09:57:56 +01:00
Yang Liu 37697e2ec7 [DYNAREC] Optimized grab_segdata calls on MODREG (#2319) 2025-02-07 09:38:30 +01:00
Yang Liu f5eb3c1e9b [LA64_DYNAREC] Added 64 88 MOV opcode (#2318) 2025-02-07 08:32:53 +01:00
ptitSeb 5cfd379e97 [ARM64_DYNAREC] Small optims/fixes for a few F2 0F prefixed opcodes 2025-02-06 18:11:04 +01:00
ptitSeb fecaf3111b [ARM64_DYNAREC] Added a comment in emitter on FCMP behaviour 2025-02-06 18:06:37 +01:00
ptitSeb ff6f34aadf [INTERPRETER] Small optim on HADDPS and HSUBPS 2025-02-06 18:04:52 +01:00
ptitSeb 4c3d55fb5c [ARM64_DYNAREC] Fixed fstp long double when fastround==0 2025-02-06 17:58:48 +01:00
ptitSeb d2a5005dcc [RCFILE] Adjusted MALLOC_HACK to be an integer between 0 and 2 instead of a Boolean 2025-02-06 14:46:55 +01:00
Yang Liu 05e1b422d3 [DOCS] Added per-file settings documentation (#2317) 2025-02-06 09:22:52 +01:00
ptitSeb 69f49f79e4 [DYNAREC] Fixed a potential SEGFAULT in FindDynablockFromNativeAddress, and added aprofile for BeamNG.drive linux version (for #424) 2025-02-05 23:29:43 +01:00
ptitSeb 2453eb9b2d [RCFILE] Added a new profile 2025-02-05 11:25:58 +01:00
ptitSeb 93b4813ee2 Remove memory location test for traping wine syscall, box64 doesn't need that 2025-02-05 09:48:07 +01:00
ptitSeb 7cbe71c218 [DYNAREC] Fixed a rare issue when flags would not be computed on 1st opcode of a block if a jump go there (and added a profile for fixed MGSV:TPP)" 2025-02-04 21:12:53 +01:00
ptitSeb 8bb53e1001 [ARM64_DYNAREC] Reduce the number of false positive for DYNAREC_MISSING=1 by showing only null-sized block missing opcode 2025-02-03 15:54:32 +01:00
ptitSeb f79af5afd4 [ARM64_DYNAREC] Optmized RCR Eb, CL, and fixed RCL Eb, CL opcode 2025-02-03 13:45:04 +01:00
ptitSeb 7c27085bd3 [ARM64_DYNAREC] Optimized RCL Eb, CL opcode 2025-02-03 12:18:44 +01:00
ptitSeb 53834f2b29 [ARM64_DYNAREC] Added more details on Need optim message for easier grep 2025-02-03 11:47:55 +01:00
ptitSeb 7c09957263 [ARM64_DYNAREC] Small optims on a few 66 prefixed opcodes 2025-02-03 11:34:11 +01:00
Yang Liu 242832fa3c Added auto-generated x64Int3 printer (#2311)
* Added auto-generated x64Int3 printer

* Fixed minor type errors
2025-02-02 16:46:21 +01:00
ptitSeb 9beb6b4f63 [ARM64_DYNAREC] Small improvment on 64 prefixed opcodes 2025-02-02 16:14:33 +01:00
ptitSeb 0861a88d6e [COSIM] Don't do div by 0 signal on interpreter part when testing 2025-02-02 16:11:39 +01:00
ptitSeb 1c0dc8ec7c [COSIM] Reduce false negative on rcl/rcr OF flag 2025-02-02 16:10:56 +01:00
ptitSeb b21776f9b0 [RCFILE] Add some print of NODYNAREC and DYNAREC_TEST when applyed 2025-02-02 16:10:03 +01:00
Yang Liu 998f164aa3 [ENV] More tweaks on recoding env mapping (#2309)
* [ENV] More tweaks on recoding env mapping

* review
2025-02-01 20:03:01 +01:00
Yang Liu 58d8627cea [RV64_DYNAREC] Fixed F2 0F E6 opcode for vector (#2310) 2025-02-01 19:43:10 +01:00
Yang Liu 877ca41451 [ENV] Fixed crash when rcfile does not exist (for #2295) (#2307)
* [ENV] Fixed crash when rcfile does not exist (for #2295)

* review
2025-02-01 17:29:39 +01:00
Yang Liu 94dedd47c6 [CI] Fixed xuantie-qemu build (#2306) 2025-02-01 16:04:15 +01:00
ptitSeb 1173c1d23f [ARM64_DYNAREC] Small optim and fixes to a few MMX opcodes 2025-02-01 12:06:55 +01:00
ptitSeb d9c9575e6a [RCFILE] Added one more profile 2025-02-01 12:04:43 +01:00
ptitSeb 2239f92816 [ARM64_DYNAREC] Various small fixes and optims in a few AVX opcodes 2025-01-31 16:50:51 +01:00
ptitSeb 637e177408 [ARM64_DYNAREC] Fixed mxcsr sync with fpsr on SSE_SLUSHTO0, and added a profile that needs it 2025-01-31 16:31:10 +01:00
ptitSeb bb653e6888 [ARM64_DYNAREC] Small change on defered flag handling to make sure it's marked to None when needed 2025-01-31 16:30:10 +01:00
ptitSeb 09e07973dd [INTERPRETER] Fixed some AVX opcode that would not zero upper part of register when not using vex.w 2025-01-31 16:29:09 +01:00
ptitSeb 6b7afd7f8e [DOCS] Fixed BIGBLOCK is 2 by default now 2025-01-31 14:30:19 +01:00
ptitSeb eb7858d23a [BOX32][WRAPPER] Fixed a 32bits libcups wrapped function 2025-01-30 15:23:23 +01:00
ptitSeb 1db09fe897 More improvmnet to map with fd tracking 2025-01-29 20:37:08 +01:00
ptitSeb 22a5b573d5 [RCFILE] Added some more profiles 2025-01-29 18:36:37 +01:00
ptitSeb f12f366a3d [DYNAREC] Make BIGBLOCK=2 default 2025-01-29 18:35:57 +01:00
ptitSeb b51ab081ae [ANDROID] Nope, re-disable map with fd tracking on Android 2025-01-29 18:22:09 +01:00
ptitSeb 50fcaf04b4 [ANDROID] Try to re-enable map with fd tracking on Android 2025-01-29 18:14:51 +01:00
ptitSeb 96bca6eac3 Improved map with fd tracking 2025-01-29 18:12:29 +01:00
ptitSeb ed7147e598 [WRAPPER] Added 1 wrapped function and fixed one on gstreamer 2025-01-29 11:45:23 +01:00
xctan 4892c68f17 [RV64_DYNAREC] Fixed lui/auipc immediate in the printer (#2299) 2025-01-28 08:07:42 +01:00
ptitSeb 3ab56994da Improved file map tracking, and use file map info in dynarec for bigblock setting 2025-01-27 16:35:50 +01:00
ptitSeb a54afc8e04 [ANDROID] Disable file map tracking on Android for now, as it seems to segfault 2025-01-27 16:05:43 +01:00
ptitSeb 01b5ee9c78 Improved generic mmap tracking 2025-01-27 15:03:52 +01:00
ptitSeb a513cd847b Added elf support to mmap tracking 2025-01-27 15:03:33 +01:00
ptitSeb 06b6871c80 [RCFILE] Add/Modify a few profiles 2025-01-27 13:28:14 +01:00
ptitSeb f5dc038621 [ENV] Improved a bit env var handling and per file env var 2025-01-27 13:27:58 +01:00
ptitSeb 38dce9138d [DYNAREC] Small change on DIRTY=1 to reduce hotpage effect 2025-01-27 13:27:13 +01:00
xctan 2aa5c5f337 [ENV] Fixed the type of BOX64_DYNAREC_STRONGMEM (#2298) 2025-01-27 11:36:07 +01:00
ptitSeb e6d2c12792 [INTERPRETER] Fixed a few warning 2025-01-26 16:46:23 +01:00
ptitSeb c3dbdf419d [BOX32][WRAPPER] Added some minium 32bits wrapping for libcups (helps wine) 2025-01-26 16:42:27 +01:00
ptitSeb c566ba970d [BOX32][WRAPPER] Add some minimum 32bits gnutls wrapping (helps wine) 2025-01-26 14:14:58 +01:00
ptitSeb 81925643e8 [BOX32][WRAPPER] Added some more 32bits wrapped function, and improved wrapping of 32bits ld-linux.so 2025-01-26 13:21:47 +01:00
ptitSeb 285c874e53 [AR64_DYNAREC] Removed a few more use of TABLE64 2025-01-26 13:12:37 +01:00
ptitSeb ba078c63a8 [WRAPPER] Added a few more wrapped function (to emulate recent SDL2) 2025-01-26 13:11:25 +01:00
ptitSeb a54959a6e3 [ARM64_DYNAREC] Added AVX.F3.0F38 F5 opcode 2025-01-26 13:10:36 +01:00
ptitSeb c573742845 Expanded file mapping tracking for future use (might help #2295) 2025-01-25 18:57:02 +01:00
ptitSeb dab01b8b9f [ARM64_DYNAREC] Added experimental synch of fpsr and mxcsr for the flags, when BOX64_SSE_FLUSHTO0 is used 2025-01-25 18:52:02 +01:00
xctan 9e58047980 [RV64_DYNAREC] Added unaligned codegen for MOVSW (#2296) 2025-01-25 16:03:15 +01:00
Yang Liuandxctan 6f8f37e8ff [RV64_DYNAREC] Optimized GETIP (#2294)
Co-authored-by: xctan <[email protected]>
2025-01-24 21:35:47 +01:00
Yang Liu 3ec950726b [RV64_DYNAREC] Removed some TABLE64 usage (#2291) 2025-01-24 16:02:32 +01:00
Yang Liu cec62dad44 [RV64_DYNAREC] Force priv opcode flags to be at least defered if safeflags=2 ([LA64_DYNREC] too) (#2293) 2025-01-24 15:19:18 +01:00
Yang Liu 89eca28d3a [RV64_DYNAREC] Restricted add/sub RSP optimization ([LA64_DYNAREC] too) (#2292) 2025-01-24 15:08:17 +01:00
ptitSeb 313e4854a0 Added syscall 439 (for #2290) 2025-01-24 09:54:14 +01:00
xctan 8c1ffca530 [RV64_DYNAREC] Added codegen for unaligned stores (#2289)
* [RV64_DYNAREC] Added another special SIGBUS case

* [RV64_DYNAREC] Added codegen for unaligned stores
2025-01-24 08:10:45 +01:00
Yang Liu 7099774a3c [DYNAREC] Added preliminary per-file settings (#2288) 2025-01-23 18:46:18 +01:00
ptitSeb 925f6a9922 [WRAPPER] Improved libpcap wrapping (still for #2282) 2025-01-23 14:59:22 +01:00
Yang Liu 356200159a [ENV] Fixed zydis initialization regression (#2287) 2025-01-23 14:07:38 +01:00
Yang Liu f0d8712275 Clean up UnityPlayer.dll detection from my_mmap64 (#2286) 2025-01-23 11:43:24 +01:00
ptitSeb fe3b66b018 [WRAPPER] Reworked libatk wrapping with new wrapperhelper (will help #2280) 2025-01-23 10:19:50 +01:00
ptitSeb 83af8c6cdf [WRAPPER] Added 1 more wrapped function to libnss3 (for #2280) 2025-01-23 10:11:54 +01:00
ptitSeb ad5b5ea617 [WRAPPER] Reworked libcap wrapping with new wrapperhelper 2025-01-23 10:09:58 +01:00
ptitSeb b439817467 [WRAPPER] Added wrapped libpcap with new wrapper helper (should help #2282) 2025-01-23 10:04:26 +01:00
Yang Liu 276191cdcf [LA64_DYNAREC] Added fastnan handling to more 0F opcodes (fixes CI) (#2285) 2025-01-23 08:58:30 +01:00
Yang Liu 8438b61747 [RV64_DYNAREC] Added fastnan handling to more 0F opcodes (fixes CI) (#2284) 2025-01-23 08:08:00 +01:00
ptitSeb f4a9f8dd79 [ARM64_DYNAREC] Added a few AVX opcode and Improved/Fixed some existing SSE and AVX ones 2025-01-22 20:37:17 +01:00
ptitSeb f235c7f702 [INTERPRETER] Improved (V)ADD/MUL/SUB/DIV P(S/D), and improved avx test too 2025-01-22 20:36:31 +01:00
ptitSeb 8e1e2c7840 [ARM64_DYNAREC] Remove another use of Table64 2025-01-22 17:44:52 +01:00
Yang Liu 0b632afbfe [DOCS] Auto-generated USAGE.md and box64.pod (#2283) 2025-01-22 11:56:31 +01:00
Yang Liu 89dcd2566b Fixed various issues introduced in the env infra refactor (#2281)
* Open trace file again after apply env files

* dynrec_df=1 by default

* more fixes

* more fixes

* more
2025-01-22 10:29:21 +01:00
Yang Liu 314edea645 Added [BOX64] prefix for all the stdout logs (#2279)
* Added [BOX64] prefix for all the stdout logs

* Remove some hardcoded prefix

* review
2025-01-21 19:08:09 +01:00
Yang Liu fe28bd93bd Changed some functions name and visibility (#2278) 2025-01-21 17:44:53 +01:00
Yang Liu d882a5c8fe [ENV] Optimized BOX64ENV log a bit (#2277) 2025-01-21 17:13:12 +01:00
Yang Liu 044dec0bfa [ENV] Initial refactor of env variables infrastructure (#2274)
* [ENV] Initial refactor of env variables infrastructure

* Ported BOX64_DYNAREC_LOG

* Ported more options

* Ported BOX64_MALLOC_HACK

* Ported BOX64_DYNAREC_TEST

* Ported more options

* Ported more options

* Ported more options

* Ported all options

* Removed old rcfile parser

* Fix

* review

* fix

* fix

* more fixes
2025-01-21 16:13:51 +01:00
Pablo Labs ed8b6fe9db [RCFILE] Add MiSide Profile (#2276) 2025-01-21 08:12:59 +01:00
ptitSeb c98b4c8f45 [RCFILE] Added 2 new profiles 2025-01-20 19:42:11 +01:00
ptitSeb b78d81d319 [ARM64_DYNAREC] Removed many use of TABLE64 that would just slowdown build of the dynablock for not much memory saved 2025-01-20 19:41:43 +01:00
ptitSeb 9f3be89e12 [ANDROID] Removed the forced NOLOADADDRESS build parameter for Android builds 2025-01-20 16:50:18 +01:00
ptitSeb 9e0b300354 [CI] Fixed a typo 2025-01-20 16:49:14 +01:00
ptitSeb dde6d26236 [CI] Try to use gihub arm runner on linux arm build 2025-01-20 16:41:57 +01:00
ptitSeb e6eac39759 [ARM64_DYNAREC] Small optim for DB E2 opcode 2025-01-19 15:20:43 +01:00
ptitSeb 5654e77625 [INTERPRETER] Fixed AVX.66.0F38 0E/0F opcodes 2025-01-19 13:58:06 +01:00
ptitSeb c9f01d975d [ARM64_DYNAREC] Added 64/65 1B opcode 2025-01-18 15:47:08 +01:00
ptitSeb 1fe213f900 [ARM64_DYNAREC] Fixed OF flags for rcr 8bits and 16bits 2025-01-18 15:46:48 +01:00
ptitSeb 802002b7a3 [TRACE] Added TID on Strange SIGSEGV with Access Error message 2025-01-18 12:20:34 +01:00
ptitSeb 69a7c00841 [ARM64_DYNAREC] Fixed AVX.66.0F38 17 opcode 2025-01-18 12:19:53 +01:00
ptitSeb c24f040888 [INTERPRETER] Fixed AVX.66.0F38 17 opcode and improved AVX.66.0F38 0E/0F opcodes 2025-01-18 12:19:33 +01:00
ptitSeb 0f225fc1a0 [ARM64_DYNAREC] Fixed F0 0F BA opcodes with ip relative addressing 2025-01-18 12:18:31 +01:00
ptitSeb 666506e834 [BOX32] Fixed some issue with previous commit on box32 loading wine/proton 2025-01-17 15:08:41 +01:00
ptitSeb 21c0a2e7d7 Added some hack to simulate seccomp/bpf Windows syscalls handling in proton 2025-01-17 12:24:10 +01:00
ptitSeb 03204f709e [TRACE] Fixed a typo in a debug message 2025-01-17 12:06:19 +01:00
Yang Liu 6827fc6cc9 [RV64_DYNAREC] Refined printer for more thead instructions (#2272) 2025-01-17 11:40:18 +01:00
Yang Liu cff4798249 [RV64_DYNAREC] Optimized 16bit constant RCL/RCR opcodes (#2270) 2025-01-16 13:36:23 +01:00
Yang Liu 93bf308179 [RV64_DYNAREC] Optimized 16bit constant ROR opcodes (#2268) 2025-01-16 13:18:31 +01:00
Yang Liu 166c4858a1 [RV64_DYNAREC] Optimized 16bit constant ROL opcodes (#2267) 2025-01-16 10:20:31 +01:00
Yang Liu 4b8fb02198 [ARM64_DYNAREC] Removed an unused arg in SET_DFNONE (#2266) 2025-01-16 08:20:55 +01:00
ptitSeb 8432f7d8e2 [DYNAREC] Introduce BOX64_DYNAREC_DIRTY and some profile to use it 2025-01-15 18:24:54 +01:00
ptitSeb ec675564c6 [ARM64_DYNAREC] Added one more case of fastround=2 for AVX.F2.0F 5A opcode 2025-01-15 17:05:29 +01:00
ptitSeb 8c71178238 [ARM64_DYNAREC] Added unaligned code for F3 0F 7F opcode 2025-01-15 14:23:37 +01:00
ptitSeb 72df0bd1a0 Fixed dlsym with RTLD_NEXT and preloaded libs 2025-01-15 11:48:58 +01:00
ptitSeb 6035cbd5c1 [ARM64_DYNAREC] Allow new ClearCache also for Android 2025-01-14 20:41:16 +01:00
ptitSeb d7007dd3cc Small changes on envv and arv managment 2025-01-14 20:38:00 +01:00
ptitSeb 9c5daf5954 [RCFILE] Log before applying the change 2025-01-14 20:38:00 +01:00
Yang Liu a57bc9e780 [RV64_DYNAREC] Fixed simm12 overflow in some places ([LA64_DYNAREC] too) (#2264) 2025-01-14 19:04:35 +01:00
ptitSeb 2e2bed4374 [DYNAREC] Better handling of Clear Instruction Cache, also [ARM64_DYNAREC] inlined instruction cache clear (but not for [ANDROID] to keep it safe) 2025-01-14 16:16:21 +01:00
ptitSeb 4eeaddf490 Small improvment on signal handling and db/x64pc fetching 2025-01-14 16:14:51 +01:00
Yang Liu 0cd53ca748 [RV64_DYNAREC] Fixed stack out of sync in native call (#2263) 2025-01-14 14:51:25 +01:00
Yang Liu fa2bd920bd [RV64_DYNAREC] Fixed offsetof(x64emu_t, scratch) usage overflow ([LA64_DYNAREC] too) (#2262) 2025-01-14 12:47:23 +01:00
Yang Liu 613f2cccf1 [CORE] Simplified xhead* detection and standardized extension display (#2261) 2025-01-14 09:20:25 +01:00
Yang Liu d91461f468 [RV64_DYNAREC] Fixed SET_ELEMENT_WIDTH (#2260)
... also removed some unnecessary instructions in vector_loadmask
2025-01-14 08:13:18 +01:00
ptitSeb bcc497c865 This should fix the non-dynarec build 2025-01-13 17:27:36 +01:00
ptitSeb 2414f82c38 Try to improve full x86 state gathering on Signal 2025-01-13 16:12:44 +01:00
Pablo Labs fd7d811b29 [CI] Create Box64 Packages for MiceWine (.rat) (#2256)
* [CI] Create Box64 Packages for MiceWine (.rat)

* Use Default Name on Generated .rat file
2025-01-12 08:33:56 +01:00
Yang Liu e533cd0ea1 [SIGNAL][RV64] Supported more opcodes for special cases (#2253) 2025-01-11 17:07:59 +01:00
ptitSeb 9b7e5d69b2 This should fix non-Dynarec builds 2025-01-11 13:50:54 +01:00
ptitSeb 0c5e6d867f Another attempt at fixing non-Dynarec builds 2025-01-11 13:41:27 +01:00
ptitSeb 32c646d0d2 This should fix non-Dynarec builds 2025-01-11 12:48:36 +01:00
ptitSeb 35a6828209 [ARM64_DYNAREC] Better handling unaligned access to device memory, with regeration of code 2025-01-11 12:38:35 +01:00
Yang Liu 2b66675a08 [RV64_DYNAREC] Fixed a 16bit SHR pastpath edge case (#2251) 2025-01-11 12:03:55 +01:00
ptitSeb 93638ac95a [BOX32][WRAPPER] Added 1 32bits function to libc 2025-01-11 10:26:02 +01:00
ptitSeb f489761e68 [BOX32] Improved elf memory managment for 32bits process 2025-01-11 10:26:02 +01:00
Yang Liu 56ccde005e [RV64_DYNAREC] Disabled dynamic sew on MOVDQA as a workaround (#2249) 2025-01-10 19:51:33 +01:00
Yang Liu 47e4aa0b84 [SIGNAL][RV64] Added special unaligned cases handling (#2248) 2025-01-10 15:56:43 +01:00
ptitSeb b977d84f11 [ARM64_DYNAREC] Reworked a bit DB / 7 opcode 2025-01-10 15:51:08 +01:00
ptitSeb b7f14ff338 [INTERPRETER] Small cosmetic fix for D2LD helper function 2025-01-10 15:50:32 +01:00
ptitSeb 86211e5970 [USAGE] Added some missing settings in documentation 2025-01-10 14:49:48 +01:00
ptitSeb d8669d7c7d [ARM64_DYNAREC] Fixed SQXT(U)N printer 2025-01-10 13:04:28 +01:00
ptitSeb 0d8e02a3fe Don't try to use free a custom block if init is not done 2025-01-10 12:10:57 +01:00
ptitSeb 1e681cead0 Creating an emu structure for a thread will use a minimal stack now ([BOX32] too, also using MAP_32BIT attribute) 2025-01-10 12:10:20 +01:00
ptitSeb 53f2423578 [BOX32] Better handling of pthread_mutex 2025-01-10 12:08:49 +01:00
Yang Liu 6cdfa05604 [RV64_DYNAREC] Fixed MOVMSKPS RVV 1.0 path (#2246) 2025-01-09 18:45:58 +01:00
ptitSeb d55e879879 [BOX32][WRAPPER] Added support of BOX64_MAXCPU in 32bits wrapped SDL2 2025-01-09 16:56:07 +01:00
ptitSeb d377433997 [WRAPPER] Added support of BOX64_MAXCPU in wrapped SDL2, plus some various other CPUInfo fixes 2025-01-09 16:56:07 +01:00
xctan 207073bf36 [RV64_DYNAREC] Fixed some typos (#2244)
* [RV64_DYNAREC] Fixed CMPXCHG8B

* [RV64_DYNAREC] Fixed typo
2025-01-09 08:10:41 +01:00
ptitSeb 316f31a4bb [ARM64_DYNAREC] Small fixes for some 8bits OR and XOR opcodes on regs with no flags (should help #2243 again) 2025-01-08 23:05:42 +01:00
ptitSeb ada8efcdef [ARM64_DYNAREC] Small fix for 80 /4 opcode on regs with no flags (should help #2243) 2025-01-08 19:51:46 +01:00
ptitSeb 99d0889cfd [INTERPRETER] Removed some useless tests on x87 comp 2025-01-08 15:59:14 +01:00
Hagb (Junyu Guo 郭俊余) 653a67c8ad Port rounding of some x87 instructions from Box86 (#2242)
* Port rounding of some x87 instructions from Box86

Ported from https://github.com/ptitSeb/box86/pull/951. The original pull
request and this commit also contain some improvements on precision of
`F2XM1` and `FYL2XP1`.

* Run fpu_rounding test with dynarec only for ARM64

They have been implemented on dynarec only for ARM64.
2025-01-08 15:34:15 +01:00
ptitSeb b99893d1c3 [ARM64_DYNAREC] Remove bloated x87 comp code 2025-01-08 15:08:42 +01:00
ptitSeb a5c4d01649 Updated 32bits test19 too 2025-01-08 15:08:17 +01:00
ptitSeb 82105a1543 [INTERPRETER] Improved x87 emulation a bit ([ARM64_DYNAREC] too) 2025-01-08 14:43:14 +01:00
Leslie Zhai c65910fd25 [WRAPPED] Added monstartup (#2241)
* [WRAPPED] Added monstartup

* [WRAPPED] Added monstartup for not defined STATICBUILD

* [WRAPPED] Fix monstartup wrong signature

* [WRAPPED] Change monstartup signature about STATICBUILD

* [WRAPPED] monstartup is WEAK symbol.
2025-01-08 13:46:02 +01:00
ptitSeb b5de464e85 [ARM64_DYNAREC] Added FCMEQ printer 2025-01-07 20:40:09 +01:00
ptitSeb 81eb0b45b3 [ARM64_DYNAREC]Small optimisation for 8bits and 16bits NOT opcode on register 2025-01-07 20:39:47 +01:00
ptitSeb c772d1ab49 Small fix to program break tracking 2025-01-07 15:39:02 +01:00
ptitSeb 1af7c15801 Trace program program to not allocate memory over there (help TalosPrinciple2, probably other UE5 games too) 2025-01-07 15:34:11 +01:00
ptitSeb e11901a7a6 [TRACE] Small change in Double segfault trace 2025-01-07 15:33:22 +01:00
ptitSeb 0b2f84df54 [ARM64_DYNAREC] Small optim to 8bits AND opcodes with constant and without flags 2025-01-07 15:17:42 +01:00
ptitSeb a1ff40733b [ARM64_DYNAREC] Optimized 8bits XOR when no flags is needed 2025-01-07 10:40:46 +01:00
ptitSeb a61888e06c [ARM64_DYNAREC] Optimized 8bits OR when no flags is needed 2025-01-07 09:58:13 +01:00
ptitSeb 691259ec0d [BOX32] Use 32bits malloc when building LinkMaplib 2025-01-06 20:26:44 +01:00
ptitSeb 91e678da5b [BOX32][WRAPPER] Added a few more 32bts wrapped functions to libc and libresolv 2025-01-06 20:25:54 +01:00
ptitSeb 8a7c2b5228 [INTERPRETER] Added a check of CS validity on IRET opcode 2025-01-06 17:07:19 +01:00
ptitSeb e7710f59fa [BOX32] Fixed some signature issues with wrapped libXrender 2025-01-06 17:06:44 +01:00
Leslie Zhai 4039f3c249 [WRAPPED] Added xdr_string and xdr_free (#2235)
* [WRAPPED] Added xdr_string

* [WRAPPED] Added check rpc/xdr header file

* [WRAPPED] Add xdr_free

* [WRAPPED] Use my->Func instead

* [WRAPPED] Change GOM(xdr_string) to GO(xdr_string)
2025-01-06 10:29:59 +01:00
ValdikSS 6f46ccdd5a Fix crash with incorrect argv[0]: rewrite it only if "box64" is present (#2233) 2025-01-06 08:42:08 +01:00
ptitSeb b79ba11d95 [DYNAREC] Imroved log on signal and flags/sse info gathering. [ARM64_DYNAREC] Fixed some case of nat flags being incorectly used 2025-01-05 14:59:59 +01:00
ptitSeb 5a35184ba7 [INTERPRETER] Added a few more cpu extension and associated opcodes ([ARM64_DYNAREC] added some of the new opcodes too) 2025-01-05 14:57:24 +01:00
ptitSeb db801da658 [ARM64_DYNAREC] Added a new emiter 2025-01-05 14:55:28 +01:00
ptitSeb f160fe3300 [ARM64_DYNAREC] Small improvments on (V)PMOVMSKB opcodes 2025-01-05 14:55:28 +01:00
ValdikSS 5d5dd3a3bc Document BOX64_ARG0 argv[0] rewriting variable (#2234) 2025-01-05 14:08:27 +01:00
ptitSeb 5fa65a4b38 [ARM64_DYNAREC] Small optim on specific case of XOR with -1 const 2025-01-04 12:30:28 +01:00
ptitSeb cc34c75fc3 [INTERPRETER] Fixed opcode name in comment 2025-01-04 12:30:28 +01:00
ptitSeb 7fb1a34947 [ARM64_DYNAREC] Don't simplify flags for add rsp, const when safeflags=2 is used 2025-01-04 12:30:28 +01:00
ptitSeb d087020139 [ARM64_DYNAREC] Small improvment on edge cases double to int x87 conversions 2025-01-04 12:30:28 +01:00
Leslie Zhai 4065e61ec5 [DYNAREC] Appended instruction name to symbol (#2228) 2025-01-03 14:33:45 +01:00
ptitSeb da6b799a10 [ARM64_DYNAREC] Small fixes to sse info retreiving on signal 2025-01-02 20:41:36 +01:00
ptitSeb 967c73efd1 [ARM64_DYNAREC] Fixed native flags with signal, and added sse handling 2025-01-02 19:00:49 +01:00
ptitSeb 6a35cd2a56 [ARM64_DYNAREC] Change native flags handling in signal to make it more extensible 2025-01-02 17:35:43 +01:00
ptitSeb ebf03f8878 [ARM64_DYNAREC] Improved ADCX opcode 2025-01-01 16:39:30 +01:00
ptitSeb d7dbee5126 [ARM64_DYNAREC] Improved native flags handling 2025-01-01 16:39:00 +01:00
ptitSeb 08930381e9 [ARM64_DYNAREC] Improved a bit MULX opcode 2025-01-01 12:12:19 +01:00
ptitSeb 495c98a488 [ARM64_DYNAREC] Small improvements to POPCNT and ADOX opcodes 2025-01-01 09:46:19 +01:00
ptitSeb 80a4b61e5c [BOX32] Fixed build 2024-12-31 22:34:08 +01:00
ptitSeb 1d20968f82 [ARM64_DYNAREC] Improved signal handling and flags handling (tbd on other archs) 2024-12-31 22:27:55 +01:00
ptitSeb ca8d569e63 [ARM64_DYNAREC] Fixed some issue with shrd/shld opcodes 2024-12-31 22:05:42 +01:00
ptitSeb 670770e24a [ARM64_DYNAREC] Small improvement to MULX opcode 2024-12-30 20:38:23 +01:00
ptitSeb b55b138303 [WRAPPER] Fixed a small mystake with latest ALTNAME work 2024-12-28 22:39:13 +01:00
olegos2 d0c7cb46e7 [WRAPPED][ANDROID] Add libGL ALTNAME (#2225) 2024-12-28 22:03:36 +01:00
olegos2 6e1e7de52b [ANDROID] Add a few ALTNAMEs and unwrap ifdefs for lib names (#2224)
* [WRAPPED][ANDROID] A few more ALTNAMEs

* [WRAPPED][ANDROID] Unwrap ifdefs for lib names
2024-12-28 20:13:17 +01:00
olegos2 bb0a445a6b Spelling/typo fixes in code and documentation updates (#2223)
* Fix typo DLOpenned->DLOpened

* Fix a typo in comments: versionned->versioned

* Fix a typo in comment: cleanning->cleaning

* Update COMPILE.md and USAGE.md

* A few more typos in comments
2024-12-28 17:06:51 +01:00
Chi-Kuan Chiu 7157803c03 [DOCS] Improve cross-build instructions (#2196)
Include a note for users utilizing environments
where only the box64 binary is available.
This addition ensures that users can install
the necessary libraries before running box64.
2024-12-28 16:38:11 +01:00
東雲なの b7c5adae3d Use uname -m to get CPU architecture (#2222)
Use uname -m to get CPU architecture is simplier than lscpu
2024-12-28 16:34:19 +01:00
Yang Liu 809b663350 [LA64_DYNAREC] Some minor fixes on bad variable usage (#2221) 2024-12-28 15:37:30 +01:00
ptitSeb 1c4f1cb8c2 [ARM64_DYNAREC][TRACE] Added printer for CNT opcode 2024-12-28 14:33:10 +01:00
ptitSeb cace5f0ccb [INTERPRETER] Fixed 32bits ADCX/ADOX opcodes 2024-12-28 13:50:32 +01:00
ptitSeb 4aaa0b5d24 [ARM64_DYNAREC] Fixed and improved flags for F3 0F B8 opcode 2024-12-28 12:10:13 +01:00
ptitSeb c0829b807c [INTERPRETER] Added 66 F3 0F B8 opcode 2024-12-28 12:05:31 +01:00
ptitSeb 7d3cdb06e3 [INTERPRETER] Small (mostly cosmetic) change to POCNT opcode 2024-12-28 12:05:11 +01:00
ptitSeb 42f3884478 Update README.md 2024-12-28 09:19:44 +01:00
ptitSeb fcd46e2cdc [ANDROID] Another attempt at fixing the build 2024-12-27 22:54:13 +01:00
ptitSeb f36f9d290d [ANDROID] Fix build 2024-12-27 22:43:49 +01:00
ptitSeb ae512cc4ed [ANDROID] Fixed definition of android_sigaction_t 2024-12-27 22:15:01 +01:00
ptitSeb 4fd59da003 [ANDROID] Try to fix signal handling on android 2024-12-27 22:10:24 +01:00
ptitSeb e2d7cc5011 Exposed MMXext for CPUTYPE=1 2024-12-27 18:47:32 +01:00
ptitSeb 79413a4147 [INTERPRETER] Exposed SSE4a for CPUTYPE=1, implemented all 4 opcodes 2024-12-27 18:32:37 +01:00
ptitSeb 80b357da41 [BOX32] Adapted signatures of 2 32bits libc wrapped functions 2024-12-27 18:08:06 +01:00
ptitSeb a54f516447 Introduce BOX64_CPUTYPE to choose emulating Intel or AMD cpus (no AMD specific extension yet) 2024-12-27 18:07:25 +01:00
ptitSeb 26ba1148e8 [ARM64_DYNAREC] Small optim for some specific case of slhd32 emiter 2024-12-27 13:50:19 +01:00
Yang Liu 8b2b96d5c5 [LA64_DYNAREC] Fixed some minor issues on LBT path (#2218) 2024-12-27 10:06:19 +01:00
ptitSeb e21a506936 [WRAPPER] Added 3 more wrapped functions to libxcb and freetype (for #2217) 2024-12-26 19:18:41 +01:00
ptitSeb e86c6359d6 [INTERPRETER] Improved some shift operands nd [AR64_DYNAREC] Improved shift operands and [COSIM] reduce noise on shift operands 2024-12-26 19:10:27 +01:00
ptitSeb acce64b268 [ARM64_DYNAREC] Fixed 67 8D opcode 2024-12-26 17:32:42 +01:00
Leslie Zhai 89713993cb [DYNAREC] Implement perf map (#2212)
* [DYNAREC] Implement perf map

* [DYNAREC] Use function name as the Symbol
2024-12-26 14:43:19 +01:00
Yang Liu cf24eaf9d2 [LA64_DYNAREC] Added hardware wall-clock support (#2216)
* [LA64_DYNAREC] Added hardware wall-clock support

* Refined multi-language support
2024-12-26 14:40:04 +01:00
Yang Liu cd1ac51b79 [LA64_DYNAREC] Added more opcodes (#2215) 2024-12-26 14:37:55 +01:00
Yang Liu a7ded59393 [LA64_DYNAREC] Added more opcodes (#2214) 2024-12-26 10:14:54 +01:00
Yang Liu 205ef4ddeb [LA64_DYNAREC] Added more opcodes (#2213) 2024-12-26 09:30:10 +01:00
Yang Liu 145689783f [LA64_DYNAREC] Added more opcodes and fixed CVTTPD2DQ (#2211) 2024-12-25 21:00:20 +01:00
Yang Liu 21a21b04e6 [LA64_DYNAREC] Added IRET opcode (#2210) 2024-12-25 18:52:32 +01:00
Yang Liu 87e19076ad [DYNAREC] Cleanup modreg (#2209) 2024-12-25 16:59:18 +01:00
Leslie Zhai 9492b6ca66 [LA64_DYNAREC] Added MOVLPD and MOVHPD opcodes (#2198)
* [LA64_DYNAREC] Added MOVLPD and MOVHPD opcodes

* [LA64_DYNAREC] Fix VSTELM_D idx
2024-12-25 15:56:54 +01:00
Yang Liu 4a45db781f [LA64_DYNAREC] Added more opcodes (#2208) 2024-12-25 15:40:45 +01:00
Yang Liu 0329d5fcc2 [RV64_DYNAREC] Added more opcodes ([LA64_DYNAREC] too) (#2205)
* [RV64_DYNAREC] Added 66 8E MOV opcode ([LA64_DYNAREC] too)

* Added more opcodes
2024-12-25 15:40:21 +01:00
Yang Liu f39b5514c5 [RV64_DYNAREC] Fixed various lock usage in geted ([LA64_DYNAREC] too) (#2207) 2024-12-25 15:35:47 +01:00
Yang Liu 4700a6322e [RCFILE] Added sekiro.exe entry (#2206) 2024-12-25 15:30:28 +01:00
Yang Liu 91a8fef1bb [WRAPPED] Always return ENOSYS in the deprecated sysctl (#2204) 2024-12-25 15:28:29 +01:00
Yang Liu a56a66a227 [RV64_DYNAREC] Fixed a regression in #2187 (#2203) 2024-12-24 19:38:00 +01:00
Yang Liu 1b262dac29 [LA64_DYNAREC] Added nativeflags support (#2202) 2024-12-24 18:58:49 +01:00
Yang Liu 3b15ef1cb5 [LA64_DYNAREC] Fixed 66 0F PTEST opcode (#2201) 2024-12-24 17:50:41 +01:00
Yang Liu 9ac695b9be [LA64_DYNAREC] Small optim to MOVHPS (#2200) 2024-12-24 14:19:20 +01:00
Yang Liu 05060803b2 [RV64_DYNAREC] Fixed nativeflags tmp register usage (#2199) 2024-12-24 14:06:52 +01:00
ptitSeb e84f2e4a8b [ARM64_DYNAREC] a bit more work on df=0 (still WIP) 2024-12-24 11:30:32 +01:00
DragonSWDev 6fac9ee35b Add SDL_RenderGeometryRaw wrapped function to SDL2 (#2195)
* Add SDL_RenderGeometryRaw wrapped function to SDL2

* Add missing files
2024-12-23 22:26:53 +01:00
Yang Liu 93cc31bc48 [LA64_DYNAREC] Fixed various issues in LBT path (#2197) 2024-12-23 21:29:49 +01:00
Yang Liu 13ee4acd59 [WRAPPED][BOX32] Redirected a few old symbols (#2194)
* [WRAPPED] Redirected a few old symbols

* More
2024-12-23 18:43:47 +01:00
ptitSeb 1360e7112c [ARM64_DYNAREC] Added work in progress BOX64_DYNAREC_DF env. var. 2024-12-23 13:26:52 +01:00
ptitSeb 12987af561 Fixed a warning 2024-12-23 13:26:04 +01:00
ptitSeb e071a70ec2 [DYNARC] Forgot this file from previous commit 2024-12-23 13:25:38 +01:00
ptitSeb 48db75961e [DYNAREC] Some light rework of the hotpage handling 2024-12-23 12:48:35 +01:00
ptitSeb da0820ce0a Added more rbtrees in dynarec managment, to speedup FindDynablockFromNativeAddress function 2024-12-23 12:25:56 +01:00
ptitSeb ac81132435 Try to improve clone syscal handling ([BOX32] too) 2024-12-23 12:23:18 +01:00
Yang Liu 946da43038 [LA64_DYNAREC] Fixed some LBT path issues (#2193) 2024-12-23 11:32:35 +01:00
Yang Liu cad9450e16 [LA64_DYNAREC] Optimized some 16bit shift opcodes (#2192) 2024-12-23 10:05:05 +01:00
Yang Liu 0c7cc657cc [LA64_DYNAREC] Fixed 32bit ADDIz and SUBz (#2191) 2024-12-23 08:25:29 +01:00
ptitSeb ce4590f5ba Fix build for older system (for #2190) 2024-12-23 08:24:25 +01:00
Yang Liu cd3f5ca97d [RV64_DYNAREC] Small optim to emit_and32c (#2189) 2024-12-22 21:50:05 +01:00
Yang Liu fc2a6d4dd1 [RV64_DYNAREC] Added a fast path to SHR Ew, Ib (#2188) 2024-12-22 21:41:43 +01:00
Yang Liu 85fe4c628e [RV64_DYNAREC] Made nativeflags works with 8/16bit fast path (#2187) 2024-12-22 20:30:40 +01:00
ptitSeb 1bb7d9efd8 [ARM64_DYNAREC] Reworked MUL/IMUL opcodes a bit 2024-12-22 15:22:44 +01:00
Yang Liu 25b4dd1457 [GDBJIT] Display register mapping annotations (#2185) 2024-12-22 11:17:49 +01:00
Yang Liu ea13414083 [GDBJIT] Unified the experience for all the backends (#2183) 2024-12-21 16:20:48 +01:00
ptitSeb 3e745474d3 Improved memory tracking and 32bits memory allocation 2024-12-21 15:32:17 +01:00
ptitSeb 5ad2f155c1 Changed customme block resize to lower the number of realloc 2024-12-21 12:33:22 +01:00
ptitSeb 945b4192b1 [WRAPPER] Fixed a few uninitized value used warning from Vamgrind 2024-12-21 12:33:22 +01:00
ptitSeb 3b71ba6090 [ARM64_DYNAREC] Improved DMB/DSB printer 2024-12-21 12:33:22 +01:00
Leslie Zhai 9fc4697233 [LA64_DYNAREC] Added ROUNDSD and CVTDQ2PD opcodes (#2173)
* [LA64_DYNAREC] Added ROUNDSD and CVTDQ2PD opcodes

* [LA64_DYNAREC] Added round_round

* [LA64_DYNAREC] Remove redundant instruction

* [LA64_DYNAREC] Remove useless assembler

* [LA64_DYNAREC] Made round_round more readable
2024-12-20 16:47:18 +01:00
ptitSeb 8a37b12f81 Simplified ucontext uc_link managment (closer to glibc handling) ([BOX32] too) 2024-12-20 15:39:27 +01:00
Yang Liu 6ac7d7a1db [GDBJIT] Display DynaRec info in source file (#2179)
* [GDBJIT] Display DynaRec info in source file

* fix
2024-12-20 12:59:03 +01:00
ptitSeb 291db1530c [LA64] This should fix static build 2024-12-20 12:38:57 +01:00
ptitSeb e77ea1b45c [WRAPPER] Added 1 more libc wrapped function 2024-12-20 11:43:52 +01:00
ptitSeb 80db0175e0 [WRAPPER] Added a few glib2 wrapped functions 2024-12-20 11:42:14 +01:00
ptitSeb 15f90899eb [BOX32] Don't abort when stack pointer is not correct on new thread, but return an error 2024-12-20 11:21:40 +01:00
ptitSeb e2ce483e0d [BOX32][WRAPPER] Improved obstack handling 2024-12-20 11:04:28 +01:00
ptitSeb 41b31dc58d [BOX32] use malloc_trim when it gives non 32bits pointers 2024-12-20 11:04:28 +01:00
Yang Liu f8b9c7b2b7 [LA64_DYNAREC] A few minor optimizations (#2174) 2024-12-19 16:20:16 +01:00
ptitSeb a8000cb629 [BOX32] More fixes on libc wrapping 2024-12-19 13:57:33 +01:00
ptitSeb 17f2371804 [BOX32] Boosted xcbconnection slot from 8 to 16 2024-12-19 10:35:00 +01:00
Leslie Zhai 4d377de5ab [LA64_DYNAREC] Added CLC and PMOVZXBW opcodes (#2172) 2024-12-19 09:34:54 +01:00
Leslie Zhai 956f6ffc15 [LA64_DYNAREC] Fix VPICKVE2GR_WU typo (#2171)
* [LA64_DYNAREC] Fix VPICKVE2GR_WU typo

* [LA64_DYNAREC] Fix VPICKVE2GR_BU|HU_DU typo
2024-12-19 08:11:39 +01:00
Yang Liu 600ae18d4b [RV64_DYNAREC] Fixed 32bits SUBz (#2170) 2024-12-18 21:47:06 +01:00
Yang Liu 39aa02c19c [RV64_DYNAREC] Added more LOCK prefix opcodes (#2169) 2024-12-18 21:38:17 +01:00
Yang Liu 7dcb86f500 [RV64_DYNAREC] Fixed 32bit ADDIz (#2168) 2024-12-18 20:54:08 +01:00
Yang Liu f873255a19 [RV64_DYNAREC] Fixed CMPXCHG8B (#2167) 2024-12-18 18:43:06 +01:00
Yang Liu 4662ab1c80 [RV64_DYNAREC] Added unaligned support to CMPXCHG8B opcode (#2166) 2024-12-18 18:13:52 +01:00
ptitSeb b0b34e3a2a Improved handling of stack size and addresses attribute for threads ([BOX32] too) 2024-12-18 17:18:26 +01:00
ptitSeb 631da8a532 Added an helper function to abort and backtrace (used in [BOX32] when pointer address not 32bits compatible) 2024-12-18 17:15:21 +01:00
ptitSeb f80886fd68 [ELFLOADER] Do not fornul dlclose remaining libs at exit, just lest dependancies do the unload (help gogdl and nile) 2024-12-18 17:14:04 +01:00
ptitSeb cbe7ced335 Simplfied env var and trace file initial managment 2024-12-18 16:13:30 +01:00
Yang Liu 955f6e74ab [GDBJIT] Refined RV64 and LA64 support (#2165) 2024-12-18 15:26:17 +01:00
Yang Liu 8a982e8b5e [LA64_DYNAREC] Added POPCNT opcode and fixed an issue too (#2164) 2024-12-18 09:15:21 +01:00
Yang Liu 47f5fe7caf [GDBJIT] Show x64pc in gdb, also added documentation (#2163)
* [GDBJIT] Show x64pc in gdb

* Add env. variable and documentation

* typo

* oops
2024-12-18 08:11:09 +01:00
Yang Liu 6e0f32f4ca Added initial GDBJIT support (#2162)
* Added GDBJIT support

* fix

* fix
2024-12-17 22:01:33 +01:00
ptitSeb 62eca11bee [BOX32][TRACE] Improved trace of wrapped functions 2024-12-17 14:49:08 +01:00
ptitSeb 13f5ec1524 [BOX32] Small change on how tls memory is allocated 2024-12-17 14:48:05 +01:00
ptitSeb e751d41ba7 Some (mostly) cosmetic change to x64emu initializers 2024-12-17 14:46:09 +01:00
ptitSeb 7fd884b9c1 [BOX32][WRAPPER] More fixes to sendmsg/rcvmsg wrapping (fixes some wine 32bits stuffs) 2024-12-17 14:42:53 +01:00
ptitSeb a98887589d [BOX32] Improved pre-reserve highmem, and use that memory for dynablocks 2024-12-17 13:22:20 +01:00
ptitSeb 0882f910df [BOX32][WRAPPING] Added 32bits wrapped libxcb-res and fixes some wrapped functions from libxcb 2024-12-17 09:15:59 +01:00
xctan f65c22d329 [RV64_DYNAREC] Extended simple wrapper for more int types (#2160) 2024-12-17 08:23:51 +01:00
xctan 485959195e [CMAKE] Fixed linking issue with mold (#2159) 2024-12-17 08:19:53 +01:00
ptitSeb 28fb1bb0c0 [BOX32][WRAPPER] Silence some conversion warnings 2024-12-16 14:41:44 +01:00
ptitSeb cc12620868 [WRAPPER] Added wrapped libxcb-res with new wrapperhelper 2024-12-16 13:18:26 +01:00
ptitSeb 9c89e64691 [WRAPPER] Reworked libxcb wrapping with new wrapperhelper 2024-12-16 12:52:19 +01:00
ptitSeb d432b18d23 [BOX32][WRAPPER] Added 32bits wrapped libxcb 2024-12-16 12:41:05 +01:00
ptitSeb 98c0811525 [BOX32][WRAPPER] Prepare xcb_connection_t* align functions 2024-12-16 10:52:27 +01:00
ptitSeb 77b16ae30d [BOX32][WRAPPER] Prepare xcb_connection_t* as n on box32 2024-12-16 10:51:41 +01:00
ptitSeb f4a4bdd006 [BOX32][WRAPPER] Added 32bits wrapped libx11-xcb 2024-12-16 10:04:51 +01:00
Leslie Zhai ed7dddc3d8 [LA64_DYNAREC] Added PTEST opcode (#2158) 2024-12-16 15:26:20 +08:00
Yang Liu 4c6401c66b [RV64_DYNAREC] Fixed more regressions (#2157) 2024-12-15 20:05:37 +01:00
ptitSeb 42441c99cc [BOX32][WRAPPER] More fixes on 32bits libc wrapping 2024-12-15 17:48:49 +01:00
ptitSeb f775474062 [BOX32] Try to impove pthread_cond_t handling 2024-12-15 17:04:58 +01:00
ptitSeb c30e012e8d [BOX32][WRAPPER] Some fixes to struct msghdr alignment functions 2024-12-15 17:04:26 +01:00
ptitSeb d90522bc4e [BOX32] Rollback simplied alignment of msghdr as cmsg also needs alignment (some docs are eroneous about cmsg_len field type) 2024-12-15 16:07:25 +01:00
ptitSeb 0f7bec0d38 [BOX32][WRAPPER] Moved all function wrapped from wrappedresolv.c to libc_net32.c (still should help #2156) 2024-12-15 15:39:50 +01:00
ptitSeb 201b971ad7 [BOX32][WRAPPER] Try to fix build issue for older system (for #2156) 2024-12-15 15:36:53 +01:00
ptitSeb 1c72527dc8 [BOX32][WRAPPER] Some work on 32bits xcb_connection 2024-12-15 14:57:07 +01:00
ptitSeb 5ce3e29913 [BOX32][WRAPPER] More work on libc wrapping, and some new syscall too 2024-12-15 14:15:34 +01:00
ptitSeb 1a7cff559a [BOX32][WRAPPER] Added mtrace and muntrace to 32bits wrapped libc (for #2155) 2024-12-15 11:19:04 +01:00
Yang Liu c28b0629fa [WRAPPER] Made gtkclass.c less likely to be recompiled (#2153) 2024-12-15 10:00:22 +01:00
ptitSeb 6a3c56c131 [BOX32][WRAPPER] More fixes to libc and libX11 wrapping 2024-12-14 22:51:31 +01:00
ptitSeb d03c85da90 [BOX32][WRAPPER] More fixes to libc and X11 wrapping 2024-12-14 20:56:07 +01:00
ptitSeb 6a5d831331 [BOX32][WRAPPER] Fixes and improves libc wrapping 2024-12-14 19:43:20 +01:00
ptitSeb 2164c564f2 [DYNAREC] Revert default BOX64_DYNAREC_PAUSE to 0 (for #2152) 2024-12-14 17:05:48 +01:00
ptitSeb 2a33cf4e60 [BOX32][WRAPPER] Many fixes and improvments to X11 wrapping 2024-12-14 17:04:17 +01:00
ptitSeb 6698a844f6 [BOX32][WRAPPER] Added more 32bits wrapped functions 2024-12-13 17:50:05 +01:00
ptitSeb 1c5ccefdef [BOX32][WRAPPER] Added a few more libc 32bits wrapped functions 2024-12-13 16:54:54 +01:00
ptitSeb 64bfd06be4 [BOX32][WRAPPER] Added a few 32bits wrapped function libnsl 2024-12-13 16:46:12 +01:00
ptitSeb 5bf154195d [BOX32][WRAPPER] Added a few more 32bits wrapped libc functions 2024-12-13 16:42:21 +01:00
ptitSeb 0239305f69 [BOX32][WRAPPER] Added empty 32bits wrapped libnsl 2024-12-13 16:31:37 +01:00
ptitSeb 3ee5558c70 [BOX32][WRAPPER] Added a 32bits dummy libvdpau wrapped lib 2024-12-13 16:19:12 +01:00
ptitSeb 059dc12adc [BOX32][WRAPPER] Added 32bits wrapped libdrm with new wrapperhelper 2024-12-13 16:05:50 +01:00
ptitSeb 610c63cd15 [BOX32][WRAPPER] Added a few more libc and libresolv 32bits wrapped functions 2024-12-13 15:38:13 +01:00
ptitSeb fa3db3df11 [BOX32][WRAPPER] Added a arge batch of 32bits wrapped function to X11 and friends 2024-12-13 15:24:11 +01:00
Yang Liu 4b4c0143d9 [RV64_DYNAREC] Optimize push/pop with xtheadmemidx (#2150)
* [RV64_DYNAREC] Optimize push/pop with xtheadmemidx

* fix
2024-12-13 14:57:28 +01:00
ptitSeb fa76ce1f05 [BOX32][WRAPPER] Added 3 more 32bits wrapped function to libcairo 2024-12-13 11:16:37 +01:00
ptitSeb 59bb9c2083 [BOX32][WRAPPER] Added more SDL2 32bts wrapped functions 2024-12-13 10:51:15 +01:00
ptitSeb 689d64b62a [BOX32][WRAPPER] Added 1 more libc 32bits wrapped funciton, and fixed an existing one 2024-12-13 10:30:43 +01:00
Yang Liu f6c3386960 [RV64_DYNAREC] Fixed some TO_NAT usages (#2149) 2024-12-13 08:13:33 +01:00
Yang Liu 5055866a5a [RV64_DYNAREC] Reinitialize sew after callret (#2148) 2024-12-13 08:12:18 +01:00
xctan 9f7d0c4404 [RV64_DYNAREC] Reworked ZEROUP and freed t0 (#2147)
* [RV64_DYNAREC] Reworked ZEROUP and freed t0

* [RV64_DYNAREC] Removed the definition of xMASK
2024-12-12 19:54:08 +01:00
ptitSeb 7e5aa3e7c6 [BOX32][WRAPPER] Added a few more 32bits wrapped function to libc 2024-12-12 13:34:59 +01:00
ptitSeb c7afc0b3df [BOX32][WRAPPER] Added 32bits wrapped libXdamage 2024-12-12 13:15:43 +01:00
ptitSeb 566ff08109 [BOX32][WRAPPER] Added 32bits wrapped libcairo 2024-12-12 13:09:07 +01:00
ptitSeb 2247b61ed3 [BOX32][WRAPPER] Added a few more 32bits wrapped function to libfontconfig 2024-12-12 11:53:13 +01:00
Yang Liu 55d6971a23 [RV64_DYNAREC] New register mapping (#2139)
* [RV64_DYNAREC] New register mapping

* Fix
2024-12-12 11:51:24 +01:00
Leslie Zhai 7168167400 [LA64_DYNAREC] Added more opcodes (#2145)
* [LA64_DYNAREC] Added more opcodes

* [LA64_DYNAREC] Optimize MOVZX Gw, Eb
2024-12-12 11:23:17 +01:00
ptitSeb 7e17c862cf [WRAPPER] Checked pangoft2 wrapping with new wrapperhelper 2024-12-12 10:58:27 +01:00
ptitSeb bb60cc8568 [BOX32][WRAPPER] Added more libc and libresolv 32bits wrapped functions 2024-12-12 10:48:14 +01:00
ptitSeb 857c4600dc [BOX32][WRAPPER] Another fix for older / strict compiler (for #2141) 2024-12-11 20:11:39 +01:00
ptitSeb 88bd65998f [BOX32][WRAPPER] Added one more 32bits libX11 wrapped function 2024-12-11 18:14:28 +01:00
ptitSeb ecbd382ae4 [BOX32] added a few more libc 32bits wrapped functions 2024-12-11 18:09:44 +01:00
ptitSeb 16f63a94c3 [BOX32][WRAPPER] Try to fix some build issue on older system (for #2140) 2024-12-11 18:03:30 +01:00
ptitSeb bd7ff2efd6 [ARM64_DYNAREC] Force flags to be at least defered when priv opcode is run on safeflags=2 2024-12-11 17:56:05 +01:00
ptitSeb ed21342995 [DYNAREC] Small improvments on flags when end of block if trigger early 2024-12-11 17:55:13 +01:00
ptitSeb 4c238f0e17 [ARM64_DYNAREC] Better hadnling of flags on btx opcode familly ([COSIM] and improved undefined flags when running with cosim) 2024-12-11 17:54:17 +01:00
ptitSeb 7c000adb87 [INTERPRETER][COSIM] Better flags for btx opcode familly when running cosim 2024-12-11 17:53:17 +01:00
ptitSeb 2d4f073925 [COSIM] Try to get more stable result on x87 stacks by unwinding status before calling cosim 2024-12-11 11:39:03 +01:00
ptitSeb a25aab1426 [BOX32] Added a workaround for older system (should help #2138) 2024-12-11 10:10:02 +01:00
Leslie Zhai 54f593fa75 [WRAPPER] Added libcairo.so.2 as one of NEEDED_LIBS for gtk3 (#2136) (#2137) 2024-12-11 09:23:17 +01:00
Leslie Zhai 054de8e83f [LA64] SIGRTMAX is 127 for ABI 1.0 (#2134)
* [LA64] SIGRTMAX is 127 for ABI 1.0

* [LA64] Added LARCH64_ABI_1 CMake option

* [LA64] Change MAX_SIGNAL to 128 for ABI 1.0
2024-12-11 08:10:58 +01:00
ptitSeb e6d1bf78a6 [BOX32][WRAPPER] Added 1 more 32bits libX11 wrapped function 2024-12-10 18:19:48 +01:00
ptitSeb b4b8617a92 [BOX32][WRAPPER] Fixed time signature (now steamcmd connect) 2024-12-10 18:06:10 +01:00
ptitSeb 20bad4e126 [BOX32][WRAPER] Improved pthread_mutex handling, and better trace for mutex wrapped on LOG_DEBUG 2024-12-10 18:05:14 +01:00
ptitSeb 3650609975 [BOX32][TRACE] Improved trace for a few libc calls 2024-12-10 18:03:16 +01:00
ptitSeb fe3b30ccbb [RCFILE] Added 1 more profile 2024-12-10 15:25:33 +01:00
ptitSeb ccae82e1f5 [DOC] Small improment on USAGE.md 2024-12-10 15:25:33 +01:00
Leslie ZhaiandYang Liu f1addb8b28 [LA64_DYNAREC] Added more 660F opcodes (#2127)
* [LA64_DYNAREC] Added more 660F opcodes

* [LA64_DYNAREC] Change VREPLGR2VR_D to VXOR_V

* [LA64_DYNAREC] Optimize PMULHRSW

Co-authored-by: Yang Liu <[email protected]>

---------

Co-authored-by: Yang Liu <[email protected]>
2024-12-10 10:48:24 +01:00
ptitSeb 96f5108a37 [INTERPRETER] Added 64bits 67 A1 opcode ([ARM64_DYNAREC] Too) 2024-12-09 13:16:13 +01:00
ptitSeb 3eeb10c0a6 [BOX32][WRAPPER] Better wrapping for shmat 2024-12-09 13:06:50 +01:00
ptitSeb ce3d2afad2 Change log level to INFO for Wine prereserve issues (for #2123) 2024-12-08 16:12:15 +01:00
ptitSeb bdee719767 [BOX32] Improved mutex handling, again 2024-12-08 14:51:29 +01:00
ptitSeb 42263e0be9 [BOX32][WRAPPER] Fixed some more typo on Xcursor wrapping (might help #2109) 2024-12-08 12:03:54 +01:00
ptitSeb ca08012bbf [BOX32][WRAPPER] Added a couple of 32bits wrapped functions to libc 2024-12-08 09:41:31 +01:00
Jim Huang ca47ee273e [CORE] Refine runtime messages (#2125)
This commit addresses inconsistent runtime messages by correcting
grammatical errors and typos, and properly handling singular and plural
forms.
2024-12-07 17:07:14 +01:00
Leslie Zhai eb299f500b [LA64_DYNAREC] Added AES opcodes (#2122)
* [LA64_DYNAREC] Added AES opcodes

* [LA64_DYNAREC] Use LSX instruction instead
2024-12-07 09:58:20 +01:00
ptitSeb a25b50d3aa Start of a new dev. cycle 2024-12-07 09:50:11 +01:00
ptitSeb b735a8663e Update README.md 2024-12-06 16:19:58 +01:00
468 changed files with 46296 additions and 14207 deletions

No files matched your search

+1 -1
View File
@@ -12,7 +12,7 @@ MaxEmptyLinesToKeep: 2
IndentCaseLabels: true
AlignConsecutiveMacros: true
WhitespaceSensitiveMacros: ['QUOTE']
IfMacros: ['IFX', 'IFXORNAT', 'IFX2', 'IFXA', 'IFX_PENDOR0', 'IFXX', 'IFX2X', 'IFXN', 'UFLAG_IF', 'PASS2IF']
IfMacros: ['IFX', 'IFXORNAT', 'IFX2', 'IFXA', 'IFX_PENDOR0', 'IFXX', 'IFX2X', 'IFXN', 'UFLAG_IF', 'PASS2IF', 'IF_UNALIGNED', 'IF_ALIGNED']
UseTab: Never
IndentPPDirectives: None
---
+47 -11
View File
@@ -29,7 +29,7 @@ jobs:
matrix:
platform: [X64, RISCV, RK3588, ARM64, ANDROID, TERMUX, LARCH64, ANDROID_GLIBC]
type: [Release, Trace, StaticBuild, Box32]
os: [ubuntu-latest]
os: [ubuntu-latest, ubuntu-22.04-arm]
exclude:
- platform: ANDROID
type: StaticBuild
@@ -41,6 +41,22 @@ jobs:
type: Box32
- platform: TERMUX
type: Box32
- platform: X64
os: ubuntu-22.04-arm
- platform: RISCV
os: ubuntu-22.04-arm
- platform: RK3588
os: ubuntu-latest
- platform: ARM64
os: ubuntu-latest
- platform: ANDROID
os: ubuntu-22.04-arm
- platform: TERMUX
os: ubuntu-22.04-arm
- platform: LARCH64
os: ubuntu-22.04-arm
- platform: ANDROID_GLIBC
os: ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
@@ -53,6 +69,7 @@ jobs:
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' ]]; then
sudo apt-get -y install git cmake make python3 patchelf
if [[ ${{ matrix.platform }} == 'ANDROID' || ${{ matrix.platform }} == 'TERMUX' ]]; then
sudo apt-get -y install p7zip
wget https://dl.google.com/android/repository/android-ndk-r26b-linux.zip
unzip android-ndk-r26b-linux.zip
echo "BOX64_COMPILER=$PWD/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV
@@ -63,7 +80,7 @@ jobs:
sudo chmod 755 -R /system
elif [[ ${{ matrix.platform }} == 'ANDROID_GLIBC' ]]; then
sudo apt-get -y install git gcc-aarch64-linux-gnu
echo "BOX64_PLATFORM_MARCRO=-DARM64=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV
echo "BOX64_PLATFORM_MARCRO=-DARM64=1 -DWINLATOR_GLIBC=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
else
sudo apt-get -y install git gcc-aarch64-linux-gnu
@@ -71,7 +88,6 @@ jobs:
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
fi
if [[ ${{ matrix.platform }} == 'TERMUX' ]]; then
sudo apt-get -y install p7zip
wget https://mirrors.utermux.dev/termux/termux-main/pool/main/liba/libandroid-sysv-semaphore/libandroid-sysv-semaphore_0.1_aarch64.deb
7z x libandroid-sysv-semaphore_0.1_aarch64.deb
tar -xf data.tar.xz
@@ -92,7 +108,7 @@ jobs:
elif [[ ${{ matrix.platform }} == 'RISCV' ]]; then
echo BOX64_PLATFORM_MARCRO="-DRV64=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=riscv64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-riscv64-linux-gnu cmake make python3 ninja-build
sudo apt-get -y install git gcc-riscv64-linux-gnu cmake make python3 ninja-build libglib2.0-dev
elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then
sudo mkdir /usr/local/larch
wget -O- -q https://github.com/loongson/build-tools/releases/download/2023.08.08/CLFS-loongarch64-8.1-x86_64-cross-tools-gcc-glibc.tar.xz | sudo tar -C /usr/local/larch --strip-components=1 --xz -xf -
@@ -241,13 +257,6 @@ jobs:
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
elif [[ ${{ matrix.platform }} != 'X64' ]]; then # AArch64
export INTERPRETER=qemu-aarch64-static
export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim
else
ctest -j$(nproc)
fi
@@ -256,6 +265,9 @@ jobs:
id: git-info
run: echo "SHORT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
- name: "Get Box64 Version"
run: echo "BOX64_VERSION=$(cat src/box64version.h | grep BOX64_MAJOR | cut -d " " -f 3).$(cat src/box64version.h | grep BOX64_MINOR | cut -d " " -f 3).$(cat src/box64version.h | grep BOX64_REVISION | cut -d " " -f 3)" >> $GITHUB_ENV
- name: "Packaging WCP file for Winlator"
if: matrix.platform == 'ANDROID_GLIBC' && matrix.type != 'StaticBuild'
run: |
@@ -277,6 +289,23 @@ jobs:
patchelf --set-interpreter /data/data/com.winlator/files/imagefs/usr/lib/ld-linux-aarch64.so.1 ./box64
tar --zstd -cf box64-latest.wcp box64 profile.json
- name: "Package Rat File for MiceWine"
if: matrix.platform == 'ANDROID' && matrix.type != 'StaticBuild'
run: |
cd build
mkdir -p files/usr/bin
cp box64 files/usr/bin
echo "name=Box64 (CI Build)" > pkg-header
echo "category=Box64" >> pkg-header
echo "version=${BOX64_VERSION}-${SHORT_COMMIT}" >> pkg-header
echo "architecture=aarch64" >> pkg-header
echo "vkDriverLib=" >> pkg-header
7z -tzip -mx=5 a box64-latest.rat files pkg-header
- name: "Upload Artifact"
uses: actions/upload-artifact@v4
with:
@@ -289,3 +318,10 @@ jobs:
with:
name: box64-latest-${{ matrix.type }}-wcp
path: build/box64-latest.wcp
- name: "Upload Rat File"
if: matrix.platform == 'ANDROID' && matrix.type != 'StaticBuild'
uses: actions/upload-artifact@v4
with:
name: box64-MiceWine-${{ matrix.type }}
path: build/box64-latest.rat
+14
View File
@@ -73,3 +73,17 @@ backup/
# macOS
.DS_Store
# Archives
*.7z
*.deb
*.eopkg
*.gz
*.rar
*.rpm
*.tar*
*.xbps
*.xz
*.zip
*.zst
*.zstd
+70 -13
View File
@@ -30,9 +30,10 @@ 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(WINLATOR_GLIBC "Set to ON if targeting an Android device with Winlator Glibc" ${WINLATOR_GLIBC})
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(SAVE_MEM "Set to ON to build dynarec with some slower memory saving optimizations" ${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})
@@ -41,6 +42,8 @@ option(CI "Set to ON if running in CI" ${CI})
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
option(BOX32 "Set to ON to add Linux 32bits support (experimental, do not use)" ${BOX32})
option(BOX32_BINFMT "Also setup binfmt integration for box32" ${BOX32_BINFMT})
option(LARCH64_ABI_1 "Set to ON if building for Loongarch64 ABI 1.0 system" ${LARCH64_ABI_1})
option(GDBJIT "Set to ON to enable GDB JIT support" ${GDBJIT})
if(TERMUX)
set(TERMUX_PATH "/data/data/com.termux/files")
@@ -52,6 +55,10 @@ if(LARCH64)
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC ON CACHE BOOL "")
if(LARCH64_ABI_1)
message(STATUS "Build for Loongarch64 ABI 1.0 system")
add_definitions(-DLA64_ABI_1)
endif()
endif()
if(RV64)
set(LD80BITS OFF CACHE BOOL "")
@@ -86,10 +93,15 @@ if(SW64)
endif()
if(ANDROID)
set(TERMUX_PATH "/data/data/com.termux/files")
set(NOLOADADDR ON CACHE BOOL "")
#set(NOLOADADDR ON CACHE BOOL "") #no need to force this setting it seems now
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
if(GDBJIT)
message(STATUS "Build with GDBJIT support")
add_definitions(-DGDBJIT)
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
@@ -245,6 +257,9 @@ endif()
if(TERMUX)
add_definitions(-DTERMUX)
endif()
if(WINLATOR_GLIBC)
add_definitions(-DWINLATOR_GLIBC)
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
@@ -360,6 +375,7 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
"${BOX64_ROOT}/src/emu/x64compstrings.c"
"${BOX64_ROOT}/src/emu/x64emu.c"
"${BOX64_ROOT}/src/emu/x64printer.c"
"${BOX64_ROOT}/src/emu/x64int3.c"
"${BOX64_ROOT}/src/emu/x87emu_private.c"
"${BOX64_ROOT}/src/emu/x64primop.c"
@@ -381,11 +397,12 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/tools/box64stack.c"
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
"${BOX64_ROOT}/src/tools/gdbjit.c"
"${BOX64_ROOT}/src/tools/my_cpuid.c"
"${BOX64_ROOT}/src/tools/fileutils.c"
"${BOX64_ROOT}/src/tools/pathcoll.c"
"${BOX64_ROOT}/src/tools/rbtree.c"
"${BOX64_ROOT}/src/tools/rcfile.c"
"${BOX64_ROOT}/src/tools/env.c"
"${BOX64_ROOT}/src/tools/wine_tools.c"
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
)
@@ -411,6 +428,7 @@ if(BOX32)
"${BOX64_ROOT}/src/librarian/globalsymbols32.c"
"${BOX64_ROOT}/src/libtools/myalign32.c"
"${BOX64_ROOT}/src/libtools/myalign64_32.c"
"${BOX64_ROOT}/src/libtools/myalignxcb32.c"
"${BOX64_ROOT}/src/libtools/signal32.c"
"${BOX64_ROOT}/src/libtools/threads32.c"
"${BOX64_ROOT}/src/libtools/libc_net32.c"
@@ -620,6 +638,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrender.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbrenderutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbres.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshape.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbshm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbsync.c"
@@ -660,6 +679,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX64_ROOT}/src/wrapped/wrappedpam.c"
"${BOX64_ROOT}/src/wrapped/wrappedpcap.c"
"${BOX64_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX64_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
@@ -767,7 +787,7 @@ if(NOT CI)
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" "STATICBUILD" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "STATICBUILD" "LA64" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
@@ -816,6 +836,7 @@ if(BOX32)
"${BOX64_ROOT}/src/wrapped32/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped32/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxdamage.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxext.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxfixes.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxrender.c"
@@ -827,10 +848,19 @@ if(BOX32)
"${BOX64_ROOT}/src/wrapped32/wrappedlibxxf86vm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedxinerama.c"
"${BOX64_ROOT}/src/wrapped32/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcbres.c"
"${BOX64_ROOT}/src/wrapped32/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped32/wrappedudev1.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibuuid.c"
"${BOX64_ROOT}/src/wrapped32/wrappedgnutls.c"
"${BOX64_ROOT}/src/wrapped32/wrappedtcmallocminimal.c"
"${BOX64_ROOT}/src/wrapped32/wrappedcairo.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibdrm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibvdpau.c"
"${BOX64_ROOT}/src/wrapped32/wrappednsl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibcups.c"
)
endif()
string(REPLACE ".c" "_private.h" MODROOT ${BOX64_ROOT})
@@ -849,7 +879,7 @@ if(BOX32)
OUTPUT "${BOX64_ROOT}/src/wrapped32/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers_32.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "STATICBUILD" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "WINLATOR_GLIBC" "STATICBUILD" "--"
${WRAPPEDS32_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers_32.py"
DEPENDS ${WRAPPEDS32} ${WRAPPEDS32_HEAD}
@@ -877,6 +907,7 @@ if(ARM_DYNAREC)
${DYNAREC_SRC}
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_arch.c"
"${BOX64_ROOT}/src/dynarec/arm64/arm64_immenc.c"
"${BOX64_ROOT}/src/dynarec/arm64/arm64_printer.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_jmpnext.c"
@@ -937,6 +968,7 @@ if(RV64_DYNAREC)
${DYNAREC_SRC}
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_functions.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_arch.c"
"${BOX64_ROOT}/src/dynarec/rv64/rv64_printer.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_jmpnext.c"
"${BOX64_ROOT}/src/rv64detect.c"
@@ -1016,14 +1048,21 @@ if(LARCH64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_64.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_6664.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_660f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f0.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_67.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f0.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f20f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f30f.c"
)
endif()
if(GDBJIT)
set(GDBJITREADER "${BOX64_ROOT}/gdbjit/reader.c")
endif()
if(DYNAREC)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped/generated/wrapper.h"
@@ -1067,6 +1106,10 @@ if(DYNAREC)
$<TARGET_OBJECTS:native_pass3>
$<TARGET_OBJECTS:test_interpreter>
)
if(GDBJIT)
add_library(box64gdbjitreader SHARED ${GDBJITREADER})
endif()
endif()
# creates git_head.h
@@ -1105,7 +1148,7 @@ 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 -lutil -Wl,--as-needed -pthread")
set_property(TARGET ${BOX64} APPEND_STRING PROPERTY LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -lutil -Wl,--as-needed -pthread ")
endif()
endif()
if(DYNAREC)
@@ -1116,9 +1159,9 @@ target_link_libraries(${BOX64} interpreter)
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-no-pie -Wl,--image-base=${BOX64_ELF_ADDRESS}")
set_property(TARGET ${BOX64} APPEND_STRING PROPERTY LINK_FLAGS "-no-pie -Wl,--image-base=${BOX64_ELF_ADDRESS} ")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
set_property(TARGET ${BOX64} APPEND_STRING PROPERTY LINK_FLAGS "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS} ")
endif()
endif()
else()
@@ -1126,7 +1169,7 @@ else()
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
if(WITH_MOLD) # --image-base requires -no-pie in mold!
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-no-pie -lm")
set_property(TARGET ${BOX64} APPEND_STRING PROPERTY LINK_FLAGS "-no-pie -lm ")
endif()
target_link_options(${BOX64} PUBLIC LINKER:--image-base=${BOX64_ELF_ADDRESS})
else()
@@ -1156,6 +1199,9 @@ if(NOT _x86 AND NOT _x86_64)
install(PROGRAMS ${CMAKE_SOURCE_DIR}/tests/box64-bash DESTINATION ${TERMUX_PATH}/usr/bin)
endif()
endif()
if (GDBJIT)
install(TARGETS box64gdbjitreader RUNTIME DESTINATION lib)
endif()
if(NOT NO_CONF_INSTALL)
configure_file(system/box64.conf.cmake system/box64.conf)
if(NOT TERMUX)
@@ -1462,6 +1508,17 @@ add_test(avx_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${B
set_tests_properties(avx_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0;BOX64_AVX=2")
add_test(fpu_rounding ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test31 -D TEST_OUTPUT=tmpfile31.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref31.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(ARM_DYNAREC)
set_tests_properties(fpu_rounding PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0;BOX64_DYNAREC_TEST=1")
else()
set_tests_properties(fpu_rounding PROPERTIES ENVIRONMENT "BOX64_DYNAREC=0")
endif()
else()
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
@@ -1741,8 +1798,8 @@ if(BOX32)
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME multiple_dlopen_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test21 -D TEST_OUTPUT=tmpfile32_21.txt
add_test(NAME multiple_dlopen_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test21 -D TEST_OUTPUT=tmpfile32_21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
+2 -1
View File
@@ -34,6 +34,7 @@ Box64 offers environment variables to control its behavior. For details, see [Us
## 🚀 Compiling and Installation
- [Compilation Instructions](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md)
- [Bundle x86 Libraries](https://github.com/ptitSeb/box64/blob/main/docs/BUNDLE-X86-LIBS.md)
- [Wine Installation for Box64](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
---
@@ -50,7 +51,7 @@ Box64 requires 64-bit libraries on the host system, as it directly translates x8
**Notes**
1. Box32 mode is in the making, which aims to support 32-bit binaries on Box64, you can enable it at build time, but do not expect everything to work. There is actually a few things that works, amny that don't. It's a known issue, no need to create tickets about it for now.
1. Box32 mode is in the making, which aims to support 32-bit binaries on Box64, you can enable it at build time, but do not expect everything to work. There is actually a few things that work, many that don't. It's a known issue, no need to create tickets about it for now.
2. Some installers may default to x86 on 64-bit host OSes, causing compatibility issues. Workaround: Use a fake `uname` that returns "x86_64" for `-m`.
---
+38
View File
@@ -0,0 +1,38 @@
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/bluez-libs-5.72-2.el9.i686.rpm,af1aba8e6fa5ccf33032d58a3acc59368c07d532293396db205fb9a4bc1241ae
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/bluez-libs-5.72-2.el9.x86_64.rpm,49c273813b4616240acdae8dae893192658c7541482f9bbb2c46dfe19b61877d
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.i686.rpm,75f808f0f5f93aceb4e477aa5f302edbed07a605a0644f0ea929d4ea609e36a0
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.x86_64.rpm,b4763ca410f8479b2775efb55ba09e6722948af7526180a56309e3e090c27010
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gmp-6.2.0-13.el9.i686.rpm,fe352f7d197ebdf2c92bbd6e548f9f6b7ac9e69e7a9d6c9861a6274482e79d73
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gmp-6.2.0-13.el9.x86_64.rpm,babe0b1385e723476a216d5f4b72453e031c3d683b19344786c2bddf7203cb04
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.i686.rpm,64cf0b0136d3f9b80b07ce2d4b8ce6a4ab86617e8ef9baf560bdfa5edef825ea
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.x86_64.rpm,16c48c504fe62f8e19cac7c6442d3e08bba487f610c2f533116dac32357cda86
https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_amd64.deb,d5ae55e3a9838d12358530cd03218cc0d18127a84e9cfc73bdf79dacd40b25e4
https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_i386.deb,625e5189304d4d3bfb27cb821e257816c5ce761b1696b5da5ca4fa1035c48463
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.i686.rpm,686ac26afe2073a3607f26fd1592a8ccd9b78f6eec6e872528634b43c4e04dd7
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.x86_64.rpm,9a2bdc6807b22ffb6294b30dcc13e20198abe5facaeefcf1bfacec3e1013e3c2
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm,d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm,d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libidn2-2.3.0-7.el9.i686.rpm,4458e2d416b5e6714ec664c4f88791eee7d1e707026a5854d948a6159911465b
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libidn2-2.3.0-7.el9.x86_64.rpm,c3ff43237c05258ee0dd77c28540fc8d0d824f1567b115ddfd555b78d2ee0e7a
https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-32bit-3.0.3-21-1-x86_64.eopkg,5624990281f6520026aa2252c711f02d4916099aeac63accc83bd2135b9d3220
https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-3.0.3-21-1-x86_64.eopkg,c92f19d446b4c2450306f13b1a908f2552400da09301996fe349fee243d964d2
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.i686.rpm,9e4ff6fa0251c5357ae8f648b3e396d0043d5b3f2fb28d23325f5bd592c67aee
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.x86_64.rpm,83b4b333e335654674032d1cda4d7deb328b5a409f95e3952c3dc482b684fd8f
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libpng-1.6.37-12.el9.i686.rpm,66bf967e84f0d8e7a0059f2b7dda33482ff5e4fe088d0e3bc86dc54e6c7c97be
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libpng-1.6.37-12.el9.x86_64.rpm,ebb3e927dfafa0b199e00e2bef4c10c85fc82a70c359faf9aeb599eda70bfa5e
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm,ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm,d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libtasn1-4.16.0-8.el9_1.i686.rpm,9cbd11277e89bd0d4a80900bee01ca71b0c582c9cb5744f5035135b2ed907c85
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libtasn1-4.16.0-8.el9_1.x86_64.rpm,2dd3a1ad2785df642cb03dfed6dfbeec929ff8b14e52e61272ca7e89f86ba3cd
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.i686.rpm,2155c688b516ab359d0c47be6d73e51d3c65f199ed5591f7bb7ce6d5d9799977
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.x86_64.rpm,25ab4a8ad997b450b4a34a777f5a0678eea72ca1665944a7a461ac63de4b25bf
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libunistring-0.9.10-15.el9.i686.rpm,792600a879fbd94ce4bf249713b0cb3a166c147cfad397e8a15e6b4f01c75997
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libunistring-0.9.10-15.el9.x86_64.rpm,d2f86fbee729a4900a433a6c52a3cb95d9b52b1d79c9e719ee3ef509813eb6d9
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.i686.rpm,e38c5185fea611330ea253db020315dd564507bf95c48a81dbe7db186ce4214b
https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.x86_64.rpm,3c340337a073975636d198a282503f32a54bf85fb5345522a2c22e530b8d6c9e
https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.i686.rpm,13bc8758355c3ec885f414e0e86efad29a7fe82c0999cdb3754d666949c06cc5
https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.x86_64.rpm,fb4aaa22b2e2f2fc0c451b87ac464e8746d240397d64e79f6bfd38f4e9128a5a
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/nettle-3.9.1-1.el9.i686.rpm,e5610fe3b25cfca1616440e1a8a7489fd37b0852f182fdda87ab8e196d981970
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/nettle-3.9.1-1.el9.x86_64.rpm,9786b6610d17aa495fb640ba6d046bf73704915b82d12e6d8339090ff4891de5
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/p11-kit-0.25.3-3.el9_5.i686.rpm,abe4ab924b405c236eaf3fa067fed50ac66d15d0ef42c782a745788c1a9c5b91
https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/p11-kit-0.25.3-3.el9_5.x86_64.rpm,0e1bd97e697a9fa3b4e508b945cf352b73b06e4e8218c14ac5fb912b0022c646
1 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/bluez-libs-5.72-2.el9.i686.rpm af1aba8e6fa5ccf33032d58a3acc59368c07d532293396db205fb9a4bc1241ae
2 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/bluez-libs-5.72-2.el9.x86_64.rpm 49c273813b4616240acdae8dae893192658c7541482f9bbb2c46dfe19b61877d
3 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.i686.rpm 75f808f0f5f93aceb4e477aa5f302edbed07a605a0644f0ea929d4ea609e36a0
4 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/fribidi-1.0.10-6.el9.2.x86_64.rpm b4763ca410f8479b2775efb55ba09e6722948af7526180a56309e3e090c27010
5 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gmp-6.2.0-13.el9.i686.rpm fe352f7d197ebdf2c92bbd6e548f9f6b7ac9e69e7a9d6c9861a6274482e79d73
6 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gmp-6.2.0-13.el9.x86_64.rpm babe0b1385e723476a216d5f4b72453e031c3d683b19344786c2bddf7203cb04
7 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.i686.rpm 64cf0b0136d3f9b80b07ce2d4b8ce6a4ab86617e8ef9baf560bdfa5edef825ea
8 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/gnutls-3.8.3-4.el9_4.x86_64.rpm 16c48c504fe62f8e19cac7c6442d3e08bba487f610c2f533116dac32357cda86
9 https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_amd64.deb d5ae55e3a9838d12358530cd03218cc0d18127a84e9cfc73bdf79dacd40b25e4
10 https://archive.debian.org/debian/pool/main/c/curl/libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_i386.deb 625e5189304d4d3bfb27cb821e257816c5ce761b1696b5da5ca4fa1035c48463
11 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.i686.rpm 686ac26afe2073a3607f26fd1592a8ccd9b78f6eec6e872528634b43c4e04dd7
12 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libgomp-11.5.0-2.el9.alma.1.x86_64.rpm 9a2bdc6807b22ffb6294b30dcc13e20198abe5facaeefcf1bfacec3e1013e3c2
13 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.i686.rpm d9c44bb34c990fdcc6987feefacfc9e1e7997ca25f1e0a59c9adc9c16f2266d1
14 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libICE-1.0.10-8.el9.x86_64.rpm d0b867203384942985c3c4ad6fc9ec0000fcc9965408451a6cdef8df06a3833c
15 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libidn2-2.3.0-7.el9.i686.rpm 4458e2d416b5e6714ec664c4f88791eee7d1e707026a5854d948a6159911465b
16 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libidn2-2.3.0-7.el9.x86_64.rpm c3ff43237c05258ee0dd77c28540fc8d0d824f1567b115ddfd555b78d2ee0e7a
17 https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-32bit-3.0.3-21-1-x86_64.eopkg 5624990281f6520026aa2252c711f02d4916099aeac63accc83bd2135b9d3220
18 https://cdn.getsol.us/repo/shannon/libj/libjpeg-turbo/libjpeg-turbo-3.0.3-21-1-x86_64.eopkg c92f19d446b4c2450306f13b1a908f2552400da09301996fe349fee243d964d2
19 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.i686.rpm 9e4ff6fa0251c5357ae8f648b3e396d0043d5b3f2fb28d23325f5bd592c67aee
20 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libogg-1.3.4-6.el9.x86_64.rpm 83b4b333e335654674032d1cda4d7deb328b5a409f95e3952c3dc482b684fd8f
21 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libpng-1.6.37-12.el9.i686.rpm 66bf967e84f0d8e7a0059f2b7dda33482ff5e4fe088d0e3bc86dc54e6c7c97be
22 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libpng-1.6.37-12.el9.x86_64.rpm ebb3e927dfafa0b199e00e2bef4c10c85fc82a70c359faf9aeb599eda70bfa5e
23 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.i686.rpm ec68b3def828ba442248f3cff495f42c4af3dd58f38c8daad07dfddc109d999a
24 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libSM-1.2.3-10.el9.x86_64.rpm d00318843a50138829b470a97b8db1a00723b10bca23c16a8386d9ab670e4c64
25 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libtasn1-4.16.0-8.el9_1.i686.rpm 9cbd11277e89bd0d4a80900bee01ca71b0c582c9cb5744f5035135b2ed907c85
26 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libtasn1-4.16.0-8.el9_1.x86_64.rpm 2dd3a1ad2785df642cb03dfed6dfbeec929ff8b14e52e61272ca7e89f86ba3cd
27 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.i686.rpm 2155c688b516ab359d0c47be6d73e51d3c65f199ed5591f7bb7ce6d5d9799977
28 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libtheora-1.1.1-31.el9.x86_64.rpm 25ab4a8ad997b450b4a34a777f5a0678eea72ca1665944a7a461ac63de4b25bf
29 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libunistring-0.9.10-15.el9.i686.rpm 792600a879fbd94ce4bf249713b0cb3a166c147cfad397e8a15e6b4f01c75997
30 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/libunistring-0.9.10-15.el9.x86_64.rpm d2f86fbee729a4900a433a6c52a3cb95d9b52b1d79c9e719ee3ef509813eb6d9
31 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.i686.rpm e38c5185fea611330ea253db020315dd564507bf95c48a81dbe7db186ce4214b
32 https://repo.almalinux.org/almalinux/9.5/AppStream/x86_64/os/Packages/libvorbis-1.3.7-5.el9.x86_64.rpm 3c340337a073975636d198a282503f32a54bf85fb5345522a2c22e530b8d6c9e
33 https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.i686.rpm 13bc8758355c3ec885f414e0e86efad29a7fe82c0999cdb3754d666949c06cc5
34 https://repo.almalinux.org/almalinux/8.10/BaseOS/x86_64/os/Packages/nettle-3.4.1-7.el8.x86_64.rpm fb4aaa22b2e2f2fc0c451b87ac464e8746d240397d64e79f6bfd38f4e9128a5a
35 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/nettle-3.9.1-1.el9.i686.rpm e5610fe3b25cfca1616440e1a8a7489fd37b0852f182fdda87ab8e196d981970
36 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/nettle-3.9.1-1.el9.x86_64.rpm 9786b6610d17aa495fb640ba6d046bf73704915b82d12e6d8339090ff4891de5
37 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/p11-kit-0.25.3-3.el9_5.i686.rpm abe4ab924b405c236eaf3fa067fed50ac66d15d0ef42c782a745788c1a9c5b91
38 https://repo.almalinux.org/almalinux/9.5/BaseOS/x86_64/os/Packages/p11-kit-0.25.3-3.el9_5.x86_64.rpm 0e1bd97e697a9fa3b4e508b945cf352b73b06e4e8218c14ac5fb912b0022c646
+93
View File
@@ -0,0 +1,93 @@
#!/bin/bash
set -x
extract_pkg_auto() {
# Example x86_64 package name: libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_amd64.deb
# Example x86 package name: libcurl3-gnutls_7.74.0-1.3+deb11u7~bpo11+1_i386.deb
if echo "${1}" | grep -q -P ".deb$"; then
echo "DEB (Debian) package detected."
ar x "$(basename "${1}")"
tar --extract --file data.tar*
# Example x86_64 package name: curl-gnutls-8.1.2-44-1-x86_64.eopkg
# Example x86 package name: curl-gnutls-32bit-8.1.2-44-1-x86_64.eopkg
elif echo "${1}" | grep -q -P ".eopkg$"; then
echo "EOPKG (Solus Linux) package detected."
unzip -o "$(basename "${1}")"
tar --extract --file install.tar.xz
# Example x86_64 package name: bluez-libs-5.63-1.el8.x86_64.rpm
# Example x86 package name: bluez-libs-5.63-1.el8.i686.rpm
elif echo "${1}" | grep -q -P ".rpm$"; then
echo "RPM (Fedora) detected."
rpm2cpio "$(basename "${1}")" | cpio -idmv
# Example x86_64 package name: libjpeg-turbo-3.0.1_1.x86_64.xbps
# Example x86 package name: libjpeg-turbo-32bit-3.0.1_1.x86_64.xbps
elif echo "${1}" | grep -q -P ".xbps$"; then
echo "XBPS (Void Linux) package detected."
tar --extract --file "$(basename "${1}")"
else
echo "Unknown package."
echo "Unsupported package type."
exit 1
fi
}
box64_dir=$(pwd)
dir_tmp_local="$(mktemp --directory)"
cd "${dir_tmp_local}"
for line in $(cat "${box64_dir}/box64-bundle-x86-libs.csv");
do pkg_url="$(echo "${line}" | cut -d, -f1)"
pkg_checksum_expected="$(echo "${line}" | cut -d, -f2)"
pkg_name="$(basename "${pkg_url}")"
curl --silent --location --remote-name "${pkg_url}"
pkg_checksum_actual="$(sha256sum ${pkg_name} | awk '{print $1}')"
if [[ "${pkg_checksum_expected}" -ne "${pkg_checksum_actual}" ]];
then echo "Invalid checksum for ${pkg_name}"
echo "Expected: ${pkg_checksum_expected}"
echo "Actual: ${pkg_checksum_actual}"
exit 1
fi
extract_pkg_auto "${pkg_name}"
done
# Start preperation of bundles.
mkdir -p \
"${dir_tmp_local}/bundle-libs/usr/lib/box64-i386-linux-gnu" \
"${dir_tmp_local}/bundle-libs/usr/lib/box64-x86_64-linux-gnu" \
"${dir_tmp_local}/bundle-pkgs" \
# Copy Debian family libraries.
cp --archive "${dir_tmp_local}"/usr/lib/i386-linux-gnu/*.so* "${dir_tmp_local}/bundle-libs/usr/lib/box64-i386-linux-gnu"
cp --archive "${dir_tmp_local}"/usr/lib/x86_64-linux-gnu/*.so* "${dir_tmp_local}/bundle-libs/usr/lib/box64-x86_64-linux-gnu"
# Copy Fedora family libraries.
cp --archive "${dir_tmp_local}"/usr/lib/*.so* "${dir_tmp_local}/bundle-libs/usr/lib/box64-i386-linux-gnu"
cp --archive "${dir_tmp_local}"/usr/lib64/*.so* "${dir_tmp_local}/bundle-libs/usr/lib/box64-x86_64-linux-gnu"
# Copy Solus and Void Linux family libraries.
cp --archive "${dir_tmp_local}"/usr/lib32/*.so* "${dir_tmp_local}/bundle-libs/usr/lib/box64-i386-linux-gnu"
# Create "<LIBRARY_FILE>.so" symlinks.
for dir_lib in \
"${dir_tmp_local}/bundle-libs/usr/lib/box64-i386-linux-gnu" \
"${dir_tmp_local}/bundle-libs/usr/lib/box64-x86_64-linux-gnu"
# If two or more libraries of the same name exist, this will symlink the oldest version.
# Pipe this into a reverse sort `| sort -r` to symlink the newest version.
do for lib in $(ls -1 "${dir_lib}")
# Example output: libbluetooth.so
do lib_base="$(echo "${lib}" | cut -d. -f1,2)"
if ! ls "${dir_lib}/${lib_base}" 2> /dev/null
then ln -s "${lib}" "${dir_lib}/${lib_base}"
fi
done
done
mv "${dir_tmp_local}"/*.deb "${dir_tmp_local}/bundle-pkgs/"
mv "${dir_tmp_local}"/*.eopkg "${dir_tmp_local}/bundle-pkgs/"
mv "${dir_tmp_local}"/*.rpm "${dir_tmp_local}/bundle-pkgs/"
tar --directory "${dir_tmp_local}/bundle-libs" --create --file "${box64_dir}/box64-bundle-x86-libs.tar.gz" .
tar --directory "${dir_tmp_local}/bundle-pkgs" --create --file "${box64_dir}/box64-bundle-x86-pkgs.tar.gz" .
# Clean up.
cd -
rm -r -f "${dir_tmp_local}"
+10
View File
@@ -1,3 +1,13 @@
box64 (0.3.4) unstable; urgency=low
* This version is Faster and more compatible
* => The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet)
* => On ARM64, Box64 now support more DRM types than before.
* => BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now.
* Please check CHAGELOG.md for more details
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2025 10:30:33 -0100
box64 (0.3.2) unstable; urgency=low
* Introduced Box32 to run 32bits apps on 64bits OS
+2 -1
View File
@@ -21,4 +21,5 @@ override_dh_shlibdeps:
--exclude=libcrypto.so.1.1 \
--exclude=libmbedx509.so.1 \
--exclude=libcrypto.so.1.0.0 \
--exclude=libssl.1.0.0
--exclude=libssl.so.1.0.0 \
--exclude=box64-bash
+66
View File
@@ -0,0 +1,66 @@
# Bundling x86 Libraries
The script `box64-bundle-x86-libs.sh` is provided to download, extract, and re-bundle x86_64 and x86 libraries for use with Box64/Box32 and Box86. These libraries improve Box emulation. This bundle provides a much smaller size compared to using a full root file system of an operating system.
## Usage
### Administrator
Install required dependencies for the bundle script.
- Debian
```
sudo apt-get update
sudo apt-get install coreutils curl binutils rpm2cpio tar zstd
```
Run `box64-bundle-x86-libs.sh`. This will create two archives:
- `box64-bundle-x86-libs.tar.gz` = All of the extracted library files in the directory structure of `usr/lib/box64-i386-linux-gnu` and `usr/lib/box64-x86_64-linux-gnu`.
- `box64-bundle-x86-pkgs.tar.gz` = All of the Linux distribution packages used to extract the library files. This is only created for preservation purposes and is otherwise unused.
Extract the library archive. Box will automatically search these paths for library files to emulate.
```
sudo tar --extract --file box64-bundle-x86-libs.tar.gz --directory /
```
### Developer
Add new packages to the `box64-bundle-x86-libs.csv` file in the format of `<PACKAGE_URL>,<SHA256_CHECKSUM>`.
Supported packages:
- DEB (Debian)
- EOPKG (Solus)
- RPM (Fedora)
- XBPS (Void Linux)
Preference of operating system packages that provide a library:
1. RPMs from AlmaLinux 9 provide 10 years of updates.
2. DEBs from Debian 11 provide 5 years of updates.
3. EOPKG from Solus provide old variants of obscure 32-bit libraries.
4. XBPS from Void Linux provide updated variants of obscure 32-bit libraries.
5. Other (whereever a library is packaged)
For finding package names that contian a specific library file, use the [pkgs.org](https://pkgs.org/) website. Otherwise, use one of these package manager commands on a x86_64 Linux distribution:
- DEB
- `apt-file <LIBRARY_FILE>`
- EOPKG
- Does not support file search. Use pkgs.org instead.
- RPM
- `dnf provides <LIBRARY_FILE>`
- XBPS
- `xbps-query --repository --ownedby <LIBRARY_FILE>`
Once the package name is found, find the exact URL for downloading it.
- DEB = Explore "main" and "contrib". Search for packages with the name "deb11" in it. Use the "amd64.deb" and "i386.deb" packages.
- https://archive.debian.org/debian/pool/
- EOPKG = Use the "`<VERSION>-<RELEASE>-x86_64.eopkg`" and "`32bit-<VERSION>-<RELEASE>-x86_64.eopkg`" packages.
- https://cdn.getsol.us/repo/shannon/
- RPM = Navigate to the "`<MAJOR>.<MINOR>`" version directory first. Then explore "AppStream" and "BaseOS". Use the "x86_64.rpm" and "i686.rpm" packages.
- https://repo.almalinux.org/almalinux/
- XBPS = There are too many files in the repository to display on a web browser. Use pkgs.org instead to find the exact URL for downloading it.
- https://repo-default.voidlinux.org/current/
Download the package and then find the checksum with the `sha256sum` command.
Major Linux distributions such as AlmaLinux and Debian provide archives of packages. Rolling distributions such as Arch Linux, Solus, and Void Linux do not. In those cases, use the [Internet Archive](https://web.archive.org/) to archive any rolling release package used by Box by using the "Save Page Now" feature. If the error "Save Page Now browser crashed" appears, it can be safely ignored. The archive will still have been saved.
+36
View File
@@ -1,3 +1,39 @@
v0.3.4
======
* This version is Faster and more compatible:
=> The RV64 backend got faster and more stable, with lots of RVV 1.0 / xThreadVector support to emulate SSE/SSE2+ opcode (no AVX yet)
=> On ARM64, Box64 now support more DRM types than before.
=> BOX32 can run steam now. At least on ARM64 backend, it's still not working on RV64 and LA64 for now.
* Added support to emulate Windows Syscall (needs Proton and a 48bits address space for now)
* Added BOX64_DYNAREC_DIRTY to have a faster (but less safe) way to handle code that write in it's current page
* Added a few rarely used opcodes
* Added experimental support for GDBJIT, that allow an x86/x86_64 program to be debugged on ARM/RV64/LA64 platform with x86 regs and opcode view (might generate a lot of file tho)
* Added support for Perf tools in a similar way if GDBJIT, to have an x86 fine view of the performances
* Reworked undefined flags for common operations, to be similar to real CPU
* Reworked cpuid handling, adding BOX64_CPUTYPE support to select Intel/AMD emulation (no 3DNow! support on AMD for now)
* Reworked ucontext link to be closer to the real thing (and make it more simple)
* Improved memory traking, file descriptor backed memory map, and detect wine loaded dll
* Introduced settings per library and dll (mostly for Dynarec)
* Wrapper: More functions addes, and some fixes too
* BOX32: Many fixes around pthreads wrapping
* BOX32: More functions wrapped.
* BOX32: More libraies wrapped.
* BOX32: Some reworks on how high memory (higher than 32bits) is masked, and can be used for Dynarec blocks.
* Dynarec: The usual batch of fixes, improvments and opcodes additions on all 3 supported backend
* Dynarec: Some fixes to NativeFlags handling, both on ARM64 and RV64
* Dynarec: Added optimized REP MOVSB (expected for default CPUTYPE=0, according to new cpuid return)
* Dynarec: LA64: more opcoded addes, using hardware extensions like AES
* Dynarec: RV64: More work on using RVV 1.0 and xTheadVector extension to emulate SSE/SSE2+ opcodes
* Dynarec: RV64: Added informations on flags when building blocks, to be used when a signal happens to rebuild a x86 context more accurate
* Dynarec: ARM64: Reworked undefined flags for common operations, to be similar to real CPU
* Dynarec: ARM64: Added informations on flags and xmm/ymm/x87 register when building blocks, to be used when a signal happens to rebuild a x86 context 100% accurate
* TRACE: Reworked how trace for wrapped function call is printed.
* TRACE: Reworked logs to prefix each line with a (optionaly colored) BOX32 or BOX64
* COSIM: Some rework on cosim to limit false negative, especialy when handling x87 operations
* LA64: Added limited support for ABI 1.0
* CI: github CI now also generate MiceWine .rat archive, along with Winlator .wcp archive and regular linux builds.
* RCFile: Added many new games profiles (both for speed improvment or for compatibilty)
v0.3.2
======
* Introduced Box32 to run 32bits apps on 64bits OS
+81 -46
View File
@@ -5,10 +5,12 @@ If you don't want to compile box64 yourself and prefer to use third-party pre-bu
You can also generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
Additional installation steps may be necessary when copying only the box64 executable file without running make install in cross-build environments. See [Cross-compiling](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#Cross-compiling)
## Per-platform compiling instructions
----
### The general approach
### The general approach is:
```
git clone https://github.com/ptitSeb/box64
cd box64
@@ -20,10 +22,11 @@ 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.
- You can use `make -j1`, `make -j2` with less jobs to prevent running out of memory
- You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on a Linux Kernel mixed with Android, like on RK3588.
#### Example of generic ARM64 build for linux platforms
#### 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
@@ -36,21 +39,21 @@ sudo systemctl restart systemd-binfmt
#### for RK3399
Using a 64bit OS:
On a 64bit OS:
```
-D RK3399=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for RK3588 / RK3588S
Using a 64bit OS:
On a 64bit OS:
```
-D RK3588=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Raspberry Pi 3
Warning, you need a 64bit OS:
On a 64bit OS:
If building on the Pi, you will also need a large swap (3 GB+)
[optionally reduce GPU memory to a minimum (e.g. 16 MB) using `raspi-config`
@@ -66,7 +69,7 @@ Still, this can be faster if your build is attended.
#### for Raspberry Pi 4
Warning, you need a 64bit OS:
On a 64bit OS:
```
-D RPI4ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -80,7 +83,7 @@ Warning, you need a 64bit OS:
#### for TEGRA X1
Using a 64bit OS:
On a 64bit OS:
```
-D TEGRAX1=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -88,7 +91,7 @@ Using a 64bit OS:
#### for Jetson Xavier/T194
Using a 64bit OS:
On a 64bit OS:
```
-D TEGRA_T194=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -96,16 +99,16 @@ Using a 64bit OS:
#### for Jetson Orin/T234
Using a 64bit OS:
On a 64bit OS:
Caution: please use gcc-11 or higher, older gcc doesn't know cortex-a78ae
Note: use gcc-11 or higher, older gcc doesn't know cortex-a78ae
```
-D TEGRA_T234=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for ODROID N2/N2+
Using a 64bit OS:
On a 64bit OS:
```
-D ODROIDN2=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -113,7 +116,7 @@ Using a 64bit OS:
#### for Snapdragon
Using a 64bit OS:
On a 64bit OS:
```
-D SD845=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -125,18 +128,18 @@ or
-D SD888=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
Depending how recent your Snapdragon is
Depending on how recent your Snapdragon is
#### for Phytium
Using a 64bit OS:
On a 64bit OS:
```
-D PHYTIUM=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for ADLink machines
Using a 64bit OS:
On a 64bit OS:
```
-D ADLINK=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
@@ -151,7 +154,7 @@ Only test on Asahi with Fedora, using the default "16K page" kernel
#### for LoongArch
Using a 64bit OS:
On a 64bit OS:
```
-D LARCH64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -159,7 +162,7 @@ Using a 64bit OS:
#### for RISC-V
Using a 64bit OS:
On a 64bit OS:
```
-D RV64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -167,7 +170,7 @@ Using a 64bit OS:
#### for PowerPC 64 LE
Using a 64bit OS:
On a 64bit OS:
```
-D PPC64LE=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -175,7 +178,7 @@ Using a 64bit OS:
#### for LX2160A
Using a 64bit OS:
On a 64bit OS:
```
-D LX2160A=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -183,7 +186,7 @@ Using a 64bit OS:
#### for Termux
You must have ARM64 Device for build box64.
You must have ARM64 machine to build box64.
##### in CHRoot/PRoot
@@ -193,15 +196,16 @@ You must have ARM64 Device for build box64.
##### in Termux (Native)
NOTE: BUILDING BOX64 IN TERMUX NATIVE IS EXPERIMENTAL AND DOESN'T GONNA RUN LINUX BINARIES IN NATIVE TERMUX BOX64!!!
Note: Box64 in native termux is experimental and won't run linux binaries!
You also needed have `libandroid-sysv-semaphore` and `libandroid-spawn` libraries:
You also need `libandroid-sysv-semaphore` and `libandroid-spawn` libraries.
```
-D TERMUX=1 -DCMAKE_C_COMPILER=clang -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for x86_64 Linux
```
-D LD80BITS=1 -D NOALIGN=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
@@ -215,58 +219,58 @@ Alternatively, you can **use the curses-based ccmake (or any other gui frontend
### Customize your build
#### Use ccache if you have it
#### Use ccache when present
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
Add `-DUSE_CCACHE=1` option if you have ccache and plan to touch the sources.
#### To have some debug info
#### Include debug information
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
Add `-DCMAKE_BUILD_TYPE=RelWithDebInfo` option for an optimized build with debug information embedded. That way, if you want to debug a crash or analyze performance, you have symbols.
#### To have a Trace Enabled build
#### Build with trace
To have a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. But you will need to have the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime. Use version v3.2.1, as later version changed the API and will no longer work with box64
To have a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. You will need the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime to get x86 trace. Use version v3.2.1, as later versions have changed the API and no longer work with box64.
#### To have ARM Dynarec
#### Build ARM DynaRec
Dynarec is only available on ARM (for the meantime), Activate it by using `-DARM_DYNAREC=1`.
Add `-DARM_DYNAREC=1` option to enable DynaRec on ARM machines.
#### To have a build using less memory
#### Save memory at run time
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.
You can use `-DSAVE_MEM` to have a build that will try to save some memory. For now, it only increases the jumptable from 4 levels to 5. The added granularity avoids wasting space, but adds one more read from memory when jumping between blocks.
#### Not building from a git clone
#### Build outside of a git repo
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).
Box64 uses git SHA1 to show last commit in version number, use `-DNOGIT=1` option when building outside of a git repo (for example, downloading a release source code zip from github).
#### 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).
Add `-DWITH_MOLD=1` option when GNU ld is extremely slow. Then run `mold -run make -j4` to build (make sure [Mold](https://github.com/rui314/mold) is installed).
#### Build a statically linked box64
You can now build box64 statically linked, with `-DSTATICBUILD`. This is to use inside an x86_64 chroot. Note that this version of box64 will have just the minimum of wrapped libs. So only libc, libm and libpthread basically are wrapped. Other libs (like libGL or libvulkan, SDL2, etc...) will not be wrapped and x86_64 version will be used. It's designed to be used in docker image, or in headless server.
Also, the Static Build is highly experimental, but feedback are always welcomed.
You can now build box64 statically linked, with `-DSTATICBUILD` to use inside of a x86_64 chroot. Note that this version of box64 will only have the minimal wrapped libs, such as libc, libm and libpthread. Other libs (like libGL or libvulkan, SDL2, etc...) will use x86_64 versions. A static build is intended to be used in a docker image, or in a headless server. It is highly experimental, but feedback is always welcome.
----
## Testing
----
A few tests are included with box64.
They can be launched using the `ctest` command.
The tests are very basic and only tests some functionality for now.
The tests are very basic and only test some functionality for now.
----
## Debian Packaging
----
Box64 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you might want in `debian/rules`.
## Pre-build packages
----
Box64 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you want in `debian/rules`.
## Pre-built packages
### Debian-based Linux
You can use the [Pi-Apps-Coders apt repository](https://github.com/Pi-Apps-Coders/box64-debs) to install precompiled box64 debs, updated every 24 hours.
```
@@ -296,3 +300,34 @@ Signed-By: /usr/share/keyrings/box64-archive-keyring.gpg" | sudo tee /etc/apt/so
sudo apt update
sudo apt install box64-generic-arm -y
```
## Cross-compiling
----
### Set Up the Cross-Compiler
For example, to compile Box64 for RISC-V on an x86 machine, you can get prebuilt GNU toolchain from the [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain/releases)
### Run CMake with Cross-Compilation Options
Follow the per-platform compilation instructions to configure the CMake options for your target architecture.
In particular, you must specify the cross-compiler. For example:
```
-DCMAKE_C_COMPILER=riscv64-unknown-linux-gnu-gcc # Or whichever cross-compiler you use
```
### Running tests with QEMU (optional)
To do a quick check, run:
```
qemu-riscv64 -L path/to/your/riscv64/sysroot box64 --help
```
You can run `dirname $(find -name libc.so.6)` to determine whether sysroot is provided by the prebuilt GNU toolchain or not.
To run CTest-based tests under QEMU:
```
ctest -j$(nproc)
```
### Installing on the Target Machine
After successfully cross-compiling, copy the box64 executable to your RISC-V device. Note that simply copying the binary does not automatically install Box64’s shared libraries. Because `make install` does not run on the target during cross-compilation, libraries required for emulation may be missing.
To fix this, copy the shared libraries folder from the Box64 repository (`x64lib` or `x86lib`) to your target. Place them into the proper library search paths, for example:
- `/usr/lib/box64-x86_64-linux-gnu/` (for x86_64)
- `/usr/lib/box64-i386-linux-gnu/` (for i386)
+695 -426
View File
File diff suppressed because it is too large. Load diff
+558 -278
View File
File diff suppressed because it is too large. Load diff
+134
View File
@@ -0,0 +1,134 @@
# Usage: python gen.py
import json
import os
from collections import defaultdict
script_dir = os.path.dirname(os.path.abspath(__file__))
usage_file = os.path.join(script_dir, 'usage.json')
with open(usage_file, 'r') as file:
data = json.load(file)
with open(os.path.join(script_dir, '../USAGE.md'), 'w') as md_file:
md_file.write("""<!--- This file is generated by gen.py, do not edit it directly. -->
Usage
----
There are many environment variables to control Box64's behaviour, which will be listed below by category.
### Configuration files
In addition to environment variables, by default, Box64 also looks for 2 places for rcfile: the system-wide `/etc/box64.box64rc` and user-specific `~/.box64rc`.
Settings priority follows this order (from highest to lowest): `~/.box64rc` > `/etc/box64.box64rc` > environment variables.
Example configuration:
```
[factorio]
BOX64_DYNAREC_SAFEFLAGS=0
BOX64_DYNAREC_BIGBLOCK=2
BOX64_DYNAREC_FORWARD=1024
BOX64_DYNAREC_CALLRET=1
```
This configuration will apply the specified settings application-wide to any executable named `factorio`.
### Advanced usage
1. **Wildcard Matching**
Asterisks (`*`) can be used for basic pattern matching in application names. For instance, `[*setup*]` will match any program containing "setup" in its name. Note this implements simple wildcard matching rather than full regex support.
2. **Custom Configuration File**
The `BOX64_RCFILE` environment variable can specify an alternative configuration file instead of the default `/etc/box64.box64rc`.
3. **Per-File Settings**
Sections starting with `/` apply to specific files. For example:
```
[/d3d9.dll]
BOX64_DYNAREC_SAFEFLAGS=0
```
These settings will only affect the `d3d9.dll` file. This syntax also works for **emulated** Linux libraries, e.g., `[/libstdc++.so.6]`.
----
""")
categories = defaultdict(list)
for entry in data:
categories[entry["category"]].append(entry)
for category, entries in categories.items():
md_file.write(f"## {category}\n\n")
for entry in entries:
md_file.write(f"### {entry['name']}\n\n{entry['description']}\n\n")
for option in entry['options']:
md_file.write(f" * {option['key']}: {option['description']} {"[Default]" if option['default'] else ""}\n")
md_file.write("\n")
with open(os.path.join(script_dir, '../box64.pod'), 'w') as pod_file:
pod_file.write("""=head1 NAME
box64 - Linux Userspace x86_64 Emulator with a twist
=head1 SYNOPSIS
B<box64> [B<--help>] [B<--version>] I<executable>
=head1 DESCRIPTION
B<Box64> lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux
systems, like ARM (host system needs to be 64-bit little-endian). Since B<Box64>
uses the native versions of some "system" libraries, like libc, libm, SDL, and
OpenGL, it's easy to integrate and use with most applications, and performance
can be surprisingly high in many cases. B<Box64> integrates with DynaRec (dynamic
recompiler) for the ARM64 platform, providing a speed boost between 5 to 10
times faster than using only the interpreter.
=head1 OPTIONS
=over 8
=item B<-h,--help>
Print box64 help and quit.
=item B<-v,--version>
Print box64 version and quit.
=back
=head1 BRIEF USAGE
There are many environment variables to control B<Box64>'s behaviour. In
addition to environment variables, B<Box64> also looks for 2 places for rcfile:
F</etc/box64.box64rc> and F<~/.box64rc>, in the format of .ini files.
Settings priority: F<~/.box64rc> > F</etc/box64.box64rc> > environment variables.
Example:
[factorio]
BOX64_DYNAREC_SAFEFLAGS=0
BOX64_DYNAREC_BIGBLOCK=2
BOX64_DYNAREC_FORWARD=1024
BOX64_DYNAREC_CALLRET=1
=head1 ENVIRONMENT VARIABLES
=over 8
""")
for entry in data:
pod_file.write(f"\n=item B<{entry['name']}> =I<{ '|'.join(option['key'] for option in entry['options']) }>\n\n{entry['description']}\n\n")
for option in entry['options']:
pod_file.write(f" * {option['key']} : {option['description']} {"[Default]" if option['default'] else ""}\n")
pod_file.write("\n")
pod_file.write("""
=back
=cut
""")
+1605
View File
File diff suppressed because it is too large. Load diff
+45
View File
@@ -0,0 +1,45 @@
#include "gdbjit.h"
#include <stdio.h>
static char block_name_buffer[16];
static enum gdb_status read_debug_info(struct gdb_reader_funcs* self, struct gdb_symbol_callbacks* cbs, void* memory, long memory_sz)
{
gdbjit_block_t* block = (gdbjit_block_t*)memory;
struct gdb_object* object = cbs->object_open(cbs);
struct gdb_symtab* symtab = cbs->symtab_open(cbs, object, block->filename);
sprintf(block_name_buffer, "%x", block->x64start);
cbs->block_open(cbs, symtab, NULL, block->start, block->end, block_name_buffer);
cbs->line_mapping_add(cbs, symtab, block->nlines, block->lines);
cbs->symtab_close(cbs, symtab);
cbs->object_close(cbs, object);
return GDB_SUCCESS;
}
enum gdb_status unwind_frame(struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs)
{
return GDB_SUCCESS;
}
struct gdb_frame_id get_frame_id(struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs)
{
struct gdb_frame_id frame = {0xdeadbeef, 0};
return frame;
}
void destroy_reader(struct gdb_reader_funcs* self) {}
__attribute__((visibility("default"))) struct gdb_reader_funcs* gdb_init_reader(void)
{
static struct gdb_reader_funcs funcs = {GDB_READER_INTERFACE_VERSION, NULL, read_debug_info, unwind_frame, get_frame_id, destroy_reader};
return &funcs;
}
__attribute__((visibility("default"))) int plugin_is_GPL_compatible (void)
{
return 0;
}
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# create necessary directories
mkdir -p ~/steam
mkdir -p ~/steam/tmp
cd ~/steam/tmp
# download latest deb and unpack
wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
ar x steam.deb
tar xf data.tar.xz
# remove deb archives, not needed anymore
rm ./*.tar.xz ./steam.deb
# move deb contents to steam folder
mv ./usr/* ../
cd ../ && rm -rf ./tmp/
# create run script
echo '#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam $@' > steam
# make script executable and move
chmod +x steam
sudo mv steam /usr/local/bin/
echo "Script complete."
+63 -6
View File
@@ -363,7 +363,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
gbl : JumbledGlobals = {}
redirects: JumbledRedirects = {}
filespec : JumbledFilesSpecific = {}
functions: Dict[str, Filename] = {}
halt_required = False # Is there a GO(*, .FE*) or similar in-batch error(s)?
# First read the files inside the headers
@@ -842,24 +842,25 @@ def main(root: str, files: Iterable[Filename], ver: str):
# H could be allowed maybe?
allowed_simply: Dict[str, str] = {"ARM64": "v", "RV64": "v"}
allowed_regs : Dict[str, str] = {"ARM64": "cCwWiuIUlLp", "RV64": "CWuIUlLp"}
allowed_regs : Dict[str, str] = {"ARM64": "cCwWiuIUlLp", "RV64": "CWIUlLp"}
allowed_fpr : Dict[str, str] = {"ARM64": "fd", "RV64": "fd"}
allowed_sextw : Dict[str, str] = {"ARM64": "", "RV64": "cwiu"}
# Detect functions which return in an x87 register
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
return_x87: str = "D"
# Sanity checks
forbidden_simple: Dict[str, str] = {"ARM64": "EDVOSNHPAxXYb", "RV64": "EcwiDVOSNHPAxXYb"}
forbidden_simple: Dict[str, str] = {"ARM64": "EDVOSNHPAxXYb", "RV64": "EDVOSNHPAxXYb"}
assert(all(k in allowed_simply for k in forbidden_simple))
assert(all(k in allowed_regs for k in forbidden_simple))
assert(all(k in allowed_fpr for k in forbidden_simple))
for k1 in forbidden_simple:
assert(len(allowed_simply[k1]) + len(allowed_regs[k1]) + len(allowed_fpr[k1]) + len(forbidden_simple[k1]) == len(allowed_conv.values))
assert(len(allowed_simply[k1]) + len(allowed_regs[k1]) + len(allowed_fpr[k1]) + len(allowed_sextw[k1]) + len(forbidden_simple[k1]) == len(allowed_conv.values))
assert(all(c not in allowed_regs[k1] for c in allowed_simply[k1]))
assert(all(c not in allowed_simply[k1] + allowed_regs[k1] for c in allowed_fpr[k1]))
assert(all(c not in allowed_simply[k1] + allowed_regs[k1] + allowed_fpr[k1] for c in forbidden_simple[k1]))
assert(all(c in allowed_simply[k1] + allowed_regs[k1] + allowed_fpr[k1] + forbidden_simple[k1] for c in allowed_conv.values))
assert(all(c in allowed_simply[k1] + allowed_regs[k1] + allowed_fpr[k1] + allowed_sextw[k1] + forbidden_simple[k1] for c in allowed_conv.values))
assert(all(c in allowed_conv.values for c in return_x87))
assert(all(c in forbidden_simple[k] for c in depends_on_ld for k in forbidden_simple))
@@ -872,6 +873,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
for k in forbidden_simple:
regs_count: int = 0
fpr_count : int = 0
sextw_mask: int = 0
if v.get_convention() is not allowed_conv:
continue
@@ -884,6 +886,9 @@ def main(root: str, files: Iterable[Filename], ver: str):
fpr_count = fpr_count + 1
elif c in allowed_simply[k]:
continue
elif c in allowed_sextw[k]:
sextw_mask |= 1 << regs_count
regs_count += 1
else:
break
else:
@@ -891,6 +896,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
if (regs_count <= 6) and (fpr_count <= 8):
# All checks passed!
ret_val = 1 + fpr_count
ret_val |= sextw_mask << 4
if v[0] in allowed_fpr[k]:
ret_val = -ret_val
ret[k] = ret_val
@@ -1027,6 +1033,26 @@ def main(root: str, files: Iterable[Filename], ver: str):
#ifndef __{filename}UNDEFS_H_
#define __{filename}UNDEFS_H_
""",
"x64printer.c": """
#include <inttypes.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "x64emu.h"
#include "x64emu_private.h"
#include "wrapper.h"
#define PRIp "p"
#define PRIf "f"
#define PRILf "Lf"
#define PRIs "s"
void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int tid, wrapper_t w)
{lbr}
#ifdef HAVE_TRACE
if (0) {lbr}
"""
}
files_guard = {
@@ -1049,6 +1075,14 @@ def main(root: str, files: Iterable[Filename], ver: str):
"fnundefs.h": """
#endif // __{filename}UNDEFS_H_
""",
"x64printer.c": """
else
#endif // HAVE_TRACE
{lbr}
snprintf(buff, buffsz, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), func, R_RDI, R_RSI, R_RDX);
{rbr}
{rbr}
"""
}
@@ -1724,7 +1758,30 @@ def main(root: str, files: Iterable[Filename], ver: str):
if k != str(Clauses()):
file.write("#endif\n")
file.write(files_guard["wrapper.h"].format(lbr="{", rbr="}", version=ver))
# E v c w i I C W u U f d D l L p V O S N H P A x X Y b
formats_map = ["(error)", "(error)", "i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f", "f", "Lf", "i64", "u64", "p", "p", "(error)", "(error)", "(error)", "u64", "p", "p", "(error)", "(error)", "(error)", "(error)"]
# Rewrite the x64printer.c file:
with open(os.path.join(root, "src", "emu", "x64printer.c"), 'w') as file:
file.write(files_header["x64printer.c"].format(lbr="{", rbr="}", version=ver))
for k in gbls:
if k != str(Clauses()):
file.write("#if {k}\n".format(k=k))
for signature in gbls[k]:
sig = signature if signature[2] != "E" else (signature[:2]+signature[3:])
if any(letter in sig[2:] for letter in "OSNxXYb") or signature.endswith('FE'):
continue
formats = sig[2:].replace("G", "UU")
params = '' if formats == "v" else ", " + function_args_systemV(FunctionType(formats))[:-2]
formats = '' if formats == "v" else ', '.join("%\" PRI{x} \"".format(x=formats_map[FunctionType(sig).get_convention().values.index(t)]) for t in formats)
file.write(" {rbr} else if (w == {signature}) {lbr}\n".format(signature=signature, lbr="{", rbr="}"))
file.write(" snprintf(buff, buffsz, \"%04d|%p: Calling %s({formats})\", tid, *(void**)(R_RSP), func{params});\n".format(formats=formats, params=params))
if k != str(Clauses()):
file.write("#endif\n")
file.write(" }\n")
file.write(files_guard["x64printer.c"].format(lbr="{", rbr="}", version=ver))
# Rewrite the *types.h files:
for k in conventions:
td_types[k][conventions[k].values.index('A')] = "va_list"
+15 -7
View File
@@ -583,8 +583,8 @@ class FileSpec:
# CONSTANT- rvalues: valid replacement values (outside of structures)
# CONSTANT- validrepl: valid replacement values (for structures)
# structs: structure ids and additional data
values: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'h', 'H', 'a', 'A', 'V', 'O', 'S', '2', 'P', 'N', 'M', 's', 'r', 'b', 'B', '_', 't', 'X']
rvalues: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'h', 'H', 'a', 'A', 'V', 'O', 'S', '2', 'P', 'N', 'M', 's', 'r', 'b', 'B', '_', 't', 'X']
values: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'h', 'H', 'a', 'A', 'V', 'O', 'S', '2', 'P', 'N', 'M', 's', 'r', 'b', 'B', '_', 't', 'X', 'n']
rvalues: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'h', 'H', 'a', 'A', 'V', 'O', 'S', '2', 'P', 'N', 'M', 's', 'r', 'b', 'B', '_', 't', 'X', 'n']
validrepl: Sequence[str] = ['c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'h', 'H', 'a', 'A', 'V', 'O', 'S', '2', 'P', 'N', 'M', 's', 'r', 'b', 'B', '_']
def __init__(self) -> None:
@@ -1150,7 +1150,8 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
"\n#error Invalid return type: wo structure declaration\n", # B
"\n#error Invalid return type: end of structure declaration\n", # _
"R_EAX = to_cstring(fn({0}));", # t
"R_EAX = to_ptrv(addDisplay(fn({0})));", # X
"R_EAX = to_ptrv(addDisplay(fn({0})));", # X
"\n#error Invalid return type: xcb_connection_t*\n", # n
]
asargs = [
"emu, ", # E
@@ -1188,6 +1189,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
"\n#error Invalid argument type: end of structure declaration\n", # _
"\n#error Invalid argument type: maybe-high string\n",# t
"getDisplay(from_ptriv(R_ESP + {p})), ", # X
"aligned_xcb, ", # n
]
if len(FileSpec.values) != len(asreturns):
raise NotImplementedError("len(values) = {lenval} != len(asreturns) = {lenvals}".format(lenval=len(FileSpec.values), lenvals=len(asreturns)))
@@ -1201,6 +1203,9 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
CType[(value, CType.ReadWrite.none)].aspre = ""
CType[(value, CType.ReadWrite.none)].asarg = asarg
CType[(value, CType.ReadWrite.none)].aspost = ""
if value == 'n':
CType[(value, CType.ReadWrite.none)].aspre = f"void *aligned_xcb = align_xcb_connection32(from_ptriv(R_ESP + {{p}})); "
CType[(value, CType.ReadWrite.none)].aspost = f" unalign_xcb_connection32(aligned_xcb, from_ptriv(R_ESP + {{p}}));"
for ctn in CType.getSingletons():
CType[ctn].generate_converters()
@@ -1300,6 +1305,9 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
void* getDisplay(void*);
void* addDisplay(void*);
void* align_xcb_connection32(void* src);
void unalign_xcb_connection32(void* src, void* dst);
""",
"wrapper32.h": """
#ifndef __WRAPPER32_H_
@@ -1405,8 +1413,8 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
files_guard[fhdr] = trim(files_guard[fhdr])
# Typedefs
# E v c w i I C W u U f d D K l L p h H a A V O S 2 P N M s r b B _ t X
tdtypes = ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "uintptr_t", "uintptr_t", "void*", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "...", "...", "void*", "\n#error _\n", "\n#error _\n", "\n#error _\n", "\n#error _\n", "char*", "void*"]
# E v c w i I C W u U f d D K l L p h H a A V O S 2 P N M s r b B _ t X n
tdtypes = ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "uintptr_t", "uintptr_t", "void*", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "...", "...", "void*", "\n#error _\n", "\n#error _\n", "\n#error _\n", "\n#error _\n", "char*", "void*", "void*"]
if len(FileSpec.values) != len(tdtypes):
raise NotImplementedError("len(values) = {lenval} != len(tdtypes) = {lentypes}".format(lenval=len(FileSpec.values), lentypes=len(tdtypes)))
def generate_typedefs(funs: Iterable[FunctionType], file):
@@ -1431,8 +1439,8 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
for i in range(2, len(funtype.orig.replaced))) + ");\n")
# Wrappers
# E v c w i I C W u U f d D K l L p h H a A V O S 2 P N M s r b B _ t X
deltas = [0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 8, 4, 0, 0, 0, 1, 1, 4, 1, 4, 4]
# E v c w i I C W u U f d D K l L p h H a A V O S 2 P N M s r b B _ t X n
deltas = [0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 4, 4, 4, 4, 1, 4, 4, 8, 4, 0, 0, 0, 1, 1, 4, 1, 4, 4, 4]
# Asserts
if len(FileSpec.values) != len(deltas):
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(FileSpec.values), lendeltas=len(deltas)))
+7 -7
View File
@@ -147,11 +147,11 @@ ulong_t to_hash_d(uintptr_t p) {
}
typedef struct struct_locale_s {
void* p0[13];
void* p0[13]; // struct __locale_data *
void* p1; //const unsigned short int *__ctype_b;
void* p2; //const int *__ctype_tolower;
void* p3; //const int *__ctype_toupper;
void* p4[13];
void* p4[13]; //const char*
} struct_locale_t;
// not a real structure
#define LOCALE_SIGN 0x54abcd845412LL
@@ -180,7 +180,7 @@ void to_struct_locale(ptr_t d, const struct_locale_t *src) {
dest->p0[i] = to_hashv(src->p0[i]);
}
for(int i=0; i<13; ++i) {
dest->p4[i] = to_hashv(src->p4[i]);
dest->p4[i] = to_cstring(src->p4[i]);
}
// copy the 3 ctype int (1st is short int, but int will do)
memcpy(dest->type_b, src->p1-128*sizeof(short), 384*sizeof(short));
@@ -194,9 +194,9 @@ void free_struct_locale(const struct_locale_t *src) {
for(int i=0; i<13; ++i) {
to_hash_d((uintptr_t)src->p0[i]);
}
for(int i=0; i<13; ++i) {
/*for(int i=0; i<13; ++i) {
to_hash_d((uintptr_t)src->p4[i]);
}
}*/
}
// Convert from locale key to original 64bits value
@@ -314,7 +314,7 @@ ptr_t to_cstring(char* p) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
ret = to_ptrv(box_strdup(p));
ret = to_ptrv(box32_strdup(p));
int r;
k = kh_put(strings, const_strings, (char*)from_ptrv(ret), &r);
kh_value(const_strings, k) = ret;
@@ -335,7 +335,7 @@ ptr_t to_cstring_d(char* p) {
} else {
ret = kh_value(const_strings, k);
kh_del(strings, const_strings, k);
free(from_ptrv(ret));
box32_free(from_ptrv(ret));
}
pthread_rwlock_unlock(&hash_lock);
return ret;
+9 -11
View File
@@ -19,7 +19,6 @@
#include "wrapper.h"
#include "x64emu.h"
#include "signals.h"
#include "rcfile.h"
#include "gltools.h"
#include "rbtree.h"
#include "dynarec.h"
@@ -49,7 +48,6 @@ void finiAllHelpers(box64context_t* context)
static int finied = 0;
if(finied)
return;
DeleteParams();
fini_pthread_helper(context);
fini_signal_helper();
fini_bridge_helper();
@@ -77,8 +75,8 @@ void free_tlsdatasize(void* p)
if(!p)
return;
tlsdatasize_t *data = (tlsdatasize_t*)p;
box_free(data->ptr);
box_free(p);
actual_free(data->ptr);
actual_free(p);
if(my_context)
pthread_setspecific(my_context->tlskey, NULL);
}
@@ -181,8 +179,8 @@ static void atfork_child_box64context(void)
void freeCycleLog(box64context_t* ctx)
{
if(cycle_log) {
for(int i=0; i<cycle_log; ++i) {
if(BOX64ENV(rolling_log)) {
for(int i=0; i<BOX64ENV(rolling_log); ++i) {
box_free(ctx->log_call[i]);
box_free(ctx->log_ret[i]);
}
@@ -194,10 +192,10 @@ void freeCycleLog(box64context_t* ctx)
}
void initCycleLog(box64context_t* context)
{
if(cycle_log) {
context->log_call = (char**)box_calloc(cycle_log, sizeof(char*));
context->log_ret = (char**)box_calloc(cycle_log, sizeof(char*));
for(int i=0; i<cycle_log; ++i) {
if(BOX64ENV(rolling_log)) {
context->log_call = (char**)box_calloc(BOX64ENV(rolling_log), sizeof(char*));
context->log_ret = (char**)box_calloc(BOX64ENV(rolling_log), sizeof(char*));
for(int i=0; i<BOX64ENV(rolling_log); ++i) {
context->log_call[i] = (char*)box_calloc(256, 1);
context->log_ret[i] = (char*)box_calloc(128, 1);
}
@@ -303,7 +301,7 @@ void FreeBox64Context(box64context_t** context)
if(--(*context)->forked >= 0)
return;
box64context_t* ctx = *context; // local copy to do the cleanning
box64context_t* ctx = *context; // local copy to do the cleaning
//clean_current_emuthread(); // cleaning main thread seems a bad idea
if(ctx->local_maplib)
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 3
#define BOX64_REVISION 2
#define BOX64_REVISION 4
#endif //__BOX64_VERSION_H_
+1 -1
View File
@@ -9,7 +9,7 @@
void PrintBox64Version()
{
printf_log(LOG_NONE, "Box64%s%s v%d.%d.%d %s built on %s %s\n",
printf_ftrace(1, "Box64%s%s v%d.%d.%d %s built on %s %s\n",
#ifdef HAVE_TRACE
" with trace",
#else
+15
View File
@@ -1,6 +1,21 @@
#include "box64version.h"
#ifdef NOGIT
#define GITREV "nogit"
#else
#include "git_head.h"
#endif
#ifndef __BUILD_INFO_H__
#define __BUILD_INFO_H__
void PrintBox64Version(void);
#define BOX64_BUILD_INFO_STR_HELPER(x) #x
#define BOX64_BUILD_INFO_STR(x) BOX64_BUILD_INFO_STR_HELPER(x)
#define BOX64_BUILD_INFO_STRING \
"Box64" \
" v" BOX64_BUILD_INFO_STR(BOX64_MAJOR) "." BOX64_BUILD_INFO_STR(BOX64_MINOR) "." BOX64_BUILD_INFO_STR(BOX64_REVISION) \
" " GITREV
#endif //__BUILD_INFO_H__
+313 -1315
View File
File diff suppressed because it is too large. Load diff
+218 -114
View File
@@ -7,6 +7,7 @@
#include <pthread.h>
#include <errno.h>
#include <syscall.h>
#include <sys/personality.h>
#include "box64context.h"
#include "elfloader.h"
@@ -34,6 +35,7 @@
// init inside dynablocks.c
static mmaplist_t *mmaplist = NULL;
static rbtree_t *rbt_dynmem = NULL;
static uint64_t jmptbl_allocated = 0, jmptbl_allocated1 = 0, jmptbl_allocated2 = 0, jmptbl_allocated3 = 0;
#ifdef JMPTABL_SHIFT4
static uint64_t jmptbl_allocated4 = 0;
@@ -85,6 +87,7 @@ typedef struct blocklist_s {
static int n_blocks = 0; // number of blocks for custom malloc
static int c_blocks = 0; // capacity of blocks for custom malloc
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
static int setting_prot = 0;
typedef union mark_s {
struct {
@@ -317,6 +320,16 @@ static size_t sizeBlock(void* sub)
return SIZE_BLOCK(s->next);
}
static int isBlockChainCoherent(blockmark_t* m, blockmark_t* end)
{
while(m) {
if(m>end) return 0;
if(m==end) return 1;
m = NEXT_BLOCK(m);
}
return 0;
}
// return 1 if block is coherent, 0 if not (and printf the issues)
int printBlockCoherent(int i)
{
@@ -327,6 +340,8 @@ int printBlockCoherent(int i)
int ret = 1;
blockmark_t* m = (blockmark_t*)p_blocks[i].block;
if(!m) {printf_log(LOG_NONE, "Warning, block #%d is NULL\n", i); return 0;}
// check coherency of the chained list first
if(!isBlockChainCoherent(m, (blockmark_t*)(p_blocks[i].block+p_blocks[i].size-sizeof(blockmark_t)))) {printf_log(LOG_NONE, "Warning, block #%d chained list is not coherent\n", i); return 0;}
// check if first is correct
blockmark_t* first = getNextFreeBlock(m);
if(p_blocks[i].first && p_blocks[i].first!=first) {printf_log(LOG_NONE, "First %p and stored first %p differs for block %d\n", first, p_blocks[i].first, i); ret = 0;}
@@ -486,17 +501,18 @@ void* internal_customMalloc(size_t size, int is32bits)
// add a new block
int i = n_blocks++;
if(n_blocks>c_blocks) {
c_blocks += 4;
c_blocks += box64_is32bits?8:256;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks*sizeof(blocklist_t));
}
size_t allocsize = (fullsize>MMAPSIZE)?fullsize:MMAPSIZE;
allocsize = (allocsize+box64_pagesize-1)&~(box64_pagesize-1);
p_blocks[i].block = NULL; // incase there is a re-entrance
p_blocks[i].first = NULL;
p_blocks[i].size = 0;
if(is32bits) // unlocking, because mmap might use it
mutex_unlock(&mutex_blocks);
void* p = is32bits
?mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0)
?box_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_32BIT, -1, 0)
:internal_mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(is32bits)
mutex_lock(&mutex_blocks);
@@ -521,11 +537,13 @@ void* internal_customMalloc(size_t size, int is32bits)
if(blockstree)
rb_set(blockstree, (uintptr_t)p, (uintptr_t)p+allocsize, i);
if(mapallmem) {
// defer the setProtection...
//setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
defered_prot_p = (uintptr_t)p;
defered_prot_sz = allocsize;
defered_prot_prot = PROT_READ|PROT_WRITE;
if(setting_prot) {
// defer the setProtection...
defered_prot_p = (uintptr_t)p;
defered_prot_sz = allocsize;
defered_prot_prot = PROT_READ|PROT_WRITE;
} else
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
}
return ret;
}
@@ -601,7 +619,7 @@ void* customRealloc32(void* p, size_t size)
void internal_customFree(void* p, int is32bits)
{
if(!p) {
if(!p || !inited) {
return;
}
uintptr_t addr = (uintptr_t)p;
@@ -777,8 +795,12 @@ size_t customGetUsableSize(void* p)
#ifdef DYNAREC
#define NCHUNK 64
typedef struct mapchunk_s {
blocklist_t chunk;
rbtree_t* tree;
} mapchunk_t;
typedef struct mmaplist_s {
blocklist_t chunks[NCHUNK];
mapchunk_t chunks[NCHUNK];
mmaplist_t* next;
} mmaplist_t;
@@ -789,30 +811,10 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
uintptr_t addr = (uintptr_t)p;
int i= 0;
mmaplist_t* list = mmaplist;
if(!list)
return NULL;
while(list) {
if ((addr>(uintptr_t)list->chunks[i].block)
&& (addr<((uintptr_t)list->chunks[i].block+list->chunks[i].size))) {
blockmark_t* sub = (blockmark_t*)list->chunks[i].block;
while((uintptr_t)sub<addr) {
blockmark_t* n = NEXT_BLOCK(sub);
if((uintptr_t)n>addr) {
// found it!
// self is the field of a block
return *(dynablock_t**)((uintptr_t)sub+sizeof(blockmark_t));
}
sub = n;
}
return NULL;
}
++i;
if(i==NCHUNK) {
i = 0;
list = list->next;
}
mapchunk_t* bl = (mapchunk_t*)rb_get_64(rbt_dynmem, (uintptr_t)p);
if(bl) {
dynablock_t** ret = (dynablock_t**)rb_get_64(bl->tree, (uintptr_t)p);
if(ret) return *ret;
}
return NULL;
}
@@ -821,6 +823,7 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
void* box32_dynarec_mmap(size_t size)
{
// find a block that was prereserve before and big enough
size = (size+box64_pagesize-1)&~(box64_pagesize-1);
uint32_t flag;
static uintptr_t cur = 0x100000000LL;
uintptr_t bend = 0;
@@ -859,19 +862,20 @@ uintptr_t AllocDynarecMap(size_t size)
int i = 0;
uintptr_t sz = size + 2*sizeof(blockmark_t);
while(1) {
if(list->chunks[i].maxfree>=size) {
if(list->chunks[i].chunk.maxfree>=size) {
// looks free, try to alloc!
size_t rsize = 0;
void* sub = getFirstBlock(list->chunks[i].block, size, &rsize, list->chunks[i].first);
void* sub = getFirstBlock(list->chunks[i].chunk.block, size, &rsize, list->chunks[i].chunk.first);
if(sub) {
void* ret = allocBlock(list->chunks[i].block, sub, size, &list->chunks[i].first);
if(rsize==list->chunks[i].maxfree)
list->chunks[i].maxfree = getMaxFreeBlock(list->chunks[i].block, list->chunks[i].size, list->chunks[i].first);
void* ret = allocBlock(list->chunks[i].chunk.block, sub, size, &list->chunks[i].chunk.first);
if(rsize==list->chunks[i].chunk.maxfree)
list->chunks[i].chunk.maxfree = getMaxFreeBlock(list->chunks[i].chunk.block, list->chunks[i].chunk.size, list->chunks[i].chunk.first);
rb_set_64(list->chunks[i].tree, (uintptr_t)ret, (uintptr_t)ret+size, (uintptr_t)ret);
return (uintptr_t)ret;
}
}
// check if new
if(!list->chunks[i].size) {
if(!list->chunks[i].chunk.size) {
// alloc a new block, aversized or not, we are at the end of the list
size_t allocsize = (sz>DYNMMAPSZ)?sz:DYNMMAPSZ;
// allign sz with pagesize
@@ -905,9 +909,11 @@ uintptr_t AllocDynarecMap(size_t size)
#endif
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE | PROT_EXEC);
list->chunks[i].block = p;
list->chunks[i].first = p;
list->chunks[i].size = allocsize;
list->chunks[i].chunk.block = p;
list->chunks[i].chunk.first = p;
list->chunks[i].chunk.size = allocsize;
list->chunks[i].tree = rbtree_init("dynamap");
rb_set_64(rbt_dynmem, (uintptr_t)p, (uintptr_t)p+allocsize, (uintptr_t)&list->chunks[i]);
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
@@ -917,10 +923,11 @@ uintptr_t AllocDynarecMap(size_t size)
n->next.x32 = 0;
n->prev.x32 = m->next.x32;
// alloc 1st block
void* ret = allocBlock(list->chunks[i].block, p, size, &list->chunks[i].first);
list->chunks[i].maxfree = getMaxFreeBlock(list->chunks[i].block, list->chunks[i].size, list->chunks[i].first);
if(list->chunks[i].maxfree)
list->chunks[i].first = getNextFreeBlock(m);
void* ret = allocBlock(list->chunks[i].chunk.block, p, size, &list->chunks[i].chunk.first);
list->chunks[i].chunk.maxfree = getMaxFreeBlock(list->chunks[i].chunk.block, list->chunks[i].chunk.size, list->chunks[i].chunk.first);
if(list->chunks[i].chunk.maxfree)
list->chunks[i].chunk.first = getNextFreeBlock(m);
rb_set_64(list->chunks[i].tree, (uintptr_t)ret, (uintptr_t)ret+size, (uintptr_t)ret);
return (uintptr_t)ret;
}
// next chunk...
@@ -939,23 +946,16 @@ void FreeDynarecMap(uintptr_t addr)
if(!addr)
return;
int i= 0;
mmaplist_t* list = mmaplist;
while(list) {
if ((addr>(uintptr_t)list->chunks[i].block)
&& (addr<((uintptr_t)list->chunks[i].block+list->chunks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
size_t newfree = freeBlock(list->chunks[i].block, list->chunks[i].size, sub, &list->chunks[i].first);
if(list->chunks[i].maxfree < newfree)
list->chunks[i].maxfree = newfree;
return;
}
++i;
if(i==NCHUNK) {
i = 0;
list = list->next;
}
mapchunk_t* bl = (mapchunk_t*)rb_get_64(rbt_dynmem, addr);
if(bl) {
void* sub = (void*)(addr-sizeof(blockmark_t));
size_t newfree = freeBlock(bl->chunk.block, bl->chunk.size, sub, &bl->chunk.first);
if(bl->chunk.maxfree < newfree)
bl->chunk.maxfree = newfree;
rb_unset(bl->tree, addr, addr+newfree);
return;
}
}
@@ -1020,42 +1020,27 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
}
}
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
// Will return 1 if at least 1 db in the address range
int cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
{
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
dynablock_t* db = NULL;
uintptr_t end = addr+size;
int ret = 0;
while (start_addr<end) {
start_addr = getDBSize(start_addr, end-start_addr, &db);
if(db) {
ret = 1;
if(destroy)
FreeRangeDynablock(db, addr, size);
else
MarkRangeDynablock(db, addr, size);
}
}
return ret;
}
// Will return 1 if at least 1 db in the address range
int isDBFromAddressRange(uintptr_t addr, size_t size)
{
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
dynarec_log(LOG_DEBUG, "isDBFromAddressRange %p/%p -> %p => ", (void*)addr, (void*)start_addr, (void*)(addr+size-1));
dynablock_t* db = NULL;
uintptr_t end = addr+size;
while (start_addr<end) {
start_addr = getDBSize(start_addr, end-start_addr, &db);
if(db) {
dynarec_log(LOG_DEBUG, "1\n");
return 1;
}
}
dynarec_log(LOG_DEBUG, "0\n");
return 0;
}
#ifdef JMPTABL_SHIFT4
static uintptr_t *create_jmptbl(uintptr_t idx0, uintptr_t idx1, uintptr_t idx2, uintptr_t idx3, uintptr_t idx4)
{
@@ -1472,7 +1457,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
uint32_t prot;
uintptr_t bend;
if (!rb_get_end(memprot, addr, &prot, &bend) || !(prot&PROT_DYN)) {
dynarec_log(LOG_DEBUG, "0\n");
dynarec_log_prefix(0, LOG_DEBUG, "0\n");
UNLOCK_PROT_READ();
return 0;
} else {
@@ -1480,24 +1465,42 @@ int isprotectedDB(uintptr_t addr, size_t size)
}
}
UNLOCK_PROT_READ();
dynarec_log(LOG_DEBUG, "1\n");
dynarec_log_prefix(0, LOG_DEBUG, "1\n");
return 1;
}
uintptr_t hotpage = 0;
int hotpage_cnt = 0;
static uintptr_t hotpage = 0;
static int hotpage_cnt = 0;
static int repeated_count = 0;
static uintptr_t repeated_page = 0;
#define HOTPAGE_MARK 64
#define HOTPAGE_DIRTY 2
void SetHotPage(uintptr_t addr)
{
hotpage = addr&~(box64_pagesize-1);
hotpage_cnt = HOTPAGE_MARK;
hotpage_cnt = BOX64ENV(dynarec_dirty)?HOTPAGE_DIRTY:HOTPAGE_MARK;
}
void CheckHotPage(uintptr_t addr)
{
uintptr_t page = (uintptr_t)addr&~(box64_pagesize-1);
if(repeated_count==1 && repeated_page==page) {
dynarec_log(LOG_DEBUG, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count);
SetHotPage(repeated_page);
repeated_count = 0;
repeated_page = 0;
} else {
repeated_count = 1;
repeated_page = page;
}
}
int isInHotPage(uintptr_t addr)
{
if(!hotpage_cnt)
return 0;
--hotpage_cnt;
return (addr>=hotpage) && (addr<hotpage+box64_pagesize);
int ret = (addr>=hotpage) && (addr<hotpage+box64_pagesize);
if(ret)
--hotpage_cnt;
return ret;
}
int checkInHotPage(uintptr_t addr)
{
@@ -1520,7 +1523,8 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
rb_get_end(memprot, cur, &oprot, &bend);
if(bend>end) bend = end;
uint32_t dyn=(oprot&PROT_DYN);
if(!(dyn&PROT_NEVERPROT)) {
uint32_t never = dyn&PROT_NEVERPROT;
if(!(never)) {
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
int ret = mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
@@ -1529,7 +1533,7 @@ void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
dyn = PROT_DYNAREC_R;
}
}
uint32_t new_prot = prot?(prot|dyn):prot;
uint32_t new_prot = prot?(prot|dyn):(prot|never);
if (new_prot != oprot)
rb_set(memprot, cur, bend, new_prot);
cur = bend;
@@ -1541,10 +1545,12 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot)
{
size = ALIGN(size);
LOCK_PROT();
++setting_prot;
uintptr_t cur = addr & ~(box64_pagesize-1);
uintptr_t end = ALIGN(cur+size);
rb_set(mapallmem, cur, end, 1);
rb_set(memprot, cur, end, prot);
--setting_prot;
UNLOCK_PROT();
}
@@ -1597,11 +1603,19 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
size = ALIGN(size);
addr &= ~(box64_pagesize-1);
LOCK_PROT();
rb_set(mapallmem, addr, addr+size, 1);
uint32_t val;
uintptr_t endb;
int there = rb_get_end(mapallmem, addr, &val, &endb);
// block is here or absent, no half-block handled..
if(!there)
rb_set(mapallmem, addr, addr+size, 1);
UNLOCK_PROT();
// don't need to add precise tracking probably
}
uintptr_t pbrk = 0;
uintptr_t old_brk = 0;
uintptr_t* cur_brk = NULL;
void loadProtectionFromMap()
{
if(box64_mapclean)
@@ -1618,6 +1632,8 @@ void loadProtectionFromMap()
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
if(!pbrk && strstr(buf, "[heap]"))
pbrk = s;
if(s>0x7fff00000000LL)
have48bits = 1;
}
@@ -1626,9 +1642,13 @@ void loadProtectionFromMap()
if(!shown48bits) {
shown48bits = 1;
if(have48bits)
printf_log(LOG_INFO, "BOX64: Detected 48bits at least of address space\n");
printf_log(LOG_INFO, "Detected 48bits at least of address space\n");
else
printf_log(LOG_INFO, "BOX64: Didn't detect 48bits of address space, considering it's 39bits\n");
printf_log(LOG_INFO, "Didn't detect 48bits of address space, considering it's 39bits\n");
}
if(!pbrk) {
printf_log(LOG_INFO, "Warning, program break not found\n");
if(cur_brk) pbrk = *cur_brk; // approximate is better than nothing
}
fclose(f);
box64_mapclean = 1;
@@ -1679,6 +1699,11 @@ int memExist(uintptr_t addr)
void* find31bitBlockNearHint(void* hint_, size_t size, uintptr_t mask)
{
// first, check if program break as changed
if(pbrk && cur_brk && *cur_brk!=old_brk) {
old_brk = *cur_brk;
setProtection(pbrk, old_brk-pbrk, PROT_READ|PROT_WRITE);
}
uint32_t prot;
uintptr_t hint = (uintptr_t)hint_;
if(hint_<LOWEST) hint = (uintptr_t)WINE_LOWEST;
@@ -1728,6 +1753,11 @@ void* find47bitBlock(size_t size)
}
void* find47bitBlockNearHint(void* hint, size_t size, uintptr_t mask)
{
// first, check if program break as changed
if(pbrk && cur_brk && *cur_brk!=old_brk) {
old_brk = *cur_brk;
setProtection(pbrk, old_brk-pbrk, PROT_READ|PROT_WRITE);
}
uint32_t prot;
if(hint<LOWEST) hint = LOWEST;
uintptr_t bend = 0;
@@ -1859,7 +1889,7 @@ void reverveHigMem32(void)
// printf_log(LOG_DEBUG, " Failed to reserve %zx sized block\n", cur_size);
cur_size>>=1;
} else {
rb_set(mapallmem, (uintptr_t)cur, (uintptr_t)cur+cur_size, 1);
rb_set(mapallmem, (uintptr_t)cur, (uintptr_t)cur+cur_size, 2);
//printf_log(LOG_DEBUG, "Reserved high %p (%zx)\n", cur, cur_size);
}
}
@@ -1893,7 +1923,7 @@ void reverveHigMem32(void)
}
}
printf_log(LOG_INFO, "Memory higher than 32bits reserved\n");
if(box64_log>=LOG_DEBUG) {
if (BOX64ENV(log)>=LOG_DEBUG) {
uintptr_t start=0x100000000LL;
int prot;
uintptr_t bend;
@@ -1904,6 +1934,7 @@ void reverveHigMem32(void)
start = bend;
}
}
personality(ADDR_LIMIT_32BIT);
}
#endif
void my_reserveHighMem()
@@ -1915,6 +1946,20 @@ void my_reserveHighMem()
#ifdef BOX32
if(box64_is32bits) {
reverveHigMem32();
// now reserve some memory in low address (because wine tend to allocate everything for itself)
void* p[20];
#define SZ 2*1024*1024
size_t n = sizeof(p)/sizeof(p[0]);
for(size_t i=0; i<n; ++i)
p[i] = box32_malloc(SZ-128);
if (BOX64ENV(log)>=LOG_DEBUG) {
printf_log(LOG_DEBUG, "Reserved %u MB of low memory [", (SZ)*n);
for(size_t i=0; i<n; ++i)
printf_log(LOG_DEBUG, "%p%s", p[i], (i==(n-1))?"]\n":", ");
}
for(size_t i=0; i<n; ++i)
box32_free(p[i]);
#undef SZ
return;
}
#endif
@@ -1945,14 +1990,8 @@ void my_reserveHighMem()
void reserveHighMem()
{
char* p = getenv("BOX64_RESERVE_HIGH");
if(!box64_is32bits)
#if 0//def ADLINK
if(p && p[0]=='0')
#else
if(!p || p[0]=='0')
#endif
return; // don't reserve by default
if(!box64_is32bits && !BOX64ENV(reserve_high))
return; // don't reserve by default on 64bits
my_reserveHighMem();
}
@@ -1962,6 +2001,7 @@ void init_custommem_helper(box64context_t* ctx)
if(inited) // already initialized
return;
inited = 1;
cur_brk = dlsym(RTLD_NEXT, "__curbrk");
blockstree = rbtree_init("blockstree");
// if there is some blocks already
if(n_blocks)
@@ -1971,7 +2011,7 @@ void init_custommem_helper(box64context_t* ctx)
sigfillset(&critical_prot);
init_mutexes();
#ifdef DYNAREC
if(box64_dynarec) {
if(BOX64ENV(dynarec)) {
#ifdef JMPTABL_SHIFT4
for(int i=0; i<(1<<JMPTABL_SHIFT4); ++i)
box64_jmptbl4[i] = box64_jmptbldefault3;
@@ -1989,6 +2029,7 @@ void init_custommem_helper(box64context_t* ctx)
box64_jmptbldefault0[i] = (uintptr_t)native_next;
}
lockaddress = kh_init(lockaddress);
rbt_dynmem = rbtree_init("rbt_dynmem");
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
// init mapallmem list
@@ -2029,25 +2070,26 @@ void fini_custommem_helper(box64context_t *ctx)
}
#ifdef JMPTABL_SHIFT4
}
if(box64_log) printf("Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- jump table: %lld kio (%lld level 4, %lld level 3, %lld level 2, %lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated4, jmptbl_allocated3, jmptbl_allocated2, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#else
if(box64_log) printf("Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- jump table: %lld kio (%lld level 3, %lld level 2, %lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated3, jmptbl_allocated2, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#endif
if(box64_log)
testAllBlocks();
if(BOX64ENV(log)) printf("Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- jump table: %lld kio (%lld level 4, %lld level 3, %lld level 2, %lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated4, jmptbl_allocated3, jmptbl_allocated2, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#else
if(BOX64ENV(log)) printf("Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- jump table: %lld kio (%lld level 3, %lld level 2, %lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated3, jmptbl_allocated2, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#endif
if(BOX64ENV(log)) testAllBlocks();
#endif
if(!inited)
return;
inited = 0;
#ifdef DYNAREC
if(box64_dynarec) {
if(BOX64ENV(dynarec)) {
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
mmaplist_t* head = mmaplist;
mmaplist = NULL;
while(head) {
for (int i=0; i<NCHUNK; ++i) {
if(head->chunks[i].block)
internal_munmap(head->chunks[i].block, head->chunks[i].size);
if(head->chunks[i].chunk.block)
internal_munmap(head->chunks[i].chunk.block, head->chunks[i].chunk.size);
if(head->chunks[i].tree)
rbtree_delete(head->chunks[i].tree);
}
mmaplist_t *old = head;
head = head->next;
@@ -2080,6 +2122,8 @@ void fini_custommem_helper(box64context_t *ctx)
}
kh_destroy(lockaddress, lockaddress);
lockaddress = NULL;
rbtree_delete(rbt_dynmem);
rbt_dynmem = NULL;
#endif
rbtree_delete(memprot);
memprot = NULL;
@@ -2146,3 +2190,63 @@ int internal_munmap(void* addr, unsigned long length)
#endif
return ret;
}
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0x200000
#endif
#ifndef MAP_32BIT
#define MAP_32BIT 0x40
#endif
EXPORT void* box_mmap(void *addr, size_t length, int prot, int flags, int fd, ssize_t offset)
{
if(prot&PROT_WRITE)
prot|=PROT_READ; // PROT_READ is implicit with PROT_WRITE on i386
int new_flags = flags;
void* old_addr = addr;
#ifndef NOALIGN
new_flags&=~MAP_32BIT; // remove MAP_32BIT
if((flags&MAP_32BIT) && !(flags&MAP_FIXED)) {
// MAP_32BIT only exist on x86_64!
addr = find31bitBlockNearHint(old_addr, length, 0);
} else if (box64_wine || 1) { // other mmap should be restricted to 47bits
if (!(flags&MAP_FIXED) && !addr)
addr = find47bitBlock(length);
}
#endif
void* ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
#if !defined(NOALIGN)
if((ret!=MAP_FAILED) && (flags&MAP_32BIT) &&
(((uintptr_t)ret>0xffffffffLL) || ((box64_wine) && ((uintptr_t)ret&0xffff) && (ret!=addr)))) {
int olderr = errno;
internal_munmap(ret, length);
loadProtectionFromMap(); // reload map, because something went wrong previously
addr = find31bitBlockNearHint(old_addr, length, 0); // is this the best way?
new_flags = (addr && isBlockFree(addr, length) )? (new_flags|MAP_FIXED) : new_flags;
if((new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE))==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
if(old_addr && ret!=old_addr && ret!=MAP_FAILED)
errno = olderr;
} else if((ret!=MAP_FAILED) && !(flags&MAP_FIXED) && ((box64_wine)) && (addr && (addr!=ret)) &&
(((uintptr_t)ret>0x7fffffffffffLL) || ((uintptr_t)ret&~0xffff))) {
int olderr = errno;
internal_munmap(ret, length);
loadProtectionFromMap(); // reload map, because something went wrong previously
addr = find47bitBlockNearHint(old_addr, length, 0); // is this the best way?
new_flags = (addr && isBlockFree(addr, length)) ? (new_flags|MAP_FIXED) : new_flags;
if((new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE))==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
if(old_addr && ret!=old_addr && ret!=MAP_FAILED) {
errno = olderr;
if(old_addr>(void*)0x7fffffffff && !have48bits)
errno = EEXIST;
}
}
#endif
return ret;
}
EXPORT int box_munmap(void* addr, size_t length)
{
int ret = internal_munmap(addr, length);
return ret;
}
+6 -3
View File
@@ -2,6 +2,8 @@
#include <unistd.h>
#include <stdint.h>
#include "env.h"
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
@@ -24,17 +26,18 @@ void setProtection(uintptr_t addr, size_t size, uint32_t prot);
void freeProtection(uintptr_t addr, size_t size);
void* internal_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
int internal_munmap(void* addr, unsigned long length);
void* box_mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset);
extern int running32bits;
extern int box64_mmap32;
extern box64env_t box64env;
EXPORT void* mmap64(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
{
void* ret;
if(!addr && ((running32bits && box64_mmap32) || (flags&MAP_32BIT) || box64_is32bits))
ret = my_mmap64(NULL, addr, length, prot, flags | MAP_32BIT, fd, offset);
if(!addr && ((running32bits && BOX64ENV(mmap32)) || (flags&MAP_32BIT) || box64_is32bits))
ret = box_mmap(addr, length, prot, flags | MAP_32BIT, fd, offset);
else
ret = internal_mmap(addr, length, prot, flags, fd, offset);
if(ret!=MAP_FAILED && mapallmem)
+34 -3
View File
@@ -144,6 +144,9 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur
// always
#define c__ 0b1110
//FCMP type of opcode produce:
// if any NAN: CV / v1 == v2: ZC / v1 < v2: N / v1 > v2: C
int convert_bitmask(uint64_t bitmask);
#define convert_bitmask_w(A) convert_bitmask(((uint64_t)(A) << 32) + (uint32_t)(A))
#define convert_bitmask_x(A) convert_bitmask((uint64_t)A)
@@ -205,17 +208,26 @@ int convert_bitmask(uint64_t bitmask);
#define SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG_ASR(Rd, Rn, Rm, asr) FEMIT(ADDSUB_REG_gen(1, 1, 1, 0b10, Rm, asr, Rn, Rd))
#define SUBx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, lsl, Rn, Rd))
#define SUBw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b00, Rm, lsl, Rn, Rd))
#define SUBw_REG_ASR(Rd, Rn, Rm, asr) EMIT(ADDSUB_REG_gen(0, 1, 0, 0b10, Rm, asr, Rn, Rd))
#define SUBSw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd))
#define SUBSw_REG_LSR(Rd, Rn, Rm, lsr) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b01, Rm, lsr, Rn, Rd))
#define SUBSw_REG_ASR(Rd, Rn, Rm, asr) FEMIT(ADDSUB_REG_gen(0, 1, 1, 0b10, Rm, asr, Rn, Rd))
#define SUBxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSxw_REG_ASR(Rd, Rn, Rm, asr) FEMIT(ADDSUB_REG_gen(rex.w, 1, 1, 0b10, Rm, asr, Rn, Rd))
#define CMPSx_REG(Rn, Rm) SUBSx_REG(xZR, Rn, Rm)
#define CMPSx_REG_ASR(Rn, Rm, asr) SUBSx_REG_ASR(xZR, Rn, Rm, asr)
#define CMPSw_REG(Rn, Rm) SUBSw_REG(wZR, Rn, Rm)
#define CMPSw_REG_LSR(Rn, Rm, lsr) SUBSw_REG_LSR(wZR, Rn, Rm, lsr)
#define CMPSw_REG_ASR(Rn, Rm, asr) SUBSw_REG_ASR(wZR, Rn, Rm, asr)
#define CMPSxw_REG(Rn, Rm) SUBSxw_REG(xZR, Rn, Rm)
#define CMPSxw_REG_ASR(Rn, Rm, asr) SUBSxw_REG_ASR(xZR, Rn, Rm, asr)
#define NEGx_REG(Rd, Rm) SUBx_REG(Rd, xZR, Rm);
#define NEGw_REG(Rd, Rm) SUBw_REG(Rd, wZR, Rm);
#define NEGxw_REG(Rd, Rm) SUBxw_REG(Rd, xZR, Rm);
@@ -248,6 +260,10 @@ int convert_bitmask(uint64_t bitmask);
#define SBCSw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
#define SUB_ext(sf, op, S, Rm, option, imm3, Rn, Rd) ((sf)<<31 | (op)<<30 | (S)<<29 | 0b01011<<24 | 1<<21 | (Rm)<<16 | (option)<<13 | (imm3)<<10 | (Rn)<<5 | (Rd))
#define SUBxw_UXTB(Rd, Rn, Rm) EMIT(SUB_ext(rex.w, 1, 0, Rm, 0b000, 0, Rn, Rd))
#define SUBw_UXTB(Rd, Rn, Rm) EMIT(SUB_ext(0, 1, 0, Rm, 0b000, 0, 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) FEMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
@@ -290,18 +306,24 @@ int convert_bitmask(uint64_t bitmask);
#define LDRx_REG_LSL3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
#define LDRx_REG_UXTW3(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b010, 1, Rn, Rt))
#define LDRx_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRx_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRw_REG_LSL2(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt))
#define LDRw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDRw_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRxw_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b011, 0, Rn, Rt))
#define LDRz_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
#define LDRxw_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, 0b110, 0, Rn, Rt))
#define LDRxw_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b10+rex.w, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRz_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b110, 0, Rn, Rt))
#define LDRz_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(rex.is32bits?0b10:0b11, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRB_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define LDRB_REG_UXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b010, 0, Rn, Rt))
#define LDRB_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, 0b110, 0, Rn, Rt))
#define LDRB_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b00, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRH_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define LDRH_REG_SXTW(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, 0b110, 0, Rn, Rt))
#define LDRH_REGz(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b01, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDRS_U12_gen(size, op1, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSHx_U12(Rt, Rn, imm12) EMIT(LDRS_U12_gen(0b01, 0b01, 0b10, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
@@ -314,6 +336,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDRS_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_REG(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define LDRSW_REG_SXTW(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define LDRSW_REGz(Rt, Rn, Rm) EMIT(LDRS_REG_gen(0b10, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define LDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | (imm19)<<5 | (Rt))
#define LDRx_literal(Rt, imm19) EMIT(LDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Rt))
@@ -390,12 +413,15 @@ int convert_bitmask(uint64_t bitmask);
#define STRw_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b110, 0, Rn, Rt))
#define STRB_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, 0b011, 0, Rn, Rt))
#define STRB_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, 0b110, 0, Rn, Rt))
#define STRB_REGz(Rt, Rn, Rm) EMIT(STR_REG_gen(0b00, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define STRH_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b01, Rm, 0b011, 0, Rn, Rt))
#define STRH_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b01, Rm, 0b110, 0, Rn, Rt))
#define STRxw_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, 0b011, 0, Rn, Rt))
#define STRxw_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, 0b110, 0, Rn, Rt))
#define STRxw_REGz(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.w?0b11:0b10, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
#define STRz_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b011, 0, Rn, Rt))
#define STRz_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, 0b110, 0, Rn, Rt))
#define STRz_REGz(Rt, Rn, Rm) EMIT(STR_REG_gen(rex.is32bits?0b10:0b11, Rm, rex.is32bits?0b110:0b011, 0, Rn, Rt))
// LOAD/STORE PAIR
#define MEMPAIR_gen(size, L, op2, imm7, Rt2, Rn, Rt) ((size)<<31 | 0b101<<27 | (op2)<<23 | (L)<<22 | (imm7)<<15 | (Rt2)<<10 | (Rn)<<5 | (Rt))
@@ -560,7 +586,7 @@ int convert_bitmask(uint64_t bitmask);
#define CSINV_gen(sf, Rm, cond, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (Rd))
#define CSINVx(Rd, Rn, Rm, cond) EMIT(CSINV_gen(1, Rm, cond, Rn, Rd))
#define CSINVw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(0, Rm, cond, Rn, Rd))
#define CSINVxw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(rex.w?, Rm, cond, Rn, Rd))
#define CSINVxw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(rex.w, Rm, cond, Rn, Rd))
#define CINVx(Rd, Rn, cond) CSINVx(Rd, Rn, Rn, invertCond(cond))
#define CINVw(Rd, Rn, cond) CSINVw(Rd, Rn, Rn, invertCond(cond))
#define CINVxw(Rd, Rn, cond) CSINVxw(Rd, Rn, Rn, invertCond(cond))
@@ -694,6 +720,7 @@ int convert_bitmask(uint64_t bitmask);
#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 BFCz(Rd, lsb, width) if(rex.is32bits) {BFCw(Rd, lsb, width);} else {BFCx(Rd, lsb, width);}
// 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)
@@ -918,10 +945,12 @@ int convert_bitmask(uint64_t bitmask);
#define VLD64(A, B, C) if(unscaled) {VLDR64_I9(A, B, C);} else {VLDR64_U12(A, B, C);}
#define VLD32(A, B, C) if(unscaled) {VLDR32_I9(A, B, C);} else {VLDR32_U12(A, B, C);}
#define VLD16(A, B, C) if(unscaled) {VLDR16_I9(A, B, C);} else {VLDR16_U12(A, B, C);}
#define VLD8(A, B, C) if(unscaled) {VLDR8_I9(A, B, C);} else {VLDR8_U12(A, B, C);}
#define VST128(A, B, C) if(unscaled) {VSTR128_I9(A, B, C);} else {VSTR128_U12(A, B, C);}
#define VST64(A, B, C) if(unscaled) {VSTR64_I9(A, B, C);} else {VSTR64_U12(A, B, C);}
#define VST32(A, B, C) if(unscaled) {VSTR32_I9(A, B, C);} else {VSTR32_U12(A, B, C);}
#define VST16(A, B, C) if(unscaled) {VSTR16_I9(A, B, C);} else {VSTR16_U12(A, B, C);}
#define VST8(A, B, C) if(unscaled) {VSTR8_I9(A, B, C);} else {VSTR8_U12(A, B, C);}
#define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
#define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
@@ -1141,7 +1170,9 @@ int convert_bitmask(uint64_t bitmask);
#define VFMOVDQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 1, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
#define FMOV_scalar_imm(type, imm8, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (imm8)<<13 | 0b100<<10 | (Rd))
// FMOV to Sd, imm=7 :~6:6:6:6:6:6:5:4 :3:2:1:0....
#define FMOVS_8(Sd, u8) EMIT(FMOV_scalar_imm(0b00, u8, Sd))
// FMOV to Dd, imm=7 :~6:6:6:6:6:6:6:6:6:5:4 :3:2:1:0....
#define FMOVD_8(Dd, u8) EMIT(FMOV_scalar_imm(0b01, u8, Dd))
// VMOV
@@ -1297,7 +1328,7 @@ int convert_bitmask(uint64_t bitmask);
#define VFRSQRTSQS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
#define VFRSQRTSQD(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
// CMP
// CMP . NZCV: unordere=0011, eq=0110, inf=1000, sup=0010
#define FCMP_scalar(type, Rn, Rm, opc) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
#define FCMPS(Sn, Sm) FEMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
#define FCMPD(Dn, Dm) FEMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
@@ -1826,7 +1857,7 @@ int convert_bitmask(uint64_t bitmask);
#define FCMLTS_0(Rd, Rn) EMIT(FCMP_0_scalar(0, 0, 0b10, (Rn), (Rd)))
#define FCMLTD_0(Rd, Rn) EMIT(FCMP_0_scalar(0, 1, 0b10, (Rn), (Rd)))
// Scalar Float CMP
// Scalar Float CMEQ
#define FCMP_op_scalar(U, E, sz, Rm, ac, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (E)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b1110<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define FCMEQS(Rd, Rn, Rm) EMIT(FCMP_op_scalar(0, 0, 0, (Rm), 0, (Rn), (Rd)))
#define FCMEQD(Rd, Rn, Rm) EMIT(FCMP_op_scalar(0, 0, 1, (Rm), 0, (Rn), (Rd)))
+60 -16
View File
@@ -554,6 +554,16 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "SUBS %s, %s, %s %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[shift], imm);
return buff;
}
if(isMask(opcode, "f1001011001mmmmmoooiiinnnnnddddd", &a)) {
const char* shifts[2][8] = {{ "UXTB", "UXTH", "LSL", "UXTX", "SXTB", "SXTH", "SXTW", "SXTX"}, {"UXTB", "UXTH", "UXTW", "LSL", "SXTB", "SXTH", "SXTW", "SXTX" }};
if(((sf==0 && shift==2) || (sf==1 && shift==3)) && imm==0)
snprintf(buff, sizeof(buff), "SUB %s, %s, %s", sf?XtSp[Rd]:WtSp[Rd], sf?XtSp[Rn]:WtSp[Rn], sf?XtSp[Rm]:WtSp[Rm]);
else if(shift==0)
snprintf(buff, sizeof(buff), "SUB %s, %s, %s %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[sf][shift]);
else
snprintf(buff, sizeof(buff), "SUB %s, %s, %s %s %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], shifts[sf][shift], imm);
return buff;
}
// ---- LOGIC
if(isMask(opcode, "f11100100Nrrrrrrssssssnnnnnddddd", &a)) {
uint64_t i = DecodeBitMasks(a.N, imms, immr);
@@ -743,8 +753,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "BFC %s, %d, %d", sf?Xt[Rd]:Wt[Rd], lsb, width);
else
snprintf(buff, sizeof(buff), "BFI %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], lsb, width);
} else
snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
} else {
if(Rn==31 && immr==0)
snprintf(buff, sizeof(buff), "BFC %s, %d, %d", sf?Xt[Rd]:Wt[Rd], immr, imms-immr+1);
else
snprintf(buff, sizeof(buff), "BFXIL %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
}
return buff;
}
// ---- BRANCH / TEST
@@ -768,17 +782,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
if(isMask(opcode, "f0110100iiiiiiiiiiiiiiiiiiittttt", &a)) {
int offset = signExtend(imm, 19)<<2;
snprintf(buff, sizeof(buff), "CBZ %s, #%+di\t; %p", Xt[Rt], offset>>2, (void*)(addr + offset));
snprintf(buff, sizeof(buff), "CBZ %s, #%+di\t; %p", sf?Xt[Rt]:Wt[Rt], offset>>2, (void*)(addr + offset));
return buff;
}
if(isMask(opcode, "f0110101iiiiiiiiiiiiiiiiiiittttt", &a)) {
int offset = signExtend(imm, 19)<<2;
snprintf(buff, sizeof(buff), "CBNZ %s, #%+di\t; %p", Xt[Rt], offset>>2, (void*)(addr + offset));
return buff;
}
if(isMask(opcode, "f0110100iiiiiiiiiiiiiiiiiiittttt", &a)) {
int offset = signExtend(imm, 19)<<2;
snprintf(buff, sizeof(buff), "CBZ %s, #%+di\t; %p", Xt[Rt], offset>>2, (void*)(addr + offset));
snprintf(buff, sizeof(buff), "CBNZ %s, #%+di\t; %p", sf?Xt[Rt]:Wt[Rt], offset>>2, (void*)(addr + offset));
return buff;
}
if(isMask(opcode, "s0110110sssssiiiiiiiiiiiiiittttt", &a)) {
@@ -1324,6 +1333,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "FCMP %c%d, %c%d", s, Rn, s, Rm);
return buff;
}
//FCMEQ
if(isMask(opcode, "000111100f1mmmmm111001nnnnnddddd", &a)) {
char s = (sf==0)?'S':'D';
snprintf(buff, sizeof(buff), "FCMEQ %c%d, %c%d, %c%d", s, Rd, s, Rn, s, Rm);
return buff;
}
//FCMP vector
if(isMask(opcode, "0QU01110cf1mmmmm111001nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
@@ -1574,12 +1589,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
// LD1/ST1 single structure
if(isMask(opcode, "0Q0011010L000000cc0Sffnnnnnttttt", &a)) {
if(isMask(opcode, "0Q0011010Lo00000cc0Sffnnnnnttttt", &a)) {
int scale = a.c;
int idx = 0;
const char* Y[] = {"B", "H", "S", "D"};
switch(scale) {
case 3: scale = sf; /* rep = 1; */ break;
case 3: scale = sf; /* rep = 1; */ idx=(8*(a.Q+1))>>scale; break;
case 0: idx = (a.Q<<3) | (a.S<<2) | sf; break;
case 1: idx = (a.Q<<2) | (a.S<<1) | (sf>>1); break;
case 2: if(!(sf&1))
@@ -1590,7 +1605,10 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
break;
}
snprintf(buff, sizeof(buff), "%s1 {V%d.%s}[%d], [%s]", a.L?"LD":"ST", Rt, Y[scale], idx, XtSp[Rn]);
if(!option && a.L && scale==3)
snprintf(buff, sizeof(buff), "LD1R {V%d.%d%s}, [%s]", Rt, idx, Y[scale], XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%s1 {V%d.%s}[%d], [%s]", a.L?"LD":"ST", Rt, Y[scale], idx, XtSp[Rn]);
return buff;
}
// LDUR/STUR
@@ -1637,6 +1655,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "%cQXTN%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Vd, Rn, Va);
return buff;
}
if(isMask(opcode, "01U11110ff100001010010nnnnnddddd", &a)) {
const char Z[] = {'B', 'H', 'S', 'D', '?'};
snprintf(buff, sizeof(buff), "SQXT%sN %c%d, %c%d", a.U?"U":"", Z[sf], Rd, Z[sf+1], Rn);
return buff;
}
// (S/U)SSHL(2) / (U/S)XTL(2)
if(isMask(opcode, "0QU011110hhhhiii101001nnnnnddddd", &a)) {
@@ -1667,6 +1690,15 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// CNT
if(isMask(opcode, "0Q00111000100000010110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B"};
const char* Vd = Y[a.Q];
const char* Va = Y[a.Q];
snprintf(buff, sizeof(buff), "CNT V%d.%s, V%d.%s", Rd, Vd, Rn, Va);
return buff;
}
// DUP
if(isMask(opcode, "0Q001110000iiiii000001nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -1713,14 +1745,26 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// DMB ISH
// DMB
if(isMask(opcode, "11010101000000110011nnnn10111111", &a)) {
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
const char* barrier[] = {
"???", "???", "???", "???", // 0-3
"???", "???", "???", "???", // 4-7
"???", "ISHLD", "ISHST", "ISH", // 8-11
"???", "LD", "ST", "SY" // 12-15
};
snprintf(buff, sizeof(buff), "DMB %s", barrier[Rn]);
return buff;
}
// DSB ISH/ISHST
// DSB
if(isMask(opcode, "11010101000000110011nnnn10011111", &a)) {
snprintf(buff, sizeof(buff), "DSB %s", (Rn==0b1011)?"ISH":((Rn==0b1010)?"ISHST":"???"));
const char* barrier[] = {
"???", "???", "???", "???", // 0-3
"???", "???", "???", "???", // 4-7
"???", "ISHLD", "ISHST", "ISH", // 8-11
"???", "LD", "ST", "SY" // 12-15
};
snprintf(buff, sizeof(buff), "DSB %s", barrier[Rn]);
return buff;
}
File diff suppressed because it is too large. Load diff
+282 -139
View File
@@ -165,7 +165,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x09:
INST_NAME("WBINVD");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_ud, -1);
@@ -177,7 +181,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_ud, -1);
@@ -212,7 +220,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x0E:
INST_NAME("femms");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_ud, -1);
@@ -248,8 +260,20 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
IF_UNALIGNED(ip) {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x1) {
MOVx_REG(x1, wback);
wback = x1;
}
for(int i=0; i<16; ++i) {
VST1_8(v0, i, wback);
ADDx_U12(wback, wback, 1);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
}
SMWRITE2();
}
break;
@@ -325,7 +349,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x18:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if (MODREG) {
INST_NAME("NOP (multibyte)");
} else
switch((nextop>>3)&7) {
@@ -355,6 +379,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x19:
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
@@ -422,7 +447,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if (box64_dynarec_fastround) {
if (BOX64ENV(dynarec_fastround)) {
VFCVTZSS(q0, v1);
} else {
if(arm64_frintts) {
@@ -456,7 +481,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if (box64_dynarec_fastround) {
if (BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIS(q0, v1);
x87_restoreround(dyn, ninst, u8);
@@ -499,11 +524,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
FCMPS(v0, s0);
FCOMI(x1, x2, 0, v0, s0, 1); // disabled precise cmp
FCOMI(x1, x2);
break;
case 0x30:
INST_NAME("WRMSR");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_priv, -1);
@@ -1003,16 +1032,17 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(gd, 0);
if(MODREG) {
// EX is an xmm reg
GETEX(q0, 0, 0);
q0 = fpu_get_scratch(dyn, ninst);
GETEX(v0, 0, 0);
SQXTN_16(q0, v0); // reduces the 4 32bits to 4 16bits
VMOVQDto(x1, q0, 0);
LSRx(x1, x1, 31);
LSRx(x1, x1, 15);
BFIx(gd, x1, 0, 1);
LSRx(x1, x1, 32);
LSRx(x1, x1, 16);
BFIx(gd, x1, 1, 1);
VMOVQDto(x1, q0, 1);
LSRx(x1, x1, 31);
LSRx(x1, x1, 16);
BFIx(gd, x1, 2, 1);
LSRx(x1, x1, 32);
LSRx(x1, x1, 16);
BFIx(gd, x1, 3, 1);
} else {
// EX is memory
@@ -1108,15 +1138,41 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ADDPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFADDQS(v0, v0, q0);
GETGX(q1, 1);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFADDQS(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x59:
INST_NAME("MULPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFMULQS(v0, v0, q0);
GETGX(q1, 1);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFMULQS(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x5A:
INST_NAME("CVTPS2PD Gx, Ex");
@@ -1136,8 +1192,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SUBPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFSUBQS(v0, v0, q0);
GETGX(q1, 1);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFSUBQS(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x5D:
INST_NAME("MINPS Gx, Ex");
@@ -1147,7 +1216,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
VFMINQS(v0, v0, v1);
if(!box64_dynarec_fastnan && (v0!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v0!=v1)) {
q0 = fpu_get_scratch(dyn, ninst);
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
@@ -1157,8 +1226,21 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFDIVQS(v0, v0, q0);
GETGX(q1, 1);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFDIVQS(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
@@ -1168,7 +1250,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
VFMAXQS(v0, v0, v1);
if(!box64_dynarec_fastnan && (v0!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v0!=v1)) {
q0 = fpu_get_scratch(dyn, ninst);
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
@@ -1532,7 +1614,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOVD Ed, Gm");
nextop = F8;
GETGM(v0);
if((nextop&0xC0)==0xC0) {
if (MODREG) {
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
if(rex.w) {
FMOVxD(ed, v0);
@@ -1641,8 +1723,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xA3:
INST_NAME("BT Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
GETGD;
if(MODREG) {
@@ -1669,11 +1754,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA4:
nextop = F8;
INST_NAME("SHLD Ed, Gd, Ib");
if(geted_ib(dyn, addr, ninst, nextop)) {
if(geted_ib(dyn, addr, ninst, nextop)&(rex.w?63:31)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
GETGD;
u8 = F8;
u8 = F8&(rex.w?63:31);
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
@@ -1684,9 +1769,11 @@ 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");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGD;
GETED(0);
if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}
@@ -1714,8 +1801,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
GETGD;
if(MODREG) {
@@ -1751,11 +1841,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
if(geted_ib(dyn, addr, ninst, nextop)) {
if(geted_ib(dyn, addr, ninst, nextop)&(rex.w?63:31)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
GETGD;
u8 = F8;
u8 = F8&(rex.w?63:31);
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
@@ -1766,9 +1856,11 @@ 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");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGD;
GETED(0);
if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);}
@@ -1805,7 +1897,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("FXSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FXSAVE)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1813,7 +1905,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("FXRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FXRSTOR)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1823,24 +1915,57 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("LDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
if(box64_sse_flushto0) {
MRS_fpcr(x1); // get fpscr
if(BOX64ENV(sse_flushto0)) {
MRS_fpcr(x2); // get fpscr
LSRw_IMM(x3, ed, 15); // get FZ bit
BFIw(x1, x3, 24, 1); // inject FZ bit
BFIw(x2, x3, 24, 1); // inject FZ bit
EORw_REG_LSR(x3, x3, ed, 1); // FZ xor DAZ
BFIw(x1, x3, 1, 1); // inject AH bit
MSR_fpcr(x1); // put new fpscr
BFIw(x2, x3, 1, 1); // inject AH bit
MSR_fpcr(x2); // put new fpscr
}
if(BOX64ENV(sse_flushto0)) {
// try to sync mxcsr with fpsr on the flag side
/* mapping is
ARM -> X86
0 -> 0 // Invalid operation
1 -> 2 // Divide by 0
2 -> 3 // Overflow
3 -> 4 // underflow
4 -> 5 // Inexact
5 -> 1 // denormal
*/
// doing X86 -> ARM here, 0 1 2 3 4 5 -> 0 2 3 4 5 1
if(ed!=x1)
MOVw_REG(x1, ed); // x1 = 543210
RORw(x3, x1, 2); // x3 = 10.....5432
BFIw(x1, x3, 1, 4); // x1 = 54320
RORw(x3, x3, 32-1); // x3 = 0.....54321
BFIw(x1, x3, 5, 1); // x1 = 154320
MRS_fpsr(x2);
BFIx(x2, x1, 0, 6);
MSR_fpsr(x2);
}
break;
case 3:
INST_NAME("STMXCSR Md");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
if(BOX64ENV(sse_flushto0)) {
// sync with fpsr, with mask from mxcsr
MRS_fpsr(x1);
// doing ARM -> X86 here, 543210 => 432150
UBFXw(x2, x1, 1, 5); // x2 = 54321
BFIw(x1, x2, 2, 4); // x1 = 432110
LSRw(x2, x2, 4); // x2 = 5
BFIw(x1, x2, 1, 1); // x1 = 432150
//BFXILw(x3, x4, 7, 6); // this would the mask, but let's ignore that for now
BFIw(x4, x1, 0, 6); // inject back the flags
}
STW(x4, ed, fixedaddress);
break;
case 4:
INST_NAME("XSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (XSAVE)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1849,7 +1974,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5:
INST_NAME("XRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (XRSTOR)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1858,7 +1983,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
MESSAGE(LOG_DUMP, "Need Optimization (CLFLUSH)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
@@ -1871,7 +1996,11 @@ 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_SET);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
nextop = F8;
GETGD;
GETED(0);
@@ -1880,10 +2009,9 @@ 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);
SET_DFNONE(x4);
SET_DFNONE();
IFX(X_CF|X_OF) {
ASRx(x4, gd, 63);
CMPSx_REG(x3, x4);
CMPSx_REG_ASR(x3, gd, 63);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
@@ -1901,10 +2029,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMULL(gd, gd, ed);
LSRx(x3, gd, 32);
MOVw_REG(gd, gd);
SET_DFNONE(x4);
SET_DFNONE();
IFX(X_CF|X_OF) {
ASRw(x4, gd, 31);
CMPSw_REG(x3, x4);
CMPSw_REG_ASR(x3, gd, 31);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
@@ -1917,12 +2044,13 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MULxw(gd, gd, ed);
}
}
IFX(X_AF | X_PF | X_ZF | X_SF)
if(box64_dynarec_test) {
// to avoid noise during test
MOV32w(x1, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x1);
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, gd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3);
break;
case 0xB1:
@@ -1954,8 +2082,12 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xB3:
INST_NAME("BTR Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
SET_DFNONE();
nextop = F8;
GETGD;
if(MODREG) {
@@ -2028,8 +2160,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
gd = x2;
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
@@ -2041,12 +2176,17 @@ 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)
}
break;
case 5:
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
@@ -2070,8 +2210,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
@@ -2094,8 +2237,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
@@ -2123,8 +2269,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBB:
INST_NAME("BTC Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
GETGD;
if(MODREG) {
@@ -2159,8 +2308,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBC:
INST_NAME("BSF Gd, Ed");
SETFLAGS(X_ZF, SF_SET_DF);
SET_DFNONE(x1);
SETFLAGS(X_ZF, SF_SET);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
@@ -2182,8 +2331,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
SETFLAGS(X_ZF, SF_SET_DF);
SET_DFNONE(x1);
SETFLAGS(X_ZF, SF_SET);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
@@ -2384,11 +2533,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC7:
// rep has no impact here
nextop = F8;
if(MODREG) switch((nextop>>3)&7) {
if(MODREG) switch((nextop>>3)&7) {
case 6:
INST_NAME("RDRAND Ed");
SETFLAGS(X_ALL, SF_SET_DF);
SET_DFNONE(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
GETED(0);
IFX(X_OF|X_SF|X_ZF|X_PF|X_AF) {
MOV32w(x1, (1<<F_OF)|(1<<F_SF)|(1<<F_ZF)|(1<<F_PF)|(1<<F_AF));
@@ -2404,6 +2553,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
IFX(X_CF) { BFIw(xFlags, x3, F_CF, 1); }
MOVxw_REG(ed, x1);
break;
case 7:
INST_NAME("RDPID Ed");
GETED(0);
CALL_(helper_getcpu, ed, x2);
break;
default:
DEFAULT;
} else switch((nextop>>3)&7) {
@@ -2442,8 +2596,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("RDRAND Ed");
SETFLAGS(X_ALL, SF_SET_DF);
SET_DFNONE(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
IFX(X_OF|X_SF|X_ZF|X_PF|X_AF) {
MOV32w(x1, (1<<F_OF)|(1<<F_SF)|(1<<F_ZF)|(1<<F_PF)|(1<<F_AF));
BICw(xFlags, xFlags, x1);
@@ -2480,50 +2634,28 @@ 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, ninst);
}
else {
q0 = d1;
}
q1 = fpu_get_scratch(dyn, ninst);
VMOVBto(x1, d1, 0);
MOVZw(x2, 16);
SUBSw_REG(x2, x2, x1);
B_MARK(cGT);
VMOVQDfrom(d0, 0, xZR);
B_NEXT_nocond;
MARK;
VDUPQS(q1, x2);
UXTL_16(q0, d0);
USHLQ_32(q0, q0, q1);
VUZP2Q_16(q0, q0, q0);
VMOVeD(d0, 0, q0, 0);
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
UQXTN_32(v0, d1);
MOVI_32(v1, 16);
UMIN_32(v0, v0, v1); // limit to 0 .. +15 values
VDUP_16(v0, v0, 0); // only the low 8bits will be used anyway
NEG_16(v0, v0);
USHL_16(d0, d0, v0);
break;
case 0xD2:
INST_NAME("PSRLD Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
if(MODREG) {
q0 = fpu_get_scratch(dyn, ninst);
}
else {
q0 = d1;
}
q1 = fpu_get_scratch(dyn, ninst);
VMOVBto(x1, d1, 0);
MOVZw(x2, 32);
SUBSw_REG(x2, x2, x1);
B_MARK(cGT);
VMOVQDfrom(d0, 0, xZR);
B_NEXT_nocond;
MARK;
VDUPQD(q1, x2);
UXTL_32(q0, d0);
USHLQ_64(q0, q0, q1);
VUZP2Q_32(q0, q0, q0);
VMOVeD(d0, 0, q0, 0);
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
UQXTN_32(v0, d1);
MOVI_32(v1, 32);
UMIN_32(v0, v0, v1); // limit to 0 .. +31 values
VDUP_32(v0, v0, 0); // only the low 8bits will be used anyway
NEG_32(v0, v0);
USHL_32(d0, d0, v0);
break;
case 0xD3:
INST_NAME("PSRLQ Gm,Em");
@@ -2531,11 +2663,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGM(d0);
GETEM(d1, 0);
v0 = fpu_get_scratch(dyn, ninst);
//MOVI_64(v0, 64); not 64!
MOV32w(x1, 64);
VMOVQDfrom(v0, 0, x1);
MOVI_32(v0, 64);
UMIN_32(v0, v0, d1); // limit to 0 .. +64 values (will force 32bits upper part to 0)
NEG_64(v0, v0);
NEG_32(v0, v0);
UXTL_32(v0, v0);
USHL_R_64(d0, d0, v0);
break;
case 0xD4:
@@ -2667,7 +2798,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(d1, 0);
URHADD_16(d0, d0, d1);
break;
case 0xE4:
INST_NAME("PMULHUW Gm,Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
VUMULL_16(q0, v0, v1);
VUMULL2_16(q1, v0, v1);
UQSHRN_16(v0, q0, 16);
UQSHRN2_16(v0, q1, 16);
break;
case 0xE5:
INST_NAME("PMULHW Gm,Em");
nextop = F8;
@@ -2759,8 +2901,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGM(d0);
GETEM(d1, 0);
v0 = fpu_get_scratch(dyn, ninst);
VMOVHto(x1, d1, 0);
VDUPH(v0, x1);
v1 = fpu_get_scratch(dyn, ninst);
UQXTN_32(v0, d1);
MOVI_32(v1, 16);
UMIN_32(v0, v0, v1); // limit to 0 .. +16 values
VDUP_16(v0, v0, 0);
USHL_16(d0, d0, v0);
break;
case 0xF2:
@@ -2803,7 +2948,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
q0 = fpu_get_scratch(dyn, ninst);
VSMULL_16(q0, v0, v1);
VADDPQ_32(q0, q0, q0); //ADDP from Q to non-Q?
VMOVQ(v0, q0);
VMOV(v0, q0);
break;
case 0xF6:
INST_NAME("PSADBW Gm, Em");
@@ -2812,10 +2957,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
VEOR(d1, d1, d1); // is it necessary?
UABDL_8(d0, q0, q1);
UADDLVQ_16(d1, d0);
VMOVeD(q0, 0, d1, 0);
UABDL_8(d0, q0, q1); // 8bits absolute difference in 16bits
UADDLVQ_16(d1, d0); // sum accros vector on the 16bits value inside a 32bits scalar
UXTL_32(d1, d1); // 32bits -> 64bits
VMOV(q0, d1);
break;
case 0xF7:
INST_NAME("MASKMOVQ Gm, Em");
@@ -2826,9 +2971,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
d1 = fpu_get_scratch(dyn, ninst);
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);
VBIT(d0, q0, d1);
VSTR64_U12(d0, xRDI, 0);
break;
case 0xF8:
File diff suppressed because it is too large. Load diff
+243 -99
View File
@@ -436,21 +436,42 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
nextop = F8;
GETSEW(x1, (opcode==0x69)?2:1);
if(opcode==0x69) i32 = F16S; else i32 = F8S;
MOV32w(x2, i32);
MULw(x2, x2, x1);
UFLAG_RES(x2);
gd=x2;
GWBACK;
UFLAG_DF(x1, d_imul16);
SET_DFNONE();
IFX(X_CF|X_OF) {
ASRw(x1, x2, 15);
CMPSw_REG_ASR(x1, x2, 31);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRw(x3, x2, 15);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, x2, x3);
break;
case 0x6A:
INST_NAME("PUSH Ib");
u16 = (uint16_t)F8S;
MOV32w(x2, u16);
i16 = F8S;
MOV32w(x2, (uint16_t)i16);
PUSH1_16(x2);
break;
@@ -643,9 +664,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
u8 = (nextop&0x38)>>3;
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
if((nextop&0xC0)==0xC0) { // reg <= seg
if (MODREG) {
BFIz(TO_NAT((nextop & 7) + (rex.b << 3)), x3, 0, 16);
} else { // mem <= seg
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x3, wback, fixedaddress);
SMWRITE2();
@@ -656,7 +677,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Seg,Ew");
nextop = F8;
u8 = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
@@ -671,7 +692,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POP Ew");
nextop = F8;
POP1_16(x1);
if((nextop&0xC0)==0xC0) {
if (MODREG) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BFIz(wback, x1, 0, 16);
} else {
@@ -718,12 +739,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET);
SMREAD();
POP1_16(x1); // probably not usefull...
POP1_16(x1);
MOV32w(x2, 0x7FD7);
ANDw_REG(x1, x1, x2);
ORRw_mask(x1, x1, 0b011111, 0); //mask=0x00000002
BFIw(xFlags, x1, 0, 16);
MOV32w(x1, 0x3F7FD7);
ANDw_REG(xFlags, xFlags, x1);
ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002
SET_DFNONE(x1);
SET_DFNONE();
if(box64_wine) { // should this be done all the time?
TBZ_NEXT(xFlags, F_TF);
// go to epilog, TF should trigger at end of next opcode, so using Interpreter only
@@ -732,7 +753,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
INST_NAME("MOV AX,Od");
if(rex.is32bits)
u64 = F32;
else
@@ -745,7 +766,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
INST_NAME("MOV Od,AX");
if(rex.is32bits)
u64 = F32;
else
@@ -761,17 +782,53 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("REP MOVSB");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
IF_UNALIGNED(ip) {
// special optim for large RCX value on forward case only
// but because it's unaligned path, check if a byte per byt is needed, and do 4-bytes per 4-bytes only instead
if(BOX64DRENV(dynarec_safeflags)) {
SUBx_REG(x2, xRDI, xRSI);
CMPSx_U12(x2, 4);
B_MARK(cCC);
}
ORRw_REG(x1, xRSI, xRDI);
ANDw_mask(x1, x1, 0, 1); //mask = 3
CBNZw_MARK(x1);
MARK3;
CMPSx_U12(xRCX, 4);
B_MARK(cCC);
LDRw_S9_postindex(x1, xRSI, 4);
STRw_S9_postindex(x1, xRDI, 4);
SUBx_U12(xRCX, xRCX, 4);
CBNZx_MARK3(xRCX);
CBZx_MARKLOCK(xRCX);
} else {
if(BOX64DRENV(dynarec_safeflags)) {
SUBx_REG(x2, xRDI, xRSI);
CMPSx_U12(x2, 8);
B_MARK(cCC);
}
// special optim for large RCX value on forward case only
MARK3;
CMPSx_U12(xRCX, 8);
B_MARK(cCC);
LDRx_S9_postindex(x1, xRSI, 8);
STRx_S9_postindex(x1, xRDI, 8);
SUBx_U12(xRCX, xRCX, 8);
CBNZx_MARK3(xRCX);
CBZx_MARKLOCK(xRCX);
}
MARK; // Part with DF==0
LDRB_S9_postindex(x1, xRSI, 1);
STRB_S9_postindex(x1, xRDI, 1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
B_MARKLOCK_nocond;
MARK2; // Part with DF==1
LDRB_S9_postindex(x1, xRSI, -1);
STRB_S9_postindex(x1, xRDI, -1);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
MARKLOCK;
// done
} else {
INST_NAME("MOVSB");
@@ -818,9 +875,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
@@ -918,9 +977,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1:
case 2:
if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
CBZx_NEXT(xRCX);
UXTHw(x1, xRAX);
TBNZ_MARK2(xFlags, F_DF);
@@ -962,9 +1023,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xBF:
INST_NAME("MOV Reg16, Iw");
u16 = F16;
MOV32w(x1, u16);
gd = TO_NAT((opcode & 7) + (rex.b << 3));
BFIz(gd, x1, 0, 16);
if(u16) {
MOV32w(x1, u16);
BFIz(gd, x1, 0, 16);
} else
BFCz(gd, 0, 16);
break;
case 0xC1:
@@ -972,7 +1036,7 @@ 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");
u8 = geted_ib(dyn, addr, ninst, nextop) & 15;
u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f;
if (u8) {
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
@@ -986,7 +1050,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("ROR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 15) {
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8)&0x1f;
@@ -999,7 +1063,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 31) {
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
@@ -1013,7 +1077,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
INST_NAME("RCR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 31) {
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
@@ -1074,13 +1138,20 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
u16 = F16;
MOV32w(x1, u16);
BFIz(ed, x1, 0, 16);
if(u16) {
MOV32w(x1, u16);
BFIz(ed, x1, 0, 16);
} else
BFCz(ed, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
MOV32w(x1, u16);
STH(x1, ed, fixedaddress);
if(u16) {
MOV32w(x1, u16);
STH(x1, ed, fixedaddress);
} else {
STH(xZR, ed, fixedaddress);
}
SMWRITELOCK(lock);
}
break;
@@ -1148,9 +1219,10 @@ 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, CL");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
@@ -1159,50 +1231,58 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x4, 16);
SUBx_REG(x2, x4, x2);
GETEW(x1, 0);
IFX2(X_OF, && !BOX64ENV(cputype)) {
LSRw(x4, ed, 14);
EORw_REG_LSR(x4, x4, x4, 1);
BFIw(xFlags, x4, F_OF, 1);
}
ORRw_REG_LSL(ed, ed, ed, 16);
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
SUBw_U12(x2, x2, 15);
CBNZw_MARK(x2);
EORw_REG_LSR(x3, ed, ed, 15);
BFIw(xFlags, x3, F_OF, 1);
MARK;
IFX2(X_OF, && BOX64ENV(cputype)) {
EORxw_REG_LSR(x3, ed, ed, 15);
BFIw(xFlags, x3, F_OF, 1);
}
IFX(X_CF) {
BFIw(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Ew, CL");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
GETEW(x1, 0);
IFX2(X_OF, && !BOX64ENV(cputype)) {
EORw_REG_LSR(x4, ed, ed, 15);
BFIw(xFlags, x4, F_OF, 1);
}
ORRw_REG_LSL(ed, ed, ed, 16);
LSRw_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
SUBw_U12(x2, x2, 1);
CBNZw_MARK(x2);
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;
IFX2(X_OF, && BOX64ENV(cputype)) {
LSRxw(x2, ed, 14); // x2 = d>>6
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFIw(xFlags, x2, F_OF, 1);
}
IFX(X_CF) {
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);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
MESSAGE(LOG_DUMP, "Need Optimization (RCL Ex, CL)\n");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
@@ -1211,10 +1291,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
INST_NAME("RCR Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
MESSAGE(LOG_DUMP, "Need Optimization (RCR Ew, CL)\n");
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_OF|X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
@@ -1224,9 +1306,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
CBZw_NEXT(x2);
@@ -1237,9 +1321,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
CBZw_NEXT(x2);
@@ -1250,9 +1336,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
UFLAG_IF {
CBZw_NEXT(x2);
@@ -1264,7 +1352,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xD9:
nextop = F8;
if(MODREG) {
@@ -1273,7 +1361,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FNSTENV16)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1293,7 +1381,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 4:
INST_NAME("FRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FRSTOR16)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1301,7 +1389,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("FNSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FNSAVE16)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -1329,9 +1417,15 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("NOT Ew");
GETEW(x1, 0);
MVNw_REG(ed, ed);
EWBACK;
if(MODREG) {
CALCEW();
int mask = convert_bitmask_x(0xffff);
EORx_mask(wback, wback, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
GETEW(x1, 0);
MVNw_REG(ed, ed);
EWBACK;
}
break;
case 3:
INST_NAME("NEG Ew");
@@ -1342,25 +1436,66 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4:
INST_NAME("MUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
GETEW(x1, 0);
UXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIz(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_mul16);
SET_DFNONE();
IFX(X_CF|X_OF) {
CMPSw_REG_LSR(xZR, x1, 16);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, xRAX, 15);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3);
break;
case 5:
INST_NAME("IMUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
GETSEW(x1, 0);
SXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIz(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_imul16);
SET_DFNONE();
IFX(X_CF|X_OF) {
ASRw(x2, x1, 15);
CMPSw_REG_ASR(x2, x1, 31);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, xRAX, 15);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3);
break;
case 6:
INST_NAME("DIV Ew");
@@ -1368,7 +1503,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETEW(x1, 0);
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
if(box64_dynarec_div0) {
if(BOX64ENV(dynarec_div0)) {
CBNZw_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
@@ -1382,19 +1517,27 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
SET_DFNONE();
IFX(X_OF) {BFCw(xFlags, F_OF, 1);}
IFX(X_CF) {BFCw(xFlags, F_CF, 1);}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10
IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40
IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX(X_SF) {BFCw(xFlags, F_SF, 1);}
IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04
IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);}
break;
case 7:
INST_NAME("IDIV Ew");
SKIPTEST(x1);
SETFLAGS(X_ALL, SF_SET);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET);
} else if(BOX64ENV(cputype)) {
SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET);
}
GETSEW(x1, 0);
if(box64_dynarec_div0) {
if(BOX64ENV(dynarec_div0)) {
CBNZw_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
@@ -1410,25 +1553,26 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
if(!BOX64ENV(dynarec_safeflags)) {
SET_DFNONE();
}
IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10
IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);}
IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);}
break;
}
break;
case 0xF8:
INST_NAME("CLC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
BFCx(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
ORRx_mask(xFlags, xFlags, 1, 0, 0); // xFlags | 1
break;
+194 -78
View File
@@ -168,6 +168,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SMWRITE2();
break;
case 0x18:
case 0x19:
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
@@ -231,7 +233,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFCVTZSQD(q0, v1);
SQXTN_32(q0, q0);
} else {
@@ -267,7 +269,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGM(q0);
GETEX(v1, 0, 0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIDQ(q0, v1);
FCVTXN(q0, q0);
@@ -312,7 +314,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 0);
GETEXSD(q0, 0, 0);
FCMPD(v0, q0);
FCOMI(x1, x2, 0, v0, q0, 0); //disable precise cmp
FCOMI(x1, x2);
break;
case 0x38: // SSSE3 opcodes
@@ -475,7 +477,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0x14:
INST_NAME("PBLENDVPS Gx,Ex");
INST_NAME("BLENDVPS Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
@@ -483,13 +485,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = fpu_get_scratch(dyn, ninst);
if(q0!=q1) {
VSSHRQ_32(v1, v0, 31); // bit[31]-> bit[31..0]
VBICQ(q0, q0, v1);
VANDQ(v1, q1, v1);
VORRQ(q0, q0, v1);
VBITQ(q0, q1, v1);
}
break;
case 0x15:
INST_NAME("PBLENDVPD Gx,Ex");
INST_NAME("BLENDVPD Gx,Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
@@ -497,9 +497,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = fpu_get_scratch(dyn, ninst);
if(q0!=q1) {
VSSHRQ_64(v1, v0, 63); // bit[63]-> bit[63..0]
VBICQ(q0, q0, v1);
VANDQ(v1, q1, v1);
VORRQ(q0, q0, v1);
VBITQ(q0, q1, v1);
}
break;
@@ -530,7 +528,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MOV32w(x1, (1<<F_PF)|(1<<F_AF)|(1<<F_OF)|(1<<F_SF));
BICw_REG(xFlags, xFlags, x1);
}
SET_DFNONE(x1);
SET_DFNONE();
break;
case 0x1C:
@@ -924,13 +922,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_CF, SF_SUBSET);
GETED(0);
GETGD;
MRS_nzcv(x3);
BFIx(x3, xFlags, 29, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
IFNATIVE_BEFORE(NF_CF) {
if(INVERTED_CARRY_BEFORE) {
if(arm64_flagm)
CFINV();
else {
MRS_nzcv(x3);
EORx_mask(x3, x3, 1, 35, 0); //mask=1<<NZCV_C
MSR_nzcv(x3);
}
}
} else {
MRS_nzcv(x3);
BFIx(x3, xFlags, 29, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
}
IFX(X_CF) {
ADCSxw_REG(gd, gd, ed);
CSETw(x3, cCS);
BFIw(xFlags, x3, F_CF, 1);
IFNATIVE(NF_CF) {} else {
CSETw(x3, cCS);
BFIw(xFlags, x3, F_CF, 1);
}
} else {
ADCxw_REG(gd, gd, ed);
}
@@ -1014,9 +1026,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
u8 = F8&0b1111;
if(u8==0b0011) {
VMOVeD(q0, 0, q1, 0);
} else if(u8==0b1100) {
u8&=~0b0011;
}
if(u8==0b1100) {
VMOVeD(q0, 1, q1, 1);
} else for(int i=0; i<4; ++i)
u8&=~0b1100;
}
for(int i=0; i<4; ++i)
if(u8&(1<<i)) {
VMOVeS(q0, i, q1, i);
}
@@ -1224,6 +1240,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x41:
INST_NAME("DPPD Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
v0 = fpu_get_scratch(dyn, ninst);
VFMULQD(v0, q0, q1);
// mask some, duplicate all, mask some
for(int i=0; i<2; ++i)
if(!(u8&(1<<(4+i)))) {
VMOVQDfrom(v0, i, xZR);
}
FADDPD(v0, v0);
VDUPQ_64(q0, v0, 0);
for(int i=0; i<2; ++i)
if(!(u8&(1<<i))) {
VMOVQDfrom(q0, i, xZR);
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
@@ -1404,7 +1441,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
// flags
IFX(X_ALL) {
SET_DFNONE(x4);
SET_DFNONE();
IFX(X_CF) {
CMPSw_REG(x1, xZR);
CSETw(x4, cNE);
@@ -1417,7 +1454,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
CSETw(x5, cLT);
BFIw(xFlags, x5, F_ZF, 1);
}
IFX(F_SF) {
IFX(X_SF) {
CMPSw_REG(x2, x4);
CSETw(x5, cLT);
BFIw(xFlags, x5, F_SF, 1);
@@ -1626,7 +1663,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(q0, 0, 0);
GETGX_empty(q1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -1681,7 +1718,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -1689,7 +1726,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFADDQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
@@ -1701,7 +1738,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -1709,7 +1746,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFMULQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
@@ -1721,7 +1758,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
if(box64_dynarec_fastround==2) {
if(BOX64ENV(dynarec_fastround)==2) {
FCVTXN(v0, v1);
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
@@ -1734,7 +1771,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTISQ(v0, v1);
x87_restoreround(dyn, ninst, u8);
@@ -1769,7 +1806,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -1777,7 +1814,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFSUBQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
@@ -1791,7 +1828,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(v1, 0, 0);
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box64_dynarec_fastnan && v0!=v1) {
if(!BOX64ENV(dynarec_fastnan) && v0!=v1) {
q0 = fpu_get_scratch(dyn, ninst);
VFCMEQQD(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VANDQ(v0, v0, q0);
@@ -1805,7 +1842,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(q0, 0, 0);
GETGX(q1, 1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -1813,7 +1850,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFDIVQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
@@ -1827,7 +1864,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(v1, 0, 0);
// FMIN/FMAX wll not copy the value if v0[x] is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box64_dynarec_fastnan && v0!=v1) {
if(!BOX64ENV(dynarec_fastnan) && v0!=v1) {
q0 = fpu_get_scratch(dyn, ninst);
VFCMEQQD(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VANDQ(v0, v0, q0);
@@ -2247,7 +2284,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(q1, 1);
GETEX(q0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -2258,7 +2295,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
}
VFADDPQD(q1, q1, q0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
@@ -2315,8 +2352,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xA3:
INST_NAME("BT Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD
if(MODREG) {
@@ -2354,9 +2394,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ew, Gw, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x2);
GETEW(x1, 0);
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
@@ -2369,8 +2411,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xAB:
INST_NAME("BTS Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD
if(MODREG) {
@@ -2394,6 +2439,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ORRx_REG(ed, ed, x1);
if(wback) {
STH(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
@@ -2415,9 +2461,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ew, Gw, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
if(BOX64DRENV(dynarec_safeflags)>1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET);
} else
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x2);
GETEW(x1, 0);
ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f
@@ -2428,23 +2476,77 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
emit_shrd16(dyn, ninst, ed, gd, x4, x5, x6);
EWBACK;
break;
case 0xAE:
nextop = F8;
if(MODREG)
switch (nextop) {
default:
DEFAULT;
}
else
switch((nextop>>3)&7) {
case 6:
INST_NAME("CLWB Ed");
MESSAGE(LOG_DUMP, "Need Optimization (CLWB)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(native_clflush, -1, 0);
break;
case 7:
INST_NAME("CLFLUSHOPT Ed");
MESSAGE(LOG_DUMP, "Need Optimization (CLFLUSHOPT)?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL_(native_clflush, -1, 0);
break;
default:
DEFAULT;
}
break;
case 0xAF:
INST_NAME("IMUL Gw,Ew");
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
nextop = F8;
GETSEW(x1, 0);
GETSGW(x2);
MULw(x2, x2, x1);
UFLAG_RES(x2);
GWBACK;
UFLAG_DF(x1, d_imul16);
SET_DFNONE();
IFX(X_CF|X_OF) {
ASRw(x1, x2, 15);
CMPSw_REG_ASR(x1, x2, 31);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, gd, 15);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3);
break;
case 0xB3:
INST_NAME("BTR Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD
if(MODREG) {
@@ -2513,18 +2615,26 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
switch((nextop>>3)&7) {
case 4:
INST_NAME("BT Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
gd = x2;
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)
}
break;
case 5:
INST_NAME("BTS Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
@@ -2537,8 +2647,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 6:
INST_NAME("BTR Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
@@ -2550,8 +2663,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 7:
INST_NAME("BTC Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
GETEW(x1, 1);
u8 = F8;
u8&=(rex.w?0x3f:0x0f);
@@ -2568,8 +2684,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); // GETGD
if(MODREG) {
@@ -2600,7 +2719,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xBC:
INST_NAME("BSF Gw,Ew");
SETFLAGS(X_ZF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
@@ -2624,7 +2743,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xBD:
INST_NAME("BSR Gw,Ew");
SETFLAGS(X_ZF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
@@ -2882,20 +3001,17 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
q1 = fpu_get_scratch(dyn, ninst);
GETEX(q0, 0, 0);
GETGD;
TABLE64(x1, (uintptr_t)&mask_shift8);
VLDR64_U12(v0, x1, 0); // load shift
MOVI_8(v1, 0x80); // load mask
VAND(q1, v1, q0);
USHL_8(q1, q1, v0); // shift
UADDLV_8(q1, q1); // accumalte
VMOVBto(gd, q1, 0);
TABLE64(x2, 0x0706050403020100LL);
VDUPQD(v0, x2);
VSHRQ_8(q1, q0, 7);
USHLQ_8(q1, q1, v0); // shift
UADDLV_8(v1, q1); // accumalte
VMOVBto(gd, v1, 0);
// and now the high part
VMOVeD(q1, 0, q0, 1);
VAND(q1, v1, q1); // keep highest bit
USHL_8(q1, q1, v0); // shift
VMOVeD(q1, 0, q1, 1);
UADDLV_8(q1, q1); // accumalte
VMOVBto(x1, q1, 0);
BFIx(gd, x1, 8, 8);
VMOVBto(x2, q1, 0);
BFIw(gd, x2, 8, 8);
break;
case 0xD8:
INST_NAME("PSUBUSB Gx, Ex");
@@ -3024,7 +3140,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFCVTZSQD(v0, v1); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
} else {
+41 -47
View File
@@ -58,17 +58,16 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
v1 = fpu_get_scratch(dyn, ninst);
if(rex.is32bits)
VLDR64_REG_SXTW(v1, x4, ed);
else
VLDR64_REG(v1, ed, x4);
VLD64(v1, ed, fixedaddress);
}
FCMPD(v0, v1);
FCOMI(x1, x2, 0, v0, v1, 0); //disable precise cmp
FCOMI(x1, x2);
break;
case 0x6F:
@@ -80,13 +79,12 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
SMREAD();
if(rex.is32bits)
VLDR128_REG_SXTW(v0, x4, ed);
else
VLDR128_REG(v0, ed, x4);
ADDz_REG(x4, x4, ed);
ed = x4;
VLD128(v0, ed, fixedaddress);
}
break;
@@ -98,12 +96,11 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVQ(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.is32bits)
VSTR128_REG_SXTW(v0, x4, ed);
else
VSTR128_REG(v0, ed, x4);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
VST128(v0, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -117,12 +114,11 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.is32bits)
VSTR64_REG_SXTW(v0, x4, ed);
else
VSTR64_REG(v0, ed, x4);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
VST64(v0, ed, fixedaddress);
SMWRITE();
}
break;
@@ -138,7 +134,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
@@ -148,7 +144,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_or16c(dyn, ninst, x1, i16, x2, x4);
@@ -158,7 +154,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
@@ -169,7 +165,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
@@ -179,7 +175,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_and16c(dyn, ninst, x1, i16, x2, x4);
@@ -188,7 +184,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
@@ -198,7 +194,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
@@ -207,7 +203,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
@@ -233,15 +229,14 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(rex.w?3:1), rex.w?7:1, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
if(rex.w) {
STRx_REG(gd, ed, x4);
STx(gd, ed, fixedaddress);
} else {
if(rex.is32bits)
STRH_REG_SXTW(gd, x4, ed);
else
STRH_REG(gd, ed, x4);
STH(gd, ed, fixedaddress);
}
SMWRITE();
}
@@ -261,16 +256,15 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(rex.w?3:1), rex.w?7:1, rex, NULL, 0, 0);
ADDz_REG(x4, x4, ed);
ed = x4;
if(rex.w) {
LDRx_REG(gd, ed, x4);
LDx(gd, ed, fixedaddress);
} else {
if(rex.is32bits)
LDRH_REG_SXTW(x1, x4, ed);
else
LDRH_REG(x1, ed, x4);
LDH(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
}
+29 -17
View File
@@ -158,6 +158,8 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MARK3;
LDRH_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
SUBw_UXTB(x3, x3, x1);
CBNZw_MARK3(x3);
CMPSw_REG(x6, x1);
B_MARK(cNE);
// EAX == Ed
@@ -166,8 +168,8 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
STRH_U12(gd, wback, 0);
}
}
SMDMB();
MARK;
SMDMB();
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp16(dyn, ninst, x6, x1, x3, x4, x5);}
BFIx(xRAX, x1, 0, 16);
@@ -295,30 +297,36 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
if(arm64_atomics) {
LDADDALH(x5, x1, wback);
UFLAG_IF {
emit_add16(dyn, ninst, x1, x5, x3, x4);
LDADDALH(x5, x1, wback);
} else {
STADDLH(x5, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
ADDw_REG(x4, x1, x5);
STLXRH(x3, x4, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICH) {
B_NEXT_nocond;
B_MARK2_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);
SUBw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
ADDw_REG(x4, x1, x5);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
STRH_U12(x4, wback, 0); // put the whole value
SMDMB();
}
MARK2;
UFLAG_IF {
emit_add16(dyn, ninst, x1, x5, x3, x4);
}
}
break;
case 1: //OR
@@ -472,30 +480,34 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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);
SUBw_REG(x4, x1, x5);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICH) {
B_NEXT_nocond;
B_MARK2_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);
SUBw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
SUBw_REG(x4, x1, x5);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
STRH_U12(x4, wback, 0); // put the whole value
SMDMB();
}
MARK2;
UFLAG_IF {
emit_sub16(dyn, ninst, x1, x5, x3, x4);
}
}
break;
case 6: //XOR
+56 -3
View File
@@ -55,11 +55,64 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
#endif
switch(opcode) {
case 0xB8:
INST_NAME("POPCNT Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE();
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
v1 = fpu_get_scratch(dyn, ninst);
VEORQ(v1, v1, v1);
VMOVQDfrom(v1, 0, ed);
CNT_8(v1, v1);
UADDLV_8(v1, v1);
VMOVHto(gd, v1, 0);
IFX(X_ALL) {
IFX(X_AF|X_PF|X_SF|X_OF|X_CF) {
MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF));
BICw(xFlags, xFlags, x1);
}
IFX(X_ZF) {
CMPSw_U12(gd, 0);
IFNATIVE(NF_EQ) {}
else {
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1);
}
}
}
GWBACK;
break;
case 0xBC:
INST_NAME("TZCNT Gw, Ew");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
TSTxw_REG(ed, ed);
IFX(X_CF) {
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
RBITw(x3, ed); // reverse
CLZw(gd, x3); // x2 gets leading 0 == TZCNT
MOV32w(x3, 16);
CSELw(gd, x3, gd, cEQ); // if src is zero, use bit width as res
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
GWBACK;
break;
case 0xBD:
INST_NAME("LZCNT Gw, Ew");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
@@ -68,14 +121,14 @@ uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
LSLw_IMM(ed, ed, 16);
CLZw(gd, ed);
SUBw_U12(gd, gd, 16); // sub zero cnt of high word
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
EWBACK;
GWBACK;
break;
default:
+99 -59
View File
@@ -38,6 +38,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int32_t i32;
int64_t j64, i64;
int16_t i16;
uint64_t u64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
@@ -57,7 +58,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
while(opcode==0x67) opcode = F8;
// reset rex after 67
GETREX();
@@ -215,7 +216,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
FCOMI(x1, x2, 0, v0, s0, 1); //disabled precise cmp
FCOMI(x1, x2);
break;
default:
DEFAULT;
@@ -916,7 +917,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x6B:
INST_NAME("IMUL Gd, Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags)>1 && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
nextop = F8;
GETGD;
GETED32(1);
@@ -927,14 +932,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UFLAG_IF {
SMULH(x3, ed, x4);
MULx(gd, ed, x4);
SET_DFNONE(x1);
IFX(X_ZF | X_PF | X_AF | X_SF) {
MOV32w(x1, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x1);
}
SET_DFNONE();
IFX(X_CF | X_OF) {
ASRx(x4, gd, 63);
CMPSx_REG(x3, x4);
CMPSx_REG_ASR(x3, gd, 63);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
@@ -952,14 +952,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMULL(gd, ed, x4);
LSRx(x3, gd, 32);
MOVw_REG(gd, gd);
SET_DFNONE(x1);
IFX(X_ZF | X_PF | X_AF | X_SF) {
MOV32w(x1, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x1);
}
SET_DFNONE();
IFX(X_CF | X_OF) {
ASRw(x4, gd, 31);
CMPSw_REG(x3, x4);
CMPSw_REG_ASR(x3, gd, 31);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
@@ -972,6 +967,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MULxw(gd, ed, x4);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, gd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, gd, x3);
break;
case 0x70:
@@ -1171,9 +1173,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
DEFAULT;
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=gd) {
MOVw_REG(gd, ed);
}
MOVw_REG(gd, ed); // need to trucate to 32bits as it's 67 prefixed
}
break;
@@ -1196,6 +1196,15 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
u64 = F32;
MOV64z(x1, u64);
lock=isLockAddress(u64);
SMREADLOCK(lock);
LDRxw_U12(xRAX, x1, 0);
break;
case 0xA9:
INST_NAME("TEST EAX, Id");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -1457,7 +1466,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_SET);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -1469,29 +1482,32 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_IF {
SET_DFNONE(x4);
IFX(X_CF|X_OF) {
CMPSxw_U12(xRDX, 0);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
SET_DFNONE();
IFX(X_CF|X_OF) {
CMPSxw_U12(xRDX, 0);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
IFX(X_AF | X_PF | X_ZF | X_SF)
if(box64_dynarec_test) {
// to avoid noise during test
MOV32w(x3, (1<<F_ZF)|(1<<F_AF)|(1<<F_PF)|(1<<F_SF));
BICw(xFlags, xFlags, x3);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, xRAX, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
if(BOX64ENV(dynarec_safeflags) && BOX64ENV(cputype)) {
SETFLAGS(X_OF|X_CF, SF_SET);
} else {
SETFLAGS(X_ALL, SF_SET);
}
GETED32(0);
if(rex.w) {
if(ed==xRDX) gd=x3; else gd=xRDX;
@@ -1503,9 +1519,24 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVw_REG(xRAX, xRDX);
LSRx(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_imul64:d_imul32);
SET_DFNONE();
IFX(X_CF|X_OF) {
CMPSxw_REG_ASR(xRDX, xRAX, rex.w?63:31);
CSETw(x3, cNE);
IFX(X_CF) {
BFIw(xFlags, x3, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x3, F_OF, 1);
}
}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_ZF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && !BOX64ENV(cputype)) {
LSRxw(x3, xRAX, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
IFX2(X_PF, && !BOX64ENV(cputype)) emit_pf(dyn, ninst, xRAX, x3);
break;
case 6:
INST_NAME("DIV Ed");
@@ -1543,17 +1574,25 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
SET_DFNONE();
IFX(X_OF) {BFCw(xFlags, F_OF, 1);}
IFX(X_CF) {BFCw(xFlags, F_CF, 1);}
IFX2(X_AF, && !BOX64ENV(cputype)) {BFCw(xFlags, F_AF, 1);}
IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10
IFX2(X_ZF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 26, 0);} //mask=0x40
IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX(X_SF) {BFCw(xFlags, F_SF, 1);}
IFX2(X_PF, && !BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 30, 0);} //mask=0x04
IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);}
break;
case 7:
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET);
} else if(BOX64ENV(cputype)) {
SETFLAGS(X_SF|X_PF|X_ZF|X_AF, SF_SET);
}
if(!rex.w) {
GETSED32w(0);
MOVw_REG(x3, xRAX);
@@ -1585,12 +1624,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
SET_DFNONE(x2);
IFX(X_AF | X_SF | X_CF | X_PF | X_ZF | X_OF)
if(box64_dynarec_test) {
MOV32w(x1, (1<<F_AF) | (1<<F_SF) | (1<<F_CF) | (1<<F_PF) | (1<<F_ZF) | (1<<F_OF));
BICw(xFlags, xFlags, x1);
}
if(!BOX64ENV(dynarec_safeflags)) {
SET_DFNONE();
}
IFX2(X_AF, && BOX64ENV(cputype)) {ORRw_mask(xFlags, xFlags, 28, 0);} //mask=0x10
IFX2(X_ZF, && BOX64ENV(cputype)) {BFCw(xFlags, F_ZF, 1);}
IFX2(X_SF, && BOX64ENV(cputype)) {BFCw(xFlags, F_SF, 1);}
IFX2(X_PF, && BOX64ENV(cputype)) {BFCw(xFlags, F_PF, 1);}
break;
}
break;
@@ -1613,7 +1653,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF((box64_dynarec_safeflags>1) ||
PASS2IF((BOX64DRENV(dynarec_safeflags)>1) ||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
@@ -1622,7 +1662,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
}
GETED32(0);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
if(BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock)>1) {
BARRIER(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
@@ -1630,7 +1670,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
*ok = 0;
}
GETIP_(addr);
if(box64_dynarec_callret) {
if(BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
@@ -1647,7 +1687,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
if(box64_dynarec_callret && addr >= (dyn->start + dyn->isize)) {
if(BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
j64 = getJumpTableAddress64(addr);
+20 -16
View File
@@ -68,9 +68,10 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
if(MODREG) { // reg <= reg
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
STRw_REG(gd, ed, x4);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
STz(gd, x4, fixedaddress);
}
break;
@@ -81,9 +82,10 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
if(MODREG) { // reg => reg
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem => reg
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
LDRw_REG(gd, ed, x4);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
LDz(gd, x4, fixedaddress);
}
break;
@@ -94,17 +96,18 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
POP1_32(x1);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), x1);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
POP1_32(x1);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
STRw_REG(x1, ed, x4);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
STz(x1, x4, fixedaddress);
}
break;
case 0xA1:
INST_NAME("MOV EAX, Seg:[Od]");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if(i32<4096 && !(i32&3)) {
LDRw_U12(xRAX, x4, i32);
} else if(i32<256) {
@@ -118,7 +121,7 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
case 0xA3:
INST_NAME("MOV Seg:[Od], EAX");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if(i32<4096 && !(i32&3)) {
STRw_U12(xRAX, x4, i32);
} else if(i32<256) {
@@ -131,16 +134,17 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
case 0xFF:
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
if (MODREG) {
DEFAULT;
} else { // mem <= i32
} else {
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0, 0, 0);
LDRw_REG(x3, ed, x4);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, 0);
ADDz_REG(x4, x4, ed);
LDW(x3, x4, fixedaddress);
PUSH1_32(x3);
}
break;
+29 -8
View File
@@ -85,15 +85,21 @@ uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGD;
GETED32(0);
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
if(rex.w) {
// 64bits mul
if((gd==xRDX) || (gd==ed) || (gd==vd))
gb1 = x3;
else
gb1 = gd;
UMULH(gb1, xRDX, ed);
if(gd!=vd) {MULx(vd, xRDX, ed);}
if(gb1==x3) {
MOVx_REG(gd, gb1);
}
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
if(gd!=vd) {MOVw_REG(vd, x3);}
LSRx(gd, x3, 32);
}
break;
@@ -120,14 +126,29 @@ uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
}
break;
case 0x6E:
INST_NAME("VMOVD Gx, Ed");
nextop = F8;
GETGX_empty(v0);
GETED(0);
VEORQ(v0, v0, v0); // RAZ vector
if(rex.w) {
FMOVDx(v0, ed);
} else {
FMOVSw(v0, ed);
}
YMM0(gd);
break;
default:
DEFAULT;
}
}
else {DEFAULT;}
if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
if((*ok==-1) && (BOX64ENV(dynarec_log)>=LOG_INFO || BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_missing)==1))
if(!dyn->size || BOX64ENV(dynarec_log)>LOG_INFO || BOX64DRENV(dynarec_dump)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
}
return addr;
}
+418
View File
@@ -0,0 +1,418 @@
#include <stddef.h>
#include <stdio.h>
#include <signal.h>
#include <ucontext.h>
#include <string.h>
#include "debug.h"
#include "dynablock.h"
#include "x64emu.h"
#include "emu/x64emu_private.h"
#include "x64run.h"
#include "emu/x64run_private.h"
#include "dynarec/dynablock_private.h"
#include "dynarec_arm64_arch.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_native.h"
//order might be important, so define SUPER for the right one
#define SUPER() \
GO(flags) \
GO(x87) \
GO(mmx) \
GO(sse) \
GO(ymm) \
typedef struct arch_flags_s
{
uint8_t defered:1;
uint8_t nf:1;
uint8_t eq:1;
uint8_t vf:1;
uint8_t cf:1;
uint8_t inv_cf:1;
} arch_flags_t;
#define X87_ST_D 0
#define X87_ST_F 1
#define X87_ST_I64 2
typedef struct arch_x87_s
{
int8_t delta; //up to +/-7
uint8_t x87; // 1bit is STx present
uint16_t x87_type; // 2bits per STx type
uint32_t x87_pos; //4bits per STx position (well, 3 would be enough)
} arch_x87_t;
typedef struct arch_mmx_s
{
uint8_t mmx; //1bit for each mmx reg present
} arch_mmx_t;
typedef struct arch_sse_s
{
uint16_t sse; //1bit for each sse reg present
} arch_sse_t;
typedef struct arch_ymm_s
{
uint16_t ymm0; // 1bit for ymm0
uint16_t ymm; // 1bit for each ymm present
uint64_t ymm_pos; // 4bits for position of each ymm present
} arch_ymm_t;
typedef struct arch_arch_s
{
#define GO(A) uint16_t A:1;
SUPER()
#undef GO
uint16_t unaligned:1;
uint16_t seq:10; // how many instruction on the same values
} arch_arch_t;
typedef struct arch_build_s
{
#define GO(A) uint8_t A:1;
SUPER()
#undef GO
uint8_t unaligned;
#define GO(A) arch_##A##_t A##_;
SUPER()
#undef GO
} arch_build_t;
static arch_build_t static_build[MAX_INSTS+2] = {0};
static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch)
{
memset(arch, 0, sizeof(arch_build_t));
// flags
if((dyn->insts[ninst].f_entry.dfnone==0) || dyn->insts[ninst].need_nat_flags || dyn->insts[ninst].before_nat_flags) {
arch->flags = 1;
arch->flags_.defered = dyn->insts[ninst].f_entry.dfnone==0;
uint8_t flags = dyn->insts[ninst].need_nat_flags | dyn->insts[ninst].before_nat_flags;
arch->flags_.vf = flags&NF_VF;
arch->flags_.nf = flags&NF_SF;
arch->flags_.eq = flags&NF_EQ;
arch->flags_.cf = flags&NF_CF;
if(arch->flags_.cf)
arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry;
}
// got through all naoncache to gather regs assignments
int idx;
for(int i=0; i<32; ++i)
if(dyn->insts[ninst].n.neoncache[i].v!=-1)
switch(dyn->insts[ninst].n.neoncache[i].t) {
case NEON_CACHE_XMMW:
arch->sse = 1;
arch->sse_.sse |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_MM:
arch->mmx = 1;
arch->mmx_.mmx |= 1<<dyn->insts[ninst].n.neoncache[i].n;
break;
case NEON_CACHE_YMMW:
arch->ymm = 1;
arch->ymm_.ymm |= 1<<dyn->insts[ninst].n.neoncache[i].n;
idx = i;
if(idx>=EMM0 && idx<=EMM0+8)
idx-=EMM0;
else
idx-=SCRATCH0-8;
arch->ymm_.ymm_pos |= idx<<(dyn->insts[ninst].n.neoncache[i].n*4);
break;
case NEON_CACHE_ST_D:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_D)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_F:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_F)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_ST_I64:
arch->x87 = 1;
arch->x87_.x87 |= 1<<dyn->insts[ninst].n.neoncache[i].n;
arch->x87_.x87_pos = (i-EMM0)<<(dyn->insts[ninst].n.neoncache[i].n*4);
arch->x87_.x87_type = (X87_ST_I64)<<(dyn->insts[ninst].n.neoncache[i].n*2);
break;
case NEON_CACHE_XMMR:
case NEON_CACHE_YMMR:
default:
// doing nothing, it's just a value read in memory
break;
}
// ymm0
if(dyn->insts[ninst].ymm0_out) {
arch->ymm = 1;
arch->ymm_.ymm0 = dyn->insts[ninst].ymm0_out;
}
// x87 top
if(dyn->insts[ninst].n.x87stack) {
arch->x87 = 1;
arch->x87_.delta = dyn->insts[ninst].n.x87stack;
}
// opcode can handle unaligned
arch->unaligned = dyn->insts[ninst].unaligned;
return arch->flags + arch->x87 + arch->mmx + arch->sse + arch->ymm + arch->unaligned;
}
static int sizeof_arch(arch_arch_t* arch)
{
int sz = sizeof(arch_arch_t);
#define GO(A) if(arch->A) sz+=sizeof(arch_##A##_t);
SUPER()
#undef GO
return sz;
}
static int sizeof_arch_build(arch_build_t* build)
{
int sz = sizeof(arch_arch_t);
#define GO(A) if(build->A) sz+=sizeof(arch_##A##_t);
SUPER()
#undef GO
return sz;
}
size_t get_size_arch(dynarec_arm_t* dyn)
{
arch_build_t* previous = NULL;
size_t sz = 0;
int seq = 0;
int nseq = 0;
int last = 0;
if(!dyn->size) return 0;
for(int i=0; i<dyn->size; ++i) {
arch_build_t* build = static_build+i;
last = arch_build(dyn, i, build);
if(i && (!memcmp(build, previous, sizeof(arch_build_t))) && (seq<((1<<10)-1))) {
// same sequence, increment
++seq;
} else {
seq = 0;
++nseq;
previous = build;
sz += sizeof_arch_build(build);
}
}
if(nseq==1 && !last)
return 0; //empty, no flags, no nothing
return sz;
}
static void build_next(arch_arch_t* arch, arch_build_t* build)
{
#define GO(A) arch->A = build->A;
SUPER()
#undef GO
arch->unaligned = build->unaligned;
arch->seq = 0;
void* p = ((void*)arch)+sizeof(arch_arch_t);
#define GO(A) \
if(build->A) { \
memcpy(p, &(build->A##_), sizeof(arch_ ##A##_t)); \
p+=sizeof(arch_##A##_t); \
}
SUPER()
#undef GO
}
void* populate_arch(dynarec_arm_t* dyn, void* p, size_t tot_sz)
{
arch_build_t* previous = NULL;
arch_arch_t* arch = p;
arch_arch_t* next = p;
int seq = 0;
size_t total = 0;
if(!tot_sz) return NULL;
for(int i=0; i<dyn->size; ++i) {
arch_build_t* build = static_build+i;
if(i && (!memcmp(build, previous, sizeof(arch_build_t))) && (seq<((1<<10)-1))) {
// same sequence, increment
seq++;
arch->seq = seq;
} else {
int sz = sizeof_arch_build(build);
if(total+sz>tot_sz) {
printf_log(LOG_INFO, "Warning: populate_arch oversized\n");
return NULL;
}
arch = next;
build_next(arch, build);
seq = 0;
previous = build;
total += sz;
next = (arch_arch_t*)((uintptr_t)arch+sz);
}
}
return p;
}
int getX64AddressInst(dynablock_t* db, uintptr_t x64pc); // define is signal.c
// NZCV N
#define NZCV_N 31
// NZCV Z
#define NZCV_Z 30
// NZCV C
#define NZCV_C 29
// NZCV V
#define NZCV_V 28
void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc)
{
if(!db->arch_size || !db->arch)
return;
int ninst = getX64AddressInst(db, x64pc);
dynarec_log(LOG_INFO, "adjust_arch(...), db=%p, x64pc=%p, nints=%d", db, (void*)x64pc, ninst);
if(ninst<0) {
dynarec_log_prefix(0, LOG_INFO, "\n");
return;
}
if(ninst==0) {
dynarec_log_prefix(0, LOG_INFO, "\n");
CHECK_FLAGS(emu);
return;
}
// look for state at ninst-1
arch_arch_t* arch = db->arch;
arch_arch_t* next = arch;
#define GO(A) arch_##A##_t* A = NULL;
SUPER()
#undef GO
int i = 0;
while(i<ninst-1) {
arch = next;
i += 1+arch->seq;
dynarec_log_prefix(0, LOG_INFO, "[ seq=%d%s%s%s%s%s ] ", arch->seq, arch->flags?" Flags":"", arch->x87?" x87":"", arch->mmx?" MMX":"", arch->sse?" SSE":"", arch->ymm?" YMM":"");
next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch));
}
int sz = sizeof(arch_arch_t);
#define GO(A) \
if(arch->A) { \
A = (arch_##A##_t*)((uintptr_t)arch + sz); \
sz+=sizeof(arch_##A##_t); \
}
SUPER()
#undef GO
if(flags) {
dynarec_log_prefix(0, LOG_INFO, " flags[%s-%s%s%s%s] ", flags->defered?"defered":"", flags->nf?"S":"", flags->vf?"O":"", flags->eq?"Z":"", flags->cf?(flags->inv_cf?"C(inv)":"C"):"");
if(flags->defered) {
CHECK_FLAGS(emu);
//return;
}
if(flags->nf) {
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_N), F_SF);
}
if(flags->vf) {
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_V), F_OF);
}
if(flags->eq) {
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_Z), F_ZF);
}
if(flags->cf) {
if(flags->inv_cf) {
CONDITIONAL_SET_FLAG((p->uc_mcontext.pstate&(1<<NZCV_C))==0, F_CF);
} else {
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_C), F_CF);
}
}
}
struct fpsimd_context *fpsimd = NULL;
// find fpsimd struct
{
struct _aarch64_ctx * ff = (struct _aarch64_ctx*)p->uc_mcontext.__reserved;
while (ff->magic && !fpsimd) {
if(ff->magic==FPSIMD_MAGIC)
fpsimd = (struct fpsimd_context*)ff;
else
ff = (struct _aarch64_ctx*)((uintptr_t)ff + ff->size);
}
}
if(sse) {
dynarec_log_prefix(0, LOG_INFO, " sse[%x (fpsimd=%p)] ", sse->sse, fpsimd);
for(int i=0; i<16; ++i)
if(fpsimd && (sse->sse>>i)&1) {
int idx = 0;
if(i>7) {
idx = XMM8 + i - 8;
} else {
idx = XMM0 + i;
}
emu->xmm[i].u128 = fpsimd->vregs[idx];
}
}
if(ymm) {
dynarec_log_prefix(0, LOG_INFO, " ymm[%x, pos=%x, 0=%x (fpsimd=%p)] ", ymm->ymm, ymm->ymm_pos, ymm->ymm0, fpsimd);
for(int i=0; i<16; ++i) {
if(fpsimd && (ymm->ymm>>i)&1) {
int idx = (ymm->ymm_pos>>(i*4))&0xf;
if(i>7) {
idx = SCRATCH0 + i - 8;
} else {
idx = EMM0 + i;
}
emu->ymm[i].u128 = fpsimd->vregs[idx];
}
if(ymm->ymm0&(1<<i))
emu->ymm[i].u128 = 0;
}
}
if(mmx) {
dynarec_log_prefix(0, LOG_INFO, " mmx[%x (fpsimd=%p)] ", mmx->mmx, fpsimd);
for(int i=0; i<8; ++i)
if(fpsimd && (mmx->mmx>>i)&1) {
int idx = EMM0 + i;
emu->mmx[i].q = fpsimd->vregs[idx]&0xffffffffffffffffLL;
}
}
if(x87) {
dynarec_log_prefix(0, LOG_INFO, " x87[%x, pos=%x, type=%x (fpsimd=%p)] ", x87->x87, x87->x87_pos, x87->x87_type, fpsimd);
emu->top -= x87->delta;
for(int i=0; i<8; ++i) {
if(x87->x87&(1<<i)) {
int idx = EMM0 + (x87->x87_pos>>(i*4))&0x0f;
int t = (x87->x87_type>>(i*2))&0x3;
switch (t) {
case X87_ST_F:
emu->x87[(emu->top+i)&7].d = *(float*)&fpsimd->vregs[idx];
break;
case X87_ST_I64:
emu->x87[(emu->top+i)&7].d = *(int64_t*)&fpsimd->vregs[idx];
break;
case X87_ST_D:
emu->x87[(emu->top+i)&7].d = *(double*)&fpsimd->vregs[idx];
break;
}
}
}
}
dynarec_log_prefix(0, LOG_INFO, "\n");
}
int arch_unaligned(dynablock_t* db, uintptr_t x64pc)
{
if(!db)
return 0;
if(!db->arch_size || !db->arch)
return 0;
int ninst = getX64AddressInst(db, x64pc);
if(ninst<0) {
return 0;
}
// look for state at ninst
arch_arch_t* arch = db->arch;
arch_arch_t* next = arch;
int i = -1;
while(i<ninst) {
arch = next;
i += 1+arch->seq;
next = (arch_arch_t*)((uintptr_t)next + sizeof_arch(arch));
}
return arch->unaligned;
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef __DYNAREC_ARM_ARCH_H__
#define __DYNAREC_ARM_ARCH_H__
#include <stddef.h>
#include <ucontext.h>
#include "x64emu.h"
#include "box64context.h"
#include "dynarec.h"
#include "dynarec_arm64_private.h"
// get size of arch specific info (can be 0)
size_t get_size_arch(dynarec_arm_t* dyn);
//populate the array
void* populate_arch(dynarec_arm_t* dyn, void* p, size_t sz);
//adjust flags and more
void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc);
// get if instruction can be regenerated for unaligned access
int arch_unaligned(dynablock_t* db, uintptr_t x64pc);
#endif // __DYNAREC_ARM_ARCH_H__
+3 -2
View File
@@ -71,8 +71,9 @@ uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = dynarec64_AVX_F3_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else {DEFAULT;}
if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
if((*ok==-1) && (BOX64ENV(dynarec_log)>=LOG_INFO || BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_missing)==1))
if(!dyn->size || BOX64ENV(dynarec_log)>LOG_INFO || BOX64DRENV(dynarec_dump)) {
dynarec_log(LOG_NONE, "Dynarec unimplemented AVX opcode size %d prefix %s map %s opcode %02X ", 128<<vex.l, avx_prefix_string(vex.p), avx_map_string(vex.m), opcode);
}
return addr;
}
+140 -39
View File
@@ -290,7 +290,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
FCMPS(v0, s0);
FCOMI(x1, x2, 0, v0, s0, 1); //disable precise cmp
FCOMI(x1, x2);
break;
case 0x50:
@@ -302,7 +302,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
// EX is an xmm reg
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v0, 0, 0); } else { GETEY(v0); }
if(!l) { GETEX_Y(v0, 0, 0); } else { GETEY(v0); }
SQXTN_16(q0, v0); // reduces the 4 32bits to 4 16bits
VMOVQDto(x1, q0, 0);
LSRx(x1, x1, 15);
@@ -440,22 +440,50 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x58:
INST_NAME("VADDPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFADDQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFADDQS(v0, v2, v1);
} else YMM0(gd)
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd)
break;
case 0x59:
INST_NAME("VMULPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFMULQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFMULQS(v0, v2, v1);
} else YMM0(gd)
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTPS2PD Gx, Ex");
@@ -480,17 +508,31 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x5C:
INST_NAME("VSUBPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFSUBQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFSUBQS(v0, v2, v1);
} else YMM0(gd)
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINPS Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
@@ -498,7 +540,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMINQS(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v2!=v1)) {
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
@@ -508,17 +550,31 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0x5E:
INST_NAME("VDIVPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VFDIVQS(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFDIVQS(v0, v2, v1);
} else YMM0(gd)
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXPS Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
@@ -526,7 +582,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMAXQS(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v2!=v1)) {
VFCMEQQS(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
@@ -568,19 +624,52 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("VLDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
if(box64_sse_flushto0) {
MRS_fpcr(x1); // get fpscr
if(BOX64ENV(sse_flushto0)) {
MRS_fpcr(x2); // get fpscr
LSRw_IMM(x3, ed, 15); // get FZ bit
BFIw(x1, x3, 24, 1); // inject FZ bit
BFIw(x2, x3, 24, 1); // inject FZ bit
EORw_REG_LSR(x3, x3, ed, 1); // FZ xor DAZ
BFIw(x1, x3, 1, 1); // inject AH bit
MSR_fpcr(x1); // put new fpscr
BFIw(x2, x3, 1, 1); // inject AH bit
MSR_fpcr(x2); // put new fpscr
}
if(BOX64ENV(sse_flushto0)) {
// try to sync mxcsr with fpsr on the flag side
/* mapping is
ARM -> X86
0 -> 0 // Invalid operation
1 -> 2 // Divide by 0
2 -> 3 // Overflow
3 -> 4 // underflow
4 -> 5 // Inexact
5 -> 1 // denormal
*/
// doing X86 -> ARM here, 0 1 2 3 4 5 -> 0 2 3 4 5 1
if(ed!=x1)
MOVw_REG(x1, ed); // x1 = 543210
RORw(x3, x1, 2); // x3 = 10.....5432
BFIw(x1, x3, 1, 4); // x1 = 54320
RORw(x3, x3, 32-1); // x3 = 0.....54321
BFIw(x1, x3, 5, 1); // x1 = 154320
MRS_fpsr(x2);
BFIx(x2, x1, 0, 6);
MSR_fpsr(x2);
}
break;
case 3:
INST_NAME("VSTMXCSR Md");
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
LDRw_U12(x4, xEmu, offsetof(x64emu_t, mxcsr));
if(BOX64ENV(sse_flushto0)) {
// sync with fpsr, with mask from mxcsr
MRS_fpsr(x1);
// doing ARM -> X86 here, 543210 => 432150
UBFXw(x2, x1, 1, 5); // x2 = 54321
BFIw(x1, x2, 2, 4); // x1 = 432110
LSRw(x2, x2, 4); // x2 = 5
BFIw(x1, x2, 1, 1); // x1 = 432150
//BFXILw(x3, x4, 7, 6); // this would the mask, but let's ignore that for now
BFIw(x4, x1, 0, 6); // inject back the flags
}
STW(x4, ed, fixedaddress);
break;
default:
@@ -634,15 +723,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
if(v2==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
VDUPQ_32(v0, v2, u8&3);
} else if(v2==v1 && (u8==0xe0)) { // easy special case
} else if(v2==v1 && (u8==0xe0)) { // elements 3 2 0 0
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) { // easy special case
} else if(v2==v1 && (u8==0xe5)) { // elements 3 2 1 1
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
} else if(v2==v1 && (u8==0xa0)) { // elements 2 2 0 0
VTRNQ1_32(v0, v1, v2);
} else if(v2==v1 && (u8==0xf5)) { // elements 3 3 1 1
VTRNQ2_32(v0, v1, v2);
} else if(v2==v1 && (u8==0xb1)) { // elements 2 3 0 1
VREV64Q_32(v0, v1);
} else if(MODREG && u8==0x88) { // elements 2 0 2 0
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
} else if(MODREG && u8==0xdd) { // elements 3 1 3 1
VUZP2Q_32(v0, v2, v1);
} else {
if((v0==v1) || (v0==v2)) {
@@ -674,15 +769,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGY_empty_VY(v0, v2, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
if(v2==v1 && (u8&0x3)==((u8>>2)&3) && (u8&0xf)==((u8>>4)&0xf)) {
VDUPQ_32(v0, v2, u8&3);
} else if(v2==v1 && (u8==0xe0)) {
} else if(v2==v1 && (u8==0xe0)) { // elements 3 2 0 0
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) {
} else if(v2==v1 && (u8==0xe5)) { // elements 3 2 1 1
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
} else if(v2==v1 && (u8==0xa0)) { // elements 2 2 0 0
VTRNQ1_32(v0, v1, v2);
} else if(v2==v1 && (u8==0xf5)) { // elements 3 3 1 1
VTRNQ2_32(v0, v1, v2);
} else if(v2==v1 && (u8==0xb1)) { // elements 2 3 0 1
VREV64Q_32(v0, v1);
} else if(MODREG && u8==0x88) { // elements 2 0 2 0
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
} else if(MODREG && u8==0xdd) { // elements 3 1 3 1
VUZP2Q_32(v0, v2, v1);
} else {
if(s0) d0 = v0;
+165 -24
View File
@@ -39,6 +39,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
int q0, q1, q2;
int d0, d1, d2;
int s0;
int need_tst;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
@@ -68,21 +69,32 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
GETGD;
GETED(0);
GETVD;
IFX(X_ZF)
need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
IFXNATIVE(X_CF, NF_CF) need_tst = 1;
if(need_tst)
BICSxw(gd, ed, vd);
else
BICxw(gd, ed, vd);
IFX(X_ZF) {
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF)
BFCw(xFlags, F_OF, 1);
IFX(X_CF)
BFCw(xFlags, F_CF, 1);
IFX(X_SF) {
LSRxw_IMM(x1, gd, rex.w?63:31);
BFIw(xFlags, x1, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw_IMM(x1, gd, rex.w?63:31);
BFIw(xFlags, x1, F_SF, 1);
}
}
break;
case 0xF3:
@@ -99,24 +111,108 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
BFIw(xFlags, x3, F_CF, 1);
}
SUBxw_U12(x3, ed, 1);
IFX(X_ZF)
need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
if(need_tst)
ANDSxw_REG(vd, ed, x3);
else
ANDxw_REG(vd, ed, x3);
IFX(X_ZF) {
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(x3, vd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(x3, vd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
}
IFX(X_OF) BFCw(xFlags, F_OF, 1);
if(box64_dynarec_test) {
IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
if (BOX64ENV(dynarec_test)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
}
break;
case 2:
INST_NAME("BLSMSK Vd, Ed");
SETFLAGS(X_ALL, SF_SET);
GETED(0);
GETVD;
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1);
}
SUBxw_U12(x3, ed, 1);
need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
EORxw_REG(vd, ed, x3);
if(need_tst)
TSTxw_REG(vd, vd);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw(x3, vd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
}
IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
if (BOX64ENV(dynarec_test)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
}
break;
case 3:
INST_NAME("BLSI Vd, Ed");
SETFLAGS(X_ALL, SF_SET);
GETED(0);
GETVD;
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1);
}
NEGxw_REG(x3, ed);
need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
if(need_tst)
ANDSxw_REG(vd, ed, x3);
else
ANDxw_REG(vd, ed, x3);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETMw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw(x3, vd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
}
IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
if (BOX64ENV(dynarec_test)) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
}
break;
default:
DEFAULT;
}
@@ -131,27 +227,72 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
GETVD;
UXTBw(x1, vd);
CMPSw_U12(x1, rex.w?64:32);
CSETxw(x2, cPL);
IFX(F_CF) {
CSETMxw(x2, cPL);
IFX(X_CF) {
BFIw(xFlags, x2, F_CF, 1);
}
MVNxw_REG(x2, x2); //prepare mask
B_MARK(cPL);
LSLxw_REG(x2, x2, x1);
MARK;
IFX(X_ZF) {
need_tst = 0;
IFX(X_ZF) need_tst = 1;
IFXNATIVE(X_SF, NF_SF) need_tst = 1;
IFXNATIVE(X_OF, NF_VF) need_tst = 1;
if(need_tst) {
BICSxw(gd, ed, x2);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
} else
BICxw(gd, ed, x2);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(x3, gd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(x3, gd, rex.w?63:31);
BFIw(xFlags, x3, F_SF, 1);
}
}
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_OF) BFCw(xFlags, F_OF, 1);
IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
break;
case 0xF7:
INST_NAME("BEXTR Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET);
GETGD;
GETED(0);
GETVD;
MOV64xw(x1, 0);
UXTBw(x2, vd); // start
BFXILw(x3, vd, 8, 8); // length
TSTw_REG(x3, x3);
B_MARK(cEQ);
LSRxw_REG(x1, ed, x2);
CMPSw_U12(x3, rex.w?64:32);
B_MARK(cGE);
MOV32w(x2, rex.w?64:32);
SUBw_REG(x2, x2, x3);
LSLxw_REG(x1, x1, x2);
LSRxw_REG(x1, x1, x2);
TSTxw_REG(x1, x1);
MARK;
MOVxw_REG(gd, x1);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
}
}
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
IFX(X_CF) BFCw(xFlags, F_CF, 1);
IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
IFX(X_SF) IFNATIVE(NF_SF) {} else {BFCw(xFlags, F_SF, 1);}
break;
default:
+67 -54
View File
@@ -56,9 +56,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
#if STEP > 1
static const int8_t mask_shift8[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
#endif
/* Remember to not create a new fpu_scratch after some GY/VY/EY is created, because Y can be in the scratch area and might overlap (and scratch will win) */
@@ -273,7 +270,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
GETGX(v0, 0);
GETEXSD(q0, 0, 0);
FCMPD(v0, q0);
FCOMI(x1, x2, 0, v0, q0, 0); //disable precise cmp
FCOMI(x1, x2);
break;
case 0x50:
@@ -298,13 +295,13 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x51:
INST_NAME("VSQRTPD Gx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 0); } else { GETGY_empty_EY(v0, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFCMEQQD(d0, v1, v1); // 0 if NAN, 1 if not NAN
VFSQRTQD(v0, v1);
@@ -362,19 +359,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x58:
INST_NAME("VADDPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFADDQD(v0, v2, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -386,19 +383,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x59:
INST_NAME("VMULPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFMULQD(v0, v2, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -410,9 +407,9 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5A:
INST_NAME("VCVTPD2PS Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
if(box64_dynarec_fastround==2) {
if(BOX64ENV(dynarec_fastround)==2) {
FCVTXN(v0, v1);
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x4);
@@ -421,7 +418,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
}
if(vex.l) {
GETEY(v1);
if(box64_dynarec_fastround==2) {
if(BOX64ENV(dynarec_fastround)==2) {
FCVTXN2(v0, v1);
} else {
FCVTN2(v0, v1);
@@ -434,14 +431,14 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VCVTPS2DQ Gx, Ex");
nextop = F8;
u8 = sse_setround(dyn, ninst, x1, x2, x6);
if(!box64_dynarec_fastround && !arm64_frintts) {
if(!BOX64ENV(dynarec_fastround) && !arm64_frintts) {
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
MOVI_32_lsl(d1, 0x80, 3);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v1, 0, 0); GETGX_empty(v0); } else { GETGY_empty_EY(v0, v1); }
if(box64_dynarec_fastround) {
if(!l) { GETEX_Y(v1, 0, 0); GETGX_empty(v0); } else { GETGY_empty_EY(v0, v1); }
if(BOX64ENV(dynarec_fastround)) {
VFRINTISQ(v0, v1);
VFCVTZSQS(v0, v0);
} else {
@@ -457,7 +454,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
FRINTIS(d0, d0);
VFCVTZSs(d0, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TSTw_mask(x5, 0, 0); // mask=1
TSTw_mask(x5, 0, 0); // mask=(1<<IOC)
FCSELS(d0, d0, d1, cEQ);
VMOVeS(v0, i, d0, 0);
}
@@ -470,19 +467,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5C:
INST_NAME("VSUBPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQD(q0, v1, v2); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFSUBQD(v0, v2, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -494,14 +491,14 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5D:
INST_NAME("VMINPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan)
if(!BOX64ENV(dynarec_fastnan))
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMINQD(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v2!=v1)) {
VFCMEQQD(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
@@ -511,19 +508,19 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5E:
INST_NAME("DIVPD Gx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFDIVQD(v0, v2, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -535,7 +532,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5F:
INST_NAME("VMAXPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
@@ -543,7 +540,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
// FMIN/FMAX wll not copy a NaN if either is NaN
// but x86 will copy src2 if either value is NaN, so lets force a copy of Src2 (Ex) if result is NaN
VFMAXQD(v0, v2, v1);
if(!box64_dynarec_fastnan && (v2!=v1)) {
if(!BOX64ENV(dynarec_fastnan) && (v2!=v1)) {
VFCMEQQD(q0, v0, v0); // 0 is NaN, 1 is not NaN, so MASK for NaN
VBIFQ(v0, v1, q0); // copy dest where source is NaN
}
@@ -1128,13 +1125,13 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x7C:
INST_NAME("VHADDPD Gx, Vx, Ex");
nextop = F8;
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
// but need to mix low/high part
VTRNQ1_64(q0, v2, v1);
@@ -1143,7 +1140,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFADDPQD(v0, v2, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -1189,11 +1186,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
VMOVQ(v1, v0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xffe<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
VST128(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
@@ -1254,7 +1251,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGD;
if(MODREG) {
GETEX(v0, 0, 1);
GETEX(v0, 0, 1); // no vex.l case
u8 = (F8)&7;
VMOVHto(gd, v0, u8);
} else {
@@ -1396,9 +1393,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
GETEX_Y(q0, 0, 0);
GETGD;
TABLE64(x2, (uintptr_t)&mask_shift8);
VLDR64_U12(v0, x2, 0); // load shift
VDUPQ_64(v0, v0, 0);
TABLE64(x2, 0x0706050403020100LL);
VDUPQD(v0, x2);
VSHRQ_8(q1, q0, 7);
USHLQ_8(q1, q1, v0); // shift
UADDLV_8(v1, q1); // accumalte
@@ -1620,11 +1616,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
} else {
if(box64_dynarec_fastround)
if(BOX64ENV(dynarec_fastround))
d0 = fpu_get_scratch(dyn, ninst);
GETEY(v1);
}
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFCVTZSQD(l?d0:v0, v1); // convert double -> int64
if(!l)
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
@@ -1796,12 +1792,13 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
GETEX_Y(v1, 0, 0);
UQXTN_32(q0, v1);
MOVI_32(q1, 16);
UMIN_32(q0, q0, q1); // limit to 0 .. +16 values
VDUPQ_16(q0, q0, 0); // only the low 8bits will be used anyway
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
UQXTN_32(q0, v1);
UMIN_32(q0, q0, q1); // limit to 0 .. +16 values
VDUPQ_16(q0, q0, 0); // only the low 8bits will be used anyway
if(!l) { GETGX_empty_VX(v0, v2); } else { GETGY_empty_VY(v0, v2, 0, -1, -1); }
USHLQ_16(v0, v2, q0);
}
if(!vex.l) YMM0(gd);
@@ -1811,12 +1808,13 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
GETEX_Y(v1, 0, 0);
UQXTN_32(q0, v1);
MOVI_32(q1, 32);
UMIN_32(q0, q0, q1); // limit to 0 .. +32 values
VDUPQ_32(q0, q0, 0); // only the low 8bits will be used anyway
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
UQXTN_32(q0, v1);
UMIN_32(q0, q0, q1); // limit to 0 .. +32 values
VDUPQ_32(q0, q0, 0); // only the low 8bits will be used anyway
if(!l) { GETGX_empty_VX(v0, v2); } else { GETGY_empty_VY(v0, v2, 0, -1, -1); }
USHLQ_32(v0, v2, q0);
}
if(!vex.l) YMM0(gd);
@@ -1826,12 +1824,13 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
GETEX_Y(v1, 0, 0);
UQXTN_32(q0, v1);
MOVI_32(q1, 64);
UMIN_32(q0, q0, q1); // limit to 0 .. +64 values
VDUPQ_64(q0, q0, 0); // only the low 8bits will be used anyway
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
UQXTN_32(q0, v1);
UMIN_32(q0, q0, q1); // limit to 0 .. +64 values
VDUPQ_64(q0, q0, 0); // only the low 8bits will be used anyway
if(!l) { GETGX_empty_VX(v0, v2); } else { GETGY_empty_VY(v0, v2, 0, -1, -1); }
USHLQ_64(v0, v2, q0);
}
if(!vex.l) YMM0(gd);
@@ -1881,7 +1880,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
}
if(!vex.l) YMM0(gd);
break;
case 0xF7:
INST_NAME("VMASKMOVDQU Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0); //no vex.l case
v0 = fpu_get_scratch(dyn, ninst);
VLDR128_U12(v0, xRDI, 0);
if(MODREG)
v1 = fpu_get_scratch(dyn, ninst); // need to preserve the register
else
v1 = q1;
VSSHRQ_8(v1, q1, 7); // get the mask
VBITQ(v0, q0, v1);
VSTR128_U12(v0, xRDI, 0); // put back
break;
case 0xF8:
INST_NAME("VPSUBB Gx, Vx, Ex");
nextop = F8;
+477 -129
View File
@@ -26,6 +26,8 @@
static const float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
static const double addsubpd[2] = {-1., 1.};
static const float subaddps[4] = {1.f, -1.f, 1.f, -1.f};
static const double subaddpd[2] = {1., -1.};
uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -97,7 +99,18 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
}
if(!vex.l) YMM0(gd);
break;
case 0x03:
INST_NAME("VPHADDSW Gx, Vx, Ex");
nextop = F8;
v0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 0); } else { GETGY_empty_VYEY(q0, q2, q1); }
VUZP2Q_16(v0, q2, q1);
VUZP1Q_16(q0, q2, q1);
SQADDQ_16(q0, q0, v0);
}
if(!vex.l) YMM0(gd);
break;
case 0x04:
INST_NAME("PMADDUBSW Gx, Vx, Ex");
nextop = F8;
@@ -124,7 +137,42 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
}
if(!vex.l) YMM0(gd);
break;
case 0x05:
INST_NAME("VPHSUBW Gx, Vx, Ex");
nextop = F8;
v0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 0); } else { GETGY_empty_VYEY(q0, q2, q1); }
VUZP2Q_16(v0, q2, q1);
VUZP1Q_16(q0, q2, q1);
VSUBQ_16(q0, q0, v0);
}
if(!vex.l) YMM0(gd);
break;
case 0x06:
INST_NAME("VPHSUBD Gx, Vx, Ex");
nextop = F8;
v0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 0); } else { GETGY_empty_VYEY(q0, q2, q1); }
VUZP2Q_32(v0, q2, q1);
VUZP1Q_32(q0, q2, q1);
VSUBQ_32(q0, q0, v0);
}
if(!vex.l) YMM0(gd);
break;
case 0x7:
INST_NAME("VPHSUBSW Gx, Vx, Ex");
nextop = F8;
v0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 0); } else { GETGY_empty_VYEY(q0, q2, q1); }
VUZP2Q_16(v0, q2, q1);
VUZP1Q_16(q0, q2, q1);
SQSUBQ_16(q0, q0, v0);
}
if(!vex.l) YMM0(gd);
break;
case 0x08:
INST_NAME("VPSIGNB Gx, Vx, Ex");
nextop = F8;
@@ -204,6 +252,109 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!vex.l) YMM0(gd);
break;
case 0x0E:
INST_NAME("VTESTPS GX, EX");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
GETEX_Y(v1, 0, 0);
v2 = fpu_get_scratch(dyn, ninst);
if(vex.l) {
if(!MODREG)
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETGY(q0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1);
GETEY(q1);
}
IFX(X_CF) {
VBICQ(v2, v1, v0);
VSHRQ_32(v2, v2, 31);
if(vex.l) {
VBICQ(q2, q1, q0);
VSHRQ_32(q2, q2, 31);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_CF, 1);
}
IFX(X_ZF) {
VANDQ(v2, v0, v1);
VSHRQ_32(v2, v2, 31);
if(vex.l) {
VANDQ(q2, q0, q1);
VSHRQ_32(q2, q2, 31);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_ZF, 1);
}
}
IFX(X_AF|X_SF|X_OF|X_PF) {
MOV32w(x2, (1<<F_AF) | (1<<F_OF) | (1<<F_SF) | (1<<F_PF));
BICw(xFlags, xFlags, x2);
}
break;
case 0x0F:
INST_NAME("VTESTPD GX, EX");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
GETEX_Y(v1, 0, 0);
v2 = fpu_get_scratch(dyn, ninst);
if(vex.l) {
if(!MODREG)
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETGY(q0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1);
GETEY(q1);
}
IFX(X_CF) {
VBICQ(v2, v1, v0);
VSHRQ_64(v2, v2, 63);
if(vex.l) {
VBICQ(q2, q1, q0);
VSHRQ_64(q2, q2, 63);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_CF, 1);
}
IFX(X_ZF) {
VANDQ(v2, v0, v1);
VSHRQ_64(v2, v2, 63);
if(vex.l) {
VANDQ(q2, q0, q1);
VSHRQ_64(q2, q2, 63);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_ZF, 1);
}
}
IFX(X_AF|X_SF|X_OF|X_PF) {
MOV32w(x2, (1<<F_AF) | (1<<F_OF) | (1<<F_SF) | (1<<F_PF));
BICw(xFlags, xFlags, x2);
}
break;
case 0x13:
INST_NAME("VCVTPH2PS Gx, Ex");
nextop = F8;
@@ -241,6 +392,8 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
VLDR128_U12(d0, ed, fixedaddress);
VLDR128_U12(d1, ed, fixedaddress+16);
}
MOV32w(x3, 0x03020100);
VDUPQS(q1, x3);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETVX(v2, 0);
@@ -253,14 +406,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
MOVIQ_32(q0, 7); // index and 7
VANDQ(q0, v2, q0);
SQXTN_16(q0, q0); // index in 16bits
VSHL_16(q0, q0, 1); // double the index
VZIP1Q_16(q0, q0, q0); // repeat the index by pair
MOVIQ_32_lsl(q1, 1, 2); // q1 as 16bits is 0 / 1
VADDQ_16(q0, q0, q1);
SQXTN_8(q0, q0); // index in 8bits
VSHL_8(q0, q0, 1); // double the index
VSHL_8(q0, q0, 2); // quadruple the indexes
VZIP1Q_8(q0, q0, q0); // repeat the index by pair
MOVIQ_16(q1, 1, 1);
VADDQ_8(q0, q0, q1);
// fetch the datas
VTBLQ2_8(v0, d0, q0);
@@ -272,35 +421,21 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
GETEX(v1, 0, 0);
} else {
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
}
GETEX_Y(v1, 0, 0);
v2 = fpu_get_scratch(dyn, ninst);
if(vex.l) {
GETGY(v0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1);
if(MODREG) {
GETEY(v1);
} else {
VLDR128_U12(v1, ed, fixedaddress+16);
}
} else {
if(!MODREG)
VLDR128_U12(v1, ed, fixedaddress);
}
IFX(X_ZF) {
VANDQ(v2, v0, v1);
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_ZF, 1);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETGY(q0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1);
GETEY(q1);
}
IFX(X_CF) {
VBICQ(v2, v1, v0);
if(vex.l) {
VBICQ(q2, q1, q0);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
@@ -308,6 +443,21 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_CF, 1);
}
IFX(X_ZF) {
VANDQ(v2, v0, v1);
if(vex.l) {
VANDQ(q2, q0, q1);
VORRQ(v2, v2, q2);
}
CMEQQ_0_64(v2, v2);
UQXTN_32(v2, v2);
VMOVQDto(x2, v2, 0);
ADDSx_U12(xZR, x2, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(x2, cEQ);
BFIw(xFlags, x2, F_ZF, 1);
}
}
IFX(X_AF|X_SF|X_OF|X_PF) {
MOV32w(x2, (1<<F_AF) | (1<<F_OF) | (1<<F_SF) | (1<<F_PF));
BICw(xFlags, xFlags, x2);
@@ -318,16 +468,16 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn, ninst);
VLD32(v1, ed, fixedaddress);
}
GETGX_empty(v0);
VDUPQ_32(v0, v1, 0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
GETGX_empty(v0);
VDUPQ_32(v0, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
GETGX_empty(v0);
VLDQ1R_32(v0, ed);
}
if(vex.l) {
GETGY_empty(v1, -1, -1, -1);
VMOVQ(v1, v0);
} else YMM0(gd);
break;
case 0x19:
@@ -335,16 +485,16 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn, ninst);
VLD64(v1, ed, fixedaddress);
}
GETGX_empty(v0);
VDUPQ_64(v0, v1, 0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
GETGX_empty(v0);
VDUPQ_64(v0, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
GETGX_empty(v0);
VLDQ1R_64(v0, ed);
}
if(vex.l) {
GETGY_empty(v1, -1, -1, -1);
VMOVQ(v1, v0);
} else YMM0(gd);
break;
case 0x1A:
@@ -394,7 +544,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
case 0x20:
INST_NAME("VPMOVSXBW Gx, Ex");
nextop = F8;
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);}
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);} //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -433,7 +583,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
case 0x23:
INST_NAME("VPMOVSXWD Gx, Ex");
nextop = F8;
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);}
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);} //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -457,7 +607,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
case 0x25:
INST_NAME("VPMOVSXDQ Gx, Ex");
nextop = F8;
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);}
if(vex.l) {GETEX(q1, 0, 0);} else {GETEX64(q1, 0, 0);} //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -495,7 +645,15 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
}
if(!vex.l) YMM0(gd);
break;
case 0x2A:
INST_NAME("VMOVNTDQA Gx, Ex");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 0); } else { GETGY_empty_EY(v0, v1); }
VMOVQ(v0, v1);
}
if(!vex.l) YMM0(gd);
break;
case 0x2B:
INST_NAME("VPACKUSDW Gx, Ex, Vx");
nextop = F8;
@@ -523,29 +681,115 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
case 0x2C:
INST_NAME("VMASKMOVPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
GETVX(v2, 0);
GETGX_empty(v0);
q0 = fpu_get_scratch(dyn, ninst);
// create mask
VSSHRQ_32(q0, v2, 31);
VANDQ(v0, v1, q0);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VSSHRQ_32(q0, v2, 31);
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x3, (nextop & 7) + (rex.b << 3), 0);
VANDQ(v0, v1, q0);
} else {
VEORQ(v0, v0, v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x3) {
MOVz_REG(x3, ed);
ed = x3;
}
VMOVSto(x4, q0, 0);
CBZw(x4, 4+1*4);
VLD1_32(v0, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZw(x4, 4+1*4);
VLD1_32(v0, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZw(x4, 4+1*4);
VLD1_32(v0, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZw(x4, 4+1*4);
VLD1_32(v0, 3, ed);
if(vex.l)
ADDx_U12(ed, ed, 4);
}
if(vex.l) {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
VSSHRQ_32(q0, v2, 31);
if(MODREG) {
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1);
VANDQ(v0, v1, q0);
} else {
VEORQ(v0, v0, v0);
VMOVSto(x4, q0, 0);
CBZw(x4, 4+1*4);
VLD1_32(v0, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZw(x4, 4+1*4);
VLD1_32(v0, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZw(x4, 4+1*4);
VLD1_32(v0, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZw(x4, 4+1*4);
VLD1_32(v0, 3, ed);
}
} else YMM0(gd);
break;
case 0x2D:
INST_NAME("VMASKMOVPD Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
GETVX(v2, 0);
GETGX_empty(v0);
q0 = fpu_get_scratch(dyn, ninst);
// create mask
VSSHRQ_64(q0, v2, 63);
VANDQ(v0, v1, q0);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VSSHRQ_64(q0, v2, 63);
VEORQ(v0, v0, v0);
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x3, (nextop & 7) + (rex.b << 3), 0);
VANDQ(v0, v1, q0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x3) {
MOVz_REG(x3, ed);
ed = x3;
}
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VLD1_64(v0, 0, ed);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VLD1_64(v0, 1, ed);
if(vex.l)
ADDx_U12(ed, ed, 8);
}
if(vex.l) {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
VSSHRQ_64(q0, v2, 63);
VEORQ(v0, v0, v0);
if(MODREG)
{
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1);
VANDQ(v0, v1, q0);
}
else
{
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VLD1_64(v0, 0, ed);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VLD1_64(v0, 1, ed);
}
} else YMM0(gd);
break;
case 0x2E:
@@ -557,37 +801,58 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
VSSHRQ_32(q0, v2, 31);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x3, (nextop&7)+(rex.b<<3), 1);
VBITQ(v1, v0, q0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
unscaled = 0;
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x3) {
MOVz_REG(x3, ed);
ed = x3;
}
// check if mask as anything, else skip the whole read/write to avoid a SEGFAULT.
// TODO: let a segfault trigger and check if the mask is null instead and ignore the segfault / actually triger: needs to implement SSE reg tracking first!
SQXTN_32(v1, q0);
VMOVQDto(x4, v1, 0);
CBZx(x4, 4+3*4);
VLDR128_U12(v1, ed, fixedaddress);
}
// create mask
VBITQ(v1, v0, q0);
if(!MODREG) {
VSTR128_U12(v1, ed, fixedaddress);
VMOVSto(x4, q0, 0);
CBZw(x4, 4+1*4);
VST1_32(v0, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZw(x4, 4+1*4);
VST1_32(v0, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZw(x4, 4+1*4);
VST1_32(v0, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZw(x4, 4+1*4);
VST1_32(v0, 3, ed);
if(vex.l)
ADDx_U12(ed, ed, 4);
}
if(vex.l && !is_avx_zero(dyn, ninst, vex.v)) {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
VSSHRQ_32(q0, v2, 31);
if(MODREG)
if(MODREG) {
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1, gd, vex.v, -1);
else {
SQXTN_32(v1, q0);
VMOVQDto(x4, v1, 0);
CBZx(x4, 4+3*4);
VLDR128_U12(v1, ed, fixedaddress+16);
VBITQ(v1, v0, q0);
}
VBITQ(v1, v0, q0);
if(!MODREG) {
VSTR128_U12(v1, ed, fixedaddress+16);
else {
VMOVSto(x4, q0, 0);
CBZw(x4, 4+1*4);
VST1_32(v0, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZw(x4, 4+1*4);
VST1_32(v0, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZw(x4, 4+1*4);
VST1_32(v0, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZw(x4, 4+1*4);
VST1_32(v0, 3, ed);
}
}
break;
@@ -595,43 +860,49 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
INST_NAME("VMASKMOVPD Ex, Gx, Vx");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
GETVX(v2, 0);
GETGX(v0, 0);
VSSHRQ_64(q0, v2, 63);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x3, (nextop&7)+(rex.b<<3), 1);
VBITQ(v1, v0, q0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x3) {
MOVz_REG(x3, ed);
ed = x3;
}
unscaled = 0;
v1 = fpu_get_scratch(dyn, ninst);
// check if mask as anything, else skip the whole read/write to avoid a SEGFAULT.
// TODO: let a segfault trigger and check if the mask is null instead and ignore the segfault / actually triger: needs to implement SSE reg tracking first!
SQXTN_32(q1, q0);
VMOVQDto(x4, q1, 0);
CBZx(x4, 4+3*4);
VLDR128_U12(v1, ed, fixedaddress);
}
// create mask
VBITQ(v1, v0, q0);
if(!MODREG) {
VSTR128_U12(v1, ed, fixedaddress);
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VST1_64(v0, 0, ed);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VST1_64(v0, 1, ed);
if(vex.l)
ADDx_U12(ed, ed, 8);
}
if(vex.l && !is_avx_zero(dyn, ninst, vex.v)) {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
VSSHRQ_64(q0, v2, 63);
if(MODREG)
if(MODREG) {
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1, gd, vex.v, -1);
else {
SQXTN_32(q1, q0);
VMOVQDto(x4, q1, 0);
CBZx(x4, 4+3*4);
VLDR128_U12(v1, ed, fixedaddress+16);
VBITQ(v1, v0, q0);
}
VBITQ(v1, v0, q0);
if(!MODREG) {
VSTR128_U12(v1, ed, fixedaddress+16);
else {
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VST1_64(v0, 0, ed);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VST1_64(v0, 1, ed);
}
}
break;
@@ -639,7 +910,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
INST_NAME("VPMOVZXBW Gx, Ex");
nextop = F8;
GETG;
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); }
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); } //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -681,7 +952,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
INST_NAME("VPMOVZXWD Gx, Ex");
nextop = F8;
GETG;
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); }
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); } //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -707,7 +978,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
INST_NAME("VPMOVZXDQ Gx, Ex");
nextop = F8;
GETG;
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); }
if(vex.l) { GETEX(q1, 0, 0); } else { GETEX64(q1, 0, 0); YMM0(gd); } //no GETEY
GETGX_empty(q0);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
@@ -807,9 +1078,9 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!vex.l) YMM0(gd);
break;
case 0x41:
INST_NAME("PHMINPOSUW Gx, Ex");
INST_NAME("VPHMINPOSUW Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETEX(v1, 0, 0); //no vex.l case
GETGX_empty(v0);
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
@@ -1014,6 +1285,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!l) {
GETGX_empty_VX(v0, v2);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x3) {
MOVx_REG(x3, ed);
ed = x3;
}
v1 = fpu_get_scratch(dyn, ninst);
} else {
GETGY_empty_VY(v0, v2, 0, -1, -1);
@@ -1027,12 +1302,12 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VLD1_64(v1, 0, ed);
ADDx_U12(ed, ed, 4);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VLD1_64(v1, 1, ed);
if(!l && vex.l)
ADDx_U12(ed, ed, 4);
ADDx_U12(ed, ed, 8);
} else {
VSSHRQ_32(q0, v2, 31);
VMOVSto(x4, q0, 0);
@@ -1064,31 +1339,65 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX(v0, 0); GETVX(v2, 0);
if(MODREG) {
if(MODREG) {
if(!l) {
GETGX(v0, 0); GETVX(v2, 0);
s0 = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, s0);
} else {
GETGY(v0, 0, vex.v, s0, -1); v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1);
v1 = ymm_get_reg_empty(dyn, ninst, x1, s0, gd, vex.v, -1);
}
if(rex.w)
VSSHRQ_64(q0, v2, 63);
else
VSSHRQ_32(q0, v2, 31);
VBITQ(v1, v0, q0);
} else {
if(!l) {
GETGX(v0, 0); GETVX(v2, 0);
s0 = -1;
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
EORx_REG(x4, x4, x4);
} else {
GETGY(v0, 0, vex.v, s0, -1); v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1);
}
if(rex.w)
{
VSSHRQ_64(q0, v2, 63);
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VST1_64(v0, 0, ed);
ADDx_U12(ed, ed, 8);
VMOVQDto(x4, q0, 1);
CBZx(x4, 4+1*4);
VST1_64(v0, 1, ed);
if(!l && vex.l)
ADDx_U12(ed, ed, 8);
}
} else {
GETGY(v0, 0, vex.v, s0, -1); v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1);
if(MODREG)
v1 = ymm_get_reg_empty(dyn, ninst, x1, s0, gd, vex.v, -1);
else
VLDR128_U12(v1, ed, fixedaddress+16);
{
VSSHRQ_32(q0, v2, 31);
VMOVSto(x4, q0, 0);
CBZx(x4, 4+1*4);
VST1_32(v0, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZx(x4, 4+1*4);
VST1_32(v0, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZx(x4, 4+1*4);
VST1_32(v0, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZx(x4, 4+1*4);
VST1_32(v0, 3, ed);
if(!l && vex.l)
ADDx_U12(ed, ed, 4);
}
}
if(rex.w)
VSSHRQ_64(q0, v2, 63);
else
VSSHRQ_32(q0, v2, 31);
VBITQ(v1, v0, q0);
if(!MODREG)
VSTR128_U12(v1, ed, fixedaddress+16*l);
}
// no raz of upper ymm
break;
@@ -1502,7 +1811,29 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
}
if(!vex.l) YMM0(gd);
break;
case 0xB7:
INST_NAME("VFMSUBADD231PS/D Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
TABLE64(x2, (rex.w)?((uintptr_t)&subaddpd):((uintptr_t)&subaddps));
VLDR128_U12(q0, x2, 0);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_VXEX(v0, v2, v1, 0); if(v0==v2 || v0==v1) q1 = fpu_get_scratch(dyn, ninst); } else { GETGY_VYEY(v0, v2, v1); }
if(v0!=v1 && v0!=v2) {
q1 = v0;
}
if(rex.w) {
VFMULQD(q1, v0, q0);
VFMLAQD(q1, v1, v2);
} else {
VFMULQS(q1, v0, q0);
VFMLAQS(q1, v1, v2);
}
if(q1!=v0)
VMOVQ(v0, q1);
}
if(!vex.l) YMM0(gd);
break;
case 0xB8:
INST_NAME("VFMADD231PS/D Gx, Vx, Ex");
nextop = F8;
@@ -1589,6 +1920,23 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!vex.l) YMM0(gd);
break;
case 0xDB:
INST_NAME("VAESIMC Gx, Ex");
nextop = F8;
GETGX_empty_EX(v0, v1, 0);
if(arm64_aes) {
AESIMC(v0, v1);
} else {
if(v0!=v1) {
VMOVQ(v0, v1);
}
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd);
CALL(native_aesimc, -1);
}
if(!vex.l) YMM0(gd);
break;
case 0xDC:
INST_NAME("VAESENC Gx, Vx, Ex"); // AES-NI
nextop = F8;
+81 -23
View File
@@ -135,15 +135,21 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!l) {
GETGX_empty_EX(v0, v1, 1);
u8 = F8;
if(v0==v1) {q1 = fpu_get_scratch(dyn, ninst); VMOVQ(q1, v1);}
} else {
GETGY_empty_EY(v0, v1);
if(v0==v1) {VMOVQ(q1, v1);}
}
if(((u8>>(l*2))&1)==((u8>>(1+l*2))&1))
VDUPQ_64(v0, (v0==v1)?q1:v1, ((u8>>(l*2))&1));
else for(int i=0; i<2; ++i)
VMOVeD(v0, i, (v0==v1)?q1:v1, (u8>>(i+l*2))&1);
switch(((u8>>(l*2))&3)) {
case 0b00:
case 0b11:
VDUPQ_64(v0, v1, ((u8>>(l*2))&1));
break;
case 0b10:
if(v0!=v1) VMOVQ(v0, v1);
break;
case 0b01:
VEXTQ_8(v0, v1, v1, 8); // invert 64bits values
break;
}
}
if(!vex.l) YMM0(gd);
break;
@@ -308,7 +314,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
} else YMM0(gd);
break;
case 0x0D:
INST_NAME("VPBLENDPD Gx, Vx, Ex, Ib");
INST_NAME("VBLENDPD Gx, Vx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(q0, q2, q1, 1); u8 = F8; } else { GETGY_empty_VYEY(q0, q2, q1); }
@@ -592,32 +598,60 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
u8 = geted_ib(dyn, addr, ninst, nextop);
q0 = fpu_get_scratch(dyn, ninst);
// first mask
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if(u8&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q0, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q0, q0); // expand 16bits to 32bits...
q1 = fpu_get_scratch(dyn, ninst);
// second mask
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if((u8>>4)&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q1, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q1, q1); // expand 16bits to 32bits...
if((u8&0x0f)!=0x0f) {
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if(u8&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q0, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q0, q0); // expand 16bits to 32bits...
}
if((u8&0xf0)!=0xf0) {
q1 = fpu_get_scratch(dyn, ninst);
// second mask
wb1 = 0; // mask
for(int i=0; i<4; ++i)
if((u8>>4)&(1<<i))
wb1 |= (3<<(i*2));
MOVI_64(q1, wb1); // load 8bits value as a 8bytes mask
SXTL_16(q1, q1); // expand 16bits to 32bits...
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 1); u8 = F8; } else { GETGY_empty_VYEY(v0, v2, v1); }
VFMULQS(v0, v2, v1);
VANDQ(v0, v0, q1); // second mask
if((u8&0xf0)!=0xf0) {
VANDQ(v0, v0, q1); // second mask
}
VFADDPQS(v0, v0, v0);
FADDPS(v0, v0);
VDUPQ_32(v0, v0, 0);
VANDQ(v0, v0, q0); // first mask
if((u8&0x0f)!=0x0f) {
VANDQ(v0, v0, q0); // first mask
}
}
if(!vex.l) YMM0(gd);
break;
case 0x41:
INST_NAME("VDPPD Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VXEX(v0, v1, v2, 0);
u8 = F8;
VFMULQD(v0, v1, v2);
// mask some, duplicate all, mask some
for(int i=0; i<2; ++i)
if(!(u8&(1<<(4+i)))) {
VMOVQDfrom(v0, i, xZR);
}
FADDPD(v0, v0);
VDUPQ_64(v0, v0, 0);
for(int i=0; i<2; ++i)
if(!(u8&(1<<i))) {
VMOVQDfrom(v0, i, xZR);
}
if(!vex.l) YMM0(gd);
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Vx, Ex, Ib");
nextop = F8;
@@ -770,6 +804,30 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!vex.l) YMM0(gd);
break;
case 0xDF:
INST_NAME("VAESKEYGENASSIST Gx, Ex, Ib");
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
MOV32w(x1, gd); // gx
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
MOV32w(x2, ed);
MOV32w(x3, 0); //p = NULL
} else {
MOV32w(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x3) {
MOVx_REG(x3, ed);
}
}
u8 = F8;
MOV32w(x4, u8);
CALL(native_aeskeygenassist, -1);
if(!vex.l) YMM0(gd);
break;
default:
DEFAULT;
}
+109 -38
View File
@@ -113,7 +113,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
ADDx_U12(x3, ed, 16);
VLDQ1R_64(v0, ed);
VLDQ1R_64(v0, x3);
}
}
if(!vex.l) YMM0(gd);
@@ -140,13 +140,13 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwD(gd, q0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -161,7 +161,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -171,7 +171,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -188,14 +188,14 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FCMEQD(q0, v1, v1); // 0 if NAN, 1 if not NAN
}
FSQRTD(d1, v1);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
FCMEQD(q1, d1, d1); // 0 => out is NAN
VBIC(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
@@ -211,28 +211,54 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x58:
INST_NAME("VADDSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FADDD(d1, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FADDD(q2, v1, v2); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FADDD(q2, v1, v2); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
VMOVeD(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FMULD(d1, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FMULD(q2, v1, v2); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FMULD(q2, v1, v2); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
VMOVeD(v0, 0, q2, 0);
YMM0(gd);
break;
case 0x5A:
INST_NAME("VCVTSD2SS Gx, Vx, Ex");
@@ -240,7 +266,13 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCVT_S_D(d1, v1);
if(BOX64ENV(dynarec_fastround)==2) {
FCVT_S_D(d1, v1);
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FCVT_S_D(d1, v1);
x87_restoreround(dyn, ninst, u8);
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
@@ -251,14 +283,27 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5C:
INST_NAME("VSUBSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBD(d1, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FSUBD(q2, v2, v1); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FSUBD(q2, v2, v1); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
VMOVeD(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x5D:
@@ -279,27 +324,27 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5E:
INST_NAME("VDIVSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q0, v2, v1); // propagate NAN
FCMEQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
FDIVD(d1, v2, v1);
if(!box64_dynarec_fastnan) {
FCMEQD(q1, d1, d1); // 0 => out is NAN
VBIC(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORR(d1, d1, q1); // NAN -> -NAN
FMAXD(q1, v0, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FDIVD(q2, v2, v1); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FDIVD(q2, v2, v1); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
VMOVeD(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x5F:
@@ -322,7 +367,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(!l) { GETEX_Y(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
if(v0==v1) {
VMOVQ(d0, v1);
@@ -360,6 +405,29 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
}
if(!vex.l) YMM0(gd);
break;
case 0x7D:
INST_NAME("VHSUBPS Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
if(MODREG || (v1==v2)) {
q1 = fpu_get_scratch(dyn, ninst);
} else
q1 = v1;
if(vex.l)
q2 = fpu_get_scratch(dyn, ninst);
else
q2 = q0;
// q0 will contains -1 / 0 / -1 / 0
MOVIQ_64(q0, 0xf0);
VSHLQ_32(q0, q0, 31); // keep sign bit
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
VEORQ(q1, v1, q0);
VEORQ(q2, v2, q0);
VFADDPQS(v0, q2, q1);
}
if(!vex.l) YMM0(gd);
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
@@ -389,13 +457,16 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q0 = fpu_get_scratch(dyn, ninst);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
TABLE64(x2, (uintptr_t)&addsubps);
MOV64x(x2, (uintptr_t)&addsubps);
VLDR128_U12(q0, x2, 0);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); if(v0==v1) q1 = fpu_get_scratch(dyn, ninst); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(v0==v1) {
VFMULQS(q1, v1, q0);
VFADDQS(v0, v2, q1);
//TODO: find a better way
if(!l) q1 = fpu_get_scratch(dyn, ninst);
VMOVQ(q1, v2);
VFMLAQS(q1, v1, q0);
VMOVQ(v0, q1);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VFMLAQS(v0, v1, q0);
@@ -412,12 +483,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!l) {
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
if(!box64_dynarec_fastround || vex.l)
if(!BOX64ENV(dynarec_fastround) || vex.l)
d0 = fpu_get_scratch(dyn, ninst);
} else {
GETEY(v1);
}
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFRINTIDQ(l?d0:v0, v1);
VFCVTNSQD(l?d0:v0, l?d0:v0); // convert double -> int64
if(!l)
+40 -5
View File
@@ -60,7 +60,36 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
rex_t rex = vex.rex;
switch(opcode) {
case 0xF5:
INST_NAME("PDEP Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
if(gd==ed || gd==vd) {
gb1 = gd;
gd = x4;
} else {
gb1 = 0;
}
// x3 = mask of mask, loop while not 0
MOV32w(gd, 0);
MOV64x(x2, 1);
MOV64x(x3, 1);
MARK;
TSTxw_REG(ed, x3);
B_MARK2(cEQ);
TSTxw_REG(vd, x2);
B_MARK3(cEQ);
ORRxw_REG(gd, gd, x3);
MARK3;
LSLxw_IMM(x2, x2, 1);
MARK2;
LSLxw_IMM(x3, x3, 1);
CBNZxw_MARK(x3);
if(gb1)
MOVxw_REG(gb1, gd);
break;
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
@@ -69,13 +98,19 @@ uintptr_t dynarec64_AVX_F2_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
if((gd==xRDX) || (gd==ed) || (gd==vd))
gb1 = x3;
else
gb1 = gd;
UMULH(gb1, xRDX, ed);
if(gd!=vd) {MULx(vd, xRDX, ed);}
if(gb1==x3) {
MOVx_REG(gd, gb1);
}
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
if(gd!=vd) {MOVw_REG(vd, x3);}
LSRx(gd, x3, 32);
}
break;
+95 -32
View File
@@ -140,13 +140,13 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGD;
GETEXSS(d0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwS(gd, d0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -161,7 +161,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGD;
GETEXSS(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -171,7 +171,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -234,35 +234,53 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x58:
INST_NAME("VADDSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FADDS(q2, v1, v2); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FADDS(q2, v1, v2); // the high part of the vector is erased...
}
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FADDS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
VMOVeS(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FMULS(q2, v1, v2); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FMULS(q2, v1, v2); // the high part of the vector is erased...
}
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FMULS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
VMOVeS(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x5A:
@@ -286,13 +304,13 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VCVTTPS2DQ Gx, Ex");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 0); } else { GETGY_empty_EY(v0, v1); }
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFCVTZSQS(v0, v1);
} else {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
@@ -314,14 +332,27 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5C:
INST_NAME("VSUBSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBS(d1, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FSUBS(q2, v2, v1); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FSUBS(q2, v2, v1); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
VMOVeS(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x5D:
@@ -341,14 +372,27 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x5E:
INST_NAME("VDIVSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FDIVS(d1, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FDIVS(q2, v2, v1); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
} else {
FDIVS(q2, v2, v1); // the high part of the vector is erased...
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
VMOVeS(v0, 0, q2, 0);
YMM0(gd)
break;
case 0x5F:
@@ -395,7 +439,7 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETEX(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(!l) { GETEX_Y(v1, 0, 1); GETGX(v0, 1); u8 = F8; } else { GETGY(v0, 1, MODREG?((nextop&7)+(rex.b<<3)):-1, -1, -1); GETEY(v1); }
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
VDUP_16(d0, v1, 4+(u8&3));
} else {
@@ -447,11 +491,30 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
VMOVQ(v1, v0);
} // no ymm raz here it seems
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
IF_UNALIGNED(ip) {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x1) {
MOVx_REG(x1, wback);
wback = x1;
}
for(int i=0; i<16; ++i) {
VST1_8(v0, i, wback);
ADDx_U12(wback, wback, 1);
}
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
for(int i=0; i<16; ++i) {
VST1_8(v0, i, wback);
ADDx_U12(wback, wback, 1);
}
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
}
SMWRITE2();
}
@@ -61,6 +61,35 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
switch(opcode) {
case 0xF5:
INST_NAME("PEXT Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
if(gd==ed || gd==vd) {
gb1 = gd;
gd = x4;
} else {
gb1 = 0;
}
// x3 = mask of mask, loop while not 0
MOV32w(gd, 0);
MOV64x(x3, 1LL<<(rex.w?63:31));
MARK;
TSTxw_REG(ed, x3);
B_MARK2(cEQ); // mask not set
TSTxw_REG(vd, x3);
CSINCxw(gd, gd, gd, cEQ); // return gd if TRUE, else gd+1
RORxw(gd, gd, 1);
MARK2;
LSRxw_IMM(x3, x3, 1);
CBNZxw_MARK(x3);
RBITxw(gd, gd);
if(gb1)
MOVxw_REG(gb1, gd);
break;
case 0xF7:
INST_NAME("SARX Gd, Ed, Vd");
nextop = F8;
+53 -4
View File
@@ -29,6 +29,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t ed;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
@@ -51,11 +52,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xC8:
case 0xC9:
@@ -68,11 +73,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xD0:
case 0xD1:
@@ -90,7 +99,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 0xD8:
case 0xD9:
@@ -108,7 +117,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -122,11 +131,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xE8:
case 0xE9:
@@ -139,11 +152,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
case 0xF1:
@@ -156,11 +173,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xF8:
case 0xF9:
@@ -173,11 +194,15 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
@@ -190,12 +215,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FADDD(v1, v1, s0);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
@@ -203,12 +232,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FMULD(v1, v1, s0);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
@@ -222,7 +255,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
@@ -236,7 +269,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3, x4, v1, s0, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
@@ -245,12 +278,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, v1, s0);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
@@ -258,12 +295,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FSUBS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, s0, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
@@ -271,12 +312,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, v1, s0);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
@@ -284,12 +329,16 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
if(ST_IS_F(0)) {
FDIVS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, s0, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
+57 -21
View File
@@ -128,7 +128,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD_0(v1);
}
FCOM(x1, x2, x3, x4, 0, 0, ST_IS_F(0)); // same flags...
FCOM(x1, x2, x3); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
@@ -270,7 +270,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xF0:
INST_NAME("F2XM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (F2XM1)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_f2xm1, -1);
@@ -278,7 +278,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF1:
INST_NAME("FYL2X");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FYL2X)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
@@ -288,11 +288,15 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF2:
INST_NAME("FPTAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FPTAN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_ftan, -1);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_ftan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
x87_unstackcount(dyn, ninst, x1, i1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emitting 1\n");
u8 = F8;
@@ -308,17 +312,21 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF3:
INST_NAME("FPATAN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FPATAN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fpatan, -1);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_fpatan, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF4:
INST_NAME("FXTRACT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FXTRACT)\n");
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 1);
@@ -327,8 +335,8 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF5:
INST_NAME("FPREM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
#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);
@@ -407,7 +415,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xF9:
INST_NAME("FYL2XP1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FYL2XP1)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
@@ -418,19 +426,27 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSQRTS(v1, v1);
} else {
FSQRTD(v1, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xFB:
INST_NAME("FSINCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FSINCOS)\n");
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);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_fsincos, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFC:
@@ -453,27 +469,39 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xFD:
INST_NAME("FSCALE");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FSCALE)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(native_fscale, -1);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_fscale, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FSIN)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fsin, -1);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_fsin, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FCOS)\n");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(native_fcos, -1);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
CALL_(native_fcos, -1, BOX64ENV(dynarec_fastround) ? 0 : u8);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
x87_unstackcount(dyn, ninst, x1, i1);
break;
default:
@@ -483,7 +511,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box64_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, BOX64ENV(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)) {
@@ -497,7 +525,11 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = v1;
else {
s0 = fpu_get_scratch(dyn, ninst);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FCVT_S_D(s0, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(s0, ed, fixedaddress);
@@ -507,14 +539,18 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
if(!ST_IS_F(0)) {
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FCVT_S_D(v1, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
}
VST32(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FLDENV)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
@@ -530,7 +566,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FNSTENV)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
+28 -3
View File
@@ -29,6 +29,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int64_t j64;
uint8_t ed;
uint8_t wback;
uint8_t u8;
int v1, v2;
int d0;
int s0;
@@ -130,7 +131,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -148,7 +149,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FADDD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
@@ -158,7 +163,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FMULD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
@@ -169,7 +178,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
@@ -180,7 +189,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
@@ -191,7 +200,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FSUBD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
@@ -201,7 +214,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FSUBD(v1, v2, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
@@ -211,7 +228,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FDIVD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
@@ -221,7 +242,11 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x5, x4);
FDIVD(v1, v2, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
+76 -69
View File
@@ -127,14 +127,13 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xE2:
INST_NAME("FNCLEX");
LDRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
MOV32w(x1, 0);
BFIw(x2, x1, 0, 8); // IE .. PE, SF, ES
BFIw(x2, x1, 15, 1); // B
BFCw(x2, 0, 8); // IE .. PE, SF, ES
BFCw(x2, 15, 1); // B
STRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
break;
case 0xE3:
INST_NAME("FNINIT");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FNINIT)\n");
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
CALL(reset_fpu, -1);
break;
@@ -155,7 +154,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
break;
case 0xF0:
case 0xF1:
@@ -174,7 +173,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
break;
default:
@@ -202,13 +201,17 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
FRINTZD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
@@ -228,13 +231,17 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
@@ -254,13 +261,17 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VST32(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_IOC);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
@@ -289,7 +300,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
if(box64_x87_no80bits) {
if(BOX64ENV(x87_no80bits)) {
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
VLDR64_U12(v1, ed, fixedaddress);
} else {
@@ -298,77 +309,73 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
// sync top
s0 = x87_stackcount(dyn, ninst, x3);
x87_reflectcount(dyn, ninst, x3, x4);
CALL(native_fld, -1);
// go back with the top & stack counter
x87_unstackcount(dyn, ninst, x3, s0);
x87_unreflectcount(dyn, ninst, x3, x4);
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if(box64_x87_no80bits) {
if(BOX64ENV(x87_no80bits)) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, wback, fixedaddress);
} else {
#if 0
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
if(!BOX64ENV(dynarec_fastround)) {
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
x87_reflectcount(dyn, ninst, x3, x4);
CALL(native_fstp, -1);
x87_unreflectcount(dyn, ninst, x3, x4);
} else {
// Painfully long, straight conversion from the C code, shoud be optimized
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
FMOVxD(x1, v1);
// do special value first
TSTx_mask(x1, 1, 0b00000, 0b111110); //0x7fffffffffffffffL
B_MARK(cNE);
// Zero
LSRx(x3, x1, 63-15); //x3 = sign+exp
MOVZw(x5, 0); // x5 = mantisse
B_MARK3_nocond;
MARK;
// get sign, in main ouput x5 for sign+exp
ANDx_mask(x5, x1, 1, 1, 0); //0x8000000000000000
LSRx(x5, x5, 63-15); // x5 = sign
// get exp
LSRx(x3, x1, 52); // x3 = exp11
ANDw_mask(x3, x3, 0, 0b1010); //0x7ff
ANDSx_mask(x1, x1, 1, 0, 0b110011); //0x000fffffffffffffL
LSLx_IMM(x1, x1, 11); // mantice
CMPSw_U12(x3, 0x7ff);
B_MARK2(cNE);
// NaN and Infinite
ORRw_mask(x3, x5, 0, 0b1110); //x3 = sign | 0x7fff
ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000
B_MARK3_nocond;
MARK2;
// regular / denormals
MOVZw(x4, 16383-1023); //BIAS80 - BIAS64
CBZw(x3, 4+4*4); // exp11 == 0?
// normals
ADDw_REG(x3, x3, x4); // x3 = exp16
ORRw_REG(x3, x3, x5); // x3 = sign | exp
ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000 x5 = mantisse
B_MARK3_nocond;
// denormals
CLZx(x6, x1);
ADDw_U12(x6, x6, 1); // "one"
SUBw_REG(x3, x4, x6); // x3 = exp16
ORRw_REG(x3, x3, x5); // x3 = sign | exp16
LSLx_REG(x5, x1, x6); // x5 = mantisse
MARK3;
STRx_U12(x5, wback, 0);
STRH_U12(x3, wback, 8);
}
CALL(native_fstp, -1);
#else
// Painfully long, straight conversion from the C code, shoud be optimized
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
FMOVxD(x1, v1);
// do special value first
TSTx_mask(x1, 1, 0b00000, 0b111110); //0x7fffffffffffffffL
B_MARK(cNE);
// Zero
LSRx(x3, x1, 63-15); //x3 = sign+exp
MOVZw(x5, 0); // x5 = mantisse
B_MARK3_nocond;
MARK;
// get sign, in main ouput x5 for sign+exp
ANDx_mask(x5, x1, 1, 1, 0); //0x8000000000000000
LSRx(x5, x5, 63-15); // x5 = sign
// get exp
LSRx(x3, x1, 52); // x3 = exp11
ANDw_mask(x3, x3, 0, 0b1010); //0x7ff
MOV32w(x4, 0x7ff);
CMPSw_REG(x3, x4);
B_MARK2(cNE);
// NaN and Infinite
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
CSELx(x5, x5, x4, cEQ); // x5 = mantisse
B_MARK3_nocond;
MARK2;
// regular / denormals
ANDx_mask(x1, x1, 1, 0, 0b110011); //0x000fffffffffffffL
LSLx_IMM(x1, x1, 11); //x1 = mantisse missing "1"
MOVZw(x4, 16383-1023); //BIAS80 - BIAS64
CBZw(x3, 4+3*4); // exp11 == 0?
// normals
ADDw_REG(x3, x3, x4); // x3 = exp16
ORRw_REG(x3, x3, x5); // x3 = sign | exp
ORRx_mask(x5, x1, 1, 1, 0); //0x8000000000000000 x5 = mantisse
B_MARK3_nocond;
// denormals
CLZx(x6, x1);
ADDw_U12(x6, x6, 1); // "one"
SUBw_REG(x3, x4, x6); // x3 = exp16
ORRw_REG(x3, x3, x5); // x3 = sign | exp16
LSLx_REG(x5, x1, x6); // x5 = mantisse
MARK3;
STRx_U12(x5, wback, 0);
STRH_U12(x3, wback, 8);
#endif
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
+53 -4
View File
@@ -29,6 +29,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
@@ -49,11 +50,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADD STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xC8:
case 0xC9:
@@ -66,11 +71,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMUL STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xD0:
case 0xD1:
@@ -88,7 +97,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 0xD8:
case 0xD9:
@@ -106,7 +115,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -120,11 +129,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xE8:
case 0xE9:
@@ -137,11 +150,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUB STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
case 0xF1:
@@ -154,11 +171,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 0xF8:
case 0xF9:
@@ -171,11 +192,15 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIV STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
@@ -188,7 +213,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FADDD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
@@ -196,7 +225,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FMULD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
@@ -205,7 +238,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
@@ -214,7 +247,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
@@ -223,7 +256,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FSUBD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
@@ -231,7 +268,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FSUBD(v1, v2, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
@@ -239,7 +280,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FDIVD(v1, v1, v2);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
@@ -247,7 +292,11 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
FDIVD(v1, v2, v1);
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
break;
}
return addr;
+9 -8
View File
@@ -118,7 +118,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 0xE8:
case 0xE9:
@@ -136,7 +136,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -161,19 +161,20 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STx(x2, ed, fixedaddress);
VFCVTZSd(s0, s0);
VST64(s0, ed, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
VFCVTZSd(s0, s0);
VST64(s0, ed, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x2, xZR, 1, 1, 0); //0x8000000000000000
MARK3;
STx(x2, ed, fixedaddress);
MARK3;
}
}
X87_POP_OR_FAIL(dyn, ninst, x3);
@@ -193,7 +194,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4:
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FRSTOR)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
@@ -201,7 +202,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("FNSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization (FNSAVE)\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
+29 -4
View File
@@ -29,6 +29,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t nextop = F8;
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int unscaled;
int v1, v2;
@@ -49,11 +50,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FADDP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FADDS(v1, v1, v2);
} else {
FADDD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
@@ -67,11 +72,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FMULP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FMULS(v1, v1, v2);
} else {
FMULD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD0:
@@ -90,7 +99,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
@@ -102,7 +111,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -117,11 +126,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v2, v1);
} else {
FSUBD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE8:
@@ -135,11 +148,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FSUBP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FSUBS(v1, v1, v2);
} else {
FSUBD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
@@ -153,11 +170,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVRP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v2, v1);
} else {
FDIVD(v1, v2, v1);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF8:
@@ -171,11 +192,15 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("FDIVP STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!BOX64ENV(dynarec_fastround))
u8 = x87_setround(dyn, ninst, x1, x2, x4);
if(ST_IS_F(0)) {
FDIVS(v1, v1, v2);
} else {
FDIVD(v1, v1, v2);
}
if(!BOX64ENV(dynarec_fastround))
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
@@ -215,7 +240,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, word[ED]");
@@ -227,7 +252,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3, x4, v1, v2, ST_IS_F(0));
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
+31 -24
View File
@@ -109,7 +109,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
@@ -130,7 +130,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
FCMPD(v1, v2);
}
FCOMI(x1, x2, x4, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -175,12 +175,12 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
}
VMOVSto(x3, s0, 0);
SQXTN_H_S(s0, s0);
VMOVHto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x3, 0x8000);
MARK3;
@@ -215,12 +215,12 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
VMOVSto(x3, s0, 0);
SQXTN_H_S(s0, s0);
VMOVHto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x3, 0x8000);
MARK3;
@@ -245,6 +245,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
@@ -254,12 +255,12 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
VMOVSto(x3, s0, 0);
SQXTN_H_S(s0, s0);
VMOVHto(x3, s0, 0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBNZ_MARK2(x5, FPSR_IOC);
SXTHw(x5, x3); // check if 16bits value is fine
SUBw_REG(x5, x5, x3);
CBZw_MARK3(x5);
TBNZ_MARK2(x5, FPSR_QC);
B_MARK3_nocond;
MARK2;
MOV32w(x3, 0x8000);
MARK3;
@@ -355,16 +356,22 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
B_MARK3(c__);
MARK2;
}
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
if(arm64_frintts) {
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
}
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
+42 -38
View File
@@ -27,8 +27,8 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRxw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -81,8 +81,8 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
@@ -130,8 +130,8 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
EORxw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -177,17 +177,21 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
int mask = convert_bitmask_xw(c);
if(!mask) {
if(!mask && !((!rex.w && c==0xffffffffLL) || (rex.w && c==0xffffffffffffffffLL))) {
MOV64xw(s3, c);
emit_xor32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_xor64:d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
if(!mask) {
MVNxw_REG(s1, s1);
} else {
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -233,8 +237,8 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_REG(s1, s1, s2);
@@ -285,8 +289,8 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
@@ -332,8 +336,8 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -360,8 +364,8 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
}
IFX(X_PEND) {
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
@@ -383,8 +387,8 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
EORx_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -411,8 +415,8 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4
}
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
@@ -434,8 +438,8 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
@@ -479,8 +483,8 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4
}
IFX(X_PEND) {
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
@@ -519,8 +523,8 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -547,8 +551,8 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4
}
IFX(X_PEND) {
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
@@ -570,8 +574,8 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
EORw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -598,8 +602,8 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s
}
IFX(X_PEND) {
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
@@ -622,8 +626,8 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
@@ -667,8 +671,8 @@ void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s
}
IFX(X_PEND) {
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
+58 -60
View File
@@ -29,8 +29,8 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_add64:d_add32b);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF) {
ORRxw_REG(s3, s1, s2); // s3 = op1 | op2
@@ -83,8 +83,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags==X_PEND))
{
if((s1==xRSP) && (BOX64DRENV(dynarec_safeflags)<2) && (!dyn->insts || (dyn->insts[ninst].x64.gen_flags==X_PEND) || (!BOX64ENV(dynarec_df) && (dyn->insts[ninst].x64.gen_flags==X_ALL)))) {
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<0x1000) {
ADDx_U12(s1, s1, c);
@@ -99,8 +98,8 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s5, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_add64:d_add32b);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_AF) {
IFX(X_PEND) {} else {MOV64xw(s5, c);}
@@ -167,8 +166,8 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_sub64:d_sub32);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF) {
ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2
@@ -224,8 +223,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags==X_PEND))
{
if(s1==xRSP && (BOX64DRENV(dynarec_safeflags)<2) && (!dyn->insts || (dyn->insts[ninst].x64.gen_flags==X_PEND) || (!BOX64ENV(dynarec_df) && (dyn->insts[ninst].x64.gen_flags==X_ALL)))) {
// special case when doing math on RSP and only PEND is needed: ignoring it!
if(c>=0 && c<0x1000) {
SUBxw_U12(s1, s1, c);
@@ -240,8 +238,8 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
MOV64xw(s5, c);
STRxw_U12(s5, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_sub64:d_sub32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
} else {
SET_DFNONE();
}
IFX(X_AF) {
IFX(X_PEND) {} else {MOV64xw(s5, c);}
@@ -311,8 +309,8 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add8b);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF | X_OF) {
ORRw_REG(s3, s1, s2); // s3 = op1 | op2
@@ -377,8 +375,8 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s4, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF | X_OF) {
IFX(X_PEND) {} else {MOV32w(s4, c);}
@@ -420,8 +418,8 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF|X_OF|X_CF) {
MVNw_REG(s3, s1);
@@ -467,8 +465,8 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s5, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF|X_OF|X_CF) {
MVNw_REG(s3, s1);
@@ -514,8 +512,8 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add16b);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF) {
ORRw_REG(s3, s1, s2); // s3 = op1 | op2
@@ -573,7 +571,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit ADD16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
//void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
// void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
@@ -581,7 +579,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_add16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// SET_DFNONE();
// }
// IFX(X_AF | X_OF) {
// MOV_REG(s4, s1);
@@ -647,8 +645,8 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_AF|X_OF|X_CF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
@@ -683,7 +681,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit SUB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
// void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
@@ -691,7 +689,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_sub16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// SET_DFNONE();
// }
// IFX(X_AF|X_OF|X_CF) {
// MVN_REG_LSL_IMM5(s4, s1, 0);
@@ -750,7 +748,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
{
SET_DFNONE(s4);
SET_DFNONE();
IFX(X_AF) {
if(rex.w) {
ORRx_mask(s3, s1, 1, 0, 0); // s3 = op1 | op2
@@ -797,7 +795,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
SET_DFNONE(s3);
SET_DFNONE();
IFX(X_AF | X_OF) {
ORRw_mask(s3, s1, 0, 0); // s3 = op1 | op2
ANDw_mask(s4, s1, 0, 0); // s4 = op1 & op2
@@ -825,7 +823,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
SET_DFNONE(s3);
SET_DFNONE();
IFX(X_AF | X_OF) {
ORRw_mask(s3, s1, 0, 0); // s3 = op1 | op2
ANDw_mask(s4, s1, 0, 0); // s4 = op1 & op2
@@ -853,7 +851,7 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// emit DEC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
{
SET_DFNONE(s4);
SET_DFNONE();
IFX(X_AF) {
MVNxw_REG(s3, s1);
if(rex.w) {
@@ -901,7 +899,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
// emit DEC8 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
SET_DFNONE(s3);
SET_DFNONE();
IFX(X_AF|X_OF) {
MVNw_REG(s3, s1);
ANDw_mask(s4, s3, 0, 0); // s4 = ~op1 & op2
@@ -943,7 +941,7 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// emit DEC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
SET_DFNONE(s3);
SET_DFNONE();
IFX(X_AF|X_OF) {
MVNw_REG(s4, s1);
}
@@ -990,8 +988,8 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_adc64:d_adc32b);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(INVERTED_CARRY_BEFORE) {
@@ -1056,7 +1054,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
// emit ADC32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
// void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOV32(s3, c);
@@ -1064,7 +1062,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_adc32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// SET_DFNONE();
// }
// IFX(X_AF) {
// MOV_REG(s4, s1);
@@ -1133,8 +1131,8 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(INVERTED_CARRY_BEFORE) {
@@ -1197,8 +1195,8 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(INVERTED_CARRY_BEFORE) {
@@ -1246,7 +1244,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit ADC16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
//void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
// void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
@@ -1254,7 +1252,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s3, d_adc16);
// } else IFX(X_ALL) {
// SET_DFNONE(s3);
// SET_DFNONE();
// }
// IFX(X_AF | X_OF) {
// MOV_REG(s4, s1);
@@ -1320,8 +1318,8 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_sbb64:d_sbb32);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(!INVERTED_CARRY_BEFORE) {
@@ -1390,7 +1388,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
// emit SBB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
// void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOV32(s3, c);
@@ -1398,7 +1396,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_sbb32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// SET_DFNONE();
// }
// IFX(X_AF) {
// MVN_REG_LSL_IMM5(s4, s1, 0);
@@ -1469,8 +1467,8 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sbb8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(!INVERTED_CARRY_BEFORE) {
@@ -1534,8 +1532,8 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sbb16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFNATIVE_BEFORE(NF_CF) {
if(!INVERTED_CARRY_BEFORE) {
@@ -1584,7 +1582,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit SBB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
// void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
@@ -1592,7 +1590,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s3, d_sbb16);
// } else IFX(X_ALL) {
// SET_DFNONE(s3);
// SET_DFNONE();
// }
// IFX(X_AF|X_OF|X_CF) {
// MVN_REG_LSL_IMM5(s4, s1, 0);
@@ -1656,8 +1654,8 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w?d_neg64:d_neg32);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_CF) {
TSTxw_REG(s1, s1);
@@ -1709,8 +1707,8 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_neg16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_CF) {
TSTw_REG(s1, s1);
@@ -1758,8 +1756,8 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_neg8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
} else {
SET_DFNONE();
}
IFX(X_CF) {
TSTw_REG(s1, s1);
File diff suppressed because it is too large. Load diff
+12 -12
View File
@@ -30,7 +30,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_AF) {
ORNxw_REG(s3, s2, s1); // s3 = ~op1 | op2
@@ -88,7 +88,7 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
// and now the tricky ones (and mostly unused), PF and AF
@@ -134,7 +134,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
SET_DFNONE();
}
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
@@ -206,7 +206,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
SET_DFNONE();
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF | X_OF) {
@@ -227,7 +227,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s3);
SET_DFNONE();
}
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
@@ -298,7 +298,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF | X_OF) {
@@ -318,7 +318,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
@@ -362,7 +362,7 @@ void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
@@ -410,7 +410,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
@@ -458,7 +458,7 @@ void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
@@ -517,7 +517,7 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
@@ -565,7 +565,7 @@ void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
+324 -167
View File
@@ -33,7 +33,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
int unscaled, mask;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
@@ -60,7 +60,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if (MODREG) {
if(rex.rex) {
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
@@ -77,7 +77,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
UFLAG_IF {
LDADDALB(x2, x1, wback);
emit_add8(dyn, ninst, x1, x2, x4, x5);
emit_add8(dyn, ninst, x1, x2, x4, x5);
} else {
STADDLB(x2, wback);
}
@@ -114,7 +114,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
UFLAG_IF {
LDADDALxw(gd, x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
} else {
STADDLxw(gd, wback);
}
@@ -122,23 +121,28 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
ADDxw_REG(x4, x1, gd);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
B_MARK2_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1); // substract with the byte only
CBNZw_MARK(x4); // jump if different
ADDxw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
STRxw_U12(x4, wback, 0); // put the whole value
SMDMB();
}
MARK2;
UFLAG_IF {
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
}
}
break;
@@ -147,7 +151,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if (MODREG) {
if(rex.rex) {
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
@@ -164,7 +168,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
LDSETALB(x2, x1, wback);
UFLAG_IF {
emit_or8(dyn, ninst, x1, x2, x4, x5);
emit_or8(dyn, ninst, x1, x2, x4, x5);
}
} else {
MARKLOCK;
@@ -189,7 +193,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
LDSETALxw(gd, x1, wback);
UFLAG_IF {
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
emit_or32(dyn, ninst, rex, x1, gd, x3, x4);
}
} else {
MARKLOCK;
@@ -208,8 +212,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xAB:
INST_NAME("LOCK BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
GETGD;
if(MODREG) {
@@ -226,7 +233,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ANDSw_mask(x4, x4, 0, 0); //mask=1
}
BFIw(xFlags, x4, F_CF, 1);
IFX(X_CF) {
BFIw(xFlags, x4, F_CF, 1);
}
MOV32w(x4, 1);
LSLxw_REG(x4, x4, x2);
ORRxw_REG(ed, ed, x4);
@@ -235,14 +244,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
ASRxw(x1, gd, 3); // r1 = (gd>>3)
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
ed = x1;
wback = x3;
MOV32w(x5, 1);
MARKLOCK;
LDAXRB(ed, wback);
LSRw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
IFX(X_CF) {
BFIw(xFlags, x4, F_CF, 1);
}
LSLw_REG(x4, x5, x2);
ORRw_REG(ed, ed, x4);
STLXRB(x4, ed, wback);
@@ -343,15 +355,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
UFLAG_IF {
MOVxw_REG(x1, xRAX);
CASALxw(xRAX, gd, wback);
CASALxw(x1, gd, wback);
SMDMB();
emit_cmp32(dyn, ninst, rex, x1, xRAX, x3, x4, x5);
if(!ALIGNED_ATOMICxw) {
B_MARK_nocond;
}
} else {
CASALxw(xRAX, gd, wback);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
}
}
} else {
MARKLOCK;
@@ -372,6 +386,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
LDRxw_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
SUBxw_UXTB(x3, x3, x1);
CBNZw_MARK3(x3);
CMPSxw_REG(xRAX, x1);
B_MARK(cNE);
// EAX == Ed
@@ -380,11 +396,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRxw_U12(gd, wback, 0);
SMDMB();
}
if(!ALIGNED_ATOMICxw || !arm64_atomics) {
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5); MOVxw_REG(xRAX, x1);}
else {
if(!ALIGNED_ATOMICxw || !arm64_atomics)
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
}
}
break;
@@ -395,8 +412,11 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xB3:
INST_NAME("LOCK BTR Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
nextop = F8;
GETGD;
if(MODREG) {
@@ -408,12 +428,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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) {
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);
@@ -422,14 +439,17 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ANDw_mask(x2, gd, 0, 0b00010); //mask=0x000000007
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
ASRx(x1, gd, 3); // r1 = (gd>>3), there might be an issue for negative 32bits values here
ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
if(!rex.w && !rex.is32bits) {SXTWx(x1, x1);}
ADDz_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
ed = x1;
wback = x3;
MOV32w(x5, 1);
MARKLOCK;
LDAXRB(ed, wback);
LSRw_REG(x4, ed, x2);
BFIw(xFlags, x4, F_CF, 1);
IFX(X_CF) {
BFIw(xFlags, x4, F_CF, 1);
}
LSLw_REG(x4, x5, x2);
BICw_REG(ed, ed, x4);
STLXRB(x4, ed, wback);
@@ -443,17 +463,22 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 4:
INST_NAME("LOCK BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
gd = x2;
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
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)
}
} else {
// Will fetch only 1 byte, to avoid alignment issue
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
if(u8>>3) {
ADDx_U12(x3, wback, u8>>3);
@@ -463,36 +488,44 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDAXRB(x1, wback);
ed = x1;
wback = x3;
BFXILxw(xFlags, x1, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
IFX(X_CF) {
BFXILxw(xFlags, x1, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
}
break;
case 5:
INST_NAME("LOCK BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
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_NEXT(xFlags, 0); // bit already set, jump to next instruction
MOV32w(x4, 1);
ORRxw_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)
}
mask = convert_bitmask_xw(1LL<<u8);
ORRxw_mask(ed, ed, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
// Will fetch only 1 byte, to avoid alignment issue
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
if(u8>>3) {
ADDx_U12(x3, wback, u8>>3);
wback = x3;
}
ed = x1;
MOV32w(x5, 1);
MARKLOCK;
LDAXRB(ed, wback);
BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
BFIw(ed, x5, u8&7, 1);
IFX(X_CF) {
BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
mask = convert_bitmask_xw(1LL<<(u8&7));
ORRxw_mask(ed, ed, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
STLXRB(x4, ed, wback);
CBNZw_MARKLOCK(x4);
SMDMB();
@@ -500,18 +533,22 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("LOCK BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
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_NEXT(xFlags, 0); // bit already clear, jump to next instruction
IFX(X_CF) {
BFXILxw(xFlags, ed, u8, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
BFCxw(ed, u8, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
if(u8>>3) {
ADDx_U12(x3, wback, u8>>3);
@@ -529,29 +566,36 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7:
INST_NAME("LOCK BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(!BOX64ENV(dynarec_safeflags)) {
SETFLAGS(X_ALL&~X_ZF, SF_SUBSET);
} else {
SETFLAGS(X_CF, SF_SUBSET);
}
if(MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
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);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
if(u8>>3) {
ADDx_U12(x3, wback, u8>>3);
wback = x3;
}
ed = x1;
MOV32w(x5, 1);
MARKLOCK;
LDAXRB(ed, wback);
BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
EORw_REG_LSL(ed, ed, x5, u8&7);
IFX(X_CF) {
BFXILw(xFlags, ed, u8&7, 1); // inject 1 bit from u8 to F_CF (i.e. pos 0)
}
mask = convert_bitmask_xw(1LL<<(u8&7));
ORRxw_mask(ed, ed, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
STLXRB(x4, ed, wback);
CBNZw_MARKLOCK(x4);
SMDMB();
@@ -635,16 +679,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
if(arm64_atomics) {
UFLAG_IF {
MOVxw_REG(x3, gd);
LDADDALxw(x3, gd, wback);
SMDMB();
emit_add32(dyn, ninst, rex, x3, gd, x4, x5);
LDADDALxw(gd, x1, wback);
} else {
LDADDALxw(gd, gd, wback);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
}
} else {
MARKLOCK;
@@ -652,28 +689,32 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ADDxw_REG(x4, x1, gd);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
if(!ALIGNED_ATOMICxw) {
B_MARK2_nocond;
}
}
SMDMB();
if(!ALIGNED_ATOMICxw) {
UFLAG_IF {
B_MARK2_nocond;
} else {
if(!arm64_atomics) MOVxw_REG(gd, x1);
B_NEXT_nocond;
}
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
ADDxw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x4, wback, 0);
SMDMB();
}
if(!ALIGNED_ATOMICxw || !arm64_atomics) {
MARK2;
IFX(X_ALL|X_PEND) {
MOVxw_REG(x2, x1);
emit_add32(dyn, ninst, rex, x2, gd, x3, x4);
}
MARK2;
UFLAG_IF {
MOVxw_REG(x3, x1);
emit_add32(dyn, ninst, rex, x3, gd, x4, x5);
MOVxw_REG(gd, x1);
} else if(!arm64_atomics || !ALIGNED_ATOMICxw) {
MOVxw_REG(gd, x1);
}
}
@@ -699,7 +740,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_uscat) {
if(rex.w) {
TSTx_mask(wback, 1, 0, 3);
B_MARK2(cNE);
B_MARK2(cNE);
} else {
ANDx_mask(x2, wback, 1, 0, 3); // mask = F
CMPSw_U12(x2, 8);
@@ -754,6 +795,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK2;
LDPxw_S7_offset(x2, x3, wback, 0);
LDAXRB(x5, wback);
SUBxw_UXTB(x5, x5, x2);
CBNZw_MARK2(x5);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARKSEG(cNE); // EAX!=ED[0] || EDX!=Ed[1]
@@ -794,7 +837,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
if (MODREG) {
if(rex.rex) {
wback = TO_NAT((nextop & 0x07) + (rex.b << 3));
wb2 = 0;
@@ -915,34 +958,42 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
B_MARK(cNE);
}
}
if(arm64_atomics) {
if(arm64_atomics && 0) { // disabled because 0x80000000 has no negative
NEGxw_REG(x1, gd);
UFLAG_IF {
LDADDALxw(x1, x1, wback);
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
} else {
STADDLxw(x1, wback);
}
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
SUBxw_REG(x4, x1, gd);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
SMDMB();
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
UFLAG_IF {
B_MARK2_nocond;
} else {
B_NEXT_nocond;
}
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
SUBxw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
STRxw_U12(x4, wback, 0); // put the whole value
SMDMB();
}
UFLAG_IF {
MARK2;
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
}
}
break;
@@ -951,7 +1002,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
@@ -969,31 +1020,34 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(arm64_atomics) {
UFLAG_IF {
LDEORALxw(gd, x1, wback);
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
} else {
STEORLxw(gd, wback);
}
SMDMB();
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
EORxw_REG(x4, x1, gd);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
SMDMB();
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
B_MARK2_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
EORxw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
STRxw_U12(x4, wback, 0); // put the whole value
SMDMB();
}
MARK2;
UFLAG_IF {
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
}
}
break;
@@ -1189,7 +1243,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x2, u8);
UFLAG_IF {
LDEORALB(x2, x1, wback);
emit_xor8(dyn, ninst, x1, x2, x3, x4);
emit_xor8(dyn, ninst, x1, x2, x3, x4);
} else {
STEORLB(x2, wback);
}
@@ -1238,6 +1292,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if((i64<=-0x1000) || (i64>=0x1000)) {
MOV64xw(x5, i64);
}
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -1249,35 +1306,56 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
}
if(arm64_atomics) {
MOV64xw(x3, i64);
UFLAG_IF {
LDADDALxw(x3, x1, wback);
SMDMB();
emit_add32(dyn, ninst, rex, x1, x3, x4, x5);
} else {
STADDLxw(x3, wback);
SMDMB();
if((i64>-0x1000) && (i64<0x1000)) {
MOV64xw(x5, i64);
}
UFLAG_IF {
LDADDALxw(x5, x1, wback);
} else {
STADDLxw(x5, wback);
}
SMDMB();
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
STLXRxw(x3, x1, wback);
if(i64>=0 && i64<0x1000) {
ADDxw_U12(x4, x1, i64);
} else if(i64<0 && i64>-0x1000) {
SUBxw_U12(x4, x1, -i64);
} else {
ADDxw_REG(x4, x1, x5);
}
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
B_MARK2_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
if(i64>=0 && i64<0x1000) {
ADDxw_U12(x4, x1, i64);
} else if(i64<0 && i64>-0x1000) {
SUBxw_U12(x4, x1, -i64);
} else {
ADDxw_REG(x4, x1, x5);
}
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
STRxw_U12(x4, wback, 0); // put the whole value
SMDMB();
}
MARK2;
UFLAG_IF {
if((i64<=-0x1000) || (i64>=0x1000)) {
emit_add32(dyn, ninst, rex, x1, x5, x3, x4);
} else {
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
}
}
}
break;
case 1: //OR
@@ -1286,23 +1364,22 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_or32(dyn, ninst, rex, ed, x5, x3, x4);
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
if(arm64_atomics) {
MOV64xw(x5, i64);
UFLAG_IF {
LDSETALxw(x5, x1, wback);
emit_or32(dyn, ninst, rex, x1, x5, x3, x4);
} else {
STSETLxw(x5, wback);
}
}
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_or32(dyn, ninst, rex, x1, x5, x3, x4);
emit_or32c(dyn, ninst, rex, x1, i64, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
@@ -1372,10 +1449,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STCLRLxw(x5, wback);
}
} else {
MOV64xw(x5, i64);
MARKLOCK;
LDAXRxw(x1, wback);
emit_and32(dyn, ninst, rex, x1, x5, x3, x4);
emit_and32c(dyn, ninst, rex, x1, i64, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
@@ -1388,11 +1464,13 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(x5, i64);
emit_sub32(dyn, ninst, rex, ed, x5, x3, x4);
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if((i64<=-0x1000) || (i64>=0x1000)) {
MOV64xw(x5, i64);
}
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -1404,36 +1482,64 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
}
if(arm64_atomics) {
MOV64xw(x5, -i64);
if((i64>-0x1000) && (i64<0x1000)) {
MOV64xw(x5, -i64);
} else {
NEGxw_REG(x5, x5);
}
UFLAG_IF {
LDADDALxw(x5, x1, wback);
SMDMB();
NEGxw_REG(x5, x5);
emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
if((i64<=-0x1000) || (i64>=0x1000))
NEGxw_REG(x5, x5);
} else {
STADDLxw(x5, wback);
SMDMB();
}
SMDMB();
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
STLXRxw(x3, x1, wback);
if(i64>=0 && i64<0x1000) {
SUBxw_U12(x4, x1, i64);
} else if(i64<0 && i64>-0x1000) {
ADDxw_U12(x4, x1, -i64);
} else {
SUBxw_REG(x4, x1, x5);
}
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
UFLAG_IF {
B_MARK2_nocond;
} else {
B_NEXT_nocond;
}
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
if(i64>=0 && i64<0x1000) {
SUBxw_U12(x4, x1, i64);
} else if(i64<0 && i64>-0x1000) {
ADDxw_U12(x4, x1, -i64);
} else {
SUBxw_REG(x4, x1, x5);
}
STLXRB(x3, x4, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
STRxw_U12(x4, wback, 0); // put the whole value
SMDMB();
}
UFLAG_IF {
MARK2;
if((i64<=-0x1000) || (i64>=0x1000)) {
emit_sub32(dyn, ninst, rex, x1, x5, x3, x4);
} else {
emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5);
}
}
}
break;
case 6: //XOR
@@ -1447,8 +1553,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
if(arm64_atomics) {
MOV64xw(x5, i64);
UFLAG_IF {
LDEORALxw(x5, x1, wback);
emit_xor32(dyn, ninst, rex, x1, x5, x3, x4);
@@ -1458,7 +1564,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_xor32(dyn, ninst, rex, x1, x5, x3, x4);
emit_xor32c(dyn, ninst, rex, x1, i64, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
@@ -1556,7 +1662,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(!ALIGNED_ATOMICxw) {
MARK;
LDRxw_U12(x1, ed, 0);
LDAXRB(x3, ed);
LDAXRB(x4, ed);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
STLXRB(x3, gd, ed);
CBNZx_MARK(x3);
STRxw_U12(gd, ed, 0);
@@ -1589,11 +1697,44 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LDAXRB(x1, wback);
if(arm64_atomics) {
MOV32w(x1, 0xff);
STEORLB(x1, wback);
} else {
MARKLOCK;
LDAXRB(x1, wback);
MVNw_REG(x1, x1);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
break;
default:
DEFAULT;
}
break;
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("LOCK NOT Ed");
if(MODREG) {
GETED(x1);
MVNw_REG(x1, x1);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(arm64_atomics) {
MOV64x(x1, ~0LL);
STEORLxw(x1, wback);
} else {
MARKLOCK;
LDAXRxw(x1, wback);
MVNw_REG(x1, x1);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
break;
@@ -1690,30 +1831,38 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x3, 1);
UFLAG_IF {
LDADDALxw(x3, x1, wback);
emit_inc32(dyn, ninst, rex, x1, x3, x4);
} else {
STADDLxw(x3, wback);
}
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_inc32(dyn, ninst, rex, x1, x3, x4);
STLXRxw(x3, x1, wback);
ADDxw_U12(x4, x1, 1);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
UFLAG_IF {
B_MARK2_nocond;
} else {
B_NEXT_nocond;
}
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_inc32(dyn, ninst, rex, x1, x3, x4);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
ADDxw_U12(x4, x1, 1);
STLXRB(x3, x4, wback);
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
STRxw_U12(x4, wback, 0);
SMDMB();
}
UFLAG_IF {
MARK2;
emit_inc32(dyn, ninst, rex, x1, x3, x4);
}
}
break;
case 1: //DEC Ed
@@ -1738,30 +1887,38 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV64xw(x3, -1);
UFLAG_IF {
LDADDALxw(x3, x1, wback);
emit_dec32(dyn, ninst, rex, x1, x3, x4);
} else {
STADDLxw(x3, wback);
}
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_dec32(dyn, ninst, rex, x1, x3, x4);
STLXRxw(x3, x1, wback);
SUBxw_U12(x4, x1, 1);
STLXRxw(x3, x4, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
UFLAG_IF {
B_MARK2_nocond;
} else {
B_NEXT_nocond;
}
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_dec32(dyn, ninst, rex, x1, x3, x4);
STLXRB(x3, x1, wback);
SUBxw_UXTB(x4, x4, x1);
CBNZw_MARK(x4);
SUBxw_U12(x4, x1, 1);
STLXRB(x3, x4, wback);
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
STRxw_U12(x4, wback, 0);
SMDMB();
}
UFLAG_IF {
MARK2;
emit_dec32(dyn, ninst, rex, x1, x3, x4);
}
}
break;
default:
+35 -31
View File
@@ -100,11 +100,17 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn, ninst);
if(BOX64ENV(dynarec_fastround)<2) {
u8 = sse_setround(dyn, ninst, x3, x4, x5);
}
if(rex.w) {
SCVTFDx(d1, ed);
} else {
SCVTFDw(d1, ed);
}
if(BOX64ENV(dynarec_fastround)<2) {
x87_restoreround(dyn, ninst, u8);
}
VMOVeD(v0, 0, d1, 0);
break;
@@ -113,13 +119,13 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwD(gd, q0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -134,7 +140,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -144,7 +150,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -206,19 +212,23 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x51:
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETGX(q0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
FCMLTD_0(v1, d0);
SHL_64(v1, v1, 63);
// check if any input value was NAN
FCMEQD(v0, d0, d0); // 0 if NAN, 1 if not NAN
FSQRTD(d1, d0);
VORR(d1, d1, v1);
FCMEQD(v1, d1, d1); // 0 => out is NAN
VBIC(v1, v0, v1); // forget it in any input was a NAN already
SHL_64(v1, v1, 63); // only keep the sign bit
VORR(d1, d1, v1); // NAN -> -NAN
} else {
FSQRTD(d1, d0);
}
VMOVeD(v0, 0, d1, 0);
VMOVeD(q0, 0, d1, 0);
break;
case 0x58:
@@ -227,7 +237,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -249,7 +259,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -271,7 +281,13 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
GETEXSD(d0, 0, 0);
d1 = fpu_get_scratch(dyn, ninst);
FCVT_S_D(d1, d0);
if(BOX64ENV(dynarec_fastround)>1) {
FCVT_S_D(d1, d0);
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FCVT_S_D(d1, d0);
x87_restoreround(dyn, ninst, u8);
}
VMOVeS(v0, 0, d1, 0);
break;
@@ -281,7 +297,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -319,7 +335,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
@@ -389,26 +405,14 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("HADDPS 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, ninst);
VLD128(v1, ed, fixedaddress);
}
GETEX(v1, 0, 1);
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, ninst);
VLD128(v1, ed, fixedaddress);
}
GETEX(v1, 0, 1);
d0 = fpu_get_scratch(dyn, ninst);
VUZP1Q_32(d0, v0, v1);
VUZP2Q_32(v0, v0, v1);
@@ -491,7 +495,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
q0 = fpu_get_scratch(dyn, ninst);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
MAYUSE(addsubps);
TABLE64(x2, (uintptr_t)&addsubps);
MOV64x(x2, (uintptr_t)&addsubps); // no need to use table64, as box64 is loaded in low memory
VLDR128_U12(q0, x2, 0);
VFMLAQS(v0, v1, q0);
break;
@@ -509,7 +513,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
VFRINTIDQ(v0, v1);
x87_restoreround(dyn, ninst, u8);
+96 -33
View File
@@ -131,13 +131,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD;
GETEXSS(d0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwS(gd, d0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -152,7 +152,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD;
GETEXSS(q0, 0, 0);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -162,7 +162,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
if(!box64_dynarec_fastround) {
if(!BOX64ENV(dynarec_fastround)) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
@@ -185,8 +185,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETED(0);
GETGD;
MRS_nzcv(x3);
LSRw(x4, xFlags, F_OF);
BFIx(x3, x4, 29, 1); // set C
IFNATIVE_BEFORE(NF_VF) {
LSRw(x4, x3, NZCV_V);
} else {
LSRw(x4, xFlags, F_OF);
}
BFIx(x3, x4, NZCV_C, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
IFX(X_OF) {
ADCSxw_REG(gd, gd, ed);
@@ -242,11 +246,24 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FADDS(d1, v0, d0); // the high part of the vector is erased...
VMOVeS(v0, 0, d1, 0);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
FADDS(v1, d1, d0); // the high part of the vector is erased...
FCMEQS(q0, v1, v1); // 0 => out is NAN
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FADDS(v1, d1, d0); // the high part of the vector is erased...
}
VMOVeS(d1, 0, v1, 0);
break;
case 0x59:
INST_NAME("MULSS Gx, Ex");
@@ -254,19 +271,19 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
if(!box64_dynarec_fastnan) {
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
FMULS(v1, d1, d0);
FMULS(v1, d1, d0); // the high part of the vector is erased...
FCMEQS(q0, v1, v1); // 0 => out is NAN
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FMULS(v1, d1, d0);
FMULS(v1, d1, d0); // the high part of the vector is erased...
}
VMOVeS(d1, 0, v1, 0);
break;
@@ -284,7 +301,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEX(v1, 0, 0) ;
GETGX_empty(v0);
if(box64_dynarec_fastround) {
if(BOX64ENV(dynarec_fastround)) {
VFCVTZSQS(v0, v1);
} else {
MRS_fpsr(x5);
@@ -307,11 +324,24 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FSUBS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
FSUBS(v1, d1, d0); // the high part of the vector is erased...
FCMEQS(q0, v1, v1); // 0 => out is NAN
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FSUBS(v1, d1, d0); // the high part of the vector is erased...
}
VMOVeS(d1, 0, v1, 0);
break;
case 0x5D:
INST_NAME("MINSS Gx, Ex");
@@ -332,11 +362,24 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FDIVS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
FDIVS(v1, d1, d0); // the high part of the vector is erased...
FCMEQS(q0, v1, v1); // 0 => out is NAN
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FDIVS(v1, d1, d0); // the high part of the vector is erased...
}
VMOVeS(d1, 0, v1, 0);
break;
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
@@ -417,8 +460,20 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
IF_UNALIGNED(ip) {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(wback!=x1) {
MOVx_REG(x1, wback);
wback = x1;
}
for(int i=0; i<16; ++i) {
VST1_8(v0, i, wback);
ADDx_U12(wback, wback, 1);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
}
SMWRITE2();
}
break;
@@ -454,7 +509,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xB8:
INST_NAME("POPCNT Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
v1 = fpu_get_scratch(dyn, ninst);
GETGD;
@@ -478,19 +533,27 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
CNT_8(v1, v1);
UADDLV_8(v1, v1);
VMOVQDto(gd, v1, 0);
VMOVHto(gd, v1, 0);
IFX(X_ALL) {
MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF));
BICw(xFlags, xFlags, x1);
CBNZx(gd, 4+4);
BFIw(xFlags, xFlags, F_ZF, 1);
IFX(X_AF|X_PF|X_SF|X_OF|X_CF) {
MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF));
BICw(xFlags, xFlags, x1);
}
IFX(X_ZF) {
CMPSw_U12(gd, 0);
IFNATIVE(NF_EQ) {}
else {
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1);
}
}
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
@@ -510,7 +573,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SUBSET);
SET_DFNONE(x1);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
+241 -113
View File
@@ -25,6 +25,7 @@
#include "dynarec_arm64_functions.h"
#include "custommem.h"
#include "bridge.h"
#include "gdbjit.h"
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn, int ninst)
@@ -286,7 +287,7 @@ static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int
} 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);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_combined, ninst=%d combined%c %d i=%d (stack:%d/%d)\n", ninst, (a == dyn->insts[ninst].n.combined2)?'2':'1', a ,i, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
if(!dyn->insts[ninst].n.barrier)
@@ -303,19 +304,19 @@ static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int
while(ninst>=0) {
a+=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: add pop'd ST (going backward)
int i = neoncache_get_st_f_i64(dyn, ninst, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d, i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d, i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
if(dyn->insts[ninst].n.swapped) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
} else {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
}
@@ -331,19 +332,19 @@ static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int
while((ninst!=-1) && (ninst<maxinst) && (a>=0)) {
a+=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: add push'd ST (going forward)
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && dyn->insts[ninst].n.swapped) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
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_forward, ninst=%d, a=%d st=%d:%d(%d/%d), i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop, i);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d(%d/%d), i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && !dyn->insts[ninst].n.swapped) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
a-=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: remove pop'd ST (going forward)
@@ -359,20 +360,20 @@ static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a)
{
int i = neoncache_get_current_st_f_i64(dyn, a);
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d i=%d\n", ninst, a, dyn->n.stack, i);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d i=%d\n", ninst, a, dyn->n.stack, i);
if(i<0) return;
dyn->n.neoncache[i].t = NEON_CACHE_ST_D;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if(dyn->n.combined1 || dyn->n.combined2) {
if(dyn->n.swapped) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d swapped! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d swapped! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
a = dyn->n.combined2;
else if(dyn->n.combined2 == a)
a = dyn->n.combined1;
} else {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined2);
else if(dyn->n.combined2 == a)
@@ -658,101 +659,204 @@ const char* getCacheName(int t, int n)
return buff;
}
static register_mapping_t register_mappings[] = {
{ "rax", "x10" },
{ "eax", "w10" },
{ "ax", "x10" },
{ "ah", "x10" },
{ "al", "x10" },
{ "rcx", "x11" },
{ "ecx", "w11" },
{ "cx", "x11" },
{ "ch", "x11" },
{ "cl", "x11" },
{ "rdx", "x12" },
{ "edx", "w12" },
{ "dx", "x12" },
{ "dh", "x12" },
{ "dl", "x12" },
{ "rbx", "x13" },
{ "ebx", "w13" },
{ "bx", "x13" },
{ "bh", "x13" },
{ "bl", "x13" },
{ "rsi", "x14" },
{ "esi", "w14" },
{ "si", "x14" },
{ "sil", "x14" },
{ "rdi", "x15" },
{ "edi", "w15" },
{ "di", "x15" },
{ "dil", "x15" },
{ "rsp", "x16" },
{ "esp", "w16" },
{ "sp", "x16" },
{ "spl", "x16" },
{ "rbp", "x17" },
{ "ebp", "w17" },
{ "bp", "x17" },
{ "bpl", "x17" },
{ "r8", "x18" },
{ "r8d", "w18" },
{ "r8w", "x18" },
{ "r8b", "x18" },
{ "r9", "x19" },
{ "r9d", "w19" },
{ "r9w", "x19" },
{ "r9b", "x19" },
{ "r10", "x20" },
{ "r10d", "w20" },
{ "r10w", "x20" },
{ "r10b", "x20" },
{ "r11", "x21" },
{ "r11d", "w21" },
{ "r11w", "x21" },
{ "r11b", "x21" },
{ "r12", "x22" },
{ "r12d", "w22" },
{ "r12w", "x22" },
{ "r12b", "x22" },
{ "r13", "x23" },
{ "r13d", "w23" },
{ "r13w", "x23" },
{ "r13b", "x23" },
{ "r14", "x24" },
{ "r14d", "w24" },
{ "r14w", "x24" },
{ "r14b", "x24" },
{ "r15", "x25" },
{ "r15d", "w25" },
{ "r15w", "x25" },
{ "r15b", "x25" },
{ "rip", "x27" },
};
void printf_x64_instruction(dynarec_native_t* dyn, zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
{
if(box64_dynarec_dump) {
printf_x64_instruction(rex.is32bits?my_context->dec32:my_context->dec, &dyn->insts[ninst].x64, name);
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
(box64_dynarec_dump>1)?"\e[32m":"",
(void*)(dyn->native_start+dyn->insts[ninst].address),
dyn->insts[ninst].size/4,
ninst,
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].f_entry.pending,
dyn->insts[ninst].f_entry.dfnone,
dyn->insts[ninst].f_exit.pending,
dyn->insts[ninst].f_exit.dfnone,
dyn->insts[ninst].x64.may_set?"may":"set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write);
if(dyn->insts[ninst].nat_flags_op) {
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && dyn->insts[ninst].before_nat_flags)
printf_log(LOG_NONE, " NF:%d/read:%x", dyn->insts[ninst].nat_flags_op, dyn->insts[ninst].before_nat_flags);
else
printf_log(LOG_NONE, " NF:%d", dyn->insts[ninst].nat_flags_op);
if (!BOX64DRENV(dynarec_dump) && !BOX64ENV(dynarec_gdbjit) && !BOX64ENV(dynarec_perf_map)) return;
static char buf[256];
int length = sprintf(buf, "barrier=%d state=%d/%d/%d(%d:%d->%d:%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].f_entry.pending,
dyn->insts[ninst].f_entry.dfnone,
dyn->insts[ninst].f_exit.pending,
dyn->insts[ninst].f_exit.dfnone,
dyn->insts[ninst].x64.may_set ? "may" : "set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write);
if (dyn->insts[ninst].nat_flags_op) {
if (dyn->insts[ninst].nat_flags_op == NAT_FLAG_OP_TOUCH && dyn->insts[ninst].before_nat_flags)
length += sprintf(buf + length, " NF:%d/read:%x", dyn->insts[ninst].nat_flags_op, dyn->insts[ninst].before_nat_flags);
else
length += sprintf(buf + length, " NF:%d", dyn->insts[ninst].nat_flags_op);
}
if (dyn->insts[ninst].use_nat_flags || dyn->insts[ninst].set_nat_flags || dyn->insts[ninst].need_nat_flags) {
length += sprintf(buf + length, " nf:%hhx/%hhx/%hhx", dyn->insts[ninst].set_nat_flags, dyn->insts[ninst].use_nat_flags, dyn->insts[ninst].need_nat_flags);
}
if (dyn->insts[ninst].invert_carry)
length += sprintf(buf + length, " CI");
if (dyn->insts[ninst].gen_inverted_carry)
length += sprintf(buf + length, " gic");
if (dyn->insts[ninst].before_nat_flags & NF_CF) {
length += sprintf(buf + length, " %ccb", dyn->insts[ninst].normal_carry_before ? 'n' : 'i');
}
if (dyn->insts[ninst].need_nat_flags & NF_CF) {
length += sprintf(buf + length, " %cc", dyn->insts[ninst].normal_carry ? 'n' : 'i');
}
if (dyn->insts[ninst].pred_sz) {
length += sprintf(buf + length, ", pred=");
for (int ii = 0; ii < dyn->insts[ninst].pred_sz; ++ii)
length += sprintf(buf + length, "%s%d", ii ? "/" : "", dyn->insts[ninst].pred[ii]);
}
if (!dyn->insts[ninst].x64.alive)
length += sprintf(buf + length, "not executed");
if (dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts >= 0) {
length += sprintf(buf + length, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);
}
if (dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts == -1)
length += sprintf(buf + length, ", jmp=out");
if (dyn->insts[ninst].x64.has_callret)
length += sprintf(buf + length, ", callret");
if (dyn->last_ip) {
length += sprintf(buf + length, ", last_ip=%p", (void*)dyn->last_ip);
}
for (int ii = 0; ii < 32; ++ii) {
switch (dyn->insts[ninst].n.neoncache[ii].t) {
case NEON_CACHE_ST_D: length += sprintf(buf + length, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_F: length += sprintf(buf + length, " S%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_I64: length += sprintf(buf + length, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_MM: length += sprintf(buf + length, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: length += sprintf(buf + length, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMR: length += sprintf(buf + length, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMW: length += sprintf(buf + length, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMR: length += sprintf(buf + length, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
// case NEON_CACHE_SCR: length += sprintf(buf + length, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_NONE:
default: break;
}
if(dyn->insts[ninst].use_nat_flags || dyn->insts[ninst].set_nat_flags || dyn->insts[ninst].need_nat_flags)
printf_log(LOG_NONE, " nf:%hhx/%hhx/%hhx", dyn->insts[ninst].set_nat_flags, dyn->insts[ninst].use_nat_flags, dyn->insts[ninst].need_nat_flags);
if(dyn->insts[ninst].invert_carry)
printf_log(LOG_NONE, " CI");
if(dyn->insts[ninst].gen_inverted_carry)
printf_log(LOG_NONE, " gic");
if(dyn->insts[ninst].before_nat_flags&NF_CF)
printf_log(LOG_NONE, " %ccb", dyn->insts[ninst].normal_carry_before?'n':'i');
if(dyn->insts[ninst].need_nat_flags&NF_CF)
printf_log(LOG_NONE, " %cc", dyn->insts[ninst].normal_carry?'n':'i');
if(dyn->insts[ninst].pred_sz) {
dynarec_log(LOG_NONE, ", pred=");
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);
}
if(!dyn->insts[ninst].x64.alive)
dynarec_log(LOG_NONE, " not executed");
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts>=0)
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);
if(dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)
dynarec_log(LOG_NONE, ", jmp=out");
if(dyn->insts[ninst].x64.has_callret)
dynarec_log(LOG_NONE, ", callret");
if(dyn->last_ip)
dynarec_log(LOG_NONE, ", last_ip=%p", (void*)dyn->last_ip);
for(int ii=0; ii<32; ++ii) {
switch(dyn->insts[ninst].n.neoncache[ii].t) {
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_I64: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_YMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
//case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_NONE:
default: break;
}
if (memcmp(dyn->insts[ninst].n.neoncache, dyn->n.neoncache, sizeof(dyn->n.neoncache))) {
length += sprintf(buf + length, " %s(Change:", (BOX64DRENV(dynarec_dump) > 1) ? "\e[1;91m" : "");
for (int ii = 0; ii < 32; ++ii)
if (dyn->insts[ninst].n.neoncache[ii].v != dyn->n.neoncache[ii].v) {
length += sprintf(buf + length, " V%d:%s", ii, getCacheName(dyn->n.neoncache[ii].t, dyn->n.neoncache[ii].n));
length += sprintf(buf + length, "->%s", getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n));
}
length += sprintf(buf + length, ")%s", (BOX64DRENV(dynarec_dump) > 1) ? "\e[0;32m" : "");
}
if (dyn->insts[ninst].n.ymm_used) {
length += sprintf(buf + length, " ymmUsed=%04x", dyn->insts[ninst].n.ymm_used);
}
if (dyn->ymm_zero || dyn->insts[ninst].ymm0_add || dyn->insts[ninst].ymm0_sub || dyn->insts[ninst].ymm0_out) {
length += sprintf(buf + length, " ymm0=(%04x/%04x+%04x-%04x=%04x)", dyn->ymm_zero, dyn->insts[ninst].ymm0_in, dyn->insts[ninst].ymm0_add, dyn->insts[ninst].ymm0_sub, dyn->insts[ninst].ymm0_out);
}
if (dyn->insts[ninst].purge_ymm) {
length += sprintf(buf + length, " purgeYmm=%04x", dyn->insts[ninst].purge_ymm);
}
if (dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) {
length += sprintf(buf + length, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
}
if (dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
length += sprintf(buf + length, " %s:%d/%d", dyn->insts[ninst].n.swapped ? "SWP" : "CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
}
if (BOX64DRENV(dynarec_dump)) {
printf_x64_instruction(dyn, rex.is32bits ? my_context->dec32 : my_context->dec, &dyn->insts[ninst].x64, name);
dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, %s%s\n",
(BOX64DRENV(dynarec_dump) > 1) ? "\e[32m" : "",
(void*)(dyn->native_start + dyn->insts[ninst].address), dyn->insts[ninst].size / 4, ninst, buf, (BOX64DRENV(dynarec_dump) > 1) ? "\e[m" : "");
}
if (BOX64ENV(dynarec_gdbjit)) {
static char buf2[512];
if (BOX64ENV(dynarec_gdbjit) > 1) {
sprintf(buf2, "; %d: %d opcodes, %s", ninst, dyn->insts[ninst].size / 4, buf);
dyn->gdbjit_block = GdbJITBlockAddLine(dyn->gdbjit_block, (dyn->native_start + dyn->insts[ninst].address), buf2);
}
if(memcmp(dyn->insts[ninst].n.neoncache, dyn->n.neoncache, sizeof(dyn->n.neoncache))) {
dynarec_log(LOG_NONE, " %s(Change:", (box64_dynarec_dump>1)?"\e[1;91m":"");
for(int ii=0; ii<32; ++ii) if(dyn->insts[ninst].n.neoncache[ii].v!=dyn->n.neoncache[ii].v) {
dynarec_log(LOG_NONE, " V%d:%s", ii, getCacheName(dyn->n.neoncache[ii].t, dyn->n.neoncache[ii].n));
dynarec_log(LOG_NONE, "->%s", getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n));
}
dynarec_log(LOG_NONE, ")%s", (box64_dynarec_dump>1)?"\e[0;32m":"");
zydis_dec_t* dec = rex.is32bits ? my_context->dec32 : my_context->dec;
const char* inst_name = name;
if (dec) {
inst_name = DecodeX64Trace(dec, dyn->insts[ninst].x64.addr, 0);
x64disas_add_register_mapping_annotations(buf2, inst_name, register_mappings, sizeof(register_mappings) / sizeof(register_mappings[0]));
inst_name = buf2;
}
if(dyn->insts[ninst].n.ymm_used)
dynarec_log(LOG_NONE, " ymmUsed=%04x", dyn->insts[ninst].n.ymm_used);
if(dyn->ymm_zero || dyn->insts[ninst].ymm0_add || dyn->insts[ninst].ymm0_sub || dyn->insts[ninst].ymm0_out)
dynarec_log(LOG_NONE, " ymm0=(%04x/%04x+%04x-%04x=%04x)", dyn->ymm_zero, dyn->insts[ninst].ymm0_in, dyn->insts[ninst].ymm0_add ,dyn->insts[ninst].ymm0_sub, dyn->insts[ninst].ymm0_out);
if(dyn->insts[ninst].purge_ymm)
dynarec_log(LOG_NONE, " purgeYmm=%04x", dyn->insts[ninst].purge_ymm);
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack)
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
dyn->gdbjit_block = GdbJITBlockAddLine(dyn->gdbjit_block, (dyn->native_start + dyn->insts[ninst].address), inst_name);
}
if (BOX64ENV(dynarec_perf_map) && BOX64ENV(dynarec_perf_map_fd) != -1) {
writePerfMap(dyn->insts[ninst].x64.addr, dyn->native_start + dyn->insts[ninst].address, dyn->insts[ninst].size / 4, name);
}
}
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));
dynarec_log_prefix(0, LOG_NONE, "\t%08x\t%s\n", opcode, arm64_print(opcode, (uintptr_t)dyn->block));
}
static void x87_reset(neoncache_t* n)
@@ -822,9 +926,9 @@ uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before)
{
if(dyn->insts[ninst].x64.set_flags && !before) {
dyn->insts[ninst].set_nat_flags |= flag;
if(dyn->insts[ninst].x64.use_flags) {
dyn->insts[ninst].use_nat_flags |= flag;
}
//if(dyn->insts[ninst].x64.use_flags) {
// dyn->insts[ninst].use_nat_flags |= flag;
//}
} else {
if(before)
dyn->insts[ninst].use_nat_flags_before |= flag;
@@ -861,39 +965,52 @@ static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
int nat_flags_used = 0;
int ninst = start;
while(ninst<dyn->size) {
//printf_log(LOG_INFO, "getNativeFlagsUsed ninst:%d/%d, flags=%x, used_flags=%x(%d), nat_flags_op_before:%x, nat_flags_op:%x, need_after:%x\n", ninst, start, flags, used_flags, nat_flags_used, dyn->insts[ninst].nat_flags_op_before, dyn->insts[ninst].nat_flags_op, flag2native(dyn->insts[ninst].x64.need_after));
//printf_log(LOG_INFO, "getNativeFlagsUsed ninst:%d/%d, flags=%x, used_flags=%x(%d), nat_flags_op_before:%x, nat_flags_op:%x, need_after:%x set_nat_flags:%x nat_flags_used:%x(%x)\n", ninst, start, flags, used_flags, nat_flags_used, dyn->insts[ninst].nat_flags_op_before, dyn->insts[ninst].nat_flags_op, flag2native(dyn->insts[ninst].x64.need_after),dyn->insts[ninst].set_nat_flags, dyn->insts[ninst].use_nat_flags, dyn->insts[ninst].use_nat_flags_before);
// check if this is an opcode that generate flags but consume flags before
if(dyn->insts[ninst].nat_flags_op_before)
return 0;
// check if nat flags are used "before"
if(dyn->insts[ninst].use_nat_flags_before)
if(dyn->insts[ninst].use_nat_flags_before) {
// check if the gen flags are compatible
if(dyn->insts[ninst].use_nat_flags_before&~flags)
return 0;
nat_flags_used = 1;
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && dyn->insts[ninst].use_nat_flags_before)
used_flags|=dyn->insts[ninst].use_nat_flags_before&flags;
}
// if the opcode generate flags, return
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && (start!=ninst)) {
if(!nat_flags_used)
return 0;
if(used_flags&~dyn->insts[ninst].set_nat_flags) {
// check partial changes that would destroy flag state
if(dyn->insts[ninst].use_nat_flags_before&flags)
return nat_flags_used?used_flags:0;
// but also check if there is before needed
return used_flags;
// check if flags are all refreshed, then it's ok
if((used_flags&dyn->insts[ninst].set_nat_flags)==used_flags)
return used_flags;
// incompatible
return 0;
}
return nat_flags_used?used_flags:0;
return used_flags;
}
// check if there is a callret barrier
if(dyn->insts[ninst].x64.has_callret)
return 0;
// check if nat flags are used
if(dyn->insts[ninst].use_nat_flags)
if(dyn->insts[ninst].use_nat_flags) {
// check if the gen flags are compatible
if(dyn->insts[ninst].use_nat_flags&~flags)
return 0;
nat_flags_used = 1;
// check if flags are used, but not the natives ones
used_flags |= dyn->insts[ninst].use_nat_flags&flags;
}
if(ninst!=start && dyn->insts[ninst].x64.use_flags) {
if((flag2native(dyn->insts[ninst].x64.use_flags)&~(dyn->insts[ninst].use_nat_flags))&used_flags)
return 0;
// also check if the gen flags are compatible
if((dyn->insts[ninst].use_nat_flags)&~flags)
// some flags not compatible with native, partial use not allowed
if(flag2native(dyn->insts[ninst].x64.use_flags)!=dyn->insts[ninst].use_nat_flags)
return 0;
// check if flags are used, but not the natives ones
//if(dyn->insts[ninst].use_nat_flags&~used_flags)
// return 0;
}
// check if flags are generated without native option
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags)) {
@@ -909,7 +1026,8 @@ static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
if(dyn->insts[ninst].nat_flags_op && (start!=ninst))
return 0;
// update used flags
used_flags |= (flag2native(dyn->insts[ninst].x64.need_after)&flags);
//used_flags |= (flag2native(dyn->insts[ninst].x64.need_after)&flags);
// go next
if(!dyn->insts[ninst].x64.has_next) {
// check if it's a jump to an opcode with only 1 preds, then just follow the jump
@@ -933,7 +1051,7 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
//printf_log(LOG_INFO, "propagateNativeFlags called for start=%d, flags=%x, will need:%x\n", start, flags, flag2native(dyn->insts[ninst].x64.need_after));
if(!flags) return;
// also check if some native flags are used but not genereated here
if(flag2native(dyn->insts[ninst].x64.need_after)&~flags) return;
if(flag2native(dyn->insts[ninst].x64.use_flags)&~flags) return;
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags);
//printf_log(LOG_INFO, " will use:%x, carry:%d, generate inverted carry:%d\n", used_flags, used_flags&NF_CF, dyn->insts[ninst].gen_inverted_carry);
if(!used_flags) return; // the flags wont be used, so just cancel
@@ -978,9 +1096,9 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
void updateNativeFlags(dynarec_native_t* dyn)
{
if(!box64_dynarec_nativeflags)
if(!BOX64ENV(dynarec_nativeflags))
return;
// backward check if native flags are used
// forward check if native flags are used
for(int ninst=0; ninst<dyn->size; ++ninst)
if(flag2native(dyn->insts[ninst].x64.gen_flags) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
propagateNativeFlags(dyn, ninst);
@@ -1020,3 +1138,13 @@ int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst)
return 1;
return 0;
}
void fpu_save_and_unwind(dynarec_arm_t* dyn, int ninst, neoncache_t* cache)
{
memcpy(cache, &dyn->insts[ninst].n, sizeof(neoncache_t));
neoncacheUnwind(&dyn->insts[ninst].n);
}
void fpu_unwind_restore(dynarec_arm_t* dyn, int ninst, neoncache_t* cache)
{
memcpy(&dyn->insts[ninst].n, cache, sizeof(neoncache_t));
}
@@ -67,6 +67,9 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
void fpu_save_and_unwind(dynarec_arm_t* dyn, int ninst, neoncache_t* cache);
void fpu_unwind_restore(dynarec_arm_t* dyn, int ninst, neoncache_t* cache);
// Get if ED will have the correct parity. Not emitting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_native_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta);
+87 -16
View File
@@ -580,7 +580,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
NOTEST(x2);
uintptr_t tbl = is32bits?getJumpTable32():getJumpTable64();
MAYUSE(tbl);
TABLE64(x3, tbl);
MOV64x(x3, tbl);
if(!is32bits) {
#ifdef JMPTABL_SHIFT4
UBFXx(x2, xRIP, JMPTABL_START4, JMPTABL_SHIFT4);
@@ -599,7 +599,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
NOTEST(x2);
uintptr_t p = getJumpTableAddress64(ip);
MAYUSE(p);
TABLE64(x3, p);
MOV64x(x3, p);
GETIP_(ip);
LDRx_U12(x2, x3, 0);
}
@@ -626,7 +626,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
POP1z(xRIP);
MOVz_REG(x1, xRIP);
SMEND();
if(box64_dynarec_callret) {
if(BOX64DRENV(dynarec_callret)) {
// pop the actual return address for ARM stack
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
@@ -673,7 +673,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
}
MOVz_REG(x1, xRIP);
SMEND();
if(box64_dynarec_callret) {
if(BOX64DRENV(dynarec_callret)) {
// pop the actual return address for ARM stack
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
@@ -715,7 +715,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits)
MAYUSE(j64);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
SMEND();
SET_DFNONE(x2);
SET_DFNONE();
// POP IP
NOTEST(x2);
if(is64bits) {
@@ -734,7 +734,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits)
MOV32w(x1, 0x3F7FD7);
ANDx_REG(xFlags, xFlags, x1);
ORRx_mask(xFlags, xFlags, 1, 0b111111, 0); // xFlags | 0b10
SET_DFNONE(x1);
SET_DFNONE();
if(is32bits) {
ANDw_mask(x2, x2, 0, 7); // mask 0xff
// check if return segment is 64bits, then restore rsp too
@@ -809,6 +809,42 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
//SET_NODF();
}
void call_i(dynarec_arm_t* dyn, int ninst, void* fnc)
{
MAYUSE(fnc);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
STPx_S7_preindex(x6, x7, xSP, -16);
STPx_S7_preindex(x4, x5, xSP, -16);
STPx_S7_preindex(x2, x3, xSP, -16);
STPx_S7_preindex(xEmu, x1, xSP, -16); // ARM64 stack needs to be 16byte aligned
STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller
STPx_S7_offset(xRDX, xRBX, xEmu, offsetof(x64emu_t, regs[_DX]));
STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI]));
STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8]));
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
fpu_pushcache(dyn, ninst, x7, 0);
TABLE64(x7, (uintptr_t)fnc);
BLR(x7);
LDPx_S7_postindex(xEmu, x1, xSP, 16);
LDPx_S7_postindex(x2, x3, xSP, 16);
LDPx_S7_postindex(x4, x5, xSP, 16);
#define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
GO(RAX, RCX);
GO(RDX, RBX);
GO(RSP, RBP);
GO(RSI, RDI);
GO(R8, R9);
#undef GO
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
fpu_popcache(dyn, ninst, x7, 0); // savereg will not be used
LDPx_S7_postindex(x6, x7, xSP, 16);
//SET_NODF();
}
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
{
MAYUSE(fnc);
@@ -858,19 +894,20 @@ void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
//SET_NODF();
}
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg)
{
(void)addr;
int64_t j64;
MAYUSE(j64);
if (modreg) return;
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
int t2 = x4;
if(reg==t2) ++t2;
LDRw_U12(t2, xEmu, offsetof(x64emu_t, segs_serial[segment]));
if(segment==_GS) {
/*if(segment==_GS) {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
CBNZw_MARKSEG(t2); // fast check
} else {
} else*/ {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, context));
LDRw_U12(reg, reg, offsetof(box64context_t, sel_serial));
SUBw_REG(t2, reg, t2);
@@ -1188,7 +1225,41 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
}
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
}
void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2)
{
// Synch top & stack counter
int a = dyn->n.x87stack;
if(a) {
MESSAGE(LOG_DUMP, "\tSync x87 Count of %d-----\n", a);
// Add x87stack to emu fpu_stack
LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDw_U12(s2, s2, a);
} else {
SUBw_U12(s2, s2, -a);
}
STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
if(a>0) {
SUBw_U12(s2, s2, a);
} else {
ADDw_U12(s2, s2, -a);
}
ANDw_mask(s2, s2, 0, 2); //mask=7
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// update tags
LDRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags));
if(a>0) {
LSLw_IMM(s1, s1, a*2);
} else {
ORRw_mask(s1, s1, 0b010000, 0b001111); // 0xffff0000
LSRw_IMM(s1, s1, -a*2);
}
STRH_U12(s1, xEmu, offsetof(x64emu_t, fpu_tags));
MESSAGE(LOG_DUMP, "\t-----Sync x87 Count\n");
}
}
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// Synch top & stack counter
@@ -1248,7 +1319,7 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
}
}
static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2)
{
// go back with the top & stack counter
int a = dyn->n.x87stack;
@@ -2217,7 +2288,7 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
neoncache_t cache = dyn->n;
int s1_val = 0;
int s2_val = 0;
// unload every uneeded cache
// unload every unneeded cache
// ymm0 first
int s3_top = 1;
uint16_t to_purge = dyn->ymm_zero&~dyn->insts[i2].ymm0_in;
@@ -2233,7 +2304,7 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
}
}
s3_top = 0xffff;
// check SSE first, than MMX, in order, to optimise successive memory write
// check SSE first, than MMX, in order, to optimize successive memory write
for(int i=0; i<16; ++i) {
int j=findCacheSlot(dyn, ninst, NEON_CACHE_XMMW, i, &cache);
if(j>=0 && findCacheSlot(dyn, ninst, NEON_CACHE_XMMW, i, &cache_i2)==-1)
@@ -2504,7 +2575,7 @@ void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// need to undo some things on the x87 tracking
x87_unreflectcache(dyn, ninst, s1, s2, s3);
x87_unreflectcount(dyn, ninst, s1, s2);
}
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4)
@@ -2609,10 +2680,10 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
dyn->ymm_zero = dyn->insts[reset_n].ymm0_out;
#endif
#if STEP == 0
if(box64_dynarec_dump && dyn->n.x87stack) dynarec_log(LOG_NONE, "New x87stack=%d at ResetCache in inst %d with %d\n", dyn->n.x87stack, ninst, reset_n);
if(BOX64DRENV(dynarec_dump) && dyn->n.x87stack) dynarec_log(LOG_NONE, "New x87stack=%d at ResetCache in inst %d with %d\n", dyn->n.x87stack, ninst, reset_n);
#endif
#if defined(HAVE_TRACE) && (STEP>2)
if(box64_dynarec_dump && 0) //disable for now, need more work
if(BOX64DRENV(dynarec_dump) && 0) //disable for now, need more work
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neoncache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
for(int i=0; i<32; ++i)
+125 -122
View File
@@ -74,17 +74,18 @@
LDz(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDw(D) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL,0, D); \
LDW(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETEDw(D) \
if (MODREG) { \
ed = xEAX + (nextop & 7) + (rex.b << 3); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff << 2, 3, rex, NULL, 0, D); \
LDW(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSEDw(D) \
if ((nextop & 0xC0) == 0xC0) { \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
SXTWx(x1, ed); \
wb = x1; \
@@ -106,7 +107,7 @@
ed = x1; \
}
#define GETSED32w(D) \
if ((nextop & 0xC0) == 0xC0) { \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
SXTWx(x1, ed); \
wb = x1; \
@@ -175,13 +176,10 @@
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
if (rex.is32bits) \
LDRxw_REG_SXTW(x1, O, wback); \
else \
LDRxw_REG(x1, wback, O); \
LDRxw_REGz(x1, O, wback); \
ed = x1; \
}
#define WBACKO(O) if(wback) {if(rex.is32bits) STRxw_REG_SXTW(ed, O, wback); else STRxw_REG(ed, wback, O); SMWRITE2();}
#define WBACKO(O) if(wback) {STRxw_REGz(ed, O, wback); SMWRITE2();}
//GETEDOx can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDOx(O, D) \
if (MODREG) { \
@@ -190,10 +188,7 @@
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
if (rex.is32bits) \
LDRx_REG_SXTW(x1, O, wback); \
else \
LDRx_REG(x1, wback, O); \
LDRx_REGz(x1, O, wback); \
ed = x1; \
}
//GETEDOz can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
@@ -204,14 +199,11 @@
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
if (rex.is32bits) \
LDRz_REG_SXTW(x1, O, wback); \
else \
LDRz_REG(x1, wback, O); \
LDRz_REGz(x1, O, wback); \
ed = x1; \
}
#define GETSEDOw(O, D) \
if ((nextop & 0xC0) == 0xC0) { \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
SXTWx(x1, ed); \
wb = x1; \
@@ -219,10 +211,7 @@
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, NULL, 0, D); \
if (rex.is32bits) \
LDRSW_REG_SXTW(x1, O, wback); \
else \
LDRSW_REG(x1, wback, O); \
LDRSW_REGz(x1, O, wback); \
wb = ed = x1; \
}
//FAKEELike GETED, but doesn't get anything
@@ -257,6 +246,9 @@
ed = i; \
wb1 = 1; \
}
//Compute wback for MDREG only, no fetching
#define CALCEW() \
wback = TO_NAT((nextop & 7) + (rex.b << 3)); \
//GETEW will use i for ed, and can use r3 for wback.
#define GETEW(i, D) \
if (MODREG) { \
@@ -321,6 +313,16 @@
#define EWBACKW(w) if(wb1) {STH(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFIx(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), gd, 0, 16);
// no fetch version of GETEB for MODREG path only
#define CALCEB() \
if (rex.rex) { \
wback = TO_NAT((nextop & 7) + (rex.b << 3)); \
wb2 = 0; \
} else { \
wback = (nextop & 7); \
wb2 = (wback >> 2) * 8; \
wback = TO_NAT(wback & 3); \
} \
//GETEB will use i for ed, and can use r3 for wback.
#define GETEB(i, D) \
if (MODREG) { \
@@ -409,6 +411,16 @@
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STB(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);}
// no fetch version of GETGB
#define CALCGB() \
if (rex.rex) { \
gb1 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); \
gb2 = 0; \
} else { \
gd = (nextop & 0x38) >> 3; \
gb2 = ((gd & 4) << 1); \
gb1 = TO_NAT(gd & 3); \
} \
//GETGB will use i for gd
#define GETGB(i) \
if (rex.rex) { \
@@ -704,8 +716,8 @@
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)
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&(((1<<(2+rex.w))-1)))) || BOX64ENV(dynarec_aligned_atomics))
#define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || BOX64ENV(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
@@ -716,6 +728,9 @@
// CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
// CALL_ will use x7 for the call address.
// All regs are saved, including scratch. This is use to call internal function that should not change state
#define CALL_I(F) call_i(dyn, ninst, F)
#define MARK dyn->insts[ninst].mark = dyn->native_size
#define GETMARK dyn->insts[ninst].mark
@@ -784,6 +799,10 @@
#define CBNZx_MARK2(reg) \
j64 = GETMARK2-(dyn->native_size); \
CBNZx(reg, j64)
// Branch to MARK2 if reg is not 0 (use j64)
#define CBNZw_MARK2(reg) \
j64 = GETMARK2-(dyn->native_size); \
CBNZw(reg, j64)
#define CBNZxw_MARK2(reg) \
j64 = GETMARK2-(dyn->native_size); \
CBNZxw(reg, j64)
@@ -879,6 +898,10 @@
#define B_MARKLOCK(cond) \
j64 = GETMARKLOCK-(dyn->native_size); \
Bcond(cond, j64)
// Branch to MARKLOCK unconditional (use j64)
#define B_MARKLOCK_nocond \
j64 = GETMARKLOCK-(dyn->native_size); \
B(j64)
// Branch to MARKLOCK if reg is not 0 (use j64)
#define CBNZw_MARKLOCK(reg) \
j64 = GETMARKLOCK-(dyn->native_size); \
@@ -887,6 +910,10 @@
#define CBNZx_MARKLOCK(reg) \
j64 = GETMARKLOCK-(dyn->native_size); \
CBNZx(reg, j64)
// Branch to MARKLOCK if reg is 0 (use j64)
#define CBZx_MARKLOCK(reg) \
j64 = GETMARKLOCK-(dyn->native_size); \
CBZx(reg, j64)
#ifndef IFNATIVE
#define IFNATIVE(A) if(dyn->insts[ninst].need_nat_flags&(A))
@@ -915,7 +942,7 @@
#endif
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3, s4, v1, v2, is_f) \
#define FCOM(s1, s2, s3) \
LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw)); /*offset is 8bits right?*/\
MOV32w(s1, 0b0100011100000000); \
BICw_REG(s3, s3, s1); \
@@ -925,33 +952,11 @@
CSELw(s1, s2, s1, cEQ); \
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
if(v1||v2) { \
Bcond(cVS, 10*4); \
if(is_f) { \
ORRw_mask(s4, xZR, 12, 10); /*+inf*/ \
FMOVwS(s2, v1); \
CMPSw_REG(s2, s4); \
Bcond(cEQ, 5*4); /* same */ \
FMOVwS(s2, v2); \
ORRw_mask(s4, s4, 1, 0); /*-inf*/ \
CMPSw_REG(s2, s4); \
} else { \
ORRx_mask(s4, xZR, 1, 12, 10); /*+inf*/ \
FMOVxD(s2, v1); \
CMPSx_REG(s2, s4); \
Bcond(cEQ, 5*4); /* same */ \
FMOVxD(s2, v2); \
ORRx_mask(s4, s4, 1, 1, 0); /*-inf*/ \
CMPSx_REG(s2, s4); \
} \
Bcond(cNE, 4+4); /* same */ \
MOVZw(s2, 0); \
} \
ORRw_REG_LSL(s3, s3, s1, 8); \
STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2, s4, v1, v2, is_f) \
#define FCOMI(s1, s2) \
IFX(X_OF|X_AF|X_SF|X_PEND) { \
MOV32w(s2, 0b100011010101); \
BICw_REG(xFlags, xFlags, s2); \
@@ -971,32 +976,17 @@
MOV32w(s2, 0b01000000); /* zero */ \
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
if(s4) { \
Bcond(cVS, 10*4); \
if(is_f) { \
ORRw_mask(s4, xZR, 12, 10); /*+inf*/ \
FMOVwS(s2, v1); \
CMPSw_REG(s2, s4); \
Bcond(cEQ, 5*4); /* same */ \
FMOVwS(s2, v2); \
ORRw_mask(s4, s4, 1, 0); /*-inf*/ \
CMPSw_REG(s2, s4); \
} else { \
ORRx_mask(s4, xZR, 1, 12, 10); /*+inf*/ \
FMOVxD(s2, v1); \
CMPSx_REG(s2, s4); \
Bcond(cEQ, 5*4); /* same */ \
FMOVxD(s2, v2); \
ORRx_mask(s4, s4, 1, 1, 0); /*-inf*/ \
CMPSx_REG(s2, s4); \
} \
Bcond(cNE, 4+4); /* same */ \
MOVZw(s1, 0); \
} \
ORRw_REG(xFlags, xFlags, s1); \
} \
SET_DFNONE(s1); \
SET_DFNONE(); \
#ifndef IF_UNALIGNED
#define IF_UNALIGNED(A) if(is_addr_unaligned(A))
#endif
#ifndef IF_ALIGNED
#define IF_ALIGNED(A) if (!is_addr_unaligned(A))
#endif
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STP_REGS(A, B) STPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
@@ -1075,7 +1065,7 @@
#else
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
@@ -1083,7 +1073,7 @@
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
@@ -1091,34 +1081,42 @@
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==-8) || (dyn->n.poped==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Pop, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.poped, ninst); \
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, " Warning, suspicious x87 Pop, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.poped, ninst); \
dyn->abort = 1; \
return addr; \
} \
x87_do_pop(dyn, ninst, scratch)
#endif
#define SET_DFNONE(S) do {dyn->f.dfnone_here=1; if(!dyn->f.dfnone) {STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}} while(0);
#define SET_DF(S, N) \
if((N)!=d_none) { \
MOVZw(S, (N)); \
STRw_U12(S, xEmu, offsetof(x64emu_t, df)); \
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after&X_PEND)) { \
CALL_(UpdateFlags, -1, 0); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone=0; \
} else SET_DFNONE(S)
#define SET_DFNONE() \
do { \
if (!dyn->f.dfnone) { \
STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); \
} \
if(!dyn->insts[ninst].x64.may_set) { \
dyn->f.dfnone_here = 1; \
dyn->f.dfnone = 1; \
} \
} while(0)
#define SET_DF(S, N) \
if ((N) != d_none) { \
MOVZw(S, (N)); \
STRw_U12(S, xEmu, offsetof(x64emu_t, df)); \
if (dyn->f.pending == SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after & X_PEND)) { \
CALL_I(UpdateFlags); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone = 0; \
} else \
SET_DFNONE()
#ifndef SET_NODF
#define SET_NODF() dyn->f.dfnone = 0
#endif
#define SET_DFOK() dyn->f.dfnone = 1; dyn->f.dfnone_here=1
#ifndef MAYSETFLAGS
#define MAYSETFLAGS() do {} while (0)
#endif
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
@@ -1128,7 +1126,7 @@
j64 = (GETMARKF)-(dyn->native_size); \
CBZw(x3, j64); \
} \
CALL_(UpdateFlags, -1, 0); \
CALL_I(UpdateFlags); \
MARKF; \
dyn->f.pending = SF_SET; \
SET_DFOK(); \
@@ -1142,7 +1140,7 @@
&& (dyn->insts[ninst].x64.gen_flags&(~(A)))) \
READFLAGS(((dyn->insts[ninst].x64.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x64.gen_flags)&(~(A)));\
if(dyn->insts[ninst].x64.gen_flags) switch(B) { \
case SF_SUBSET: \
case SF_SUBSET: SET_DFNONE(); dyn->f.pending = SF_SET; break; \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_SET_DF: dyn->f.pending = SF_SET; dyn->f.dfnone = 1; break; \
case SF_SET_NODF: dyn->f.pending = SF_SET; dyn->f.dfnone = 0; break; \
@@ -1166,8 +1164,10 @@
#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));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A);}
#define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags)
#define UFLAG_IF_DF if(dyn->insts[ninst].x64.gen_flags || (dyn->insts[ninst].f_entry.dfnone && dyn->insts[ninst].f_entry.dfnone_here))
#define UFLAG_IF2(A) if(dyn->insts[ninst].x64.gen_flags A)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
@@ -1188,8 +1188,8 @@
#define ARCH_RESET()
#if STEP < 2
#define GETIP(A) TABLE64(0, 0)
#define GETIP_(A) TABLE64(0, 0)
#define GETIP(A) MOV64x(xRIP, A)
#define GETIP_(A) MOV64x(xRIP, A)
#else
// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
#define GETIP(A) \
@@ -1201,20 +1201,14 @@
} \
} else { \
dyn->last_ip = (A); \
if(dyn->last_ip<0xffffffff) { \
MOV64x(xRIP, dyn->last_ip); \
} else \
TABLE64(xRIP, dyn->last_ip); \
MOV64x(xRIP, dyn->last_ip); \
}
#define GETIP_(A) \
if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \
uint64_t _delta_ip = (A)-dyn->last_ip; \
if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\
} else { \
if((A)<0xffffffff) { \
MOV64x(xRIP, (A)); \
} else \
TABLE64(xRIP, (A)); \
MOV64x(xRIP, (A)); \
}
#endif
#define CLEARIP() dyn->last_ip=0
@@ -1288,6 +1282,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define retn_to_epilog STEPNAME(retn_to_epilog)
#define iret_to_epilog STEPNAME(iret_to_epilog)
#define call_c STEPNAME(call_c)
#define call_i STEPNAME(call_i)
#define call_n STEPNAME(call_n)
#define grab_segdata STEPNAME(grab_segdata)
#define emit_cmp8 STEPNAME(emit_cmp8)
@@ -1430,6 +1425,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define fpu_purgecache STEPNAME(fpu_purgecache)
#define mmx_purgecache STEPNAME(mmx_purgecache)
#define x87_purgecache STEPNAME(x87_purgecache)
#define x87_reflectcount STEPNAME(x87_reflectcount)
#define x87_unreflectcount STEPNAME(x87_unreflectcount)
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
#define avx_purge_ymm STEPNAME(avx_purge_ymm)
@@ -1456,8 +1453,9 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
void call_i(dynarec_arm_t* dyn, int ninst, void* fnc);
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
@@ -1667,6 +1665,11 @@ void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
// purge x87 cache
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
// temporarily set x87 stack count for C functions
void x87_reflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2);
// restore count after
void x87_unreflectcount(dynarec_arm_t* dyn, int ninst, int s1, int s2);
// global fpu helper
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
@@ -1892,19 +1895,19 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
} \
break
#define NOTEST(s1) \
if(box64_dynarec_test) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.test)); \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean));\
#define NOTEST(s1) \
if (BOX64ENV(dynarec_test)) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.test)); \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean)); \
}
#define SKIPTEST(s1) \
if(box64_dynarec_test) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean));\
#define SKIPTEST(s1) \
if (BOX64ENV(dynarec_test)) { \
STRw_U12(xZR, xEmu, offsetof(x64emu_t, test.clean)); \
}
#define GOTEST(s1, s2) \
if(box64_dynarec_test) { \
MOV32w(s2, 1); \
STRw_U12(s2, xEmu, offsetof(x64emu_t, test.test)); \
#define GOTEST(s1, s2) \
if (BOX64ENV(dynarec_test)) { \
MOV32w(s2, 1); \
STRw_U12(s2, xEmu, offsetof(x64emu_t, test.test)); \
}
#define GETREX() \
+25 -17
View File
@@ -6,15 +6,16 @@
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
#define MESSAGE(A, ...) do {} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define READFLAGS(A) \
dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\
if(!BOX64ENV(dynarec_df) && (A)&X_PEND) dyn->insts[ninst].x64.use_flags = X_ALL; \
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0; \
if(!BOX64ENV(dynarec_df)) {dyn->f.dfnone=1; dyn->f.pending=0; if((A)==SF_PENDING){printf_log(LOG_INFO, "Warning, some opcode use SF_PENDING, forcing deferedflags ON\n"); SET_BOX64ENV(dynarec_df, 1); }}
#define EMIT(A) dyn->native_size+=4
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C; dyn->insts[ninst].x64.jmp_insts = 0
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
@@ -33,23 +34,27 @@
if(dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH && !dyn->insts[ninst].set_nat_flags) \
dyn->insts[ninst].nat_flags_op=NAT_FLAG_OP_UNUSABLE; \
dyn->insts[ninst].x64.has_next = (ok>0)?1:0;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing==1) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of %sOpcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, rex.is32bits?"x86 ":"x64 ",\
PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
PKip(10),PKip(11),PKip(12), \
PKip(13),PKip(14)); \
printFunctionAddr(ip, " => "); \
dynarec_log(LOG_NONE, "\n"); \
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if (ninst) { dyn->insts[ninst - 1].x64.size = ip - dyn->insts[ninst - 1].x64.addr; } \
if (BOX64ENV(dynarec_log) >= LOG_INFO || BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_missing) == 1) \
if (!dyn->size || BOX64ENV(dynarec_log) > LOG_INFO || BOX64DRENV(dynarec_dump)) { \
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of %s Opcode ", (void*)ip, rex.is32bits ? "x86" : "x64"); \
zydis_dec_t* dec = rex.is32bits ? my_context->dec32 : my_context->dec; \
if (dec) { \
dynarec_log_prefix(0, LOG_NONE, "%s", DecodeX64Trace(dec, dyn->insts[ninst].x64.addr, 1)); \
} else { \
dynarec_log_prefix(0, LOG_NONE, "%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
PKip(0), PKip(1), PKip(2), PKip(3), PKip(4), PKip(5), PKip(6), PKip(7), PKip(8), PKip(9), \
PKip(10), PKip(11), PKip(12), PKip(13), PKip(14)); \
} \
printFunctionAddr(ip, " => "); \
dynarec_log_prefix(0, LOG_NONE, "\n"); \
}
#define FEMIT(A) dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].x64.set_flags?NAT_FLAG_OP_TOUCH:NAT_FLAG_OP_UNUSABLE
#define IFNATIVE(A) if(mark_natflag(dyn, ninst, A, 0))
#define IFNATIVEN(A) if(mark_natflag(dyn, ninst, A, 0))
@@ -64,3 +69,6 @@
#define IFNATIVE_BEFORE(A) if(mark_natflag(dyn, ninst, A, 1))
#define INVERT_CARRY(A) dyn->insts[ninst].invert_carry = 1
#define INVERT_CARRY_BEFORE(A) dyn->insts[ninst].invert_carry_before = 1
// mark opcode as "unaligned" possible only if the current address is not marked as already unaligned
#define IF_UNALIGNED(A) if((dyn->insts[ninst].unaligned=(is_addr_unaligned(A)?0:1)))
#define IF_ALIGNED(A) if((dyn->insts[ninst].unaligned=(is_addr_unaligned(A)?1:0)))
+6 -6
View File
@@ -2,16 +2,16 @@
#define FINI
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define SET_NODF() \
if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \
propagate_nodf(dyn, ninst); \
dyn->f.dfnone = 0
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0; \
if(!BOX64ENV(dynarec_df)) {dyn->f.dfnone=1; dyn->f.pending=0; }
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
+1 -1
View File
@@ -2,7 +2,7 @@
#define FINI \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>(dyn->insts[ninst-1].size/4))?dyn->insts[ninst-1].x64.size:(dyn->insts[ninst-1].size/4))/15; \
}
#define MESSAGE(A, ...) do {} while (0)
+3 -3
View File
@@ -1,18 +1,18 @@
#define INIT
#define FINI \
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x64.size, dyn->insts[ninst].size/4); \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4); \
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
#define EMIT(A) \
do{ \
if(box64_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
if(BOX64DRENV(dynarec_dump)) print_opcode(dyn, ninst, (uint32_t)(A)); \
if((uintptr_t)dyn->block<dyn->tablestart) \
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
dyn->block += 4; dyn->native_size += 4; \
dyn->insts[ninst].size2 += 4; \
}while(0)
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define MESSAGE(A, ...) if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst) { \
if(dyn->insts[ninst].address!=(uintptr_t)dyn->block-(uintptr_t)dyn->native_start) dyn->abort = 1; \
@@ -122,6 +122,7 @@ typedef struct instruction_arm64_s {
unsigned normal_carry_before:1;
unsigned invert_carry:1; // this opcode force an inverted carry
unsigned df_notneeded:1;
unsigned unaligned:1; // this opcode can be re-generated for unaligned special case
flagcache_t f_exit; // flags status at end of instruction
neoncache_t n; // neoncache at end of instruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin
@@ -164,6 +165,7 @@ typedef struct dynarec_arm_s {
uint8_t doublepop;
uint8_t always_test;
uint8_t abort; // abort the creation of the block
void* gdbjit_block;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+1 -1
View File
@@ -208,7 +208,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
}
if(need_lock) {
if(box64_dynarec_wait) {
if(BOX64ENV(dynarec_wait)) {
mutex_lock(&my_context->mutex_dyndump);
} else {
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
+3 -1
View File
@@ -21,7 +21,9 @@ typedef struct dynablock_s {
uint8_t is32bits:1;
int isize;
instsize_t* instsize;
void* arch; // arch dependant per inst info (can be NULL)
size_t arch_size; // size of of arch dependant infos
void* jmpnext; // a branch jmpnext code when block is marked
} dynablock_t;
#endif //__DYNABLOCK_PRIVATE_H_
#endif //__DYNABLOCK_PRIVATE_H_
+15 -20
View File
@@ -52,7 +52,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
dynablock_t* block = NULL;
if(hasAlternate((void*)addr)) {
printf_log(LOG_DEBUG, "Jmp address has alternate: %p", (void*)addr);
if(box64_log<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
if (BOX64ENV(log)<LOG_DEBUG) dynarec_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
uintptr_t old_addr = addr;
addr = (uintptr_t)getAlternate((void*)addr); // set new address
R_RIP = addr; // but also new RIP!
@@ -63,7 +63,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
block = DBGetBlock(emu, addr, 1, is32bits);
if(!block) {
#ifdef HAVE_TRACE
if(LOG_INFO<=box64_dynarec_log) {
if(LOG_INFO<=BOX64ENV(dynarec_log)) {
if(checkInHotPage(addr)) {
dynarec_log(LOG_INFO, "Not trying to run a block from a Hotpage at %p\n", (void*)addr);
} else {
@@ -79,7 +79,7 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
if(!block->done) {
// not finished yet... leave linker
#ifdef HAVE_TRACE
if(box64_dynarec_log && !block->isize) {
if(BOX64ENV(dynarec_log) && !block->isize) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, NULL block at %p from %p (db=%p, x64addr=%p/%s)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
}
@@ -109,9 +109,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
// uc_link
void* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
#ifdef BOX32
if(box64_is32bits)
@@ -124,7 +121,6 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
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
@@ -176,7 +172,7 @@ void DynaRun(x64emu_t* emu)
{
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
#ifdef DYNAREC
if(box64_dynarec_test) {
if(BOX64ENV(dynarec_test)) {
if(emu->test.clean)
x64test_check(emu, R_RIP);
emu->test.clean = 0;
@@ -188,7 +184,7 @@ void DynaRun(x64emu_t* emu)
emu->flags.need_jmpbuf = 0;
#ifdef DYNAREC
if(!box64_dynarec)
if(!BOX64ENV(dynarec))
#endif
Run(emu, 0);
#ifdef DYNAREC
@@ -214,12 +210,20 @@ void DynaRun(x64emu_t* emu)
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
if(box64_dynarec_test)
if(BOX64ENV(dynarec_log)) {
if(ACCESS_FLAG(F_TF))
dynarec_log(LOG_INFO, "%04d|Running Interpreter @%p, emu=%p because TF is on\n", GetTID(), (void*)R_RIP, emu);
else
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_RIP, emu);
}
if (BOX64ENV(dynarec_test))
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu);
if(!BOX64ENV(dynarec_df)) {
CHECK_FLAGS(emu);
}
// block is here, let's run it!
native_prolog(emu, block->block);
}
@@ -229,15 +233,6 @@ void DynaRun(x64emu_t* emu)
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
}
if(emu->quit && emu->uc_link) {
emu->quit = 0;
#ifdef BOX32
if(box64_is32bits)
my32_setcontext(emu, emu->uc_link);
else
#endif
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
+23 -1
View File
@@ -5,6 +5,7 @@
#define instruction_native_t instruction_arm64_t
#define dynarec_native_t dynarec_arm_t
#define extcache_native_t neoncache_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
@@ -16,6 +17,7 @@
#include "arm64/arm64_printer.h"
#include "arm64/dynarec_arm64_private.h"
#include "arm64/dynarec_arm64_functions.h"
#include "arm64/dynarec_arm64_arch.h"
// Limit here is defined by LD litteral, that is 19bits
#define MAXBLOCK_SIZE ((1<<19)-200)
@@ -23,10 +25,16 @@
#define UPDATE_SPECIFICS(A) updateNativeFlags(A)
#define PREUPDATE_SPECIFICS(A)
#define ARCH_SIZE(A) get_size_arch(A)
#define ARCH_FILL(A, B, C) populate_arch(A, B, C)
#define ARCH_ADJUST(A, B, C, D) adjust_arch(A, B, C, D)
#define STOP_NATIVE_FLAGS(A, B) A->insts[B].nat_flags_op = NAT_FLAG_OP_UNUSABLE
#define ARCH_UNALIGNED(A, B) arch_unaligned(A, B)
#elif defined(LA64)
#define instruction_native_t instruction_la64_t
#define dynarec_native_t dynarec_la64_t
#define extcache_native_t lsxcache_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
@@ -42,11 +50,18 @@
#define RAZ_SPECIFIC(A, N)
#define UPDATE_SPECIFICS(A)
#define PREUPDATE_SPECIFICS(A)
#define PREUPDATE_SPECIFICS(A) updateNativeFlags(A)
#define ARCH_SIZE(A) 0
#define ARCH_FILL(A, B, C) NULL
#define ARCH_ADJUST(A, B, C, D) {}
#define STOP_NATIVE_FLAGS(A, B) {}
#define ARCH_UNALIGNED(A, B) 0
#elif defined(RV64)
#define instruction_native_t instruction_rv64_t
#define dynarec_native_t dynarec_rv64_t
#define extcache_native_t extcache_t
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \
@@ -59,12 +74,19 @@
#include "rv64/rv64_printer.h"
#include "rv64/dynarec_rv64_private.h"
#include "rv64/dynarec_rv64_functions.h"
#include "rv64/dynarec_rv64_arch.h"
// Limit here is unconditionnal jump, that is signed 21bits
#define MAXBLOCK_SIZE ((1<<20)-200)
#define RAZ_SPECIFIC(A, N)
#define UPDATE_SPECIFICS(A)
#define PREUPDATE_SPECIFICS(A) updateNativeFlags(A)
#define ARCH_SIZE(A) get_size_arch(A)
#define ARCH_FILL(A, B, C) populate_arch(A, B, C)
#define ARCH_ADJUST(A, B, C, D) {}
#define STOP_NATIVE_FLAGS(A, B) {}
#define ARCH_UNALIGNED(A, B) arch_unaligned(A, B)
#else
#error Unsupported platform
#endif
+32 -30
View File
@@ -49,12 +49,12 @@
SMWRITE(); \
} while (0)
#define SMWRITE2() \
do { \
if (box64_dynarec_strongmem >= STRONGMEM_SIMD_WRITE) { \
dyn->smwrite = 1; \
dyn->insts[ninst].will_write = 2; \
} \
#define SMWRITE2() \
do { \
if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) { \
dyn->smwrite = 1; \
dyn->insts[ninst].will_write = 2; \
} \
} while (0)
#define SMREAD()
@@ -71,7 +71,7 @@
#define SMEND() \
do { \
/* If there is any guest memory write, which is a SEQ, then compute the last_write. */ \
if (dyn->smwrite && (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE)) { \
if (dyn->smwrite && (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE)) { \
int i = ninst; \
while (i >= 0 && !dyn->insts[i].will_write) \
--i; \
@@ -88,7 +88,7 @@
#define SMWRITE() \
do { \
/* Put a barrier at every third memory write. */ \
if (box64_dynarec_strongmem >= STRONGMEM_SEQ_WRITE) { \
if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SEQ_WRITE) { \
if (++dyn->smwrite >= 3 /* Every third memory write */) { \
DMB_ISH(); \
dyn->smwrite = 1; \
@@ -110,10 +110,10 @@
} while (0)
// Similar to SMWRITE, but for SIMD instructions.
#define SMWRITE2() \
do { \
if (box64_dynarec_strongmem >= STRONGMEM_SIMD_WRITE) \
SMWRITE(); \
#define SMWRITE2() \
do { \
if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) \
SMWRITE(); \
} while (0)
// An opcode reads guest memory, this need to be put before the LOAD instruction manually.
@@ -130,22 +130,22 @@
} while (0)
// An opcode will write memory, this will be put before the STORE instruction automatically.
#define WILLWRITE() \
do { \
if (box64_dynarec_strongmem >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \
/* Will write but never written, this is the start of a SEQ, put a barrier. */ \
if (box64_dynarec_weakbarrier) \
DMB_ISHLD(); \
else \
DMB_ISH(); \
} else if (box64_dynarec_strongmem >= STRONGMEM_LAST_WRITE && box64_dynarec_weakbarrier != 2 \
&& dyn->insts[ninst].last_write) { \
/* Last write, put a barrier */ \
if (box64_dynarec_weakbarrier) \
DMB_ISHST(); \
else \
DMB_ISH(); \
} \
#define WILLWRITE() \
do { \
if (BOX64DRENV(dynarec_strongmem) >= dyn->insts[ninst].will_write && dyn->smwrite == 0) { \
/* Will write but never written, this is the start of a SEQ, put a barrier. */ \
if (BOX64ENV(dynarec_weakbarrier)) \
DMB_ISHLD(); \
else \
DMB_ISH(); \
} else if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE && BOX64ENV(dynarec_weakbarrier) != 2 \
&& dyn->insts[ninst].last_write) { \
/* Last write, put a barrier */ \
if (BOX64ENV(dynarec_weakbarrier)) \
DMB_ISHST(); \
else \
DMB_ISH(); \
} \
} while (0)
// Similar to WILLWRITE, but checks lock.
@@ -167,11 +167,11 @@
// Will be put at the end of the SEQ
#define SMEND() \
do { \
if (box64_dynarec_strongmem) { \
if (BOX64DRENV(dynarec_strongmem)) { \
/* It's a SEQ, put a barrier here. */ \
if (dyn->smwrite) { \
/* Check if the next instruction has a end loop mark */ \
if (box64_dynarec_weakbarrier) \
if (BOX64ENV(dynarec_weakbarrier)) \
DMB_ISHST(); \
else \
DMB_ISH(); \
@@ -184,6 +184,8 @@
#define SMDMB() DMB_ISH()
#endif
int is_addr_unaligned(uintptr_t addr);
#ifdef ARM64
#include "arm64/dynarec_arm64_helper.h"
#elif defined(LA64)
+102 -36
View File
@@ -1,3 +1,4 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
@@ -22,25 +23,26 @@
#include "dynarec_native.h"
#include "dynarec_arch.h"
#include "dynarec_next.h"
#include "gdbjit.h"
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
void printf_x64_instruction(dynarec_native_t* dyn, zydis_dec_t* dec, instruction_x64_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uintptr_t a = *(uintptr_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%s%p: Exit x64emu%s\n", (box64_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Exit x64emu%s\n", (BOX64DRENV(dynarec_dump)>1)?"\e[01;33m":"", (void*)ip, (BOX64DRENV(dynarec_dump)>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box64_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (void*)a, (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (BOX64DRENV(dynarec_dump)>1)?"\e[01;33m":"", (void*)ip, (void*)a, (BOX64DRENV(dynarec_dump)>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%s%p: %s", (box64_dynarec_dump>1)?"\e[01;33m":"", ip, DecodeX64Trace(dec, inst->addr));
dynarec_log(LOG_NONE, "%s%p: %s", (BOX64DRENV(dynarec_dump) > 1) ? "\e[01;33m" : "", ip, DecodeX64Trace(dec, inst->addr, 1));
} else {
dynarec_log(LOG_NONE, "%s%p: ", (box64_dynarec_dump>1)?"\e[01;33m":"", ip);
dynarec_log(LOG_NONE, "%s%p: ", (BOX64DRENV(dynarec_dump)>1)?"\e[01;33m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
dynarec_log_prefix(0, LOG_NONE, "%02X ", ip[i]);
}
dynarec_log(LOG_NONE, " %s", name);
dynarec_log_prefix(0, LOG_NONE, " %s", name);
}
// print Call function name if possible
if(ip[0]==0xE8 || ip[0]==0xE9) { // Call / Jmp
@@ -53,12 +55,12 @@ void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const cha
}
}
// end of line and colors
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log_prefix(0, LOG_NONE, "%s\n", (BOX64DRENV(dynarec_dump)>1)?"\e[m":"");
}
}
void add_next(dynarec_native_t *dyn, uintptr_t addr) {
if(!box64_dynarec_bigblock)
if (!BOX64DRENV(dynarec_bigblock))
return;
// exist?
for(int i=0; i<dyn->next_sz; ++i)
@@ -377,9 +379,10 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
need |= dyn->insts[ninst].x64.need_after;
if((need&X_PEND) && (dyn->insts[ninst].x64.state_flags==SF_SUBSET || dyn->insts[ninst].x64.state_flags==SF_SET || dyn->insts[ninst].x64.state_flags==SF_SET_NODF)) {
if((need&X_PEND) && ((dyn->insts[ninst].x64.state_flags==SF_SUBSET) || (dyn->insts[ninst].x64.state_flags==SF_SET) || (dyn->insts[ninst].x64.state_flags==SF_SET_NODF))) {
need &=~X_PEND;
need |= X_ALL;
STOP_NATIVE_FLAGS(dyn, ninst);
}
if((need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET_PENDING) {
need |= X_ALL&~(dyn->insts[ninst].x64.set_flags);
@@ -419,7 +422,7 @@ static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached)
int can_incr = ninst == max_ninst_reached; // Are we the top-level call?
int ok = 1;
while ((can_incr || ok) && ninst<dyn->size) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "update ninst=%d (%d): can_incr=%d\n", ninst, max_ninst_reached, can_incr);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "update ninst=%d (%d): can_incr=%d\n", ninst, max_ninst_reached, can_incr);
uint16_t new_purge_ymm, new_ymm0_in, new_ymm0_out;
if (dyn->insts[ninst].pred_sz && dyn->insts[ninst].x64.alive) {
@@ -430,18 +433,18 @@ static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached)
uint16_t ymm0_inter = (ninst && !(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? ((uint16_t)-1) : (uint16_t)0;
for (int i = 0; i < dyn->insts[ninst].pred_sz; ++i) {
int pred = dyn->insts[ninst].pred[i];
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\twith pred[%d] = %d", i, pred);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "\twith pred[%d] = %d", i, pred);
if (pred >= max_ninst_reached) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, " (skipped)\n");
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, " (skipped)\n");
continue;
}
int pred_out = dyn->insts[pred].x64.has_callret ? 0 : dyn->insts[pred].ymm0_out;
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, " ~> %04X\n", pred_out);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, " ~> %04X\n", pred_out);
ymm0_union |= pred_out;
ymm0_inter &= pred_out;
}
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t=> %04X,%04X\n", ymm0_union, ymm0_inter);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "\t=> %04X,%04X\n", ymm0_union, ymm0_inter);
// Notice the default values yield something coherent here (if all pred are after ninst)
new_purge_ymm = ymm0_union & ~ymm0_inter;
new_ymm0_in = ymm0_inter;
@@ -463,7 +466,7 @@ static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached)
int jmp = (dyn->insts[ninst].x64.jmp)?dyn->insts[ninst].x64.jmp_insts:-1;
if((jmp!=-1) && (jmp < max_ninst_reached)) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
// The jump goes before the last instruction reached, update the destination
// If this is the top level call, this means the jump goes backward (jmp != ninst)
// Otherwise, since we don't update all instructions, we may miss the update (don't use jmp < ninst)
@@ -477,7 +480,7 @@ static void updateYmm0s(dynarec_native_t* dyn, int ninst, int max_ninst_reached)
// Also update jumps to before (they are skipped otherwise)
int jmp = (dyn->insts[ninst].x64.jmp)?dyn->insts[ninst].x64.jmp_insts:-1;
if((jmp!=-1) && (jmp < max_ninst_reached)) {
//if(box64_dynarec_dump) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
//if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "\t! jump to %d\n", jmp);
updateYmm0s(dyn, jmp, max_ninst_reached);
}
} else {
@@ -503,6 +506,37 @@ static uint64_t static_table64[(MAX_INSTS+3)/4];
static instruction_native_t static_insts[MAX_INSTS+2] = {0};
// TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory
void ClearCache(void* start, size_t len)
{
#if defined(ARM64)
// manually clear cache, I have issue with regular function on Ampere with kernel 6.12.4
uintptr_t xstart = (uintptr_t)start;
uintptr_t xend = (uintptr_t)start + len + 1;
// Cache Type Info. Only grab the info once
static uint64_t ctr_el0 = 0;
if (ctr_el0 == 0)
__asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
const int ctr_el0_idc = (ctr_el0>>28)&1; // 0: datacache needs to be cleaned too, 1: no need
const int ctr_el0_dic = (ctr_el0>>29)&1; // 0: instruction cache needs to be cleaned, 1: no need
const uintptr_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
const uintptr_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
if (!ctr_el0_idc) {
//purge each dcache line if no icache is defined...
for (uint64_t addr=xstart&~(dcache_line_size-1); addr<xend; addr+=dcache_line_size)
__asm __volatile("dc cvau, %0" ::"r"(addr));
}
// ignoring idc...
if (1/*ctr_el0_idx*/) {
// purge each icache line
for (uint64_t addr=xstart&~(icache_line_size-1); addr<xend; addr+=icache_line_size)
__asm __volatile("ic ivau, %0" ::"r"(addr));
}
__asm __volatile("isb sy");
#else
__builtin___clear_cache(start, start+len+1);
#endif
}
void CancelBlock64(int need_lock)
{
if(need_lock)
@@ -544,7 +578,7 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) {
*(void**)(p+2*sizeof(void*)) = native_epilog;
CreateJmpNext(block->jmpnext, p+2*sizeof(void*));
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
ClearCache(actual_p+sizeof(void*), 3*sizeof(void*)); // need to clear the cache before execution...
return block;
}
@@ -560,9 +594,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
B+16 .. B+23 : jmpnext (or jmp_epilog) address. jumpnext is used when the block needs testing
B+24 .. B+31 : empty (in case an architecture needs more than 2 opcodes)
B+32 .. B+32+sz : instsize (compressed array with each instruction length on x64 and native side)
C .. C+sz : arch: arch specific info (likes flags info) per inst (can be absent)
*/
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
if(addr>=BOX64ENV(nodynarec_start) && addr<BOX64ENV(nodynarec_end)) {
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(block, addr, is32bits);
}
@@ -574,6 +609,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
protectDB(addr, 1);
// init the helper
dynarec_native_t helper = {0};
dynarec_native_t* dyn = &helper;
#ifdef GDBJIT
helper.gdbjit_block = box_calloc(1, sizeof(gdbjit_block_t));
#endif
current_helper = &helper;
helper.dynablock = block;
helper.start = addr;
@@ -589,7 +628,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// pass 0, addresses, x64 jump addresses, overall size of the block
uintptr_t end = native_pass0(&helper, addr, alternate, is32bits);
if(helper.abort) {
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
CancelBlock64(0);
return NULL;
}
@@ -671,7 +710,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
PREUPDATE_SPECIFICS(&helper);
int pos = helper.size;
int pos = helper.size-1;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// remove fpu stuff on non-executed code
@@ -704,7 +743,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// pass 1, float optimizations, first pass for flags
native_pass1(&helper, addr, alternate, is32bits);
if(helper.abort) {
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass1\n");
if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass1\n");
CancelBlock64(0);
return NULL;
}
@@ -712,7 +751,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// pass 2, instruction size
native_pass2(&helper, addr, alternate, is32bits);
if(helper.abort) {
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass2\n");
if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass2\n");
CancelBlock64(0);
return NULL;
}
@@ -720,14 +759,16 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
size_t native_size = (helper.native_size+7)&~7; // round the size...
size_t arch_size = ARCH_SIZE(&helper);
// ok, now allocate mapped memory, with executable flag on
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize;
// dynablock_t* block (arm insts) table64 jmpnext code instsize
size_t sz = sizeof(void*) + native_size + helper.table64size*sizeof(uint64_t) + 4*sizeof(void*) + insts_rsize + arch_size;
// dynablock_t* block (arm insts) table64 jmpnext code instsize arch
void* actual_p = (void*)AllocDynarecMap(sz);
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
void* tablestart = p + native_size;
void* next = tablestart + helper.table64size*sizeof(uint64_t);
void* instsize = next + 4*sizeof(void*);
void* arch = instsize + insts_rsize;
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, canceling block\n", block, sz);
CancelBlock64(0);
@@ -743,10 +784,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
helper.table64cap = helper.table64size;
helper.table64 = (uint64_t*)helper.tablestart;
// pass 3, emit (log emit native opcode)
if(box64_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64");
if(BOX64DRENV(dynarec_dump)) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u %s bytes (native=%zu, table64=%zu, instsize=%zu, arch=%zu)", (BOX64DRENV(dynarec_dump)>1)?"\e[01;36m":"", GetTID(), helper.native_size, helper.isize, is32bits?"x86":"x64", native_size, helper.table64size*sizeof(uint64_t), insts_rsize, arch_size);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s\n", (BOX64DRENV(dynarec_dump)>1)?"\e[m":"");
}
if (BOX64ENV(dynarec_gdbjit) && (!BOX64ENV(dynarec_gdbjit_end) || (addr >= BOX64ENV(dynarec_gdbjit_start) && addr < BOX64ENV(dynarec_gdbjit_end)))) {
GdbJITNewBlock(helper.gdbjit_block, (GDB_CORE_ADDR)block->actual_block, (GDB_CORE_ADDR)block->actual_block + native_size, helper.start);
}
int oldtable64size = helper.table64size;
size_t oldnativesize = helper.native_size;
@@ -757,7 +801,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
helper.insts_size = 0; // reset
native_pass3(&helper, addr, alternate, is32bits);
if(helper.abort) {
if(box64_dynarec_dump || box64_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass3\n");
if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass3\n");
CancelBlock64(0);
return NULL;
}
@@ -776,13 +820,25 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
block->always_test = helper.always_test;
block->dirty = block->always_test;
block->is32bits = is32bits;
if(arch_size) {
block->arch_size = arch_size;
block->arch = ARCH_FILL(&helper, arch, arch_size);
if(!block->arch) block->arch_size = 0;
} else {
block->arch = NULL;
block->arch_size = arch_size;
}
*(dynablock_t**)next = block;
*(void**)(next+3*sizeof(void*)) = native_next;
CreateJmpNext(block->jmpnext, next+3*sizeof(void*));
ClearCache(block->jmpnext, 4*sizeof(void*));
//block->x64_addr = (void*)start;
block->x64_size = end-start;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
if (BOX64ENV(dynarec_gdbjit) && (!BOX64ENV(dynarec_gdbjit_end) || (addr >= BOX64ENV(dynarec_gdbjit_start) && addr < BOX64ENV(dynarec_gdbjit_end)))) {
GdbJITBlockReady(helper.gdbjit_block);
}
ClearCache(actual_p+sizeof(void*), native_size); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// Check if something changed, to abort if it is
if((helper.abort || (block->hash != hash))) {
@@ -791,17 +847,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
return NULL;
}
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu, %d) & pass3 (%zu, %d)!\n", oldnativesize+oldtable64size*8, oldsize, helper.native_size+helper.table64size*8, helper.size);
printf_log(LOG_NONE, "Warning, size difference in block between pass2 (%zu, %d) & pass3 (%zu, %d)!\n", oldnativesize+oldtable64size*8, oldsize, helper.native_size+helper.table64size*8, helper.size);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
printf_log(LOG_NONE, "%s%p:", (helper.insts[i].size2!=helper.insts[i].size)?"=====> ":"", dump);
for(; dump<(uint8_t*)helper.insts[i+1].x64.addr; ++dump)
printf_log(LOG_NONE, " %02X", *dump);
printf_log(LOG_NONE, "\t%d -> %d", helper.insts[i].size2, helper.insts[i].size);
printf_log_prefix(0, LOG_NONE, " %02X", *dump);
printf_log_prefix(0, LOG_NONE, "\t%d -> %d", helper.insts[i].size2, helper.insts[i].size);
if(helper.insts[i].ymm0_pass2 || helper.insts[i].ymm0_pass3)
printf_log(LOG_NONE, "\t %04x -> %04x", helper.insts[i].ymm0_pass2, helper.insts[i].ymm0_pass3);
printf_log(LOG_NONE, "\n");
printf_log_prefix(0, LOG_NONE, "\t %04x -> %04x", helper.insts[i].ymm0_pass2, helper.insts[i].ymm0_pass3);
printf_log_prefix(0, LOG_NONE, "\n");
}
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
@@ -812,7 +868,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
//dynaFree(helper.insts);
helper.insts = NULL;
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "BOX64: Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
printf_log(LOG_NONE, "Warning, insts_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
}
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x64_addr, block->x64_size);
@@ -830,3 +886,13 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
//block->done = 1;
return (void*)block;
}
void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size, const char* inst_name)
{
char pbuf[128];
uint64_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, func_addr), (void*)func_addr, &start, &sz);
snprintf(pbuf, sizeof(pbuf), "0x%lx %ld %s:%s\n", code_addr, code_size, symbname, inst_name);
write(BOX64ENV(dynarec_perf_map_fd), pbuf, strlen(pbuf));
}
+51 -5
View File
@@ -42,7 +42,7 @@ void native_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
void native_f2xm1(x64emu_t* emu)
{
ST0.d = exp2(ST0.d) - 1.0;
ST0.d = expm1(LN2 * ST0.d);
}
void native_fyl2x(x64emu_t* emu)
{
@@ -50,11 +50,14 @@ void native_fyl2x(x64emu_t* emu)
}
void native_ftan(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
// seems that tan of glib doesn't follow the rounding direction mode
ST0.d = tan(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_fpatan(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
ST1.d = atan2(ST1.d, ST0.d);
}
void native_fxtract(x64emu_t* emu)
@@ -97,10 +100,12 @@ void native_fprem(x64emu_t* emu)
}
void native_fyl2xp1(x64emu_t* emu)
{
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
ST(1).d = log1p(ST0.d)*ST(1).d/LN2;
}
void native_fsincos(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
// seems that sincos of glib doesn't follow the rounding direction mode
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
}
@@ -110,16 +115,21 @@ void native_frndint(x64emu_t* emu)
}
void native_fscale(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
ST0.d = ldexp(ST0.d, trunc(ST1.d));
}
void native_fsin(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
// seems that sin of glib doesn't follow the rounding direction mode
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
}
void native_fcos(x64emu_t* emu)
{
#pragma STDC FENV_ACCESS ON
// seems that cos of glib doesn't follow the rounding direction mode
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
}
@@ -174,11 +184,18 @@ void native_fld(x64emu_t* emu, uint8_t* ed)
void native_ud(x64emu_t* emu)
{
if(box64_dynarec_test)
if(BOX64ENV(dynarec_test))
emu->test.test = 0;
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
}
void native_br(x64emu_t* emu)
{
if(BOX64ENV(dynarec_test))
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xb09d);
}
void native_priv(x64emu_t* emu)
{
emu->test.test = 0;
@@ -669,4 +686,33 @@ void propagate_nodf(dynarec_native_t* dyn, int ninst)
dyn->insts[ninst].df_notneeded = 1;
--ninst;
}
}
}
void x64disas_add_register_mapping_annotations(char* buf, const char* disas, const register_mapping_t* mappings, size_t mappings_sz)
{
static char tmp[32];
tmp[0] = '\0';
int len = 0;
// skip the mnemonic
char* p = strchr(disas, ' ');
if (!p) {
sprintf(buf, "%s", disas);
return;
}
p++; // skip the space
while (*p) {
while (*p && !(*p >= 'a' && *p <= 'e') && *p != 's' && *p != 'r') // skip non-register characters
p++;
if (!*p) break;
for (int i = 0; i < mappings_sz; ++i) {
if (!strncmp(p, mappings[i].name, strlen(mappings[i].name))) {
len += sprintf(tmp + len, " %s,", mappings[i].native);
p += strlen(mappings[i].name) - 1;
break;
}
}
p++;
}
if (tmp[0]) tmp[strlen(tmp) - 1] = '\0';
sprintf(buf, "%-35s ;%s", disas, tmp);
}
+8
View File
@@ -53,6 +53,7 @@ void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8);
void native_clflush(x64emu_t* emu, void* p);
void native_ud(x64emu_t* emu);
void native_br(x64emu_t* emu);
void native_priv(x64emu_t* emu);
void native_singlestep(x64emu_t* emu);
void native_int3(x64emu_t* emu);
@@ -83,6 +84,13 @@ int is_avx_zero_unset(dynarec_native_t* dyn, int ninst, int reg);
void avx_mark_zero_reset(dynarec_native_t* dyn, int ninst);
void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg);
typedef struct register_mapping_s {
const char* name;
const char* native;
} register_mapping_t;
void x64disas_add_register_mapping_annotations(char* buf, const char* disas, const register_mapping_t* mappings, size_t mappings_sz);
ADDITIONNAL_DEFINITION()
#endif //__DYNAREC_NATIVE_FUNCTIONS_H__
+21 -20
View File
@@ -57,7 +57,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
ARCH_INIT();
int reset_n = -1; // -1 no reset; -2 reset to 0; else reset to the state of reset_n
dyn->last_ip = (alternate || (dyn->insts && dyn->insts[0].pred_sz))?0:ip; // RIP is always set at start of block unless there is a predecessor!
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with box64_dynarec_bigblock==2, else it needs 3
int stopblock = 2 + ((FindElfAddress(my_context, addr) || IsAddrFileMapped(addr, NULL, NULL)) ? 0 : 1); // if block is in elf memory or file mapped memory, it can be extended with BOX64DRENV(dynarec_bigblock)==2, else it needs 3
// ok, go now
INIT;
#if STEP == 0
@@ -67,7 +67,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#if STEP == 0
if(cur_page != ((addr)&~(box64_pagesize-1))) {
cur_page = (addr)&~(box64_pagesize-1);
if(!(getProtection(addr)&PROT_READ)) {
if(!(getProtection(addr)&PROT_READ) || checkInHotPage(addr)) {
need_epilog = 1;
break;
}
@@ -123,18 +123,21 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
WILLWRITE();
}
#endif
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !ninst) {
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
}
if(box64_dynarec_test && (!box64_dynarec_test_end || (ip>=box64_dynarec_test_start && ip<box64_dynarec_test_end) )) {
if(BOX64ENV(dynarec_test) && (!BOX64ENV(dynarec_test_end) || (ip>=BOX64ENV(dynarec_test_start) && ip<BOX64ENV(dynarec_test_end)))) {
MESSAGE(LOG_DUMP, "TEST STEP ----\n");
extcache_native_t save;
fpu_save_and_unwind(dyn, ninst, &save);
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(x64test_step, 1, x5);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
fpu_unwind_restore(dyn, ninst, &save);
MESSAGE(LOG_DUMP, "----------\n");
}
#ifdef HAVE_TRACE
else if(my_context->dec && box64_dynarec_trace) {
else if(my_context->dec && BOX64ENV(dynarec_trace)) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
@@ -176,7 +179,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#if STEP > 0
if(dyn->insts[ninst].x64.has_next && dyn->insts[next].x64.barrier) {
if(dyn->insts[next].x64.barrier&BARRIER_FLOAT) {
#ifdef RV64
#if defined (RV64) || defined(LA64)
uint8_t tmp1, tmp2, tmp3;
if(dyn->insts[next].nat_flags_fusion) get_free_scratch(dyn, next, &tmp1, &tmp2, &tmp3, x1, x2, x3, x4, x5);
else { tmp1=x1; tmp2=x2; tmp3=x3; }
@@ -228,16 +231,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
#else
// check if block need to be stopped, because it's a 00 00 opcode (unreadeable is already checked earlier)
if((ok>0) && !dyn->forward && !(*(uint8_t*)addr) && !(*(uint8_t*)(addr+1))) {
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Stopping block at %p reason: %s\n", (void*)addr, "Next opcode is 00 00");
if((ok>0) && !dyn->forward && !(*(uint32_t*)addr)) {
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "Stopping block at %p reason: %s\n", (void*)addr, "Next opcode is 00 00 00 00");
ok = 0;
need_epilog = 1;
dyn->insts[ninst].x64.need_after |= X_PEND;
}
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog && ok>=0) {
// we made it!
reset_n = get_first_jump_addr(dyn, addr);
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p (ninst %d - %d)\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to, reset_n, ninst);
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p (ninst %d - %d)\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to, reset_n, ninst);
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;
@@ -247,7 +251,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
ok = 1; // in case it was 0
} else if ((dyn->forward_to < addr) || ok<=0) {
// something when wrong! rollback
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
if(BOX64DRENV(dynarec_dump)) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
ok = 0;
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst;
@@ -258,7 +262,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->forward_ninst = 0;
}
// else just continue
} else if(!ok && !need_epilog && box64_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
} else if (!ok && !need_epilog && BOX64DRENV(dynarec_bigblock) && (getProtection(addr + 3) & ~PROT_READ))
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 && (
@@ -273,9 +277,9 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
// 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+1, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
} else if(next && (int)(next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
if(!((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)next))) {
if(BOX64DRENV(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+1, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
} else if (next && (int)(next - addr) < BOX64ENV(dynarec_forward) && (getProtection(next) & PROT_READ) /*BOX64DRENV(dynarec_bigblock)>=stopblock*/) {
if (!((BOX64DRENV(dynarec_bigblock) < stopblock) && !isJumpTableDefault64((void*)next))) {
if(dyn->forward) {
if(next<dyn->forward_to)
dyn->forward_to = next;
@@ -323,9 +327,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
++ninst;
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));
if((ok>0) && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
|| (addr>=box64_nodynarec_start && addr<box64_nodynarec_end)))
#else
if ((ok > 0) && (((BOX64DRENV(dynarec_bigblock) < stopblock) && !isJumpTableDefault64((void*)addr)) || (addr >= BOX64ENV(nodynarec_start) && addr < BOX64ENV(nodynarec_end))))
#else
if((ok>0) && (ninst==dyn->size))
#endif
{
@@ -341,10 +344,8 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->forward_ninst = 0;
}
#endif
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
if(!box64_dynarec_dump && addr>=box64_nodynarec_start && addr<box64_nodynarec_end)
if(!BOX64DRENV(dynarec_dump) && addr>=BOX64ENV(nodynarec_start) && addr<BOX64ENV(nodynarec_end))
dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
--ninst;
if(!dyn->insts[ninst].x64.barrier) {
+1 -3
View File
@@ -39,7 +39,7 @@ typedef struct instruction_x64_s {
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint8_t jmp_cond:1; // 1 of conditionnal jump
uint8_t has_next:1; // does this opcode can continue to the next?
uint8_t has_callret:1; // this instruction have an optimised call setup
uint8_t has_callret:1; // this instruction have an optimized call setup
uint8_t alive:1; // this opcode gets executed (0 if dead code in that block)
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t state_flags;// One of SF_XXX state
@@ -51,6 +51,4 @@ typedef struct instruction_x64_s {
uint8_t need_after; // calculated
} instruction_x64_t;
void printf_x64_instruction(zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
#endif //__DYNAREC_PRIVATE_H_
File diff suppressed because it is too large. Load diff
+340 -124
View File
@@ -37,6 +37,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
uint8_t wb1, wback, wb2, gback;
uint8_t eb1, eb2;
uint8_t gb1, gb2;
uint8_t tmp1, tmp2, tmp3;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1;
@@ -63,8 +64,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x01:
// TODO:, /0 is SGDT. While 0F 01 D0 is XGETBV, etc...
nextop = F8;
if(MODREG) {
switch(nextop) {
if (MODREG) {
switch (nextop) {
case 0xD0:
INST_NAME("XGETBV");
BEQZ_MARK(xRCX);
@@ -77,7 +78,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
} else {
switch((nextop>>3)&7) {
switch ((nextop >> 3) & 7) {
default:
DEFAULT;
}
@@ -101,7 +102,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to set flags in "don't care" state
}
GETIP(ip);
STORE_XEMU_CALL();
CALL(native_ud, -1);
@@ -171,7 +176,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
INST_NAME("MOVLPS Ex,Gx");
GETGX(v0, 0);
if(MODREG) {
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1);
VEXTRINS_D(v1, v0, 0);
} else {
@@ -216,20 +221,18 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
INST_NAME("MOVHPS Ex,Gx");
GETGX(v0, 0);
if(MODREG) {
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1);
VEXTRINS_D(v1, v0, 0x01);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 1, 0);
v1 = fpu_get_scratch(dyn);
VEXTRINS_D(v1, v0, 0x01);
FST_D(v1, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
VSTELM_D(v0, ed, 0, 1);
SMWRITE2();
}
break;
case 0x18:
nextop = F8;
if ((nextop & 0xC0) == 0xC0) {
if (MODREG) {
INST_NAME("NOP (multibyte)");
} else
switch ((nextop >> 3) & 7) {
@@ -245,6 +248,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FAKEED;
}
break;
case 0x19:
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
@@ -303,7 +307,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("UCOMISS Gx, Ex");
}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGX(d0, 0);
@@ -339,8 +343,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x31:
INST_NAME("RDTSC");
NOTEST(x1);
// TODO: how to read the wall-clock real time on LoongArch?
CALL(ReadTSC, x3); // will return the u64 in x3
if (box64_rdtsc) {
CALL(ReadTSC, x3); // will return the u64 in x3
} else {
RDTIME_D(x3, xZR);
}
if (box64_rdtsc_shift) {
SRLI_D(x3, x3, box64_rdtsc_shift);
}
@@ -410,40 +417,102 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
}
break;
case 0xF0:
INST_NAME("MOVBE Gd, Ed");
nextop = F8;
GETGD;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LDxw(gd, ed, fixedaddress);
if (rex.w) {
REVB_D(gd, gd);
} else {
REVB_2W(gd, gd);
ZEROUP(gd);
}
break;
case 0xF1:
INST_NAME("MOVBE Ed, Gd");
nextop = F8;
GETGD;
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if (rex.w)
REVB_D(x1, gd);
else
REVB_2W(x1, gd);
SDxw(x1, wback, fixedaddress);
break;
default:
DEFAULT;
}
break;
case 0x3A: // more SSE3 opcodes
opcode = F8;
switch (opcode) {
case 0xCC:
INST_NAME("SHA1RNDS4 Gx, Ex, Ib");
nextop = F8;
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
sse_reflect_reg(dyn, ninst, ed);
ADDI_D(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1);
if (wback != x2) MV(x2, wback);
}
u8 = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDI_D(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
MOV32w(x3, u8);
CALL(sha1rnds4, -1);
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
MV(gd, ed); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x4, &fixedaddress, rex, NULL, 1, 0); \
if (la64_lbt) \
BEQZ(x1, 8); \
else \
B##NO(x1, 8); \
LDxw(gd, ed, fixedaddress); \
} \
if (!rex.w) ZEROUP(gd);
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS_FUSION(F, x1, x2, x3, x4, x5); \
if (!dyn->insts[ninst].nat_flags_fusion) { \
if (la64_lbt) { \
X64_SETJ(tmp1, I); \
} else { \
GETFLAGS; \
} \
} \
nextop = F8; \
GETGD; \
if (MODREG) { \
ed = TO_NAT((nextop & 7) + (rex.b << 3)); \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP(NATNO, 8); \
} else { \
if (la64_lbt) \
BEQZ(tmp1, 8); \
else \
B##NO(tmp1, 8); \
} \
MV(gd, ed); \
if (!rex.w) ZEROUP(gd); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, tmp2, tmp3, &fixedaddress, rex, NULL, 1, 0); \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP(NATNO, 8); \
} else { \
if (la64_lbt) \
BEQZ(tmp1, 8); \
else \
B##NO(tmp1, 8); \
} \
LDxw(gd, ed, fixedaddress); \
}
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
#undef GO
case 0x50:
INST_NAME("MOVMSPKPS Gd, Ex");
@@ -525,8 +594,22 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MULPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFMUL_S(v0, v0, q0);
GETGX(q1, 1);
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
}
VFMUL_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x5A:
INST_NAME("CVTPS2PD Gx, Ex");
@@ -546,15 +629,29 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("SUBPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFSUB_S(v0, v0, q0);
GETGX(q1, 1);
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
}
VFSUB_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x5D:
INST_NAME("MINPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
if (!box64_dynarec_fastnan && v0 != v1) {
if (!BOX64ENV(dynarec_fastnan) && v0 != v1) {
q0 = fpu_get_scratch(dyn);
// always copy from v1 if any oprand is NaN
VFCMP_S(q0, v0, v1, cUN);
@@ -568,15 +665,29 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
VFDIV_S(v0, v0, q0);
GETGX(q1, 1);
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
}
VFDIV_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
}
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
if (!box64_dynarec_fastnan && v0 != v1) {
if (!BOX64ENV(dynarec_fastnan) && v0 != v1) {
q0 = fpu_get_scratch(dyn);
// always copy from v1 if any oprand is NaN
VFCMP_S(q0, v0, v1, cUN);
@@ -587,52 +698,64 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
VFMAX_S(v0, v0, v1);
break;
#define GO(GETFLAGS, NO, YES, F, I) \
READFLAGS(F); \
i32_ = F32S; \
if(rex.is32bits) \
j64 = (uint32_t)(addr+i32_); \
else \
j64 = addr+i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(j64, 1); \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog - (dyn->native_size); \
if (la64_lbt) \
BEQZ_safe(x1, i32); \
else \
B##NO##_safe(x1, i32); \
if (dyn->insts[ninst].x64.jmp_insts == -1) { \
if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
if (la64_lbt) \
BNEZ_safe(x1, i32); \
else \
B##YES##_safe(x1, i32); \
}
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS_FUSION(F, x1, x2, x3, x4, x5); \
i32_ = F32S; \
if (rex.is32bits) \
j64 = (uint32_t)(addr + i32_); \
else \
j64 = addr + i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(j64, 1); \
if (!dyn->insts[ninst].nat_flags_fusion) { \
if (la64_lbt) { \
X64_SETJ(x1, I); \
} else { \
GETFLAGS; \
} \
} \
if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog - (dyn->native_size); \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATNO, i32); \
} else { \
if (la64_lbt) \
BEQZ_safe(x1, i32); \
else \
B##NO##_safe(x1, i32); \
} \
if (dyn->insts[ninst].x64.jmp_insts == -1) { \
if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, tmp1, tmp2, tmp3); \
jump_to_next(dyn, j64, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd, tmp1, tmp2, tmp3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATYES, i32); \
} else { \
if (la64_lbt) \
BNEZ_safe(tmp1, i32); \
else \
B##YES##_safe(tmp1, i32); \
} \
}
GOCOND(0x80, "J", "Id");
#undef GO
#undef GO
#define GO(GETFLAGS, NO, YES, F, I) \
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS(F); \
tmp1 = x1; \
tmp3 = x3; \
if (la64_lbt) { \
X64_SETJ(x3, I); \
} else { \
@@ -657,7 +780,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
GOCOND(0x90, "SET", "Eb");
#undef GO
#undef GO
case 0xA2:
INST_NAME("CPUID");
@@ -670,7 +793,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xA3:
INST_NAME("BT Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
@@ -684,18 +807,20 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LDxw(x1, x3, fixedaddress);
ed = x1;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRLxw(x4, ed, x2);
if (la64_lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
if (X_CF) {
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRLxw(x4, ed, x2);
if (la64_lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
}
break;
case 0xA4:
nextop = F8;
INST_NAME("SHLD Ed, Gd, Ib");
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
@@ -708,7 +833,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
@@ -747,7 +872,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
@@ -806,7 +931,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("LDMXCSR Md");
GETED(0);
ST_W(ed, xEmu, offsetof(x64emu_t, mxcsr));
if (box64_sse_flushto0) {
if (BOX64ENV(sse_flushto0)) {
// TODO
}
break;
@@ -820,27 +945,25 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("XSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
MOV32w(x2, rex.w?0:1);
MOV32w(x2, rex.w ? 0 : 1);
CALL((void*)fpu_xsave, -1);
break;
case 5:
INST_NAME("XRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
MOV32w(x2, rex.w?0:1);
MOV32w(x2, rex.w ? 0 : 1);
CALL((void*)fpu_xrstor, -1);
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (wback != A1) {
MV(A1, wback);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL_(native_clflush, -1, 0);
break;
default:
@@ -849,11 +972,11 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
nextop = F8;
GETGD;
GETED(0);
if (box64_dynarec_test) {
if (BOX64ENV(dynarec_test)) {
// avoid noise during test
CLEAR_FLAGS(x3);
}
@@ -921,6 +1044,38 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ZEROUP(gd);
}
break;
case 0xB3:
INST_NAME("BTR Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
SRAIxw(x1, gd, 5 + rex.w);
ADDSL(x3, wback, x1, 2 + rex.w, x1);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRL_D(x4, ed, x2);
BSTRINS_D(xFlags, x4, 0, 0);
ADDI_D(x4, xZR, 1);
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SLL_D(x4, x4, x2);
ANDN(ed, ed, x4);
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
case 0xB6:
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
@@ -931,8 +1086,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
eb2 = 0;
} else {
ed = (nextop & 7);
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
}
BSTRPICK_D(gd, eb1, eb2 * 8 + 7, eb2 * 8);
} else {
@@ -959,7 +1114,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETED(1);
u8 = F8;
@@ -972,7 +1127,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 5:
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETED(1);
u8 = F8;
@@ -990,11 +1145,10 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else if (!rex.w) {
ZEROUP(ed);
}
MARK;
break;
case 6:
INST_NAME("BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETED(1);
u8 = F8;
@@ -1011,11 +1165,10 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else if (!rex.w) {
ZEROUP(ed);
}
MARK;
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETED(1);
u8 = F8;
@@ -1039,9 +1192,43 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0xBB:
INST_NAME("BTC Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
SRAIxw(x1, gd, 5 + rex.w);
ADDSL(x3, wback, x1, 2 + rex.w, x1);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
SRL_D(x4, ed, x2);
if (la64_lbt)
X64_SET_EFLAGS(x4, X_CF);
else
BSTRINS_D(xFlags, x4, F_CF, F_CF);
ADDI_D(x4, xZR, 1);
SLL_D(x4, x4, x2);
XOR(ed, ed, x4);
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
case 0xBC:
INST_NAME("BSF Gd, Ed");
SETFLAGS(X_ZF, SF_SUBSET);
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETED(0);
@@ -1067,13 +1254,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (la64_lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
ADDI_D(x3, xZR, ~(1 << F_ZF));
AND(xFlags, xFlags, x3);
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
}
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
SETFLAGS(X_ZF, SF_SUBSET);
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETED(0);
@@ -1094,8 +1280,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (la64_lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
ADDI_D(x3, xZR, ~(1 << F_ZF));
AND(xFlags, xFlags, x3);
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
}
if (rex.w)
CLZ_D(gd, ed);
@@ -1157,6 +1342,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 7: VFCMP_S(v0, v0, v1, cOR); break; // not NaN
}
break;
case 0xC3:
INST_NAME("MOVNTI Ed, Gd");
nextop = F8;
GETGD;
if (MODREG) {
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
SDxw(gd, ed, fixedaddress);
}
break;
case 0xC6:
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
@@ -1172,6 +1368,26 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
VEXTRINS_D(v0, q1, 0x11); // v0[127:64] = q1[127:64]
}
break;
case 0xC7:
// rep has no impact here
nextop = F8;
if (MODREG) {
switch ((nextop >> 3) & 7) {
default:
DEFAULT;
}
} else {
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("Unsupported XSAVEC Ed");
FAKEED;
UDF();
break;
default:
DEFAULT;
}
}
break;
case 0xC8:
case 0xC9:
case 0xCA:
+111 -38
View File
@@ -63,27 +63,50 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch (opcode) {
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x0B:
INST_NAME("OR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0F:
opcode = F8;
switch (opcode) {
case 0x18:
case 0x19:
case 0x1F:
INST_NAME("NOP (multibyte)");
nextop = F8;
FAKEED;
break;
default:
DEFAULT;
}
break;
case 0x2B:
INST_NAME("SUB Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
@@ -102,8 +125,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0: // ADD
INST_NAME("ADD Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
@@ -111,8 +134,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
@@ -120,9 +143,9 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 2: // ADC
INST_NAME("ADC Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
@@ -130,9 +153,9 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
@@ -140,8 +163,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
@@ -149,8 +172,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
@@ -158,8 +181,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
@@ -167,8 +190,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEBO(x1, 1);
u8 = F8;
if (u8) {
@@ -185,7 +208,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
grab_segdata(dyn, addr, ninst, x6, seg, (MODREG));
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0x81) {
@@ -193,7 +216,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -208,7 +231,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -224,7 +247,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("ADC Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -246,7 +269,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("SBB Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -262,7 +285,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("AND Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -277,7 +300,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("SUB Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -292,7 +315,7 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("XOR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
@@ -307,24 +330,57 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("CMP Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64) {
MOV64xw(x2, i64);
MOV64x(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5);
break;
}
break;
case 0x88:
INST_NAME("MOV Seg:Eb, Gb");
nextop = F8;
gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
if (rex.rex) {
gb2 = 0;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd & 4) << 1);
gb1 = TO_NAT(gd & 3);
}
if (gb2) {
gd = x4;
BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
} else {
gd = gb1;
}
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) << 1); // L or H
}
BSTRINS_D(eb1, gd, eb2 + 7, eb2);
} else {
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
STX_B(gd, x4, wback);
}
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
@@ -342,8 +398,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
GETGD;
if (MODREG) { // reg <= reg
MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
@@ -359,9 +415,26 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
}
break;
case 0x8E:
INST_NAME("MOV Seg, Ew");
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
u8 = (nextop & 0x38) >> 3;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
ADDz(x4, wback, x4);
LD_HU(x1, x4, 0);
ed = x1;
}
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
ST_W(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Od");
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, 0);
if (rex.is32bits)
u64 = F32;
else
@@ -375,8 +448,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
if (MODREG) { // reg <= u8
u8 = F8;
if (!rex.rex) {
@@ -408,8 +481,8 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xC7:
INST_NAME("MOV Seg:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
if (MODREG) { // reg <= i32
i64 = F32S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
+255 -85
View File
@@ -60,7 +60,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch (opcode) {
case 0x01:
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -69,7 +69,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -78,7 +78,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
@@ -87,7 +87,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -96,7 +96,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -105,7 +105,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
@@ -115,6 +115,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x0F:
switch (rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
default:
DEFAULT;
}
@@ -122,7 +123,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -132,7 +133,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x13:
INST_NAME("ADC Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -142,7 +143,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x15:
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
u64 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV64x(x2, u64);
@@ -152,7 +153,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -162,7 +163,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -172,7 +173,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x1D:
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
BSTRPICK_D(x1, xRAX, 15, 0);
u64 = F16;
MOV64x(x2, u64);
@@ -181,7 +182,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -190,7 +191,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -199,7 +200,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
@@ -208,7 +209,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -217,7 +218,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -226,7 +227,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
@@ -235,7 +236,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -244,7 +245,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -253,7 +254,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
@@ -262,7 +263,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -270,7 +271,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -278,7 +279,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
if (i32) {
@@ -304,7 +305,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
nextop = F8;
GETSEW(x1, (opcode == 0x69) ? 2 : 1);
if (opcode == 0x69)
@@ -328,7 +329,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -344,7 +345,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("OR Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -361,7 +362,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("ADC Ew, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -378,7 +379,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("SBB Ew, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -394,7 +395,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("AND Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -410,7 +411,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("SUB Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -426,7 +427,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("XOR Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -442,7 +443,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("CMP Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
@@ -460,7 +461,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
@@ -497,6 +498,21 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRINSz(gd, x1, 15, 0);
}
break;
case 0x8E:
INST_NAME("MOV Seg, Ew");
nextop = F8;
u8 = (nextop & 0x38) >> 3;
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 0);
LD_HU(x1, wback, fixedaddress);
ed = x1;
}
ST_H(ed, xEmu, offsetof(x64emu_t, segs[u8]));
ST_H(xZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0x90:
case 0x91:
case 0x92:
@@ -515,12 +531,32 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BSTRINSz(gd, x2, 15, 0);
}
break;
case 0x98:
INST_NAME("CBW");
SLLI_D(x1, xRAX, 56);
SRAI_D(x1, x1, 56);
BSTRINSz(xRAX, x1, 15, 0);
break;
case 0xA4:
if (rep) {
INST_NAME("REP MOVSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
// special optim for large RCX value on forward case only
OR(x1, xRSI, xRDI);
ANDI(x1, x1, 7);
BNEZ_MARK(x1);
ADDI_D(x6, xZR, 8);
MARK3;
BLT_MARK(xRCX, x6);
LD_D(x1, xRSI, 0);
ST_D(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 8);
ADDI_D(xRDI, xRDI, 8);
ADDI_D(xRCX, xRCX, -8);
BNEZ_MARK3(xRCX);
B_NEXT_nocond;
MARK; // Part with DF==0
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
@@ -577,9 +613,63 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADD_D(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, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // DF==0
LD_HU(x1, xRSI, 0);
LD_HU(x2, xRDI, 0);
ADDI_D(xRSI, xRSI, 2);
ADDI_D(xRDI, xRDI, 2);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
BEQ_MARK3(x1, x2); // REPNZ
} else {
BNE_MARK3(x1, x2); // REPZ
}
BNEZ_MARK(xRCX);
B_MARK3_nocond;
MARK2; // DF=1
LD_HU(x1, xRSI, 0);
LD_HU(x2, xRDI, 0);
ADDI_D(xRSI, xRSI, -2);
ADDI_D(xRDI, xRDI, -2);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
BEQ_MARK3(x1, x2); // REPNZ
} else {
BNE_MARK3(x1, x2); // REPZ
}
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, NAT_FLAGS_NOFUSION);
GETDIR(x3, x1, 2);
LD_HU(x1, xRSI, 0);
LD_HU(x2, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(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);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
u16 = F16;
MOV32w(x2, u16);
BSTRPICK_D(x1, xRAX, 15, 0);
@@ -610,6 +700,65 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xAF:
switch (rep) {
case 1:
case 2:
if (rep == 1) {
INST_NAME("REPNZ SCASW");
} else {
INST_NAME("REPZ SCASW");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
CBZ_NEXT(xRCX);
GETDIR(x3, x1, rex.w ? 8 : 2);
if (rex.w) {
MARK;
LD_D(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
BEQ_MARK3(xRAX, x2);
} else {
BNE_MARK3(xRAX, x2);
}
BNE_MARK(xRCX, xZR);
MARK3;
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else {
BSTRPICK_D(x1, xRAX, 15, 0);
MARK;
LD_HU(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
ADDI_D(xRCX, xRCX, -1);
if (rep == 1) {
BEQ_MARK3(x1, x2);
} else {
BNE_MARK3(x1, x2);
}
BNE_MARK(xRCX, xZR);
MARK3;
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
}
break;
default:
INST_NAME("SCASW");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETDIR(x3, x1, rex.w ? 8 : 2);
if (rex.w) {
LD_D(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
} else {
BSTRPICK_D(x1, xRAX, 15, 0);
LD_HU(x2, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
}
break;
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
@@ -630,7 +779,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0:
INST_NAME("ROL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF);
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
@@ -640,7 +789,7 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF);
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
@@ -650,48 +799,42 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
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 & 15)); }
UFLAG_OP12(ed, x2)
if (MODREG) {
SLLI_D(ed, ed, 48 + (u8 & 15));
SRLI_D(ed, ed, 48);
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8) & 0x1f;
emit_shl16c(dyn, ninst, x1, u8, x5, x4, x6);
EWBACK;
} else {
SLLI_D(ed, ed, u8 & 15);
FAKEED;
F8;
}
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
INST_NAME("SHR 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 & 15)); }
UFLAG_OP12(ed, x2)
SRLI_D(ed, ed, u8 & 15);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8) & 0x1f;
emit_shr16c(dyn, ninst, x1, u8, x5, x4, x6);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 7:
INST_NAME("SAR Ew, 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 & 15)); }
UFLAG_OP12(ed, x2)
SRAI_D(ed, ed, u8 & 15);
if (MODREG) BSTRPICK_D(ed, ed, 15, 0);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
GETSEW(x1, 0);
u8 = (F8) & 0x1f;
emit_sar16c(dyn, ninst, x1, u8, x5, x4, x6);
EWBACK;
} else {
FAKEED;
F8;
}
break;
default:
DEFAULT;
@@ -717,6 +860,22 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xD3:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0xD1) {
INST_NAME("ROL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 1);
CALL_(rol16, x1, x3);
EWBACK;
break;
case 5:
if (opcode == 0xD1) {
INST_NAME("SHR Ew, 1");
@@ -726,8 +885,8 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1) MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
@@ -742,8 +901,8 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1)
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4, x6);
@@ -758,8 +917,8 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1)
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4, x6);
@@ -769,35 +928,46 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
DEFAULT;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ew");
GETEW(x1, 0);
MOV32w(x5, 0xffff);
XOR(ed, ed, x5); // No flags affected
EWBACK;
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETEW(x1, 0);
BSTRPICK_D(x2, xRAX, 15, 0);
SLLI_D(x7, xRDX, 48);
SRLI_D(x7, x7, 32);
OR(x2, x2, x7);
if(box64_dynarec_div0) {
if(BOX64ENV(dynarec_div0)) {
BNE_MARK3(ed, xZR);
GETIP_(ip);
STORE_XEMU_CALL();
@@ -815,10 +985,10 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 7:
INST_NAME("IDIV Ew");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETSEW(x1, 0);
if (box64_dynarec_div0) {
if (BOX64ENV(dynarec_div0)) {
BNE_MARK3(ed, xZR);
GETIP_(ip);
STORE_XEMU_CALL();
@@ -845,14 +1015,14 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING, NAT_FLAGS_FUSION);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -51,7 +51,7 @@ uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (ed != gd) BSTRINS_D(gd, ed, 15, 0);
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
grab_segdata(dyn, addr, ninst, x4, seg, (MODREG));
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADDz(x4, ed, x4);
+132
View File
@@ -0,0 +1,132 @@
#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 "la64_emitter.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "../dynarec_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip;
(void)rep;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
uint64_t u64;
int64_t fixedaddress;
int unscaled;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j64);
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
switch (opcode) {
case 0x81:
case 0x83:
nextop = F8;
SMDMB();
switch ((nextop >> 3) & 7) {
case 0: // ADD
if (opcode == 0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
if (MODREG) {
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64x(x5, u64);
BSTRPICK_D(x6, ed, 15, 0);
emit_add16(dyn, ninst, x6, x5, x3, x4, x2);
BSTRINS_D(ed, x6, 15, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
u64 = F16;
else
u64 = (uint16_t)(int16_t)F8S;
MOV64x(x5, u64);
if (la64_lam_bh) {
AMADD_DB_H(x1, x5, wback);
} else {
ANDI(x3, wback, 0b10);
BNEZ_MARK(x3);
// lower 16 bits
MARKLOCK;
LL_W(x1, wback, 0);
ADD_D(x4, x1, x5);
MV(x3, x1);
BSTRINS_D(x3, x4, 15, 0);
SC_W(x3, wback, 0);
BEQZ_MARKLOCK(x3);
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x1, x1, 15, 0);
}
B_MARK3_nocond;
MARK;
// upper 16 bits
XORI(wback, wback, 0b10);
MARK2;
LL_W(x1, wback, 0);
BSTRPICK_D(x3, x1, 15, 0);
SRLI_W(x1, x1, 16);
ADD_D(x4, x1, x5);
BSTRINS_D(x3, x4, 31, 15);
SC_W(x3, wback, 0);
BEQZ_MARK2(x3);
MARK3;
}
// final
IFXORNAT (X_ALL | X_PEND) {
emit_add16(dyn, ninst, x1, x5, x3, x4, x6);
}
}
break;
default:
DEFAULT;
}
SMDMB();
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 "la64_emitter.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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_66F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t 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);
switch (opcode) {
case 0x38: // these are some more SSSE4.2+ opcodes
opcode = F8;
switch (opcode) {
case 0xF1:
INST_NAME("CRC32 Gd, Ew");
nextop = F8;
GETEW(x1, 0);
GETGD;
CRCC_W_H_W(gd, gd, ed);
ZEROUP(gd);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+7 -5
View File
@@ -65,7 +65,7 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x19:
INST_NAME("SBB Ed, Gd");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGD;
GETED32(0);
@@ -75,7 +75,7 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x1A:
INST_NAME("SBB Gb, Eb");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETEB32(x2, 0);
GETGB(x1);
@@ -85,7 +85,7 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x1B:
INST_NAME("SBB Gd, Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGD;
GETED32(0);
@@ -94,7 +94,7 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0x1D:
INST_NAME("SBB EAX, Id");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
i64 = F32S;
MOV64xw(x2, i64);
emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
@@ -155,12 +155,14 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ZEROUP2(gd, ed);
}
break;
case 0xE8:
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode)
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
GETED32(0);
if (rex.w) {
if (ed == xRDX)
+34 -19
View File
@@ -25,9 +25,10 @@
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, d_xor8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -62,9 +63,10 @@ void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, d_xor8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -74,6 +76,7 @@ void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
X64_XOR_B(s1, s3);
}
XORI(s1, s1, c & 0xff);
ANDI(s1, s1, 0xff);
IFX (X_PEND)
ST_B(s1, xEmu, offsetof(x64emu_t, res));
return;
@@ -102,9 +105,10 @@ void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, d_xor16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -142,9 +146,10 @@ void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX(X_PEND) {
SET_DF(s4, rex.w ? d_xor64 : d_xor32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -193,9 +198,10 @@ void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit XOR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, rex.w ? d_xor64 : d_xor32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -259,9 +265,10 @@ void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -296,9 +303,10 @@ void emit_and8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -333,9 +341,10 @@ void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_and16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, d_tst16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -370,9 +379,10 @@ void emit_and16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -412,9 +422,10 @@ void emit_and32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit AND32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -458,9 +469,10 @@ void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, d_or16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -495,9 +507,10 @@ void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -540,9 +553,10 @@ void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// emit OR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s4, rex.w ? d_or64 : d_or32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -594,9 +608,10 @@ void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SET_DF(s3, d_or8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
+168 -160
View File
@@ -25,7 +25,8 @@
// emit ADD32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (rex.w) {
ST_D(s1, xEmu, offsetof(x64emu_t, op1));
ST_D(s2, xEmu, offsetof(x64emu_t, op2));
@@ -34,12 +35,12 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ST_W(s2, xEmu, offsetof(x64emu_t, op2));
}
SET_DF(s3, rex.w ? d_add64 : d_add32b);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_ALL) {
if (rex.w)
X64_ADD_DU(s1, s2);
else
@@ -48,14 +49,13 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ADDxw(s1, s1, s2);
if (!rex.w) ZEROUP(s1);
IFX(X_PEND)
IFX (X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF)
{
IFX (X_CF) {
if (rex.w) {
ZEROUP2(s5, s1);
ZEROUP2(s4, s2);
@@ -77,30 +77,25 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ORI(xFlags, xFlags, 1 << F_CF);
}
}
IFX(X_AF | X_OF)
{
IFX (X_AF | X_OF) {
OR(s3, s1, s2); // s3 = op1 | op2
AND(s4, s1, s2); // s4 = op1 & op2
}
ADDxw(s1, s1, s2);
IFX(X_PEND)
{
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_AF | X_OF)
{
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX(X_AF)
{
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX(X_OF)
{
IFX (X_OF) {
SRLI_D(s3, s3, rex.w ? 62 : 30);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
@@ -109,20 +104,17 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX(X_SF)
{
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PF)
{
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFX(X_ZF)
{
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
@@ -131,7 +123,8 @@ void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit ADD32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5)
{
if (s1 == xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags == X_PEND)) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
if ((s1 == xRSP) && (BOX64DRENV(dynarec_safeflags) < 2) && (!dyn->insts || (dyn->insts[ninst].x64.gen_flags == X_PEND) || (!BOX64ENV(dynarec_df) && (dyn->insts[ninst].x64.gen_flags == X_ALL)))) {
// special case when doing math on ESP and only PEND is needed: ignoring it!
if (c >= -2048 && c < 2048) {
ADDI_D(s1, s1, c);
@@ -142,25 +135,21 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
if (!rex.w) { ZEROUP(s1); }
return;
}
IFX(X_PEND | X_AF | X_CF | X_OF)
{
IFX (X_PEND | X_AF | X_CF | X_OF) {
MOV64xw(s2, c);
} else if (la64_lbt) {
MOV64xw(s2, c);
}
IFX(X_PEND)
{
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w ? d_add64 : d_add32b);
}
else IFX(X_ALL)
{
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_ALL) {
if (rex.w)
X64_ADD_DU(s1, s2);
else
@@ -169,14 +158,12 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
ADDxw(s1, s1, s2);
if (!rex.w) ZEROUP(s1);
IFX(X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
IFX (X_PEND) SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF)
{
IFX (X_CF) {
if (rex.w) {
ZEROUP2(s5, s1);
ZEROUP2(s4, s2);
@@ -198,8 +185,7 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
ORI(xFlags, xFlags, 1 << F_CF);
}
}
IFX(X_AF | X_OF)
{
IFX (X_AF | X_OF) {
OR(s3, s1, s2); // s3 = op1 | op2
AND(s4, s1, s2); // s4 = op1 & op2
}
@@ -207,30 +193,25 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
if (c >= -2048 && c < 2048) {
ADDIxw(s1, s1, c);
} else {
IFX(X_PEND | X_AF | X_CF | X_OF) { }
else
{
IFX (X_PEND | X_AF | X_CF | X_OF) {
} else {
MOV64xw(s2, c);
}
ADDxw(s1, s1, s2);
}
IFX(X_PEND)
{
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_AF | X_OF)
{
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX(X_AF)
{
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX(X_OF)
{
IFX (X_OF) {
SRLI_D(s3, s3, rex.w ? 62 : 30);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
@@ -239,20 +220,17 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX(X_SF)
{
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PF)
{
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFX(X_ZF)
{
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
@@ -261,40 +239,42 @@ void emit_add32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
// emit ADD8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add8);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_ALL) {
X64_ADD_B(s1, s2);
}
ADD_D(s1, s1, s2);
IFX(X_PEND)
ANDI(s1, s1, 0xff);
IFX (X_PEND)
ST_H(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_OF) {
IFX (X_AF | X_OF) {
OR(s3, s1, s2); // s3 = op1 | op2
AND(s4, s1, s2); // s4 = op1 & op2
}
ADD_D(s1, s1, s2);
IFX(X_AF | X_OF) {
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX(X_AF) {
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX(X_OF) {
IFX (X_OF) {
SRLI_D(s3, s3, 6);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
@@ -303,25 +283,25 @@ void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX(X_CF) {
IFX (X_CF) {
SRLI_D(s3, s1, 8);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}
IFX(X_PEND) {
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
ANDI(s1, s1, 0xff);
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_SF) {
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -329,48 +309,51 @@ void emit_add8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV32w(s4, c & 0xff);
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s4, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add8);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX(X_PEND) {} else { MOV32w(s4, c & 0xff); }
IFX (X_ALL) {
IFX (X_PEND) {
} else {
MOV32w(s4, c & 0xff);
}
X64_ADD_B(s1, s4);
}
ADDI_D(s1, s1, c & 0xff);
IFX(X_PEND)
ANDI(s1, s1, 0xff);
IFX (X_PEND)
ST_H(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_OF)
{
IFX(X_PEND) {} else { MOV32w(s4, c & 0xff); }
IFX (X_AF | X_OF) {
IFX (X_PEND) {
} else {
MOV32w(s4, c & 0xff);
}
OR(s3, s1, s4); // s3 = op1 | op2
AND(s4, s1, s4); // s4 = op1 & op2
}
ADDI_D(s1, s1, c & 0xff);
IFX(X_AF | X_OF)
{
IFX (X_AF | X_OF) {
ANDN(s3, s3, s1); // s3 = ~res & (op1 | op2)
OR(s3, s3, s4); // cc = (~res & (op1 | op2)) | (op1 & op2)
IFX(X_AF)
{
IFX (X_AF) {
ANDI(s4, s3, 0x08); // AF: cc & 0x08
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_AF);
}
IFX(X_OF)
{
IFX (X_OF) {
SRLI_D(s3, s3, 6);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
@@ -379,30 +362,25 @@ void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
ORI(xFlags, xFlags, 1 << F_OF);
}
}
IFX(X_CF)
{
IFX (X_CF) {
SRLI_D(s3, s1, 8);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_CF);
}
IFX(X_PEND)
{
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
ANDI(s1, s1, 0xff);
IFX(X_ZF)
{
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_SF)
{
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_PF)
{
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -410,11 +388,12 @@ void emit_add8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, i
// emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_add16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
@@ -481,47 +460,48 @@ void emit_add16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit SUB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub8);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_ALL) {
X64_SUB_B(s1, s2);
}
SUB_D(s1, s1, s2);
IFX(X_PEND)
ANDI(s1, s1, 0xff);
IFX (X_PEND)
ST_H(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
IFX (X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
SUB_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX(X_SF) {
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_PEND) {
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
CALC_SUB_FLAGS(s5, s2, s1, s3, s4, 8);
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -529,18 +509,19 @@ void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
// emit SUB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_sub8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s2, int s3, int s4, int s5)
{
MOV32w(s2, c&0xff);
MOV32w(s2, c & 0xff);
emit_sub8(dyn, ninst, s1, s2, s3, s4, s5);
}
// emit SUB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sub16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -558,7 +539,10 @@ void emit_sub16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
if (la64_lbt) {
BSTRPICK_D(s1, s1, 15, 0);
return;
}
CLEAR_FLAGS(s3);
SLLI_D(s1, s1, 48);
@@ -581,16 +565,17 @@ void emit_sub16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_sub64:d_sub32);
} else IFX(X_ALL) {
SET_DF(s3, rex.w ? d_sub64 : d_sub32);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_ALL) {
if (rex.w)
X64_SUB_DU(s1, s2);
else
@@ -599,34 +584,34 @@ void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
SUBxw(s1, s1, s2);
if (!rex.w) ZEROUP(s1);
IFX(X_PEND)
IFX (X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
IFX (X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
SUBxw(s1, s1, s2);
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32);
IFX(X_ZF) {
CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -634,8 +619,8 @@ void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit SUB32 instruction, from s1, constant c, store result in s1 using s2, s3, s4 and s5 as scratch
void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5)
{
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.gen_flags==X_PEND))
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
if ((s1 == xRSP) && (BOX64DRENV(dynarec_safeflags) < 2) && (!dyn->insts || (dyn->insts[ninst].x64.gen_flags == X_PEND) || (!BOX64ENV(dynarec_df) && (dyn->insts[ninst].x64.gen_flags == X_ALL)))) {
// special case when doing math on RSP and only PEND is needed: ignoring it!
if (c > -2048 && c <= 2048) {
ADDI_D(s1, s1, -c);
@@ -647,18 +632,21 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
return;
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
MOV64xw(s2, c);
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w?d_sub64:d_sub32);
} else IFX(X_ALL) {
SET_DF(s3, rex.w ? d_sub64 : d_sub32);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_PEND) {} else {MOV64xw(s2, c);}
IFX(X_ALL) {
IFX (X_PEND) {
} else {
MOV64xw(s2, c);
}
IFX (X_ALL) {
if (rex.w) {
X64_SUB_DU(s1, s2);
} else {
@@ -668,13 +656,13 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
SUBxw(s1, s1, s2);
if (!rex.w) ZEROUP(s1);
IFX(X_PEND)
IFX (X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
IFX (X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
@@ -682,32 +670,35 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
if (c > -2048 && c <= 2048) {
ADDIxw(s1, s1, -c);
} else {
IFX(X_PEND) {} else {MOV64xw(s2, c);}
IFX (X_PEND) {
} else {
MOV64xw(s2, c);
}
SUBxw(s1, s1, s2);
}
IFX(X_AF | X_CF | X_OF) {
IFX(X_PEND) {}
else if (c > -2048 && c <= 2048) {
IFX (X_AF | X_CF | X_OF) {
IFX (X_PEND) {
} else if (c > -2048 && c <= 2048) {
MOV64xw(s2, c);
}
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w?64:32);
IFX(X_ZF) {
CALC_SUB_FLAGS(s5, s2, s1, s3, s4, rex.w ? 64 : 32);
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -716,11 +707,12 @@ void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
// emit SBB8 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
void emit_sbb8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sbb8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -730,7 +722,6 @@ void emit_sbb8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
IFX (X_ALL) {
X64_SBC_B(s1, s2);
}
ANDI(s1, s3, 0xff);
IFX (X_PEND)
ST_B(s1, xEmu, offsetof(x64emu_t, res));
@@ -778,15 +769,16 @@ void emit_sbb8c(dynarec_la64_t* dyn, int ninst, int s1, int c, int s3, int s4, i
// emit SBB16 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
void emit_sbb16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_sbb16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
if (la64_lbt) {
SBC_H(s3, s1, s2);
IFX (X_ALL) {
@@ -832,11 +824,12 @@ void emit_sbb16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit SBB32 instruction, from s1, s2, store result in s1 using s3, s4 and s5 as scratch
void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w ? d_sbb64 : d_sbb32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -852,8 +845,10 @@ void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
else
X64_SBC_W(s1, s2);
}
MVxw(s1, s3);
if (rex.w)
MV(s1, s3);
else
ZEROUP2(s1, s3);
IFX (X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
@@ -895,10 +890,11 @@ void emit_sbb32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit NEG8 instruction, from s1, store result in s1 using s2 and s3 as scratch
void emit_neg8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_neg8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFX (X_AF | X_OF) {
@@ -957,10 +953,11 @@ void emit_neg8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3)
// emit NEG32 instruction, from s1, store result in s1 using s2 and s3 as scratch
void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w ? d_neg64 : d_neg32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -983,9 +980,7 @@ void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
if (la64_lbt) {
if (!rex.w) {
ZEROUP(s1);
}
if (!rex.w) ZEROUP(s1);
return;
}
@@ -1032,11 +1027,12 @@ void emit_neg32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit ADC8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -1046,7 +1042,7 @@ void emit_adc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
IFX (X_ALL) {
X64_ADC_B(s1, s2);
}
MV(s1, s3);
ANDI(s1, s3, 0xff);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -1115,11 +1111,12 @@ void emit_adc8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_adc16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -1129,7 +1126,7 @@ void emit_adc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX (X_ALL) {
X64_ADC_H(s1, s2);
}
MV(s1, s3);
BSTRPICK_D(s1, s3, 15, 0);
IFX (X_PEND) {
ST_W(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -1191,11 +1188,12 @@ void emit_adc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit ADC32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, rex.w ? d_adc64 : d_adc32b);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -1211,7 +1209,10 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
else
X64_ADC_W(s1, s2);
}
MV(s1, s3);
if (rex.w)
MV(s1, s3);
else
ZEROUP2(s1, s3);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -1294,10 +1295,11 @@ void emit_adc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit INC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch
void emit_inc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_inc8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
@@ -1360,10 +1362,11 @@ void emit_inc8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_inc16);
} else IFX (X_ZF | X_OF | X_AF | X_SF | X_PF) {
} else IFXORNAT (X_ZF | X_OF | X_AF | X_SF | X_PF) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
@@ -1429,10 +1432,11 @@ void emit_inc16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit INC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w ? d_inc64 : d_inc32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -1501,10 +1505,11 @@ void emit_inc32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit DEC8 instruction, from s1, store result in s1 using s2, s3 and s4 as scratch
void emit_dec8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_dec8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
@@ -1568,10 +1573,11 @@ void emit_dec8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// emit DEC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_dec16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFX (X_AF | X_OF) {
@@ -1636,10 +1642,11 @@ void emit_dec16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit DEC32 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, rex.w ? d_dec64 : d_dec32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFXA (X_AF | X_OF, !la64_lbt) {
@@ -1709,10 +1716,11 @@ void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit NEG16 instruction, from s1, store result in s1 using s2 and s3 as scratch
void emit_neg16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s3, d_neg16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
IFX (X_AF | X_OF) {
+451 -76
View File
@@ -25,12 +25,13 @@
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
// s2 is not 0 here and is 1..1f/3f
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -86,20 +87,117 @@ void emit_shl16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
}
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch
void emit_shl16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
// s2 is not 0 here and is 1..1f/3f
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
if (!c) return;
// c != 0
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV64x(s3, c);
ST_H(s3, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shl16);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
X64_SLL_H(s1, s3);
}
SLLI_D(s1, s1, c);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
if (c < 16) {
IFX (X_CF | X_OF) {
SRLI_D(s3, s1, 16 - c);
ANDI(s5, s3, 1); // LSB == F_CF
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
}
SLLI_D(s1, s1, c + 48);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_D(s1, s1, 48);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
if (c == 1) {
SRLI_D(s3, s1, 15);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
} else {
IFX (X_CF) {
if (c == 16) {
ANDI(s3, s1, 1);
OR(xFlags, xFlags, s3); // F_CF == 0
}
}
MV(s1, xZR);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
// OF nop
// SF nop
// AF nop
IFX (X_PF | X_ZF) {
IFX (X_ZF) {
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
ORI(xFlags, xFlags, 1 << F_PF);
}
}
}
}
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
// s2 is not 0 here and is 1..1f/3f
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_shl64 : d_shl32);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_SLL_D(s1, s2);
else
@@ -107,49 +205,49 @@ void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
SLL_D(s1, s1, s2);
if (!rex.w) { ZEROUP(s1); }
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF | X_OF) {
ADDI_D(s5, s2, rex.w?-64:-32);
IFX (X_CF | X_OF) {
ADDI_D(s5, s2, rex.w ? -64 : -32);
SUB_D(s5, xZR, s5);
SRL_W(s3, s1, s5);
ANDI(s5, s3, 1); // LSB == F_CF
IFX(X_CF) {
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
}
SLL_D(s1, s1, s2);
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_OF) {
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
ADDI_D(s3, s2, -1);
BNEZ(s3, 4 + 4 * 4);
SRLIxw(s3, s1, rex.w?63:31);
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -159,7 +257,8 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
{
if (!c) return;
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
@@ -167,14 +266,17 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
}
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DF(s4, rex.w ? d_shl64 : d_shl32);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if(la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
if (la64_lbt) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
if (rex.w)
X64_SLL_D(s1, s3);
else
@@ -182,19 +284,19 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
SLLIxw(s1, s1, c);
IFX(X_PEND) {
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF | X_OF) {
IFX (X_CF | X_OF) {
if (c > 0) {
SRLI_D(s3, s1, (rex.w ? 64 : 32) - c);
ANDI(s5, s3, 1); // LSB == F_CF
IFX(X_CF) {
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
}
@@ -206,21 +308,21 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SLLI_W(s1, s1, c);
}
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_OF) {
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
@@ -229,7 +331,73 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
OR(xFlags, xFlags, s3);
}
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL8 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_shl8);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SLL_B(s1, s2);
}
SLL_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
SLL_D(s1, s1, s2);
// s2 is not 0 here and is 1..1f/3f
CLEAR_FLAGS(s3);
IFX (X_CF | X_OF) {
SRLI_D(s5, s1, 8);
ANDI(s5, s5, 1); // LSB == F_CF
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
}
SLLI_D(s1, s1, 56);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_D(s1, s1, 56);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
ADDI_D(s3, s2, -1);
BNEZ(s3, 4 + 4 * 4);
SRLI_D(s3, s1, 7);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -237,14 +405,13 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
// emit SHR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shr8);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -294,16 +461,75 @@ void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
}
// emit SAR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch
void emit_sar8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_sar8);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SRA_B(s1, s2);
}
SRA_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
ADDI_D(s3, s2, -1);
SRA_D(s3, s1, s3);
ANDI(s3, s3, 1); // LSB == F_CF
OR(xFlags, xFlags, s3);
}
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
// OF nop
IFX (X_SF) {
// SF is the same as the original operand
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRA_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR16 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shr16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -354,17 +580,85 @@ void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
}
// emit SHR16 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch
void emit_shr16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
if (!c) return;
// c != 0
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV64x(s3, c);
ST_H(s3, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shr16);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
X64_SRL_H(s1, s3);
}
SRLI_D(s1, s1, c);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
// no need to shift
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
if (c == 1) {
SRLI_D(s3, s1, 15);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
SRLI_D(s1, s1, c);
// SF should be unset
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR32 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shr64 : d_shr32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -424,7 +718,8 @@ void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
@@ -432,19 +727,22 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shr64 : d_shr32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
if (rex.w)
X64_SRL_D(s1, s3);
else
@@ -452,15 +750,15 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
SRLIxw(s1, s1, c);
IFX(X_PEND) {
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF) {
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
@@ -470,7 +768,7 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
OR(xFlags, xFlags, s3);
}
IFX(X_OF) {
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
if (c == 1) {
@@ -486,21 +784,21 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SRLI_W(s1, s1, c);
}
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -511,11 +809,12 @@ void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_sar16);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -563,10 +862,78 @@ void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
}
// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch
void emit_sar16c(dynarec_la64_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
if (!c) return;
// c != 0
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV64x(s3, c);
ST_H(s3, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_sar16);
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
X64_SRA_H(s1, s3);
}
SRLI_D(s1, s1, c);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
// no need to shift
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
// OF nop
IFX (X_SF) {
// SF is the same as the original operand
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_D(s1, s1, c);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
IFX(X_PEND) {
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
@@ -574,19 +941,22 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_sar64 : d_sar32);
} else IFX(X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
IFX (X_PEND) {
} else {
MOV64x(s3, c);
}
IFX (X_ALL) {
if (rex.w)
X64_SRA_D(s1, s3);
else
@@ -594,15 +964,15 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
SRAIxw(s1, s1, c);
IFX(X_PEND) {
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF) {
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
@@ -622,21 +992,21 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
// SRAI_W sign-extends, so test sign bit before clearing upper bits
IFX(X_SF) {
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
@@ -647,11 +1017,12 @@ void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
{
if (!c) return;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV32w(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_ror64 : d_ror32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (!c) {
@@ -669,6 +1040,7 @@ void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
}
ROTRIxw(s1, s1, c);
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
@@ -701,11 +1073,13 @@ void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
if (!rex.w) ZEROUP(s1);
BEQ_NEXT(s2, xZR);
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_rol64 : d_rol32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -716,9 +1090,6 @@ void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
X64_ROTL_W(s1, s2);
}
if (!rex.w) ZEROUP(s1);
BEQ_NEXT(s2, xZR);
SLLxw(s3, s1, s2);
NEG_D(s4, s2);
ADDI_D(s4, s4, rex.w ? 64 : 32);
@@ -756,6 +1127,7 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
{
int64_t j64;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
if (!rex.w) {
ZEROUP(s1);
}
@@ -763,7 +1135,7 @@ void emit_ror32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_ror64 : d_ror32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -814,11 +1186,12 @@ void emit_rol32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c,
{
if (!c) return;
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
MOV32w(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_rol64 : d_rol32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (!c) {
@@ -869,6 +1242,7 @@ void emit_shld32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin
{
c &= (rex.w ? 0x3f : 0x1f);
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
@@ -877,7 +1251,7 @@ void emit_shld32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shld64 : d_shld32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
@@ -944,6 +1318,7 @@ void emit_shrd32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin
{
c &= (rex.w ? 0x3f : 0x1f);
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s1, xZR);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
@@ -952,7 +1327,7 @@ void emit_shrd32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uin
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shrd64 : d_shrd32);
} else IFX (X_ALL) {
} else IFXORNAT (X_ALL) {
SET_DFNONE();
}
if (!c) {
+276 -14
View File
@@ -8,6 +8,7 @@
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
@@ -33,6 +34,8 @@ void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_B(s1, s2);
@@ -42,6 +45,15 @@ void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
SUB_D(s6, s1, s2);
ST_B(s6, xEmu, offsetof(x64emu_t, res));
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s1);
EXT_W_B(s4, s2);
NAT_FLAGS_OPS(s3, s4);
} else {
NAT_FLAGS_OPS(s1, s2);
}
}
return;
}
@@ -70,6 +82,15 @@ void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s1);
EXT_W_B(s4, s2);
NAT_FLAGS_OPS(s3, s4);
} else {
NAT_FLAGS_OPS(s1, s2);
}
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
@@ -84,10 +105,20 @@ void emit_cmp8_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_B(s1, xZR);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else {
NAT_FLAGS_OPS(s1, xZR);
}
}
return;
}
@@ -104,6 +135,14 @@ void emit_cmp8_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else {
NAT_FLAGS_OPS(s1, xZR);
}
}
}
// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch
@@ -117,6 +156,8 @@ void emit_cmp16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_H(s1, s2);
@@ -126,6 +167,15 @@ void emit_cmp16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
SUB_D(s6, s1, s2);
ST_H(s6, xEmu, offsetof(x64emu_t, res));
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s1);
EXT_W_H(s4, s2);
NAT_FLAGS_OPS(s3, s4);
} else {
NAT_FLAGS_OPS(s1, s2);
}
}
return;
}
@@ -156,6 +206,15 @@ void emit_cmp16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s1);
EXT_W_H(s4, s2);
NAT_FLAGS_OPS(s3, s4);
} else {
NAT_FLAGS_OPS(s1, s2);
}
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
@@ -170,10 +229,20 @@ void emit_cmp16_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_H(s1, xZR);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else {
NAT_FLAGS_OPS(s1, xZR);
}
}
return;
}
@@ -190,6 +259,14 @@ void emit_cmp16_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else {
NAT_FLAGS_OPS(s1, xZR);
}
}
}
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
@@ -203,6 +280,8 @@ void emit_cmp32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
@@ -215,6 +294,20 @@ void emit_cmp32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
SUBxw(s6, s1, s2);
SDxw(s6, xEmu, offsetof(x64emu_t, res));
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (rex.w)
NAT_FLAGS_OPS(s1, s2);
else {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s1);
SEXT_W(s4, s2);
} else {
ZEROUP2(s3, s1);
ZEROUP2(s4, s2);
}
NAT_FLAGS_OPS(s3, s4);
}
}
return;
}
@@ -244,10 +337,24 @@ void emit_cmp32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (rex.w)
NAT_FLAGS_OPS(s1, s2);
else {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s1);
SEXT_W(s4, s2);
} else {
ZEROUP2(s3, s1);
ZEROUP2(s4, s2);
}
NAT_FLAGS_OPS(s3, s4);
}
}
}
// emit CMP32 instruction, from cmp s1, 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, uint8_t nextop, int s1, int s3, int s4, int s5)
{
IFX_PENDOR0 {
ST_D(s1, xEmu, offsetof(x64emu_t, op1));
@@ -258,6 +365,8 @@ void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int
SET_DFNONE();
}
NAT_FLAGS_ENABLE_CARRY();
NAT_FLAGS_ENABLE_SIGN();
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
@@ -265,6 +374,21 @@ void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int
else
X64_SUB_W(s1, xZR);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (rex.w)
NAT_FLAGS_OPS(s1, xZR);
else {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else if (MODREG) {
ZEROUP2(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else {
NAT_FLAGS_OPS(s1, xZR);
}
}
}
return;
}
@@ -278,12 +402,34 @@ void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int
}
ORI(xFlags, xFlags, 1 << F_SF);
}
int res = s1;
IFX (X_ZF | X_PF) {
if (!rex.w && MODREG) {
ZEROUP2(s5, s1);
res = s5;
}
}
IFX(X_ZF) {
BNEZ(s1, 8);
BNEZ(res, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, res, s3, s4);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (rex.w)
NAT_FLAGS_OPS(s1, xZR);
else {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
} else if (res == s5) { // zero-up'd case
NAT_FLAGS_OPS(res, xZR);
} else {
ZEROUP2(s3, s1);
NAT_FLAGS_OPS(s3, xZR);
}
}
}
}
@@ -297,14 +443,23 @@ void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
SET_DFNONE();
}
NAT_FLAGS_ENABLE_SIGN();
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
if (la64_lbt) {
IFX(X_ALL) {
X64_AND_B(s1, s2);
}
IFX_PENDOR0 {
if (dyn->insts[ninst].nat_flags_fusion) {
AND(s3, s1, s2);
ST_D(s3, xEmu, offsetof(x64emu_t, res));
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s3);
}
}
IFX_PENDOR0 {
if (!dyn->insts[ninst].nat_flags_fusion) AND(s3, s1, s2);
ST_B(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
@@ -327,6 +482,64 @@ void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
if (dyn->insts[ninst].nat_flags_fusion && dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s3);
}
}
// emit TEST8 instruction, from test s1, c, using s3, s4 and s5 as scratch
void emit_test8c(dynarec_la64_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4, int s5)
{
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE();
}
NAT_FLAGS_ENABLE_SIGN();
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
if (la64_lbt) {
IFX (X_ALL) {
ADDI_D(s3, xZR, c);
X64_AND_B(s1, s3);
}
if (dyn->insts[ninst].nat_flags_fusion) {
ANDI(s3, s1, c);
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s3);
}
}
IFX_PENDOR0 {
if (!dyn->insts[ninst].nat_flags_fusion) ANDI(s3, s1, c);
ST_B(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
ANDI(s3, s1, c); // res = s1 & c
IFX_PENDOR0 {
ST_D(s3, xEmu, offsetof(x64emu_t, res));
}
IFX (X_SF) {
SRLI_D(s4, s3, 7);
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
if (dyn->insts[ninst].nat_flags_fusion && dyn->insts[ninst].nat_flags_needsign) {
EXT_W_B(s3, s3);
}
}
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
@@ -338,13 +551,22 @@ void emit_test16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
SET_DFNONE();
}
NAT_FLAGS_ENABLE_SIGN();
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
if (la64_lbt) {
IFX (X_ALL) {
X64_AND_H(s1, s2);
}
IFX_PENDOR0 {
if (dyn->insts[ninst].nat_flags_fusion) {
AND(s3, s1, s2);
if (dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s3);
}
}
IFX_PENDOR0 {
if (!dyn->insts[ninst].nat_flags_fusion) AND(s3, s1, s2);
ST_H(s3, xEmu, offsetof(x64emu_t, res));
}
return;
@@ -368,6 +590,9 @@ void emit_test16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
IFX (X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
if (dyn->insts[ninst].nat_flags_fusion && dyn->insts[ninst].nat_flags_needsign) {
EXT_W_H(s3, s3);
}
}
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
@@ -379,6 +604,8 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
SET_DFNONE();
}
NAT_FLAGS_ENABLE_SIGN();
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
@@ -387,8 +614,17 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
X64_AND_W(s1, s2);
}
IFX_PENDOR0 {
if (dyn->insts[ninst].nat_flags_fusion) {
AND(s3, s1, s2);
if (dyn->insts[ninst].nat_flags_needsign) {
if (!rex.w) SEXT_W(s3, s3);
} else if (!rex.w) {
ZEROUP(s3);
}
}
IFX_PENDOR0 {
if (!dyn->insts[ninst].nat_flags_fusion) AND(s3, s1, s2);
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
return;
@@ -415,18 +651,27 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
if (dyn->insts[ninst].nat_flags_fusion && !rex.w) {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s3);
} else {
ZEROUP(s3);
}
}
}
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
IFX_PENDOR0 {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else {
SET_DFNONE();
}
NAT_FLAGS_ENABLE_SIGN();
if (dyn->insts[ninst].nat_flags_fusion) NAT_FLAGS_OPS(s3, xZR);
if (la64_lbt) {
IFX(X_ALL) {
MOV64xw(s3, c);
@@ -436,13 +681,23 @@ void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
X64_AND_W(s1, s3);
}
IFX_PENDOR0 {
if (c >= 0 && c <= 4095) {
ANDI(s3, s1, c);
} else {
IFX(X_ALL) { } else MOV64xw(s3, c);
AND(s3, s1, s3);
if (c >= 0 && c <= 4095) {
ANDI(s3, s1, c);
} else {
IFX (X_ALL) {
} else
MOV64xw(s3, c);
AND(s3, s1, s3);
}
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
if (!rex.w) SEXT_W(s3, s3);
} else if (!rex.w) {
ZEROUP(s3);
}
}
IFX_PENDOR0 {
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
return;
@@ -471,4 +726,11 @@ void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c,
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
if (dyn->insts[ninst].nat_flags_fusion && !rex.w) {
if (dyn->insts[ninst].nat_flags_needsign) {
SEXT_W(s3, s3);
} else {
ZEROUP(s3);
}
}
}
Loaded 100 of 468 files, more files were not shown because too many files have changed in this diff. Show more