Compare commits

...
1409 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
ptitSeb 769c6c8f61 Bumped version to v0.3.2 2024-12-06 15:59:59 +01:00
Yang Liu b250056a61 [DYNAREC] Fixed a typo which leads to regression (#2121) 2024-12-06 15:21:23 +01:00
ptitSeb e305e5f1bb [BOX32][WRAPPER] Cosmetic fix an a function signature 2024-12-06 14:48:41 +01:00
rajdakin 18ce48e2c0 [WRAPPERHELPER] Fixed a use-after-free issue (#2118) 2024-12-06 13:29:20 +01:00
Leslie Zhai 06c93c93fe [LA64_DYNAREC] Added XOR AX, Iw opcode (#2116) 2024-12-06 10:40:02 +01:00
ptitSeb 869ddcfdda [WRAPPER] Another improved dlsym wrapped function, hopefully fixing regression (should help #2115) 2024-12-06 08:53:59 +01:00
ptitSeb 65e5e86c2b [RV64_DYNAREC] Improve native flag handling 2024-12-06 08:50:49 +01:00
ptitSeb 122b5e64e8 [BOX32][WRAPPER] Added a couple more 32bits wrapped functions to libc 2024-12-05 15:19:28 +01:00
ptitSeb 6c66d66b02 [BOX32][ELFLOADER] Be less strick when a symbol for R_386_32 relocation is missing 2024-12-05 15:19:02 +01:00
ptitSeb 85d694b36e [BOX32][WRAPPER] Fixed an issue wih an X11 32bits wrapped function 2024-12-05 15:11:49 +01:00
ptitSeb 44cff3ae25 [BOX32][WRAPPER] Added one more 32bits wrapped function to libc 2024-12-05 14:21:12 +01:00
Leslie Zhai c2d7dc573a [LA64_DYNAREC] Added HLT opcode (#2112) 2024-12-05 20:03:06 +08:00
ptitSeb a30433ea12 [NON4KPAGE] Some more adjustments for non-4Kpagesize system (should help #2110) 2024-12-05 11:12:02 +01:00
Yang Liu 6f7b462d53 [DYNAREC] Introduced TO_NAT to ease register mapping changes in future (#2111) 2024-12-05 10:16:22 +01:00
ptitSeb 95e5724117 [ANDROID] Install Android libs for android build 2024-12-04 18:43:24 +01:00
ptitSeb 1eaef70d2d [ANDROID] Updaed test21 for Android build 2024-12-04 18:27:24 +01:00
ptitSeb 3ed1e565f8 Disable another execution test when pagesize is not 4K 2024-12-04 17:52:05 +01:00
ptitSeb 8d0c976a18 [BOX32] Upped max number of x11 display slot from 4 to 16 2024-12-04 17:15:14 +01:00
ptitSeb 9165ec875a [BOX32] Some fixes to a few file related 32bits wrapped function (now windows gog installer can be used with box32 and wine) 2024-12-04 16:58:05 +01:00
ptitSeb 6a7997b41e [BOX32] Fix mystake on previous commit 2024-12-04 15:47:06 +01:00
ptitSeb 2a9d863131 [BOX32][WRAPPER] Added ldiv 32bits wrapped function (now Undertale works with box32, probably other linux gamestudio games too) 2024-12-04 15:20:14 +01:00
ptitSeb e3e9a86088 Added some more termux path to automatic ld_path 2024-12-04 14:35:41 +01:00
ptitSeb d5c787c213 [RCFILE] Better profile for dav1d 2024-12-04 13:57:30 +01:00
ptitSeb 559040e290 [BOX32][WRAPPER] Added a few more X11 32bits wrapped functions 2024-12-04 11:28:43 +01:00
ptitSeb 59ba5b7f0e [BOX32][WRAPPER] Fixed a typo in Xcursor wrapping (should help #2109) 2024-12-04 09:59:57 +01:00
ptitSeb 474a43a424 [BOX32][WRAPPER] Fixed typos from previous build 2024-12-03 19:48:34 +01:00
ptitSeb fb276bdc6b [BOX32][WRAPER] Fixed Xcursor wrapping 2024-12-03 18:45:46 +01:00
ptitSeb 1c1a26626b [ELFLOADER] Fixed a typo in a hack 2024-12-03 17:41:54 +01:00
ptitSeb 93f29d8cd9 Fix X64 build 2024-12-03 14:02:48 +01:00
ptitSeb 0054dde600 Restored old test21, the CI doesn't seems to like the new one 2024-12-03 12:54:54 +01:00
ptitSeb 794f2104bc Improved signal handling ([BOX32] Too) 2024-12-03 11:43:46 +01:00
Yang Liu 036af9f55f [LA64_DYNAREC] Fixed sign extension of 8-bit immediate in 66 opcodes (#2106) 2024-12-03 11:26:24 +01:00
ptitSeb 5bde45cc86 [DYNAREC] Made weakbarrier=1 and pause=3 default 2024-12-03 11:25:10 +01:00
ptitSeb ae1739f330 Improved dlsym wrapped function, will find more symbols from emulated libs 2024-12-03 10:23:18 +01:00
Yang Liu cfc09e0965 [WRAPPER] Wrapped more symbols in libcrypto3 (#2105) 2024-12-03 10:00:48 +01:00
ptitSeb 26c9b3426f [CI] Bumped test timeout to 120 sec 2024-12-03 09:25:39 +01:00
Yang Liu 963da34562 [CMAKE] Fixed typos (#2104) 2024-12-03 08:52:50 +01:00
ptitSeb 4adad381ce [BOX32] Improved test17 2024-12-02 17:14:42 +01:00
ptitSeb e561196f44 Improved test16 2024-12-02 17:01:08 +01:00
Yang Liu 14bd1368cc [RV64_DYNAREC] Added simple opcodes fusion as "native flags" (#2102)
* [RV64_DYNAREC] Added simple opcodes fusion as "native flags"

* Disable 16bit CMOV

* review
2024-12-02 16:58:20 +01:00
ptitSeb 415fc458be [ARM64_DYNAREC] Improved some x87 opcode behaviour 2024-12-02 16:19:06 +01:00
ptitSeb f2822f1a05 [INTERPRETER] Improved some x87 opcode behaviour 2024-12-02 16:18:41 +01:00
Leslie Zhai 646dd718f5 [LA64_DYNAREC] Added INSB, INSD, OUTSB and OUTSD opcodes (#2100) 2024-12-02 11:07:45 +01:00
ptitSebandrajdakin 83ed8ebb22 Android Long Double handling (#2101)
* [ANDROID] Try to handle LongDouble in vaarg correctly

* [ANDROID] Try to enable test07

* [WRAPPED] Fixed Android long double handling (#2096)

* [WRAPPED] Fixed Android long double handling

* [WRAPPED] Force casting to uintptr_t

* [WRAPPED] Fixed a typing issue, removed a warning in the CI

---------

Co-authored-by: rajdakin <[email protected]>
2024-12-02 10:50:21 +01:00
ptitSeb 88aab487f1 [BOX32] Some improvment on steam handling 2024-12-02 10:25:12 +01:00
ptitSeb 6d1e30cd3c [BOX32][WRAPPER] Improved 32bits freetype wrapping (wine explorer have correct fonts now) 2024-12-01 17:33:57 +01:00
ptitSeb ab73969ea4 [BOX32][WRAPPER] Improved networks functions 2024-12-01 12:32:33 +01:00
ptitSeb 93b371eb8c *[ARM64_DYNAREC] Fixed some cases of memory access on BTR/BTS opcodes (for #2093) 2024-12-01 10:03:25 +01:00
ptitSeb b7007a1bdd [BOX32][WRAPPER] Added a few more FreeType wrapped functions 2024-11-30 17:00:05 +01:00
ptitSeb a26c108464 [ARM64_DYNAREC] Added F2 0F 80..8F opcodes 2024-11-30 16:59:38 +01:00
ptitSeb 2971e9729c [BOX32][WRAPPER] This should fix the build 2024-11-30 15:07:01 +01:00
ptitSeb 6b2d923041 [WRAPPER] Added 1 more function to libgcrypt 2024-11-30 14:54:51 +01:00
ptitSeb cb30db320e [BOX32][WRAPPER] Added some more libc wrapped functions 2024-11-30 14:50:48 +01:00
ptitSeb e1ae914a1d [WRAPPER] Fixed libc wrappers includes 2024-11-30 14:25:08 +01:00
ptitSeb 51aa4b0416 Added a new memExist helper function and use it instead of getMmapped were it make sense 2024-11-30 14:02:28 +01:00
ptitSeb b0db168fb5 [INTERPRETER] Added 0F 30 ocpode ([RM64_DYNAREC] too) (for #2090) 2024-11-30 11:35:14 +01:00
ptitSeb 3b3338d132 [BOX32][WRAPPER] Added a few new wrapped functions 2024-11-29 20:45:40 +01:00
ptitSeb cc50331745 [BOX32][WRAPPED] Added one more obstack wrapped function 2024-11-29 19:15:01 +01:00
ptitSeb 2777bc142f Forgot this file on previous commit 2024-11-29 19:14:17 +01:00
ptitSeb c73545e25b [BOX32][WRAPPER] Added minimum libresolv wrapping 2024-11-29 19:10:11 +01:00
ptitSeb b862e74ae4 [BOX32][WRAPPER] Added obstack_vprintf wrapped symbol 2024-11-29 18:49:14 +01:00
ptitSeb 0d662b8543 [WRAPPER] Refactored some glib2 signal handling 2024-11-29 17:07:58 +01:00
ptitSeb ea0b23b783 Better hadnling of LD_PRELOAS on Steam Pressure Vessel wrapper 2024-11-29 17:07:31 +01:00
ptitSeb f15a187087 [TRACE] Show backtrace on emit_signal too if asked 2024-11-29 10:27:59 +01:00
ptitSeb 12a82cf91f [WRAPPER] Added back faked ITM weak functions 2024-11-29 10:27:23 +01:00
ptitSeb 5af2fa49c3 [WRAPPER] Fixed wrapped dlerror behaviour 2024-11-29 10:25:21 +01:00
Yang Liu 843fe30e46 [RV64] Added nan propagation emulation for interpreter and DynaRec (#2091)
* [RV64] Added nan propagation emulation for interpreter and DynaRec

* oops
2024-11-28 15:14:45 +01:00
ptitSeb 0da561cd20 [WRAPPER] Reworked sqlite3 with new wrapperhelper 2024-11-28 10:10:17 +01:00
rajdakin fd613de55e [WRAPPERHELPER] Transform from function to data if needed (#2089) 2024-11-28 09:17:00 +01:00
Leslie Zhai b2dc460db9 [RV64_DYNAREC] Fix PTEST X_CF typo (#2088) 2024-11-28 08:11:01 +01:00
Leslie Zhai e5b7dfb524 [LA64_DYNAREC] Added LEA opcode (#2087) 2024-11-28 08:09:49 +01:00
ptitSeb de0b602748 Added syscall 280 2024-11-27 19:52:52 +01:00
ptitSeb d0d85e684d [WRAPPER] More work on gtk/gstreamer wrapping 2024-11-27 19:52:52 +01:00
Yang Liu 05b322414a [RV64_DYNAREC] Fixed another regression in vector (#2086) 2024-11-27 17:11:25 +01:00
ptitSeb 38ee050a09 [BOX32] Added 32bits syscall 2 2024-11-27 16:05:22 +01:00
Yang Liu 1ee4959c05 [LA64_DYNAREC] Added nativeflags option support (#2084) 2024-11-27 10:38:46 +01:00
Yang Liu bc9086551b [RV64_DYNAREC] Fixed more regressions for vector (#2082) 2024-11-26 20:58:12 +01:00
ptitSeb f9f0c99c1b [WRAPPER] Reworked gstvideo with new wrapperhelper 2024-11-26 17:33:46 +01:00
ptitSeb a1b46711c4 [WRAPPER] Reworked gsttag with new wrapperhelper 2024-11-26 16:44:47 +01:00
ptitSeb f6bb071f84 [WRAPPER] Reworked gstsdp with new wrapperhelper 2024-11-26 16:41:14 +01:00
ptitSeb 746a0031f8 [WRAPPER] Reworked gst-rtp and gst-rtsp with new wrapperhelper 2024-11-26 16:36:13 +01:00
ptitSeb f78d0ae471 [WRAPPER] Reworked gstriff with new wrapperhelper 2024-11-26 16:27:53 +01:00
ptitSeb 7879a33cdc [WRAPPER] Reworked gst-pbutils with new wrapperhelper 2024-11-26 16:22:39 +01:00
ptitSeb a84a9847be [WRAPPER] Reworked gstnet with new wrapperhelper 2024-11-26 16:20:06 +01:00
ptitSeb 0c54e19c5f [WRAPPER] Reworked gst-gl with new wrapperhelper 2024-11-26 16:17:44 +01:00
rajdakin d507f8a6d0 [WRAPPERHELPER] Accept and ignore semicolons instead of declarations (#2081) 2024-11-26 13:56:18 +01:00
ptitSeb b18efe4e40 [WRAPPER] Reworked gstfft with new wrapperhelper 2024-11-26 11:55:05 +01:00
ptitSeb 83d69939f3 [WRAPPER] Reworked gstcontroller with new wrapperhelper 2024-11-26 11:53:08 +01:00
ptitSeb aee5032597 [WRAPPER] Reworked gstcheck with new wrapperhelper 2024-11-26 10:45:44 +01:00
ptitSeb c7cc78194f [ARM64_DYNAREC][TRACE] Use BLR on ret/retn with TRACE to allow relevant debug informations on bad returns 2024-11-26 10:34:12 +01:00
ptitSeb 089db91b39 [WRAPPER] Reworked gstbase with new wrapperhelper 2024-11-26 10:33:04 +01:00
rajdakin cb33043dd4 [WRAPPERHELPER] Fixed a parsing error (#2079) 2024-11-26 10:16:11 +01:00
Leslie Zhai b207ecad6a [LA64_DYNAREC] Added SBB opcodes (#2076)
* [LA64_DYNAREC] Added SBB opcodes

* [LA64_DYNAREC] clang-format and fix LOCK ADC wrong ed
2024-11-26 08:27:13 +01:00
xctan 48461001d2 [RV64_DYNAREC] Fixed vector packed logical shift opcodes (#2075)
* [RV64_DYNAREC] Fixed vector packed logical shift opcodes

* [RV64_DYNAREC] Fixed a operand violation in vector CVTSD2SS
2024-11-26 08:21:57 +01:00
ptitSeb 12649d04c7 [WRAPPER] Reworked gstaudio with new wrapperhelper 2024-11-25 18:51:48 +01:00
ptitSeb 5033738f73 [WRAPPER] Reworked gstapp with new wrapperhelper 2024-11-25 18:38:51 +01:00
ptitSeb df80b9c5de [WRAPPER] Reworked wrapping of gstallocators with new wrapperhelper 2024-11-25 18:33:35 +01:00
ptitSeb ffa94268d7 [WRAPPER] Reworked gstreamer with new wrapperhelper 2024-11-25 18:06:41 +01:00
xctan b7f0996459 [RV64_DYNAREC] Fixed vector SSE unpack opcodes (#2074) 2024-11-25 18:04:04 +01:00
Chi-Kuan Chiu dcf196c2ae [RBTREE] Document the rationale for memory management (#2060)
Enhanced the rbtree.h header with detailed documentation comments for
each function.
This comment aims to clarify the role of the red-black tree in memory
management and how these functions interact with and manage memory.
2024-11-25 17:08:05 +01:00
rajdakin a71856801b [WRAPPERHELPER] Added the --gst option (#2072) 2024-11-25 16:13:04 +01:00
Yang Liu 84608fc581 [ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions (#2070)
* [ARM64_DYNAREC] Added DYNAREC_PAUSE option for hint instructions

* Use sevl for wfe

* Add docs

* Fix typo

* use switch case
2024-11-25 11:28:19 +01:00
Leslie Zhai c30a392fe8 [LA64_DYNAREC] Add adc8, adc8c, adc16 and testadc (#2069)
* [LA64_DYNAREC] Add adc8, adc8c, adc16 and testadc

* [LA64_DYNAREC] Add missing testcase

* [LA64_DYNAREC] Change ANDI+OR to BSTRINS_D for ADC AL, Ib and removed testadc

* [LA64_DYNAREC] clang-format
2024-11-25 08:12:20 +01:00
rajdakin d8c16de2ec [WRAPPERHELPER] Fixed pragma once handling (#2067) 2024-11-24 22:19:28 +01:00
Yang Liu 2d04cbe97c [ARM64_DYNAREC] Use YIELD instead of WFE (#2066) 2024-11-24 20:04:01 +01:00
xctan ab65422034 [CORE] Enhanced BOX64_DYNAREC_RV64NOEXT (#2065) 2024-11-24 19:32:39 +01:00
xctan 3bde222242 [RV64_DYNAREC] Added, fixed, and optimized opcodes (#2059)
* [RV64_DYNAREC] Added 66 0F 38 37 PCMPGTQ opcode

* [RV64_DYNAREC] Added 66 0F 17 MOVHPD opcode

* [RV64_DYNAREC] Added 66 0F 38 15 PBLENDVPD opcode

* [RV64_DYNAREC] Optimized vector SSE packed compare

* [RV64_DYNAREC] Optimized vector MMX MOVD Gm, Ed

* [RV64_DYNAREC] Optimized vector SSE PMADDWD opcode

* [RV64_DYNAREC] Added vector PCMPGTQ opcode

* [RV64_DYNAREC] Added vector 66 0F 17 MOVHPD opcode

* [RV64_DYNAREC] Optimized vector 66 0F 16 MOVHPD opcode

* [RV64_DYNAREC] Added vector PBLENDVPD opcode

* [RV64_DYNAREC] Optimized vector PMADDUBSW opcode

* [RV64_DYNAREC] Optimized vector SSE logical shifts with Ex

* [RV64_DYNAREC] Optimized vector SSE unpack

* [RV64_DYNAREC] Added F0 F6 /2 LOCK NOT opcode

* [RV64_DYNAREC] Fixed vector packed logical shift
2024-11-24 16:57:34 +01:00
ptitSeb d0af86d5bf [VULKAN] Added a new extension and a missing function 2024-11-24 15:53:12 +01:00
ptitSeb 73b17d4add [ARM64_DYNAREC] Fix a regression, as 90 opcode is not always NOP depending on REX (should help #2064) 2024-11-24 15:28:21 +01:00
Yang Liu 93fa5323c5 [ARM64_DYNAREC] Generate corresponding hint instruction for PAUSE (#2063) 2024-11-24 11:19:36 +01:00
Yang Liu b0c10c9ae5 [RV64_DYNAREC] Minor optimizations on CMPXCHG (#2062) 2024-11-24 08:49:02 +01:00
rajdakin b8ed1b9646 [WRAPPERHELPER] Added support to cast to enum (#2061) 2024-11-23 22:01:40 +01:00
ptitSeb 0912e8f16d [ARM64_DYNAREC] Small optim for emit_shld32c CF flag computation 2024-11-23 14:37:19 +01:00
ptitSeb 327dc2c835 [DYNAREC] Better detection of wait slot 2024-11-23 13:06:26 +01:00
ptitSeb 8f937788ce [BOX32] Removed a debug leftover 2024-11-23 10:21:01 +01:00
Yang Liu 52ba725fa5 Reworked on mmap address alignments for a performance regression (#2057) 2024-11-22 12:06:55 +01:00
ptitSeb a39249454e Slightly better way to decode wrappers 2024-11-21 15:28:30 +01:00
ptitSeb c1f2304c88 Small fix for XSAVE/XRSTOR opcodes ([DYNAREC] too) 2024-11-21 12:08:43 +01:00
Yang Liu 85c6e28d47 [LA64_DYNAREC] Added more opcodes for JDK (#2055) 2024-11-21 11:44:47 +01:00
Yang Liu d1a253f469 [DYNAREC] Reuse strongmem infra for all backends (#2052) 2024-11-21 08:06:47 +01:00
ptitSeb 6aa57f5c73 [RCFILE] More adjustments with new strongmem 2024-11-20 21:02:08 +01:00
ptitSeb 023aeae9e6 Removed another debug leftover 2024-11-20 20:33:47 +01:00
ptitSeb 38880ab5a4 [TRACE] Don't try to decode a bridge if memory is not mapped or un-readable 2024-11-20 20:03:48 +01:00
ptitSeb 4e19324177 Removed a debug leftover 2024-11-20 20:03:10 +01:00
Yang Liu 9757d1b67a [ARM64_DYNAREC] More optimizations on strongmem emulation (#2051) 2024-11-20 18:59:20 +01:00
theofficialgman 5422b108af update pressure_vessel function with additional valid BOX86_LD_LIBRARY_PATH (#2050) 2024-11-20 18:15:03 +01:00
ptitSeb 0d650b183f [RCFILE] Addjusted some profile with new strongmem capabilities 2024-11-20 12:47:56 +01:00
Yang Liu fa432bb9d1 [ARM64_DYNAREC] Added weakbarrier=2 to disable last write barriers (#2049) 2024-11-19 21:22:55 +01:00
Yang Liu 81e4e26dc5 [ARM64_DYNAREC] Re-enable weakbarrier for dmb.ishst (#2048) 2024-11-19 19:59:43 +01:00
Yang Liu 4f6a66f9c6 [CI] Generate and upload .wcp file for Winlator (#2045)
* [CI] Generate and upload .wcp file for Winlator

* patch box64

* test box64 before the patch

* opt out static build

* typos
2024-11-19 13:49:35 +01:00
Yang Liu 127d273ada [DYNAREC] Reworked strong memory emulation (#2043)
* [ARM64_DYNAREC] Reworked strong memory emulation

* Simplify

* [RV64,LA64_DYNAREC] Reworked strong memory emulation

* forgot this

* more tweaks
2024-11-19 09:39:57 +01:00
liuli 469d4f81eb [WRAPPER]my_dbus_message_get_args() args type error (#2042)
* [WRAPPER]my_dbus_message_get_args() args type error

* [WRAPPER]my_dbus_message_get_args() args type error
2024-11-19 08:05:40 +01:00
ptitSeb 8f08a14115 Improved Signal handling ([ARM4_DYNAREC] too) 2024-11-18 17:18:41 +01:00
ptitSeb 4ac43047d0 [BOX32] Fixed previous commit 2024-11-18 11:14:07 +01:00
ptitSeb 4257fdded3 [BOX32] Fixed long double handling on printf like functions 2024-11-18 11:07:44 +01:00
ptitSeb 56298870f6 [ARM64_DYNAREC] Only propagate native flags if at least 1 opcode consume them 2024-11-17 15:14:13 +01:00
ptitSeb 48354185dd [WRAPPER] Added last 2 wrapped function for libexpat 2024-11-17 11:45:30 +01:00
ptitSeb 5f0cbcf26d [WRAPPER] Fixed an isue with __iso99_swcanf wrapped function 2024-11-17 11:45:00 +01:00
ptitSeb ffc875c2d6 [WRAPPER] Added wrapped libzstd.so.1 support, with new wrapperhelper 2024-11-17 11:30:30 +01:00
ptitSeb 8a180e3892 [ARM64_DYNAREC] Cancel native flags when an opcode use native flags not fully covered by the generated ones 2024-11-17 11:02:21 +01:00
ptitSeb c4d3d734b1 [DYNAREC] Mark existing block as dirty when re-creating a memory block 2024-11-17 11:00:28 +01:00
ptitSeb 6e8c244b77 [TRACE] Use lower case hex on rbtree 2024-11-17 10:59:34 +01:00
ptitSeb ac2ed68228 [WRAPPER] Added 2 more wrapped function to libcrypto.so.3 (for #1271) 2024-11-16 14:39:48 +01:00
ptitSeb fb27c89282 [WRAPPER][BOX32] Fixed a few wrapped functions (for hl2) 2024-11-16 14:31:46 +01:00
ptitSeb 74bed6edcb [ARM64_DYNAREC] Fixed potential issues with 0F A3/AB/B3/BB opcodes 2024-11-16 14:31:20 +01:00
ptitSeb 49a854fa7e [INTERPRETER] Fixed potential issue with 0F A3 opcode 2024-11-16 13:44:36 +01:00
ptitSeb 5adabbbcaa [ARM64_DYNAREC] Small optim in emit_sar8c helper 2024-11-16 13:23:23 +01:00
ptitSeb 42eae3e1b4 Expose a few more CPU features 2024-11-16 12:48:12 +01:00
ptitSeb 518d2b0129 Removed a debug leftover 2024-11-16 12:19:14 +01:00
ptitSeb bc8c786b80 Smal adjustment in singal handling for no-execution error 2024-11-16 12:16:51 +01:00
Yang Liu 5ab8a6f6f4 [WRAPPER] Fixed myStackAlignGVariantNew and refined the test too (#2038) 2024-11-15 21:37:36 +01:00
ptitSeb 385a31ec11 [ARM64_DYNAREC] Various fixes and improvments to a few random opcodes 2024-11-15 21:05:41 +01:00
ptitSeb 5c49954f69 [DYNAREC] Zero'd upper 32bits of regs when switching to 32bits from 64bits 2024-11-15 21:05:06 +01:00
ptitSeb 6ce7a1ba1f [INTERPRETER] Zero'd upper 32bits of regs when switching to 32bits from 64bits 2024-11-15 21:03:59 +01:00
ptitSeb 8c1335626f [ARM64_DYNAREC] A few fixes to 8/16bits logic/math opcodes 2024-11-15 15:34:22 +01:00
ptitSeb 8b0eec097b [TRACE] More info on signal 2024-11-15 15:34:00 +01:00
ptitSeb a39c8aa5c5 [INTERPRETER] Some cleanup on base logic/math/shift operations 2024-11-15 14:37:16 +01:00
ptitSeb 27745ceebb Added support for RDMSR, just in case 2024-11-15 14:36:42 +01:00
ptitSeb 64b213fe42 [ARM64_DYNAREC] Try to not call UpdateFlags when switching to a DFNONE state but dfnone is not needed 2024-11-15 14:27:43 +01:00
ptitSeb eaca84e9ba [ARM64_DYNAREC] Very small change on on emit_rol32c helper 2024-11-15 14:26:25 +01:00
xctan bca0f4d66d [RV64_DYNAREC] Added more MMX opcodes for vector (#2037)
* [RV64_DYNAREC] Added 0F 74-76 PCMPEQB/W/D opcodes

* [RV64_DYNAREC] Added 0F 64-66 PCMPGTB/W/D opcodes

* [RV64_DYNAREC] Added 0F E1-E2 PSRAW/D opcodes

* [RV64_DYNAREC] Added 0F 6E MOVD opcode

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

* [RV64_DYNAREC] Added 0F 73 /6 PSLLQ opcode
2024-11-15 10:11:11 +01:00
ptitSeb 8c17a37d1a [ARM64_DYNAREC] Reworked 8/16/32/64bits TEST opcodes 2024-11-14 18:54:40 +01:00
xctan 979a3232f9 [RV64_DYNAREC] Added more MMX opcodes for vector (#2035)
* [RV64_DYNAREC] Added 0F 68 PUNPCKHBW opcode

* [RV64_DYNAREC] Added 0F 69 PUNPCKHWD opcode

* [RV64_DYNAREC] Added 0F 6A PUNPCKHDQ opcode

* [RV64_DYNAREC] Updated 0F 68-69 PUNPCKHBW/WD opcodes

* [RV64_DYNAREC] Added 0F 60 PUNPCKLBW opcode

* [RV64_DYNAREC] Added 0F 61 PUNPCKLWD opcode

* [RV64_DYNAREC] Added 0F 62 PUNPCKLDQ opcode

* [RV64_DYNAREC] Simplified MMX PUNPCK{L,H}{BW,WD,DQ}
2024-11-14 17:41:28 +01:00
Yang Liu 47dbbe030c [DYNAREC] Added a experimental BOX64_DYNAREC_WEAKBARRIER option (#2033)
* [DYNAREC] Added a experimental BOX64_DYNAREC_WEAKBARRIER option

* Added it to the RCFILE
2024-11-14 17:41:12 +01:00
ptitSeb d05e719ce3 [ARM64_DYNAREC] Refactor 8/16/32/64bits CMP and REP CMPS/SCAS opcodes 2024-11-14 16:43:01 +01:00
Leslie Zhai 12f4afcba2 [LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025) (#2031)
* [LA64] Implement convert x64_va_list_t to sysv_varargs for float (#2025)

* [LA64] Implement myStackAlignGVariantNew (#2025)

* [LA64] Limit the log to LOG_DEBUG (#2055)

* [LA64] Add missing file (#2025)
2024-11-14 16:01:36 +01:00
ptitSeb cd2638d11a [ARM64_DYNAREC] Some refactor on 8/16/32/64bits SHL/SHR/SAR opcodes 2024-11-14 15:00:58 +01:00
ptitSeb c87796e51c [ARM64_DYNAREC] Minor change on 16bits neg opcode 2024-11-14 12:43:30 +01:00
ptitSeb d47b555e12 [ARM64_DYNAREC] Some rework on 8/16/32/64 INC/DEC opcodes 2024-11-14 11:20:57 +01:00
Yang Liu 4e568e1fdf Minor adjustments to README, updated README_CN (#2032) 2024-11-14 11:15:36 +01:00
Diego q 0688c53675 Update README.md (#2022)
* Update README.md

I made it more readable to the normal human being, kept all important info, rewrote everything to make it cleaner, and re-organized a few things, let me know if you want anything extra added

* Update README.md

Added And Fixed Some things as requested

* Update README.md

Fixed Everything Requested
2024-11-14 08:11:01 +01:00
ptitSeb 6d523f9c7f [ARM64_DYNAREC] Small optim for 8/16/32/64bits adc/sbb opcodes 2024-11-13 20:00:02 +01:00
ptitSeb 0f4f274bc7 [ARM64_DYNAREC] Various small fixes for some 16bits math/logic opcodes 2024-11-13 19:48:44 +01:00
xctan 09b8c3b94e [RV64_DYNAREC] Added more MMX opcodes for vector (#2027)
* [RV64_DYNAREC] Added 0F D5 PMULLW opcode

* [RV64_DYNAREC] Added 0F E5 PMULHW opcode

* [RV64_DYNAREC] Added 0F F5 PMADDWD opcode

* [RV64_DYNAREC] Added 0F 6B PACKSSDW opcode

* [RV64_DYNAREC] Added 0F 63 PACKSSWB opcode

* [RV64_DYNAREC] Added 0F 67 PACKUSWB opcode

* [RV64_DYNAREC] Removed useless vsetvli in MMX PACKUSWB/SSWB/SSDW
2024-11-13 19:43:57 +01:00
ptitSeb 1dbb676f38 [ARM64_DYNAREC] Reworked 8/16/32/64bits XOR opcodes 2024-11-13 18:46:47 +01:00
ptitSeb 331866bd1d [ARM64_DYNAREC] Fixed previous commit 2024-11-13 18:32:43 +01:00
ptitSeb 2515096f56 [ARM64_DYNAREC] Reworked 8/16/32/64 OR opcodes 2024-11-13 17:34:21 +01:00
ptitSeb 8868023ce9 [ARM64_DYNAREC] Reworked 8/16/32/64bits AND opcodes 2024-11-13 17:12:03 +01:00
ptitSeb dd9d6f8f83 [ARM64_DYNAREC] Small change in sbb32 helper 2024-11-13 15:18:56 +01:00
ptitSeb 21e403c908 [WRAPPER] Added more callback slots for libwaylend-client 2024-11-13 14:39:08 +01:00
ptitSeb f66aa57594 [ARM64_DYNAREC] Improved div/idiv opcode flags (non)handling 2024-11-13 14:38:14 +01:00
Yang Liu 506cb980b1 [RV64_DYNAREC] Prefer AMO* instructions over LR/SC when possible (#2028)
* [RV64_DYNAREC] Prefer AMO* instructions over LR/SC when possible

* fixes
2024-11-13 14:22:25 +01:00
ptitSeb 937e2cf853 [ARM64_DYNAREC] Improved 32/64bits imul/mul opcodes flags handling 2024-11-13 13:31:32 +01:00
xctan 82bf71ee19 [RV64_DYNAREC] Added more MMX opcodes for vector (#2026)
* [RV64_DYNAREC] Added 0F F8-FB PSUBB/W/D/Q opcodes

* [RV64_DYNAREC] Added 0F E8 PSUBSB opcode

* [RV64_DYNAREC] Added 0F D8-D9 PSUBUSB/W opcodes

* [RV64_DYNAREC] Added 0F F1-F3 PSLLW/D/Q opcodes

* [RV64_DYNAREC] Added 0F E9 PSUBSW opcode

* [RV64_DYNAREC] Added 0F EB POR opcode

* [RV64_DYNAREC] Added 0F DB PAND opcode

* [RV64_DYNAREC] Added 0F DF PANDN opcode

* [RV64_DYNAREC] Added 0F EF PXOR opcode

* [RV64_DYNAREC] Optimized rvv MMX PSLLW/D/Q
2024-11-13 11:04:43 +01:00
xctan eb9e7b9fee [RV64_DYNAREC] Added more MMX opcodes for vector (#2024)
* [RV64_DYNAREC] Added 0F D1-D3 PSRLW/PSRLD/PSRLQ opcode

* [RV64_DYNAREC] Added 0F EC PADDSB opcode

* [RV64_DYNAREC] Added 0F DC-DD PADDUSB/PADDUSW opcode

* [RV64_DYNAREC] Added 0F FC-FE PADDB/PADDW/PADDD opcodes

* [RV64_DYNAREC] Added 0F ED PADDSW opcode

* [RV64_DYNAREC] Added 0F 7F MOVQ opcode

* [RV64_DYNAREC] Fixed some typos

* [RV64_DYNAREC] Optimized RVV MMX PSRLW/D/Q to a mask-less version
2024-11-13 10:08:16 +01:00
Yang Liu b02942c0b0 [RV64_DYNAREC] Made eflags emulation branchless with xtheadcondmov (#2019)
* [RV64_DYNAREC] Made eflags emulation branchless with xtheadcondmov

* more
2024-11-11 19:53:55 +01:00
Yang Liu 56e813ccb7 [RV64_DYNAREC] Added more MMX opcodes for vector (#2017)
* [RV64_DYNAREC] Added more MMX opcodes for vector

* fixed
2024-11-11 12:29:55 +01:00
Yang Liu cf5b94d471 [CORE][LA64] Check LASX and display its existence (#2016) 2024-11-10 17:41:31 +01:00
ptitSeb 5d941f702a Preserve errno on mmap / munmap speicifc memory traqking operations 2024-11-10 11:09:33 +01:00
ptitSeb b46925e7e0 [WRAPPER] Added wrapped libXaw with new wrapperhelper (for #1990) 2024-11-09 18:36:27 +01:00
ptitSeb e676756cda [DYNAREC] Small chnage o hotpage detection to make it less sensitive 2024-11-09 18:12:43 +01:00
ptitSeb 591958c59c [RCFILE] advertise that BOX64_DYNAREC_TEST=1 is applied 2024-11-09 18:12:09 +01:00
ptitSeb 63a80ff696 This should fix LA64 Static build 2024-11-09 17:55:31 +01:00
ptitSeb ee6e3a7a96 [WRAPPER] Added a bunch of libc wrapped functions (for #2010) 2024-11-09 16:13:18 +01:00
ptitSeb 1d607cb937 [ARM64_DYNAREC] A small optim for a specific case of 0F C6 opcode 2024-11-09 16:12:26 +01:00
ptitSeb c5ced39665 [DYNAREC] Only test page protection when needed (and using a fester way) (should address the performance regression of #2009) 2024-11-09 14:02:45 +01:00
Yang Liu 7b2e77807d [RV64_DYNAREC] Added mmx infra for vector (#2011) 2024-11-09 11:58:41 +01:00
ptitSeb 7a623ef19c Improved getcontext/setcontext ([BOX32] too) 2024-11-08 18:13:42 +01:00
ptitSeb f292be40b2 Improved syscall 56 2024-11-08 18:03:03 +01:00
Yang Liu 0166330c73 [RV64_DYNAREC] Fixed some GETEX_vector usage (#2008) 2024-11-08 10:53:43 +01:00
ptitSeb 3cc9d47032 Added some weird 67 and 64/65 prefixed opcodes ([ARM64_DYNAREC] too) 2024-11-07 17:40:48 +01:00
ptitSeb 128708db2d [ELFLOADER] Better handling of symbols with COPY / GLOB_DAT (should helps #1412, but doesn't seems to help #1860, wich is strange) 2024-11-07 17:14:19 +01:00
ptitSeb 3027ee9f3e Removed a debug leftover 2024-11-07 17:13:04 +01:00
ptitSeb 51c673e62d [BOX32][WRAPPER] Added 1 more sdl2 wrapped function (Crimsonland works now) 2024-11-07 15:52:39 +01:00
ptitSeb 56bd83f6fb Added 64/65 D8..D9 opcodes 2024-11-07 15:52:10 +01:00
ptitSeb 2473bb6902 Added 64/65 69 opcode ([ARM64_DYNAREC] too) 2024-11-07 15:03:55 +01:00
ptitSeb da0e153a05 [BOX32] Improve errno handling, and added a few more libc wrapped functions 2024-11-07 13:26:55 +01:00
Jim Huang 394e81af45 [RBTREE] Unify naming and prevent unintended symbol exposure (#2005)
Red-black tree operations now consistently use the 'rbtree_' prefix, and
internal functions remain unexposed. Tested on RV64GC, resulting in a
498-byte reduction in the .text section size.
2024-11-06 21:56:34 +01:00
rajdakin 6af8d70cc1 [WRAPPED32] Added an errno-aware calling convention (#2006) 2024-11-06 21:52:34 +01:00
ptitSeb 2dea11a9e3 [TRACE] Better for 32bits wait wrapped function 2024-11-06 19:13:08 +01:00
ptitSeb cd55c12e44 Added a few wrapped function and fixed some other (for Steam) 2024-11-06 16:09:38 +01:00
ptitSeb cb2cf7c9b1 A bit more trace for emited signals 2024-11-06 16:09:14 +01:00
ptitSeb 494786be26 Fixed a small typo 2024-11-06 16:08:50 +01:00
ptitSeb 27013d6a03 [TRACE] A few more details for some speicifc CALL variant 2024-11-06 16:07:21 +01:00
ptitSeb 3ba91a6513 [CMAKE] Fixed SD865 profile, as a77.a55 is not supported in current build chain 2024-11-06 11:53:20 +01:00
ptitSeb c547090ee0 Fixed a typo 2024-11-05 15:42:14 +01:00
ptitSeb f87b9c15d3 [ARM64_DYNAREC] Fixed some issue with frintts uses 2024-11-05 14:42:09 +01:00
ptitSeb 3d76bcde2e [ARM64_DYNAREC] Fixed newly added frrintts use 2024-11-05 14:26:33 +01:00
ptitSeb 1a6f49ce45 [ARM64_DYNAREC] Reworked a bit FASTROUND 2024-11-05 14:13:01 +01:00
ptitSeb 745a7fc034 Silenced a signal message 2024-11-05 13:59:31 +01:00
ptitSeb 6158a0ad45 Disabling memory bit test when pagesize is not 4K 2024-11-05 13:55:14 +01:00
Yang Liu a51f684c41 [WRAPPER] Wrapped 3 more symbols for libc (#2000) 2024-11-05 13:10:10 +01:00
Yang Liu 681e207af5 [RV64_DYNAREC] Added more SSE opcodes for vector (#1999) 2024-11-05 09:43:30 +01:00
ptitSeb f651b7bfb0 [WRAPPER] forgot to handle libfontconfig also 2024-11-04 16:04:59 +01:00
ptitSeb 6c53e12b49 [WRAPPER] merged android naming so no more ifdef is needed 2024-11-04 15:06:44 +01:00
ptitSeb 01c9157fce [ANDROID] Try to fix libfontconfig not loading properly 2024-11-04 13:45:38 +01:00
ptitSeb 3448e94171 Improve handling of memory protection, and excution bit 2024-11-04 11:43:27 +01:00
ptitSeb 08085be360 [DYNAREC] Reverted last 2 commit, will use CancelFillblock mecanism instead 2024-11-03 20:01:56 +01:00
ptitSeb 3809866d99 [LA64_DYNAREC] This should fix Loongarch dynarec 2024-11-03 19:29:54 +01:00
ptitSeb 52a05c9f67 [DYNAREC] Make sure the emu structure is up-to-date each time LinkNext is called 2024-11-03 19:16:35 +01:00
ptitSeb ba5aa0c83b [ARM64_DYNAREC] Fixed an issue with native flags and opcode using C Helper that use flags, like rcr and rcl 2024-11-03 17:13:12 +01:00
ptitSeb 939486fa05 Forgot that file in earlier commit 2024-11-02 09:34:34 +01:00
ptitSeb c8d98f6901 [RCFIEL] Add an option to force usage of native EGL/GLESv2 library 2024-11-02 09:28:34 +01:00
ptitSeb 38cfeeb558 [WRAPPER] Small rework on wrapper return values 2024-11-02 09:20:42 +01:00
Yang Liu cf9f8d0535 [RV64_DYNAREC] Added more opcodes for vector (#1992) 2024-11-01 19:36:23 +01:00
Yang Liu 9e43737e18 [RV64_DYNAREC] Added more opcodes for vector (#1991) 2024-11-01 18:07:18 +01:00
ptitSeb 5d03ad24c3 Added a few more gtk3/gdk3 symbols (probably gtk/gdk 4.+ symbol actually) 2024-11-01 14:37:18 +01:00
Yang Liu ac6721edac [RV64_DYNAREC] Added more opcodes for vector (#1989) 2024-11-01 11:33:52 +01:00
Yang Liu 126cf27972 [RV64_DYNAREC] Added more opcodes for vector (#1987) 2024-10-31 17:38:16 +01:00
ptitSeb 0a677c7f83 Fixed a typo (for #1986) 2024-10-31 15:29:23 +01:00
ptitSeb 63e35941e2 Small (probably cosmetic) fix for CloneEmu helper function 2024-10-31 10:43:02 +01:00
ptitSeb 3ae6992641 [RCFILE] Added a profile for AlienIsolation linux version 2024-10-31 10:42:25 +01:00
ptitSeb a243532730 Added 65 6C..6F opcodes ([ARM64_DYNAREC] too) (for #1985) 2024-10-31 10:04:11 +01:00
zymayunyan ed99f5e6d2 [rebree]The name of rbtree is set error. (#1984) 2024-10-31 09:21:52 +01:00
Yang Liu 7d1bf95d93 [RV64_DYNAREC] Added more opcodes for vector (#1983) 2024-10-30 19:53:04 +01:00
Yang Liu 93cbf59e9e [Rv64_DYNAREC] Added more opcodes for vector (#1982) 2024-10-30 16:51:55 +01:00
ptitSeb e8f9796752 Fixed a small memory invalid read with my_execv 2024-10-30 16:33:14 +01:00
Yang Liu adb423d96b [RV64_DYNAREC] Added more opcodes for vector (#1981) 2024-10-30 13:10:47 +01:00
ptitSeb 74acad3628 [WRAPPER] Wrapped remaining 2 function to libbrotidec (for #1860) 2024-10-30 11:23:30 +01:00
ptitSeb 541adff4d4 Improved clone wrapped function compatibility 2024-10-30 11:12:51 +01:00
ptitSeb 39189a746b Generate a SIGILL on unimplemented opcode 2024-10-30 11:06:17 +01:00
ptitSeb f82e938ae8 [WRAPPER] Added more crypto3 and ssl3 function, and fixed some issue with hidden callback (for #1860) 2024-10-30 11:05:43 +01:00
Yang Liu 34520c0b4f [RV64_DYNAREC] Added more opcodes for vector (#1980) 2024-10-30 11:02:09 +01:00
Yang Liu 121148da72 [RV64_DYNAREC] Added more opcodes for vector (#1979) 2024-10-29 22:04:07 +01:00
Yang Liu 1e34db98a8 [RV64_DYNAREC] Added more opcodes for vector (#1978) 2024-10-29 21:01:14 +01:00
ptitSeb 9f821d6406 [WRAPPER] Reworked ssl3 and crypto3 with new wrapperhelper (for #1860) 2024-10-29 16:55:15 +01:00
rajdakin 70a6d96748 [WRAPPERHELPER] Added pragma once support, fixed a preprocessor bug, fixed the wrapperhelper Makefile (#1977) 2024-10-29 16:31:05 +01:00
ptitSeb 4a440b6f0a [ARM64_DYNAREC] Make sure neg on 16bits is correctly computed 2024-10-29 15:19:38 +01:00
ptitSeb fdfc5c4a41 [ARM64_DYNAREC] Fixed a potential issue with native flags used while some intermediary opcode doesn't support it 2024-10-29 15:19:11 +01:00
ptitSeb 6699c0ee7f [RCFILE] Update setup and install generic profile to not use native flags 2024-10-29 14:13:53 +01:00
Yang Liu 8807b1aa3c [INTERP] Fixed overflow checking for convertion opcodes (#1976) 2024-10-29 14:11:13 +01:00
ptitSeb 2aff4239cc [BOX32] Added an option to also add binfmt integration for box32 (for #1973) 2024-10-29 14:10:05 +01:00
ptitSeb d99d18759b [ARM64_DYNAREC] Also use Native Carry flags directly when possible 2024-10-29 13:09:51 +01:00
Yang Liu 68c3be3e16 [RV64_DYNAREC] Fixed 66 0F C2 CMPPD opcode for scalar and more (#1975)
* [RV64_DYNAREC] Fixed 66 0F C2 CMPPD opcode for scalar

* more minor fixes
2024-10-29 11:16:08 +01:00
Yang Liu f148b106a5 [RV64_DYNAREC] Fixed MAXSS and MAXSD for vector (#1974) 2024-10-28 23:10:17 +01:00
Yang Liu 9ffabf4c85 [RV64_DYNAREC] Added more opcodes for vector (#1972) 2024-10-28 22:34:49 +01:00
Yang Liu aebfd61539 [RV64_DYNAREC] Added more opcodes for vector (#1970) 2024-10-28 20:16:47 +01:00
Yang Liu 8dee79d380 [RV64_DYNAREC] Added more opcodes for vector (#1969) 2024-10-28 17:32:52 +01:00
Yang Liu d3c1ea5b0f [RV64_DYNAREC] Added more opcodes for vector (#1968) 2024-10-28 14:55:58 +01:00
Yang Liu 2835a2f87d [RV64_DYNAREC] Added more opcodes for vector (#1966) 2024-10-27 22:31:20 +01:00
ptitSeb 062a098ac5 [VULKAN] Fixed a typo in a vulkan extension 2024-10-27 08:44:00 +01:00
Yang Liu 5563103453 [RV64_DYNAREC] Implemented the first AVX128 opcode for scalar only (#1962) 2024-10-26 17:50:24 +02:00
Yang Liu a1d62eb92b [RV64_DYNAREC] Refined fpu_{push,pop}cache for vector (#1960) 2024-10-26 17:06:45 +02:00
ptitSeb 138a021fad [WRAPPER] Added some ssl3 and crypto3 wrapped functions (for #1860) 2024-10-25 17:25:01 +02:00
ptitSeb bdf0e95a12 [WRAPPER] Added wrapped libbrotlidec with new warpperhelper (for #1860) 2024-10-25 16:01:28 +02:00
ptitSeb 90674b825a [BOX32] Added 1 more sdl2 wrapped function (for #1957) 2024-10-25 10:48:51 +02:00
Yang Liu b3bc09f898 [RV64_DYNAREC] Added 1 more 66 0F opcode for vector (#1956) 2024-10-24 16:09:23 +02:00
ptitSeb 320459c2c6 Make BOX64_IGNOREINT3 also ignore other privilged instructions 2024-10-24 15:24:54 +02:00
Yang Liuandxctan 8d14c10b8c [RV64_DYNAREC] Optimized horizontal opcodes (#1955)
Co-authored-by: xctan <[email protected]>
2024-10-24 09:00:01 +02:00
Chi-Kuan Chiu 2c2b252dac [Box64] Fix compilation issues (#1938) (#1952)
Fixed compilation errors related to variable declarations within
switch-case statements without enclosing braces. This adjustment
ensures compatibility with older versions of compiler.

Resolves: #1938
2024-10-22 22:08:49 +02:00
ptitSeb 8efd1e3ae0 [ARM64_DYNAREC] Added AVX.F3.0F 53 opcode 2024-10-22 14:43:34 +02:00
ptitSeb e7adc6b7f9 [BOX32] Added 1 more sdl2 wrapped function 2024-10-22 09:24:06 +02:00
ptitSeb fc7d204d4b [ARM64_DYNAREC] More work around native flags handling 2024-10-20 21:47:21 +02:00
ptitSeb 2153e7098c [ARM64_DYNAREC] Fixed edgecase on MINSS/MAXSS when comparing 0.0 and -0.0 2024-10-20 14:57:31 +02:00
ptitSeb 29beabd683 [ARM64_DYNAREC] Added BOX64_DYNAREC_NATIVEFLAGS to disable the use of native flags, as there is still a bug or two in that mode (for #1947) 2024-10-20 13:21:08 +02:00
ptitSeb 80c346060f [ARM64_DYNAREC] Some small improvment to a few shift opcode, to use flagless jump when possible 2024-10-20 11:23:55 +02:00
ptitSeb 4e10cd654f Improved 0F 0D opcode ([ARM64_DYNAREC] too) (FF7RI now have sound) 2024-10-19 15:23:26 +02:00
ptitSeb a12653a25d [TRACE] Improved 32bits trace for FF 92 opocde 2024-10-19 15:22:52 +02:00
ptitSeb f683ae95c3 [BOX32][WRAPPER] Added a few more SDL2 32bits wrapped functions 2024-10-19 13:54:28 +02:00
ptitSeb 6bdeb18253 [BOX32] Fixed to a couple of wrapped libc functions 2024-10-19 12:40:33 +02:00
ptitSeb 8f1f23c991 [BOX32][TRACE] Better trace for a sscanf variant 2024-10-19 12:39:29 +02:00
ptitSeb 42345af443 [BOX32][WRAPPER] Added 32bits wrapped regex libc functions 2024-10-19 11:05:40 +02:00
ptitSeb a5797da100 [BOX32][WRAPPER] Added some more libc wrapped function, and 32bits globalsymbol infrastructure 2024-10-19 10:38:11 +02:00
ptitSeb 0821e6acc2 [BOX32][WRAPPER] Added a few symbols to libSDL2 2024-10-18 18:59:15 +02:00
ptitSeb 0fb87c7926 [WRAPPER] Added 1 missing symbol to libSDL2 2024-10-18 18:58:58 +02:00
ptitSeb b578487d01 [BOX32] A few more fixes to libX11 wrapping 2024-10-18 16:44:47 +02:00
ptitSeb cdf81eb1d7 Now x86_64 bash can be installed as box64-bash and will be automaticly used if present 2024-10-18 14:53:13 +02:00
ptitSeb 97491658c6 Fixed box32 hash table un-init crashing on regular box64 ([BOX32] and improved a bit hash selection patter) 2024-10-18 14:51:58 +02:00
ptitSeb b2b3653d67 [ARM64_DYNAREC] Fixed a regression with native flag commit (might help #1947) 2024-10-18 12:09:03 +02:00
ptitSeb de102bec5e [VULKAN] Added 2 more extensions 2024-10-18 11:38:06 +02:00
ptitSeb 3598f2855f [BOX32] A few more X11 wrapped functions and fixes 2024-10-18 10:23:08 +02:00
ptitSeb f36a479d0f [ARM64_DYNAREC][TRACE] Update LR on jumpnext on trace build so debug info in case of jump to NULL are accurate 2024-10-18 10:22:43 +02:00
ptitSeb 5363c013e6 [WRAPPER] Added gtk_marshal to gtk2 (for #1943) 2024-10-17 15:59:50 +02:00
ptitSeb b609328ac1 [WRAPPER] Reworked libcups wrapping with new wrapperhelper 2024-10-17 15:49:26 +02:00
ptitSeb 65c2b103b1 [ARM64_DYNAREC] Added directmapping of x86 flags to N, V and Z arm64 flags 2024-10-17 15:36:13 +02:00
ptitSeb 22a89ba914 Added 1 more wrapped symbol to gtk2 (for #1943) 2024-10-17 13:07:44 +02:00
ptitSeb fda9b6f75d [WRAPPER] Reworked libharfbuzz wrapping with new wrapperhelper 2024-10-17 12:57:52 +02:00
ptitSeb b29e9b706e [WRAPPER] Added alternative libname for libFLAC 2024-10-16 12:39:57 +02:00
Yang Liu bd145ad6b2 [RV64_DYNAREC] Added a few more opcodes for vector (#1941) 2024-10-15 14:47:25 +02:00
Yang Liu fc71ec9785 [RV64_DYNAREC][LA64_DYNAREC] Fixed various issues (#1940)
* [RV64_DYNAREC] Fixed more issues for vector

* more fixes and optims

* more

* more

* more

* more
2024-10-14 14:11:57 +02:00
ptitSeb cce43790d2 [NTERPRETER] Added 64 F6 opcodes (for #1932) 2024-10-13 18:57:19 +02:00
ptitSeb 1e31e1fff8 [BOX32] Fixed dlvsym for RTLD_NEXT, like dlsym 2024-10-13 18:50:44 +02:00
ptitSeb af2a0c9747 [BOX32] Some more 32bits wrapped symbols 2024-10-13 18:39:13 +02:00
ptitSeb d30488da87 [BOX32] Added some more 32bits wrapped function to libc 2024-10-13 17:44:14 +02:00
ptitSeb 59ba2fc7ab [BOX32][WRAPPER] Hacked some support for libGLX_nvidia.so.0 2024-10-13 17:43:51 +02:00
ptitSeb 1936052e79 [WRAPPER] Hacked some support for libGLX_nvidia.so.0 2024-10-13 17:43:27 +02:00
ptitSeb 103ec5d72a [BOX32] Added some posix_file_action wrapped function, and fixed posix_spawn/exec function argument handling 2024-10-13 14:46:21 +02:00
ptitSeb 9139ec3e5c [WRAPPER] Reworked libgnutls wrapping with new wrapperhelper 2024-10-13 13:16:09 +02:00
Yang Liu 7430463b33 [CORE] Refactored %pid trace file handling (#1933) 2024-10-13 13:08:18 +02:00
ptitSeb 6f2d067f3a [INTERPRETER] Added 64/65 85 opcode ([ARM64_DYNAREC] too) (for #1932) 2024-10-13 11:35:20 +02:00
ptitSeb d31b9c9caa [BOX32] Allow internal memory to be in 32bits space if needed 2024-10-13 11:20:25 +02:00
ptitSeb 2670d37542 [RCFILE] Added a profile 2024-10-13 11:19:37 +02:00
ptitSeb 617fd69bcc [BOX32] Reworked alignment for 32bits stacks 2024-10-13 11:19:19 +02:00
ptitSeb 5fcd9d45a3 [BOX32] Added a few 32bits wrapped function libSDL2 2024-10-13 10:01:06 +02:00
ptitSeb b6cd19b78b [BOX32] More work on libX11 and friends, using more shadow structure like Screen and Visual (help wine, probably other too) 2024-10-12 18:40:31 +02:00
Yang Liu 6a3a19da68 [RV64_DYNAREC] Fixed more issues for vector (#1928)
* [RV64_DYNAREC] Fixed emitter for xtheadvector

* MOVSD can be unaligned

* fixed unaligned issues
2024-10-12 12:46:08 +02:00
ptitSeb efd103004c [BOX32] Improved X11 event handling 2024-10-12 10:45:21 +02:00
Yang Liu 18e033cdd8 [RV64_DYNAREC] Fixed 66 0F 38 17 PTEST opcode for vector (#1927) 2024-10-11 21:27:51 +02:00
Yang Liu 2a4ecc1d28 [RV64_DYNAREC] Wrapped icuuc75 (#1926) 2024-10-11 21:27:17 +02:00
Yang Liu c0c91678ba [RV64_DYNAREC] Fixed an issue in CVTTSD2SI for vector (#1925) 2024-10-11 18:34:40 +02:00
ptitSeb 7a531ed272 [BOX32] Fixed some issues with X11 and XRandR 32bits wrapping 2024-10-11 13:25:28 +02:00
ptitSeb 93e3fcb386 [BOX32][TRACE] Better for XRRSetScreenSize 2024-10-11 13:20:14 +02:00
Yang Liu 143fc90a4c [RV64_DYNAREC] Split 660f.c to speedup compilation a bit (#1924) 2024-10-11 12:25:13 +02:00
ptitSeb f65feaf9da [BOX32] Added 2 more wrapped function to libc 2024-10-11 11:03:57 +02:00
ptitSeb a17b0effa1 [BOX32] Added 2 more 32bits wrapped functions 2024-10-11 10:44:07 +02:00
ptitSeb b0d5c7a1a5 [BOX32] Added 1 more 32bits wrapped function 2024-10-11 10:26:47 +02:00
Yang Liu 9c4a407fdc [RV64_DYNAREC] Added more opcodes for vector (#1923)
* [RV64_DYNAREC] Added more opcodes for vector

* fix
2024-10-11 09:36:59 +02:00
Yang Liu 67b2151e3c [RV64_DYNAREC] Added more opcode for vector and some fixes too (#1920) 2024-10-10 20:58:45 +02:00
ptitSeb b8024469da [ARM64_DYNAREC] Added a small optim for CALL 0 / POP reg type of sequence 2024-10-10 20:55:24 +02:00
ptitSeb 7f5c826bb1 [BOX32][TRACE] Fixed trace for memcmp, strncasecmp and strncmp 2024-10-10 20:54:40 +02:00
ptitSeb acad3f3963 [BOX32] Actually fixed dlsym on RTLD_NEXT 32bits call 2024-10-10 20:32:29 +02:00
ptitSeb 1f6ce24eaa [BOX32] Added and fixed some 32bits functions for libX11 and friends 2024-10-10 19:20:29 +02:00
ptitSeb 4a82f21cc3 [BOX32] Fixed 32bits dlsym on RTLD_NEXT not working 2024-10-10 19:20:29 +02:00
Yang Liu 0cf707599d [RV64_DYNAREC] Added more opcodes for vector (#1919) 2024-10-10 18:40:02 +02:00
ptitSeb e2e6bdc4cb [BOX32][WRAPPER] Added 32bits wrapped libXss (with new wrapperhelper) 2024-10-10 17:23:49 +02:00
ptitSeb 8136186554 [WRAPPER] Reworked libXss with new wrapperhelper 2024-10-10 17:11:00 +02:00
Yang Liu 9b733041af [RV64_DYNAREC] Added more opcodes for vector (#1918) 2024-10-10 17:08:50 +02:00
ptitSeb 9e01876747 [BOX32] Improved pthread_mutex handling 2024-10-10 15:57:28 +02:00
ptitSeb ee909b8c08 [BOX32] More 32bits SDL-1.2 wrapped functions 2024-10-10 15:57:08 +02:00
ptitSeb fdf1982982 [BOX32] Fixed getifaddrs 32bits wrapped function 2024-10-10 15:53:32 +02:00
Yang Liu 88ccd7f537 [RV64_DYNAREC] Added 1 more opcode for vector, some fixes too (#1917) 2024-10-10 15:30:41 +02:00
ptitSeb c6cd9ceb75 Fixed some command line handling regression 2024-10-10 15:11:52 +02:00
ptitSeb ce735357d6 [BOX32] More 32bits wrapped functions 2024-10-10 14:57:26 +02:00
Yang Liu 887dee83eb [RV64_DYNAREC] Added more boilerplate for vector (#1916) 2024-10-10 12:15:48 +02:00
ptitSeb fd73a2bc8b [BOX32] Morewrapped SDL2 function, and improved handling of SDL_PixelFormat 2024-10-10 09:46:32 +02:00
ptitSeb 21b5f90a33 Small changed to command line argument handling 2024-10-10 08:37:59 +02:00
ptitSeb d1c5cd7b0a [BOX32][TRACE] Small improvment to SDL_RWFromFile trace 2024-10-10 08:35:58 +02:00
ptitSeb 656a36061a [BOX32] More X11 wrapping fixes 2024-10-09 21:03:41 +02:00
ptitSeb 05384f581f [BOX32] Improved again, X11 and XImage handling 2024-10-09 15:56:07 +02:00
ptitSeb 84f3c104b2 [BOX32] Improved handlong of XImage 2024-10-09 11:48:22 +02:00
ptitSeb 761f7e40de [BOX32] Fixed 32bits libc syscall 240 2024-10-09 10:23:27 +02:00
Yang Liu b760c21414 [BOX32] Fixed fcntl flock macros definitions (#1915) 2024-10-09 10:01:26 +02:00
ptitSeb bb651298c4 [BOX32] Added better handling of fcntl (should help Wine when futex_waitv syscall is not available) 2024-10-08 20:48:13 +02:00
ptitSeb 8850a11072 [BOX32] Added some more libSDL2 wrapped function (now linux limbo works, with gamepad) 2024-10-08 20:29:40 +02:00
ptitSeb 499338e80d Fixed non-Box32 builds 2024-10-08 20:06:00 +02:00
ptitSeb c12f8fa254 [BOX32] Fixed some X11 function so wine launch (and added BOX64_X11SYNC to help debug X11 programs) 2024-10-08 19:44:20 +02:00
ptitSeb 7ae36b8667 [BOX32] More 32bits wrapped functions 2024-10-08 17:38:01 +02:00
ptitSeb 591e2db712 [BOX32] Refactored X11 wrapping, and add a few more functions 2024-10-08 16:34:20 +02:00
Yang Liu 8414563ad0 [RV64_DYNAREC] Added more opcodes and small optimizations (#1914)
* [RV64_DYNAREC] Added more opcodes and small optimizations

* more

* only applies to and32c
2024-10-08 13:58:32 +02:00
ptitSeb 85fc57faa3 Improve debugging trace of rb_tree 2024-10-08 13:11:42 +02:00
ptitSeb c8e10a004b [BOX32][DYNAREC] Allocate Dynarec memory in higher prereserve regions 2024-10-08 12:56:45 +02:00
ptitSeb e1fac2404c Removed wine prereserve hack on munmap now that prereserve is better handled 2024-10-08 12:21:19 +02:00
Yang Liu 65adf2a860 [RV64_DYNAREC] Fixed CVTSS2SD and CVTSD2SS opcodes (#1913) 2024-10-08 10:53:18 +02:00
ptitSeb dea6906ae9 [WRAPPER] Reworked libresolv with new wrapper helper ([STATICBUILD] fixed potential issue with static build) 2024-10-08 10:47:44 +02:00
ptitSeb 22ccae3301 Small adjustment in 32bits custom memory hinter 2024-10-08 10:40:09 +02:00
ptitSeb 58d58b0af7 [BOX32] More adjustments to x86 structures packing & alignment (or not) 2024-10-08 09:59:44 +02:00
ptitSeb ce5daaa835 Small change in custom Aligned Memory Allocator 2024-10-07 22:56:47 +02:00
ptitSeb 8fe0681681 Some cosmetic changes and more macro, to ease future testings on custom malloc 2024-10-07 18:39:35 +02:00
ptitSeb 3987e644a8 Added 66 6A opcode ([ARM64_DYNAREC] too) (for #1911) 2024-10-07 17:26:40 +02:00
ptitSeb f073415510 [BOX32] More work on 32bits wrapped functions 2024-10-07 17:17:55 +02:00
Yang Liu 4c69bcd97a [DYNAREC] Optimized CALL/RET RAS for out of dynablock jumps (#1909) 2024-10-07 16:57:47 +02:00
ptitSeb 05aac0879e [BOX32][WRAPPER] Reworked 32bits libGL with new wrapperhelper 2024-10-07 13:32:45 +02:00
ptitSeb cb5dafe8db [BOX32][WRAPPER] Reworked 32bits libasound with new wrapperhelper 2024-10-07 11:14:43 +02:00
ptitSeb 82c7d45c4b [BOX32] Added a couple of 32bits function to libc 2024-10-07 10:45:31 +02:00
ptitSeb f81677278f Reworked mmap allocator and wine prereserve handling ([BOX32] fix handling of wine prereserve) 2024-10-07 09:25:04 +02:00
ptitSeb 2ef6011c7a [ARM64_DYNAREC] Added 64 88 opcode 2024-10-07 08:53:15 +02:00
ptitSeb 6e0b5358fb [BOX32][WRAPPING] Added 32bits wrapped libXi (with new wrapperhelper) 2024-10-06 16:44:33 +02:00
ptitSeb e783e3c794 [BOX32] Added a few more 32bits libc symbols 2024-10-06 15:19:20 +02:00
ptitSeb 8965d9bd70 [BOX32][WRAPPER] Added 32bits libuuid (with new wrapperhelper) 2024-10-06 15:16:57 +02:00
ptitSeb 37fe9bad6d [WRAPPER] Reworked wrapped libXi with new wrapperhelper 2024-10-06 15:09:18 +02:00
ptitSeb a4daf4c228 [BOX32][WRAPPER] Added 32bits wrapped libXcomposite (with new wrapperhelper) 2024-10-06 14:48:10 +02:00
ptitSeb ae080c3ad3 [BOX32] Forgot a few more x86 structure to properly align 2024-10-06 14:31:51 +02:00
ptitSeb ad0c08c2de [BOX32] Proper alignment for x86 structures 2024-10-06 14:27:19 +02:00
ptitSeb 7b93791c3f [BOX32] Addes 3 more x86 libs for convenience 2024-10-06 14:03:30 +02:00
Yang Liu 172df2cd0c [DYNAREC] Tweaking indirect jumps for CALL/RET to use the return address stack (#1907) 2024-10-06 12:19:55 +02:00
ptitSeb b395cd7ccc [BOX32] More work on various wrapper, and some bug fixes 2024-10-06 12:14:53 +02:00
ptitSeb 8ec6b15dc2 [BOX32] More work on 32bits X11 wrapping (not 12 Labor of Hercules 6 works from Steam, but not Steam itself) 2024-10-05 18:42:51 +02:00
ptitSeb 2a2f82a745 [BOX32] Added many more 32bits wrapped function (some using wrapperhelper) 2024-10-05 16:36:31 +02:00
ptitSeb 13a7801421 [BOX32][WRAPPER] Added 32bits libXinerama, with new wrapperhelper 2024-10-05 14:30:29 +02:00
ptitSeb 1a5cd1c1ff [WRAPPER] Reworked libXinerama with new wrapperhelper 2024-10-05 14:23:53 +02:00
ptitSeb 224974f218 [WRAPPERHELPER] Removed double line added by mystake 2024-10-05 14:22:59 +02:00
ptitSeb b96556f80f [BOX32][WRAPPER] Reworked 32bits libX11, with new wrapperhelper 2024-10-05 14:17:48 +02:00
ptitSeb c29be5b945 [BOX32][WRAPEPR] Reworked 32bits libfontconfig with new wrapperhelper 2024-10-05 09:54:44 +02:00
ptitSeb 21b60db107 [BOX32][WRAPPER] Added more 32bits wrapped function to libfreetype 2024-10-05 09:38:01 +02:00
ptitSeb baa3f573ae [BOX32] Added some more wrapped function and a profile (PixelJunk Shooter linux version now Works) 2024-10-04 20:57:24 +02:00
Yang Liu 0243e93e97 [RV64] Allowed disabling more extensions (#1904) 2024-10-04 20:13:25 +02:00
ptitSeb 778bbc6d08 [BOX32][WRAPPER] Reworked 32bits libXext with new wrapperhelper 2024-10-04 18:22:43 +02:00
ptitSeb 6ae502f181 [BOX32] Initalized libX11 if used without loading (becauseit's loaded indirectly with SDL2 for example) 2024-10-04 18:18:18 +02:00
ptitSeb 088720db22 [BOX32][WRAPPER] Added wraped mostly empty 32bits libXext 2024-10-04 17:37:07 +02:00
ptitSeb 3d6ecc064f [WRAPEPR] Reworked libXext wrapping with new wrapperhelper 2024-10-04 16:56:37 +02:00
ptitSeb 333bf19c00 [ARM64_DYNAREC] Worked on CF IRET opcode 2024-10-04 16:19:24 +02:00
ptitSeb 25599b91b2 [INTERPRETER] Worked on CF IRET opcode 2024-10-04 16:19:03 +02:00
ptitSeb 18305a1994 [BOX32][WRAPPER] Fixed 32bits mktime 2024-10-04 15:52:34 +02:00
ptitSeb e6f56bf5fa Fixed x86_64 build 2024-10-04 14:24:02 +02:00
ptitSeb 681c6f4e5e [TRACE] Btter trace for ioctl 2024-10-04 13:12:37 +02:00
ptitSeb 11f1c3c4ff Return the correct errno when mmap can't allocated hinted memory address 2024-10-04 13:04:28 +02:00
ptitSeb 9f4eb36c99 [BOX32][WRAPPER] More wrapped function to libc, and many fixes some existing ones 2024-10-04 12:28:11 +02:00
Yang Liu cbbafafb46 [RV64_DYNAREC] Added more opcodes for xtheadvector (#1899) 2024-10-03 19:38:26 +02:00
ptitSeb 9e853e487d [BOX32] Added more 32bits wrapped function and reworked 32bits memory allocator 2024-10-03 19:36:42 +02:00
ptitSeb 0e91ad3ed3 [BOX32] Fixed scanf type function when grabing long/ptr type of data 2024-10-03 13:51:56 +02:00
ptitSeb c5e894aab2 [BOX32] More check for low alignment in memalign wrapped functions 2024-10-03 13:50:38 +02:00
rajdakin 49aaeb3080 [WRAPPER] Fixed RV64 isSimpleWrappers (#1898) 2024-10-03 12:49:18 +02:00
Yang Liu 1c7ac8c761 [RV64_DYNAREC] Added more opcodes for xtheadvector and fixed more issues (#1897)
* [RV64_DYNAREC] Added 1 more opcode for xtheadvector

* Disabled more opcodes does not apply to xtheadvector

* Added 1 more opcode

* Added 1 more opcode

* fix
2024-10-03 12:36:04 +02:00
ptitSeb e2492a1426 [BOX32][WRAPPER] Added full wrapped support for 32bits libudev0 and libudev1 2024-10-03 12:26:38 +02:00
ptitSeb f750391c2e [BOX32] Added rolling log print on Stack corrupted call 2024-10-03 12:26:11 +02:00
ptitSeb 95d65a02bc [TRACE] Fixed StopEmu on trace build when trace is not enabled 2024-10-03 12:25:17 +02:00
ptitSeb 2685037c82 [WRAPPER] Improved libudev1 wrapped logf function 2024-10-03 12:24:34 +02:00
ptitSeb 61c46994cd [WRAPPER] Reworked libudev1 wrapping with new wrapperhelper 2024-10-03 11:51:17 +02:00
ptitSeb 8b8e6501bc [BOX32][WRAPPER] Added a few more libX11 32bits wrapped functions 2024-10-03 11:36:36 +02:00
ptitSeb c4184ef733 [BOX32] Added workaround for posix_memalign when used with align of 4 2024-10-03 11:36:12 +02:00
ptitSeb 6a5049b22c [BOX32][TRACE] Some more improved trace 2024-10-03 11:35:41 +02:00
Yang Liu 6cbcfc7ab8 [DYNAREC] Added a new missing mode for fallback opcodes (#1896) 2024-10-02 20:44:04 +02:00
rajdakin 564d06e84c [WRAPPERHELPER] Forgot to add the Makefile (#1895)
* [WRAPPERHELPER] Forgot to add the Makefile

* [WRAPPERHELPER] Also sped up the build
2024-10-02 20:42:45 +02:00
Yang Liu 8398799e1c [CI] Added xtheadvector testing (#1894) 2024-10-02 17:50:47 +02:00
Yang Liu c43d34d0cf [RV64_DYNAREC] Added preliminary xtheadvector support (#1892)
* [RV64_DYNAREC] Added preliminary xtheadvector support

* [RV64_DYNAREC] Fixed more unaligned issue
2024-10-02 09:53:29 +02:00
ptitSeb a188f4ebfe [BOX32][WRAPPER] Added a bunch of wrapped 32bits functions, and fixed a few existing ones (Now Witcher 2 Linux boot and can enter tutorial, before crashing) 2024-09-30 21:06:56 +02:00
ptitSeb e59063a13c [BOX32] Added 2 more 32bits syscalls 2024-09-30 18:02:15 +02:00
ptitSeb 2f95534bd0 [BOX32] Set default FS to 0 for 32bits apps 2024-09-30 18:01:51 +02:00
ptitSeb 2b0c8d45fa [BOX32][WRAPPER] Added 32bits wrapping for SDL2_image 2024-09-30 17:41:47 +02:00
ptitSeb c88cf6359e [BOX32] Keep low memory free by default 2024-09-30 17:41:08 +02:00
ptitSeb 62405c79c3 [DYNAREC] Start with dynarec instead of interpreter 2024-09-30 17:40:40 +02:00
ptitSeb 28dedd66b3 [BOX32][WRAPPER] Added a few more wrapped functions to libGL, libasound and libX11 2024-09-30 16:35:11 +02:00
ptitSeb f26146bc23 [BOX32][WRAPPER] nl_langinfo signature needs t as return type 2024-09-30 15:40:07 +02:00
ptitSeb 2a0489a21c [BOX32] Handling of BOX64_MAXCPU for 32bits apps 2024-09-30 15:37:53 +02:00
ptitSeb 0980c4438a [BOX32][WRAPPER] More work on SDL2 Wrapping(but TheStanleyParable still don't have mouse input working) 2024-09-30 15:37:11 +02:00
ptitSeb f7c93b68d8 [BOX32] Fixed main Elf init not always called 2024-09-30 14:00:33 +02:00
ptitSeb f7e769f8c4 [BOX32] Enable futex robust_list hack for all 32bits software for now 2024-09-30 13:59:30 +02:00
ptitSeb 7f1ce6ebfd [BOX32][WRAPPER] Manualy changed wctype_t to h in libc wrapping 2024-09-30 12:59:57 +02:00
rajdakin 4715ef2633 [WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890) 2024-09-30 12:31:45 +02:00
rajdakin 703d19b256 Various box32 wrapped libs and script fixes (#1889)
* [WRAPPED32] Fixed the rebuild_wrappers_32 script, fixed some libc signatures

* [WRAPPED32] Added back xdr functions

* [WRAPPED32] Forgot to regenerate wrappers
2024-09-30 12:26:45 +02:00
ptitSeb f7d7fbb9b0 Revert a change ffrom previous build and pushed missing BOX32 generated files too 2024-09-29 22:30:40 +02:00
Pablo Labs a6baf1f370 [ANDROID][BOX32] Fix __libc_init, Fix Some Warnings (#1887)
* [ANDROID][BOX32] Fix __libc_init, Fix Some Warnings

* Fix More Warnings

* Revert fillALProcWrapper() change
2024-09-29 22:21:40 +02:00
ptitSeb 874238f61e [BOX32][WRAPPER] Added more SDL2 and freetype function, and fixed missing fonts in many games ([BOX64] also fixed some SDL2 signature on RWops) 2024-09-29 21:10:54 +02:00
Yang Liu 9968963b97 [RV64_DYNAREC] Eliminate redundant vsetvli by tracking its usage (#1886) 2024-09-29 15:15:20 +02:00
ptitSeb 5b68e46bb7 [BOX32] Added 3 more event type to SDL2 event conversion 2024-09-29 11:34:32 +02:00
Yang Liu 9a83521ad6 [RV64_DYNAREC] Minor optimization on vector_vsetvli (#1885) 2024-09-29 10:39:28 +02:00
Yang Liu 2a7eabfb1c [RV64_DYNAREC] Refined RISC-V vector emitter (#1884) 2024-09-29 10:38:49 +02:00
Pablo Labs b4a0ae20c9 [ANDROID][BOX32] Fix Android Build, and add correct libc, libm, libdl library names on library_list_32.h (#1883)
* [ANDROID][BOX32] Fix Android Build, and add correct libc, libm, libdl library names on library_list_32.h

* Fix Various Warnings
2024-09-29 00:45:20 +02:00
ptitSeb 87493a9bc9 [BOX32] Added 1event type for SDL2_Event conversions 2024-09-28 16:09:14 +02:00
ptitSeb 0f9dac511c [BOX32][WRAPPER] Added some more 32bits libc functions 2024-09-28 15:58:29 +02:00
ptitSeb 11724fd2ad [BOX32][WRAPPER] Added 32bits wrapped/hacked libtcmallocminimal 2024-09-28 15:19:08 +02:00
ptitSeb c0955d33de [BOX32][WRAPPER] Added some minimum 32bits wrpping for fontconfig, and some fixes for iconv wrapped function signature 2024-09-28 15:13:13 +02:00
ptitSeb bc5e686fde [WRAPPER] Reworked libfontconfig with new wrapperhelper 2024-09-28 13:51:22 +02:00
ptitSeb 541489da4d [BOX32][WRAPPER] Some fixes to libexpat 32bits wrapping and more other 32bits functions 2024-09-28 13:48:08 +02:00
ptitSeb 79200d4df6 [BOX32] Fixed wrapping for glShaderSourceARB 2024-09-28 12:32:01 +02:00
ptitSeb 578bae3c37 [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed one from SDL2 2024-09-28 12:27:00 +02:00
ptitSeb 37490d1a44 [BOX32] Added 2 more 32bits syscalls 2024-09-28 11:59:12 +02:00
ptitSeb 3919bb2e7d [BOX32][WRAPPER] Added 32bits wrapped libexpat and another batch of wrapped function for 32bits libfreetype and SDL2 2024-09-28 11:17:26 +02:00
ptitSeb 93e8434a87 [WRAPPER] Reworked wrapping of libexpat with new wrapperhelper 2024-09-28 10:20:21 +02:00
ptitSeb 97a1983c59 [BOX32][WRAPPER] Added a bunch of 32bits functions to SDL2 and libc 2024-09-28 10:15:55 +02:00
Yang Liu 42e60bc7c5 [BOX32][WRAPPER] Wrapped more SDL2 functions (#1881) 2024-09-27 19:00:08 +02:00
ptitSeb 93dc8fce10 [BOX32][TRACE] Better trace for recv 2024-09-27 17:27:17 +02:00
ptitSeb 34d4cde7c4 [BOX32][WRAPPER] Added 2 more 32bits wrapped function to freetype 2024-09-27 11:11:58 +02:00
xctan 66788af44d [RV64_DYNAREC] Refined RISC-V vector disassembler (#1880)
* [RV64_DYNAREC] Refined RISC-V vector disassembler

* [RV64_DYNAREC] Formated generated code
2024-09-27 09:03:24 +02:00
Yang Liu 1a8df98cf2 [ARM64_DYNAREC] Small optim on 0F C7 /1 inst name (#1878) 2024-09-26 19:46:26 +02:00
Yang Liu 0fb0ac7994 [LA64_DYNAREC] Added unaligned support to CMPXCHG8B (#1877) 2024-09-26 19:45:40 +02:00
ptitSeb 24f278c961 [BOX32][WRAPPER] Added some more 32bits wrapped functions 2024-09-26 15:21:52 +02:00
ptitSeb d45001e4c9 [BOX32][WRAPPER] Added 32bits empty wrapped libXxf86vm 2024-09-26 13:29:35 +02:00
ptitSeb 95a0e669a2 [WRAPPER] Reworked wrapped libXxf86vm with new wrapperhelper 2024-09-26 13:29:08 +02:00
ptitSeb b80e4c552a [BOX32] Minor changes to 32bits freetype wrapping 2024-09-26 13:20:07 +02:00
Yang Liu 933dc0f5c8 [LA64_DYNAREC] Fixed emit_add16 LBT implementation (#1875) 2024-09-26 10:04:20 +02:00
Yang Liu 6a3904fc48 [BOX32][WRAPPER] Refined SDL2 display mode wrapping (#1874)
* [BOX32][WRAPPER] Refined SDL2 display mode wrapping

* review
2024-09-26 09:24:32 +02:00
Yang Liu b045dbde0f [BOX32][WRAPPER] Added preliminary wrapper for SDL2 (postal1 works) (#1872)
* [BOX32][WRAPPER] Added preliminary wrapper for SDL2 (postal1 works)

* Handle more events
2024-09-26 08:17:15 +02:00
ptitSeb b85ebc73c9 [BOX32][WRAPPER] Improved 32bits wrapping for libfreetype (still not 100% ok) 2024-09-25 19:46:55 +02:00
ptitSeb 7d76fc4945 [WRAPPER] Added 1 GLX extension ([BOX32] too) 2024-09-25 15:46:58 +02:00
ptitSeb 90332ecf6e [BOX32] Removed a warning 2024-09-25 14:51:56 +02:00
ptitSeb 0c4c89f3ca [BOX32] Fixed some locale conversion (fixed FTL.x86 not going ingame) 2024-09-25 14:47:25 +02:00
Yang Liu 62177d2ca3 [BOX32][WRAPPER] Fixed null checking in my32_SDL_SetVideoMode (#1868) 2024-09-25 13:07:26 +02:00
ptitSeb 144830bc05 [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed a few more 2024-09-25 12:29:46 +02:00
Yang Liu 24a5917b44 [LA64_DYNAREC][BOX32] Improved some 66 prefix opcodes (#1867) 2024-09-25 09:06:22 +02:00
ptitSeb b38c5f095c [BOX32][WRAPPING] More fixes with intermediate structure conversions 2024-09-24 22:37:11 +02:00
ptitSeb d7ad7f0c70 [BOX32][WRAPPING] Fixed some issue with intermediate structure conversions 2024-09-24 22:26:44 +02:00
Yang Liu dc391439ba [RV64_DYNAREC][BOX32] Added more opcodes (#1866)
* [RV64_DYNAREC][BOX32] Added more opcodes

* more
2024-09-24 21:58:47 +02:00
Yang Liu e44c43deeb [RV64_DYNAREC][BOX32] Improved some 66 prefix opcodes (#1865) 2024-09-24 21:10:50 +02:00
Yang Liu c795faf167 [LA64_DYNAREC][BOX32] Added more opcodes (#1864) 2024-09-24 21:10:10 +02:00
ptitSeb dad0913dcb [BOX32][WRAPPER] Added some more 32bits wrapped function, and fixed a few x11/glX ones too 2024-09-24 21:04:58 +02:00
ptitSeb e5db9aa874 [ARM64_DYNAREC] Fixed some issue with a few 16bits opcodes on 64bits operations 2024-09-24 21:04:57 +02:00
Yang Liu 2d0b60898c [RV64_DYNAREC] Added more opcodes for vector (#1863)
* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes
2024-09-24 17:03:11 +02:00
ptitSeb c25fc8cc24 [BOX32][WRAPPER] Added a few 32bits function to libxrandr 2024-09-24 16:50:18 +02:00
ptitSeb bddeac4b45 [BOX32] Silently enlarge thread stack size that are too small for platform 2024-09-24 16:49:52 +02:00
ptitSeb 1aa42a6779 [BOX32][TRACE] Fixed semop traces 2024-09-24 16:49:19 +02:00
ptitSeb 73b3aec3ed [ARM64_DYNAREC] Fixed reset of rex on 67 prefixed opcodes 2024-09-24 15:17:56 +02:00
ptitSeb 9568cbac0a [ARM64_DYNAREC] Added F1 opcode 2024-09-24 14:49:45 +02:00
ptitSeb a60c742fa4 [ARM64_DYNAREC] Added CA/CB ocpodes 2024-09-24 14:46:34 +02:00
ptitSeb 6313a31668 [INTEPRETER] Added a check on CS for CA/CB opecodes 2024-09-24 14:46:17 +02:00
ptitSeb 15a4be2db1 [ARM64_DYNAREC] Added 66 0F BF opcode (and cosmetic fix on interpreter) 2024-09-24 14:31:59 +02:00
ptitSeb 0c71d8d4e6 [ARM64_DYNAREC] Added 64 A8 opcode 2024-09-24 14:26:02 +02:00
ptitSeb 4409374c47 [ARM64_DYNAREC] Added 67 A9 opcode, and fixed 67 opcode with ignored REX prefix 2024-09-24 14:20:22 +02:00
ptitSeb 4299e0a3a3 [BOX32][WRAPPER] Added more 32bits wrapped functions 2024-09-24 14:13:45 +02:00
Yang Liu c4af15c2e2 [RV64_DYNAREC] Allowed disabling V extension (#1862) 2024-09-24 11:44:16 +02:00
Yang Liu eacde4008e [RV64_DYNAREC] Fixed 66 0F 38 2B PACKUSDW opcode (#1861) 2024-09-24 11:43:21 +02:00
ptitSeb 358e24ace5 [BOX32][WRAPPER] Added 32bits empty libfreetype 2024-09-24 10:18:10 +02:00
ptitSeb 7317472b5f [BOX32][WRAPPER] More 32bits wrapped functions, and a few fixes on threads handling 2024-09-23 19:45:13 +02:00
ptitSeb 9271684e5a [BOX32][WRAPPER] One more 32bits wrapped libX11 function 2024-09-23 15:12:24 +02:00
ptitSeb 929d462d05 [BOX32] Addeda few more 32bits wrapped x11 functions 2024-09-23 14:23:02 +02:00
ptitSeb e0ce06483c [NON4K][ELFLOADER] more Elfloader work for non-4k pagesize OS ([BOX32] too) 2024-09-23 14:13:28 +02:00
ptitSeb 95e78088d6 [NON4K] Fixed some typos ([BOX32] too) 2024-09-23 14:01:45 +02:00
ptitSeb dd72a4542e [BOX32][NON4K] Try to fix elfloader when elf wants to load at an address not-compatible with pagesize 2024-09-23 13:54:48 +02:00
ptitSeb 5fe0a68b46 [NON4K] Try to fix elfloader when elf wants to load at an address not-compatible with pagesize 2024-09-23 13:52:11 +02:00
ptitSeb 61486749f8 [BOX32][WRAPPER] More 32bits wrapped function to libX11 2024-09-23 13:42:09 +02:00
Yang Liu 31f574ed36 [RV64_DYNAREC] Added more opcodes for vector (#1857) 2024-09-23 12:42:59 +02:00
ptitSeb d9ff07b605 [BOX32] Improved semaphore wrapping 2024-09-23 11:39:07 +02:00
ptitSeb dbdb3d6af6 [WRAPPER] Reworked wrapped libwayland-client with new wrapperhelper 2024-09-23 10:39:30 +02:00
ptitSeb 4c0a213840 [BOX32][WRAPPER] Added 32bits wrapped openal 2024-09-23 10:19:42 +02:00
ptitSeb aa65bad62b [WRAPPER] Reworked wrapped libopenal with new wrapperhelper 2024-09-23 10:10:14 +02:00
ptitSeb 60c469ed06 [BOX32][WRAPPER] Added a couple of 32bits libx11 functions 2024-09-22 20:34:25 +02:00
ptitSeb cf87ae2e71 [WRAPPING] Fixed some (very) old issue with SDL2 RWops wrapping 2024-09-22 20:20:54 +02:00
Yang Liu ea443cfa21 [RV64_DYNAREC] Added more opcodes for vector (#1855) 2024-09-22 19:22:36 +02:00
ptitSeb 5e49e3cfaa [BOX32][WRAPPER] Added some more libX11 and libc 32bits wrapped function, and empty 32bits wrapped libXfixes, libXcursor, libXrender and libXrandr 2024-09-22 17:11:07 +02:00
ptitSeb 8574c575f5 [WRAPPER] Reworked wrapping of libXcurse, libXfixes, libXrender and libXrandr with new wrapperhelper 2024-09-22 17:10:03 +02:00
ptitSeb d2aecc0412 [BOX32][wrapper] Added some basic 32bits X11 wrapping, fixed 32bits sem_XXX wrapping, and more 32bits wrapped functions 2024-09-22 16:24:48 +02:00
Yang Liu 710d537f39 [RV64_DYNAREC] Added more opcodes for vector (#1853) 2024-09-22 15:36:25 +02:00
Yang Liu 9e44c65391 [RV64_DYNAREC] Added more opcodes for vector (#1852) 2024-09-22 11:24:08 +02:00
Yang Liu c36491cfb6 [RV64_DYNAREC] Added more opcode for vector and reinitialize sew after external call (#1851) 2024-09-22 08:36:18 +02:00
ptitSeb c2be0268b1 [BOX32][ELFLOADER] Fixed PROTECTED symbol that were not loaded correctly 2024-09-21 15:52:02 +02:00
ptitSeb 4cda6dbcfb [ELFLOADER] Fixed PROTECTED symbol that were not loaded correctly 2024-09-21 15:51:51 +02:00
ptitSeb e34afea346 [BOX32] Added some more 32bits wrapped functions 2024-09-21 14:55:42 +02:00
ptitSeb 1ea71c89a8 [BOX32] Fixed wrapping of __ctype_b, __ctype_tolower and __ctype_toupper 2024-09-21 14:22:21 +02:00
ptitSeb 856ffea797 [BOX32][TRACE] Better trace for a few more 32bits string functions 2024-09-21 14:21:49 +02:00
ptitSeb 9efae57162 [BOX32] Added 32bits wrapped libGLU 2024-09-21 12:35:26 +02:00
rajdakin 09d4cb7b38 [WRAPPERHELPER] Fixed wrapperhelper (#1850) 2024-09-21 12:29:28 +02:00
ptitSeb fb4f580922 [BOX32] Added some more 32bits wrapped functions (Chicken Invaders 3 works, but need SDL12COMPAT_OPENGL_SCALING=0) 2024-09-21 12:20:26 +02:00
Yang Liu 15842f3464 [RV64_DYNAREC] Added more opcodes for vector (#1848) 2024-09-20 18:42:04 +02:00
rajdakin e18846fac5 [WRAPPERHELPER] Fixed some bugs, added partial multiarch support (#1847) 2024-09-20 17:06:25 +02:00
Yang Liu 4aeb8ea1b0 [LA64_DYNAREC] Fixed a typo in GETGB (#1846) 2024-09-20 16:04:00 +02:00
ptitSeb 6a415b54d0 [WRAPPER] Reworked libX11 with new wrapperhelper 2024-09-20 15:28:13 +02:00
rajdakin 5abdfd9751 [WRAPPERHELPER] Added predefined mark-simple and conversions (#1845) 2024-09-20 14:32:26 +02:00
ptitSeb ab65619b99 [WRAPPER] Added an entry in gitignore for wrapperhelper 2024-09-20 12:52:54 +02:00
ptitSeb 88629f7aa6 [WRAPPER] Reworked libXft with new wrapperhelper (should help #1841) 2024-09-20 12:51:59 +02:00
ptitSeb fb11af5859 [WRAPPER] Added hack for parser helper to __attribute inline and noreturn 2024-09-20 12:49:01 +02:00
rajdakin 550b72200d Improve the wrapper helper (#1844)
* [WRAPPERHELPER] Fixed some issues, added better macros

* [WRAPPERHELPER] Fixed type_t_equal_lax
2024-09-20 12:40:06 +02:00
Yang Liu cd9d19a2bb [RV64_DYNAREC] Added more opcodes and fixed more issues for vector (#1842)
* [RV64_DYNAREC] Added 66 0F 6D PUNPCKHQDQ opcode

* [RV64_DYNAREC] Added more opcode

* [RV64_DYNAREC] Added more opcodes for vector

* [RV64_DYNAREC] Added more opcodes

* [RV64_DYNAREC] Added more opcodes

* [RV64_DYNAREC] Added more opcode

* More fixes
2024-09-20 11:30:11 +02:00
ptitSeb ca9e43d0f0 [WRAPPER] Added 1 wrapped function to libX11 (for #1204 and #1841) 2024-09-20 10:36:29 +02:00
ptitSeb 04d2f90ab3 Added Syscall 165 (for #1672) 2024-09-20 10:27:18 +02:00
LiZhuoheng 906cdb1584 [RV64_DYNAREC] Added 62 opcode (#1840) 2024-09-20 08:21:12 +02:00
Yang Liu 1978ec8b71 [RV64_DYNAREC] Fixed more issues catched on real machine (#1839) 2024-09-19 20:08:22 +02:00
ptitSeb 28f32a3ca6 [BOX32][WRAPPER] Added minimum 32bits libasound support 2024-09-19 18:57:32 +02:00
Yang Liu 3b7a448b07 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1838) 2024-09-19 17:07:59 +02:00
ptitSeb 8f0c1efc6f [WRAPPER] Reworked libasound with new wrapperhelper 2024-09-19 14:30:36 +02:00
ptitSeb c10b673fef Fixed a comment on x87 tags 2024-09-19 14:20:21 +02:00
ptitSeb bfd9f79267 [WRAPPER] Some rework on a few wrapped function foor glib2, libxcb and libxcb-private 2024-09-19 13:22:28 +02:00
ptitSeb f7c596317b [TRACE] Fixed a potential segfault when trying to trace a function from a dlopenn'd lib 2024-09-19 13:20:45 +02:00
ptitSeb e4debaf4ba [TRACE] Some better trace for a few function call 2024-09-19 13:20:02 +02:00
ptitSeb 4eeba053d5 Fixed some x87 tag handling 2024-09-19 13:19:12 +02:00
Yang Liu 7263a2e7ab [RV64_DYNAREC] Added more opcodes for vector (#1837) 2024-09-19 12:06:07 +02:00
Yang Liu ef7f25481c [RV64_DYNAREC] Added more opcodes for vector (#1836) 2024-09-19 10:43:23 +02:00
Yang Liu 35d17abeb0 [RV64_DYNAREC] Fixed more unaligned issues for vector (#1835) 2024-09-19 08:11:02 +02:00
Yang Liu 33472d3a8e [RV64_DYNAREC] Fixed some found issues in vector (#1834)
* [RV64_DYNAREC] Fixed 66 0F 63/6B PACKSSWB opcode

* [RV64_DYNAREC] Fixed 66 0F 3A 0F PALIGNR opcode

* [RV64_DYNAREC] GETGX_empty_vector should come after GETEX_vector

* [RV64_DYNAREC] Fixed unaligned memory access

* [RV64_DYNAREC] Fixed more unaligned issue

* Fix CI
2024-09-18 20:27:45 +02:00
ptitSeb e60ddf7ecd [WRAPPER] Reworked libGLU with new wrapper helper 2024-09-18 11:52:00 +02:00
ptitSeb 579332db7d [WRAPPER] Reworked libEGL with new wrapperhelper 2024-09-18 11:38:25 +02:00
ptitSeb b34c031139 [WRAPPER] Reworked libgobject-2.0 with new wrapperhelper 2024-09-18 11:31:29 +02:00
ptitSeb 46bc2e7183 [WRAPPER] Reworked wrapped libpsl.so.5 with new wrapperhelper 2024-09-18 11:00:49 +02:00
ptitSeb 26ddbf9466 [WRAPPER] Reworked wrapping glib-2.0 (stil with new wrapperhelper) 2024-09-18 10:55:00 +02:00
ptitSeb b67dc452b2 [WRAPPER] Reworked wrapped libgio-2.0 2024-09-18 10:09:59 +02:00
Yang Liu b37b6addac [RV64_DYNAREC] Added more opcodes for vector (#1833)
* [RV64_DYNAREC] Added more opcodes for vector

* review
2024-09-18 09:23:54 +02:00
ptitSeb a2dfe70cd8 [WRAPEPR] Reworked wrapping of libgdk3 2024-09-17 19:10:10 +02:00
ptitSeb 20a2b4e051 [WRAPPER] Reworked gtk3 wrapping 2024-09-17 18:36:03 +02:00
ptitSeb d7c3c3fcf9 Save flags and defered flags when runing EmuCall ([DYNAREC] Same for DynaCall) 2024-09-17 16:39:54 +02:00
ptitSeb 7d77a4b31f [DYNAREC] Track if a dynablock is for 32bits code (for future use) 2024-09-17 16:33:59 +02:00
Yang Liu 59217ccbbe [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1832) 2024-09-17 13:31:47 +02:00
Yang Liu f674953b87 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1831) 2024-09-17 09:35:15 +02:00
Yang Liu b8798c580f [RV64_DYNAREC] Added more opcodes for vector (#1830) 2024-09-16 19:38:37 +02:00
Yang Liu 2b58e8a253 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1829) 2024-09-16 19:13:21 +02:00
ptitSeb f744513941 Fixed non-box32 builds 2024-09-16 19:03:50 +02:00
ptitSeb e8ecbbdc6a [BOX32][TRACE] Improved some trace and function calls for 32bits process 2024-09-16 17:53:24 +02:00
ptitSeb 1f7c69e19e [BOX32] Added 1 more wrapped 32bits libc function 2024-09-16 17:52:47 +02:00
ptitSeb de4044d5b1 [BOX32] Fixed an issue with using 32bits OpenGL with SDL1.2 2024-09-16 17:42:22 +02:00
ptitSeb 1503241c7a [BOX32] Added some more 32bits wrapped function, and fixing some SDL ones 2024-09-16 17:25:06 +02:00
ptitSeb 37a1261693 [DYNAREC] Forgot some files in previous commit 2024-09-16 16:18:19 +02:00
ptitSeb 446d57122c [DYNAREC] Make sure jump address is wrapped on 32bits address space 2024-09-16 16:10:29 +02:00
ptitSeb 1e8807ac0a [BOX32][TRACE] Added a warning when executing 32bits code in 64bits address space 2024-09-16 16:09:11 +02:00
ptitSeb 40ac1bca84 [BOX32] Partial handling of wrapped dl_iterate_phdr 2024-09-16 15:31:46 +02:00
ptitSeb bff3b935fb Better handling of argv[0] 2024-09-16 15:30:39 +02:00
ptitSeb 9faa9f41e0 [ARM64_DYNAREC] Fixed most CD xx opcodes 2024-09-15 15:22:35 +02:00
ptitSeb 9fa43f2386 Added a hack so program that wprintf to the console actualy work if box64 already printed something 2024-09-14 17:36:45 +02:00
ptitSeb f2397256e2 [BOX32][WRAPPER] Added more 32bits sdl1 and libc symbols 2024-09-14 16:46:13 +02:00
ptitSeb e5ad7c36ec [BOX32][ELFLOADER] Fixed some issue with symbol resolver 2024-09-14 16:45:44 +02:00
ptitSeb 3b8ba5dfa6 Added 66 F3 0F BD opcode ([ARM64_DYNAREC] Too) 2024-09-14 15:21:15 +02:00
ptitSeb 2e1b58a876 [BOX32] Added a few libc 32biyts wrapped functions 2024-09-14 11:37:22 +02:00
ptitSeb de7baa0b41 [BOX32] Added (mostly untested) wrapped libGL and minimum SDL1 (SDLgears and zsnes works) 2024-09-14 10:26:38 +02:00
ptitSeb b361a0d2ff Fixed flags for AVX.0F38 F2 opcode ([ARM64_DYNAREC] too) 2024-09-14 08:46:23 +02:00
Yang Liu 0acd849f18 [RV64_DYNAREC] Added 1 more opcode for vector and some refactor and fixes too (#1824) 2024-09-13 12:16:09 +02:00
ptitSeb ed4ff15682 [BOX32][TRACE] More improved trace for some 32bits functions call 2024-09-13 12:09:35 +02:00
ptitSeb de276ddfa9 [BOX32][TRACE] Better trace for 32bits call to strtol and strtoul 2024-09-13 11:19:47 +02:00
ptitSeb 192347ea3a [BOX32] More small 32bits signature adjustments 2024-09-13 11:19:12 +02:00
ptitSeb d618cfdf0e [BOX32][TRACE] Better trace for 32bits strncasecmp calls 2024-09-13 11:15:44 +02:00
ptitSeb 0f0762a24c [BOX32] Added one more wrapped 32bits libc function 2024-09-13 11:12:41 +02:00
ptitSeb 89a49db558 [BOX32] Adjusted some 32bits wrapped functions 2024-09-13 11:08:40 +02:00
ptitSeb 1ee51a54de [BOX32][TRACE] Better trace for some 32bits wrapped function calls 2024-09-13 11:08:10 +02:00
ptitSeb 68f394a38b [TRACE] Better trace for 32bits FF 52 opcode 2024-09-13 11:07:31 +02:00
ptitSeb 32c94ac31a [BOX32] Fixed 32bits wrapped localeconv (for #1780) 2024-09-13 10:58:10 +02:00
ptitSeb af476e0d10 [BOX32] Fixed gethostbyname 32bits wrapped function (for #1780 but still crashing) 2024-09-13 10:47:47 +02:00
JunChi1022 b504d07afe [DYNAREC] fix page calculation error (#1822) 2024-09-12 19:04:28 +02:00
Yang Liu 9544fbdff9 [RV64_DYNAREC] Refactored vector SEW tracking (#1820) 2024-09-12 19:03:00 +02:00
Yang Liu 431365d1f8 [RV64_DYNAREC] Fixed a typo on vector_sew initialization (#1819) 2024-09-12 14:14:54 +02:00
ptitSeb 693b4adb4b [STATIC] Forgot this definition 2024-09-12 14:07:15 +02:00
ptitSeb 1a637cb1d8 Fixed a typo 2024-09-12 14:01:53 +02:00
ptitSeb 0d952641ed [STATIC] Try to fix static build 2024-09-12 13:56:52 +02:00
ptitSeb 418e2a00ce [BOX32] Simplified 32bits old pthread cond functions 2024-09-12 10:32:33 +02:00
ptitSeb d1d2de33e6 [WRAPPER] Added handling of old pthread cond functions 2024-09-12 10:32:11 +02:00
ptitSeb ab84faa3ca [WRAPPER] Added 1 wrapped function to glibc2 2024-09-12 10:31:29 +02:00
ptitSeb fc7f83c60b [BOX32][WRAPPER] Added support for old pthread_kill (fixing hanging steamcmd) 2024-09-11 18:01:23 +02:00
ptitSeb af028c9bad [WRAPPER] Small fixes for x86_64 build when using old pthread_kill 2024-09-11 18:00:45 +02:00
ptitSeb 29daae551c [BOX32] Improved 32bits unsupported syscall warning, and added syscall 240 2024-09-11 16:55:42 +02:00
ptitSeb e1a91ea420 [BOX32] Improved trace for 32bits pthread_setname_np 2024-09-11 16:54:17 +02:00
ptitSeb bd60ed8df0 [BOX32] Improved hash<->64bits handling 2024-09-11 16:53:51 +02:00
Yang Liu 6b6d20732e [RV64_DYNAREC] Added more 0F opcodes for vector (#1817) 2024-09-11 14:26:50 +02:00
Yang Liu 4d60b75240 [RV64_DYNAREC] Added more 0F opcodes for vector and optimized some opcodes too (#1816)
* [RV64_DYNAREC] Optimized 66 0F 67 PACKUSWB opcode

* [RV64_DYNAREC] Optimized 66 0F 6C PUNPCKLQDQ opcode

* [RV64_DYNAREC] Added some 0F opcodes for vector

* review
2024-09-11 10:25:04 +02:00
Yang Liu fc9900c8f6 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1815)
* [RV64_DYNAREC] Added more 66 0F opcodes for vector

* [RV64_DYNAREC] Fixed PACKUSWB for vlen >= 256
2024-09-10 21:11:58 +02:00
Aidan 629346b6a7 [SDORYON1] Oryon1 (Snapdragon Elite) support (#1786) 2024-09-10 19:57:36 +02:00
ptitSeb e95be7cd3f Improved legendary stability 2024-09-10 19:21:15 +02:00
ptitSeb 1bfb50f29a [WRAPPER] Updat generated wrapper files 2024-09-10 19:20:43 +02:00
rajdakin 8187c35ea8 [WRAPPERS] Fixed some wrong wrappings (#1814) 2024-09-10 17:46:10 +02:00
rajdakin 0d6028d837 [WRAPPERHELPER] Added per-arch override, always include 'stdc-predef.h', better parsing (#1813) 2024-09-10 17:25:37 +02:00
ptitSeb 2127eaea22 [BOX32] Put back pthread_t behind hash, but ease hash range to have more native values 2024-09-10 16:55:25 +02:00
ptitSeb 7794a623aa [BOX32] Fix and simplified 32bits threads handling 2024-09-10 15:10:28 +02:00
ptitSeb 0443edc034 [BOX32] Fixed wrapping 32bits version of __cxa_finalize 2024-09-10 15:09:45 +02:00
ptitSeb a7f8dbac56 [WRAPPER] Minors adjustments to pulse audio wrapping 2024-09-10 11:25:07 +02:00
Yang Liu b0ec124329 [RV64_DYNAREC] Added 66 0F D4 PADDQ opcode for vector and fixes SEW cache transform (#1812)
* [RV64_DYNAREC] Added 66 0F D4 PADDQ opcode for vector

* [RV64_DYNAREC] Transform SEW cache after fpu cache
2024-09-10 10:52:04 +02:00
ptitSeb b40121c9b0 [VULKAN] Added missing wrapper for vkCreateSamplerYcbcrConversionKHR 2024-09-10 10:43:54 +02:00
ptitSeb cc9984a082 Fixed alignement of thread funcitons (fixed regression for #1810) 2024-09-10 10:32:45 +02:00
Yang Liu c22758d794 [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1811) 2024-09-10 08:58:22 +02:00
ptitSeb 1b48cd157a [RCFILE] Slightly changed how BOX64_ARGS behave, and added BOX64_INSERT_ARGS 2024-09-09 19:45:48 +02:00
ptitSeb 362402ffbf Improved wrapped function clone handling of CLONE_NEWUSER flag 2024-09-09 17:11:29 +02:00
ptitSeb 5ce868b100 When showing opcode on SEGFAULT/SIGBUS, show if it's x86 or x64 2024-09-09 17:10:04 +02:00
ptitSeb 823d1cc004 [DYNAREC] Simplified a bit getX64Address utility function 2024-09-09 17:07:16 +02:00
ptitSeb 2ce5beae56 [WRAPPER] Added H as paramterand, added 2 wrapped function from libatomic (for linux BeamNG) 2024-09-09 17:03:46 +02:00
ptitSeb 34fcbbd7b7 [TRACE] Better trace for F3 0F 1E FA opcode 2024-09-09 16:02:37 +02:00
ptitSeb bdde96be95 [ARM64_DYNAREC] Added 64 0F 28/29 opcodes 2024-09-09 16:02:04 +02:00
rajdakin 26b7a49d82 [WRAPPERHELPER] Fixed preprocessor logic, moved type validation to machine (#1808) 2024-09-08 22:26:35 +02:00
ptitSeb fa8a5a2033 [WRAPPER] Added 2 wrapped function to libatomic 2024-09-08 17:25:58 +02:00
rajdakin c87a56ef37 [WRAPPERHELPER] Major enhancements in output quality, allow for generic type mapping (#1807) 2024-09-08 16:43:16 +02:00
rajdakin 2e04ff93ca [WRAPPED] Fixed some libc wrapped functions (#1806)
* [WRAPPED] Fixed some libc wrapped functions

* [WRAPPED] Fixed static build, added back

* [WRAPPED] Fixed unlimited wrapping

* [WRAPPED] Forgot to update
2024-09-08 15:10:45 +02:00
ptitSeb a9f96b9d62 Show x86opcode at segfault if segfault address is not pc 2024-09-08 15:06:54 +02:00
ptitSeb 8f855f5dde [ARM64_DYNAREC] Avoid computing flags if they are just recomputed at jump point 2024-09-08 14:18:03 +02:00
ptitSeb 6d3fa25d5f [ARM64_DYNAREC] Small optim for 0F C6 opcode 2024-09-08 14:03:47 +02:00
ptitSeb 57b7bcf8f4 [WRAPPING] Updated gtk3 wrapping (still more work to do) 2024-09-08 10:02:39 +02:00
rajdakin f30d75ae5d [WRAPPERHELPER] General improvements (#1804)
* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support

* [WRAPPERHELPER] Keep comments untouched
2024-09-07 20:53:51 +02:00
ptitSeb e087e7782c [WRAPPER] Fixed some OpenGL function signatures 2024-09-07 19:06:04 +02:00
ptitSeb 17fa93035a Added some more wrapeed function to libusb1 (for #1802) 2024-09-07 15:48:22 +02:00
rajdakin f0d7582845 Upgraded the wrapper helper (#1803)
* [WRAPPERHELPER] Fixed unsigned comparison in macros, added macro expanding in include commands, added -I option

* [WRAPPERHELPER] Forgot the README
2024-09-07 15:20:17 +02:00
ptitSeb 75bdb32828 Added a small fix in signe handler ucntx construction 2024-09-07 11:59:34 +02:00
ptitSeb fd633d2cee Allow dynarec_dump=2 and forbid dynarec_test=2 (fixed a regression with command line params) 2024-09-07 09:40:50 +02:00
ptitSeb a6d7d83fb3 Added a workaround with syscall if statx function is not defined in libc 2024-09-07 09:20:45 +02:00
ptitSeb a450b9d12f [ARM64_DYNAREC] Improved AVX.66.0F38 8C opcode 2024-09-06 18:01:40 +02:00
ptitSeb 5ac3eeef11 Fixed name of opcode in comment 2024-09-06 18:00:00 +02:00
ptitSeb 9838c2ccff Fixed a typo 2024-09-06 17:59:38 +02:00
ptitSeb 16cee6feb2 Added 1 wrapped function libxkbcommon 2024-09-06 16:13:35 +02:00
rajdakin 21c86f9ac6 [WRAPPED] Update libc wrappers (#1800)
* [WRAPPED] Fixed some issues in libc_private.h and the wrapper generator

* [WRAPPED] Forgot to run the Python script

* [WRAPPED] Oops
2024-09-06 15:08:01 +02:00
rajdakin 6044feb7fd Wrapper helper (#1799)
* [WRAPPERHELPER] Added wrapperhelper v0.1, tested on libc

* [WRAPPED] Removed updates to libc from this branch

* [WRAPPERHELPER] Removed GPL header and added modified LGPL header, added notes about licensing issues
2024-09-06 15:07:38 +02:00
Yip Coekjan 7dc59ac342 Eliminate duplicate hash calculations for getSymbolInSymbolMaps (#1801) 2024-09-06 14:35:32 +02:00
ptitSeb 16f156be3f Added 1 wrapped function to libgdk3 2024-09-06 10:59:03 +02:00
rajdakin 64dd09becc [WRAPPED] Removed GOS, renamed GODW into GOWD (#1797) 2024-09-05 20:26:45 +02:00
ptitSeb 19dc18f7c5 Fixed a regression introduced with box32 that broke Bladur's Gate 3 (and probably a few other) 2024-09-05 19:12:19 +02:00
Yang Liu 4e63b82f5e [CI] Refactored CI (#1795)
* [CI] Enable Box32 tests on LA64

* upgrade QEMU

* [COSIM] Removed thread-safe tests

* Use regular cosim in CI

* [CI] Simplified "Test Box64"

* exclude certain tests when testing with cosim

* review

* box64.pod too
2024-09-05 11:07:27 +02:00
ptitSeb 6bc2abae3b [ARM64_DYNAREC] Added 67 66 0F 7E opcode 2024-09-04 21:04:20 +02:00
ptitSeb 6c7f306baa [ARM64_DYNAREC] Added AVX.66.0F 51 opcode 2024-09-04 20:56:23 +02:00
ptitSeb c56517b801 More work on Custom Mem speedup 2024-09-04 17:45:28 +02:00
ptitSeb b5e405b2b4 Added an rbtree is Custom Mem Manager to speedup customFree and customRealloc 2024-09-04 15:23:37 +02:00
ptitSeb 354f46f41b Some refactor (and small bugfixes) around Custom Mem Manager 2024-09-04 14:39:44 +02:00
Yang Liu b34a50b381 [X64LIBS] Changed x86/x64 libs install directory to prevent conflicts (#1791)
* [X64LIBS] Changed x86/x64 libs install directory to prevent conflicts

* Update pressure_vessel
2024-09-04 14:13:58 +02:00
ptitSeb a973c53ea2 [BOX32] This should fix NO_ALIGN box32 build 2024-09-04 11:28:11 +02:00
ptitSeb ee7b10f064 [BOX32] Small improvments on memory management 2024-09-04 11:00:43 +02:00
Yang Liu c1ad6b5829 [CI] Speedup CI by removing some unnecessary targets (#1790) 2024-09-04 09:59:27 +02:00
ptitSeb 9eaaaaa1e3 [BOX32] Added some more 32bits wrapped function to libc 2024-09-03 20:19:34 +02:00
ptitSeb 115707a0f1 [BOX32] Fixed a missing box_free 2024-09-03 20:19:34 +02:00
ptitSeb 3179357666 [BOX32] Better trace for 32bits posix_memalign 2024-09-03 20:19:34 +02:00
ptitSeb cb7433d70a [RCFILE] Fixed some missing box_free/box_strdup in rcfile 2024-09-03 20:19:34 +02:00
ptitSeb 62021fc291 [BOX32] Better log for 32bits pointer conversion error 2024-09-03 20:19:34 +02:00
ptitSeb ab3ff07c93 [BOX32] Fixed 32bits locale memory size 2024-09-03 20:19:34 +02:00
Yang Liu 22ab62a729 [WRAPPED] Added back some libc function wrappers (#1788) 2024-09-03 12:50:02 +02:00
ptitSeb ff7a8bfdae [BOX32] Various small fixes 2024-09-02 09:53:36 +02:00
Yang Liu 27ed109394 [BOX32] Fixed build with mold (#1785) 2024-09-01 20:58:10 +02:00
rajdakin ea807eda04 [WRAPPED] Merged types D/K and Y/y in 64bits wrapped libs (#1784)
* [WRAPPED] Merged types D/K and Y/y in 64bits wrapped libs

* [WRAPPERS] Version bump

* [WRAPPED] Fixed wrapped glib2 on non-LD80BITS builds
2024-09-01 19:06:03 +02:00
JunChi1022 36321f809d [DYNAREC]: fix BICS encoding (#1783) 2024-09-01 17:58:18 +02:00
ptitSeb 254df70148 [BOX32] Better handling for FILE* 2024-09-01 17:44:32 +02:00
ptitSeb 759cef6e01 [BOX32] Fixes and hacks to get steamcmd shows the prompt 2024-09-01 17:09:54 +02:00
ptitSeb 02364151bc [BOX32] Some fixes to strtol/strtoul and read 32bits wrapped functions 2024-09-01 13:59:51 +02:00
ptitSeb 9178effd9f [BOX32] More wrapped function and a few fixes for steamclient.so (still crashing) 2024-09-01 13:07:47 +02:00
ptitSeb cce9e280ce [BOX32] New batch of 32bits wrapped functions for steamconsole.so 2024-08-31 17:30:22 +02:00
ptitSeb 5468d8b08e [BOX32] One more 32bits wrapped function for libvstdlib_s.so 2024-08-31 17:20:01 +02:00
ptitSeb 497f629761 [BOX32] Another batch of 32bits wrapped function, for libvstdlib_s.so this time 2024-08-31 15:59:48 +02:00
ptitSeb 6f08601479 [BOX32] Another batch of 32bits wrapped function, for libtier0_s.so 2024-08-31 14:52:45 +02:00
ptitSeb 6d6739ccea [BOX32] More 32bits wrapped functions 2024-08-31 11:39:55 +02:00
ptitSeb d2511e66fb [RCFILE] Added support fro cursor (for #1778) 2024-08-31 09:05:36 +02:00
Yang Liu e23eb14809 [RV64_DYNAREC] Added xthead* extensions to the new printer (#1781) 2024-08-31 07:47:28 +02:00
Yang Liu f5dbe2156c [RV64_DYNAREC] Refactored rv64_printer (#1779)
* [RV64_DYNAREC] Refactored printer

* Fixed one more issue
2024-08-30 20:32:15 +02:00
ptitSeb 723b94da05 [BOX32] More 32bits wrapped function and fixes 2024-08-30 18:54:16 +02:00
ptitSeb 7ecdced486 [BOX32] Added more 32bits wrapped function and fixes 2024-08-30 15:59:07 +02:00
ptitSeb 13b72df762 [BOX32] Define native_statvfs to avoid build errors 2024-08-30 13:50:37 +02:00
Yang Liu 95b38b7f79 [CI] Added 60s timeout per test (#1777) 2024-08-30 13:24:15 +02:00
ptitSeb 3fb5052223 [BOX32] More 32bits wrapped functions and fixes 2024-08-30 13:22:48 +02:00
Yang Liu 62b93a0785 Wrapped 1 more function for libxcb (#1776) 2024-08-30 12:30:23 +02:00
ptitSeb 371b45c420 [BOX32] Added detection of steam and steamcmd 2024-08-30 10:13:42 +02:00
ptitSeb 4dcf14d026 [ARM64_DYNAREC] Added 67 F3 0F 38 F6 opcode (for #1775) 2024-08-30 10:02:49 +02:00
ptitSeb 854ee95d69 Added 67 F3 0F 38 F6 opcode (for #1775) 2024-08-30 09:58:42 +02:00
ptitSeb 9ac536a1dd [BOX32] More fixes to ctype_b_loc and added a few more wrapped functions 2024-08-29 18:17:57 +02:00
Yang Liu 9820bee5e7 [BOX32][LA64_DYNAREC] Added preliminary box32 support (#1773) 2024-08-29 17:16:39 +02:00
ptitSeb b02302a5cf [BOX32] Fixed 32bits localtime_r wrapped function 2024-08-29 16:32:14 +02:00
ptitSeb 9633ad35a8 [BOX32] Added more 32bits wrapped function and more fixes 2024-08-29 16:30:39 +02:00
ptitSeb 4bd6294862 [TRACE] Added one 32bits jump decoding dest address 2024-08-29 16:30:09 +02:00
ptitSeb 63e525697f [BOX32][TRACE] Improve function trace log 2024-08-29 16:29:21 +02:00
ptitSeb 4cdd46819f [TRACE] Improved trace on symbol name 2024-08-29 11:10:45 +02:00
Yang Liu 0450371e28 [RV64_DYNAREC] Fixed a falsy optimization, better EMIT macro (#1769) 2024-08-28 23:06:29 +02:00
Yang Liu d9e5f8183f [RV64_DYNAREC] Optimized jump_to_next using XTheadBb instructions (#1768)
* [RV64_DYNAREC] Optimized jump_to_next using XTheadBb instructions

* fixed some bad bad typos
2024-08-28 23:05:02 +02:00
Yang Liu abbaf9b593 [BOX32][RV64_DYNAREC] Fixed more issues and enable CI for box32 (#1767)
* [BOX32][RV64_DYNAREC] Fixed more issues

* fix

* fix

* enable Ci for box32

* add some comments
2024-08-28 19:48:22 +02:00
ptitSeb 126c59b4a4 [BOX32] More wrapped 32bits functions, and some fixes too 2024-08-28 18:35:24 +02:00
ptitSeb b7be225846 [BOX32] More 32bits wrapped functions 2024-08-28 17:12:00 +02:00
ptitSeb 041eb4e69d [BOX32] Adding some more 32bits wrapped functions 2024-08-28 15:03:16 +02:00
ptitSeb 04157f2502 [ARM64_DYNAREC] Not using simpleWrapper when dynarec_test is on 2024-08-28 15:02:48 +02:00
Yang Liu 189222cb66 [BOX32][RV64_DYNAREC] Added preliminary box32 support to RV64 (#1766)
* [BOX32][RV64_DYNAREC] Added preliminary box32 support to RV64

* fix

* fix fix

* fix
2024-08-28 14:01:50 +02:00
ptitSeb 6835c4aaf5 [BOX32] Fixed some error log in elfloader32 2024-08-28 12:44:53 +02:00
Yang Liu 875a2ef3a9 [RV64_DYNAREC] Added a fast path for some 16bit opcodes (#1765) 2024-08-27 20:23:42 +02:00
ptitSeb bfbf18688b [ARM64_DYNAREC] Small refactor around get_segdata usage 2024-08-27 18:57:36 +02:00
Yang Liu 9de694c46b [RV64_DYNAREC] Added a fast path for some 8bit opcodes (#1763)
* [RV64_DYNAREC] Added a fast path for some 8bit opcodes

* fix

* more

* more
2024-08-27 18:55:11 +02:00
KreitinnSoftware 220c5ee47d [CTEST] Use BOX64_LD_LIBRARY_PATH instead of default LD_LIBRARY_PATH (#1764) 2024-08-27 18:34:58 +02:00
ptitSeb 99f2207fd4 [ARM64_DYNAREC] Mark new upper YMM part as new, so the can be unwind too (for #1759) 2024-08-27 10:57:51 +02:00
KreitinnSoftware 50623f32f6 Revert "[ANDROID] Not use 'libbsd.so' as needed lib and don't define NEEDED_L…" (#1762)
This reverts commit a7c61d8e20.
2024-08-27 08:37:40 +02:00
b5105a1e57 Added preliminary Box32 support (#1760)
* Improve the ReserveHigMemory helper function

* [BOX32] Added some wrapping infrastructure

* [BOX32] More wrapped 32bits lib infrastructure

* [BOX32] Added callback and tls 32bits handling

* [BOX32] Added more 32bits, around wrappers and elfs

* [BOX32] Added the 32bits version of myalign

* [BOX32] More wrapped libs and 32bits fixes and imrpovments

* [BOX32] Added some 32bits tests

* [BOX32] Try to enable some Box32 build and test on the CI

* [BOX32] Disable Box32 testing on CI platform that use qemu

* [BOX32] Another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Small fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Yet another fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Fixed a typo in CI script

* [BOX32] Better scratch alighnment and enabled more tests

* [BOX32] Added (partial) wrapped 32bits librt

* [BOX32] Added mention of Box32 in README

* [BOX32] Added phtread handling, and numerous fixes to 32bits handling. [ARM64_DYNAREC] Fixed access to segment with negative offset

* [BOX32] Added system libs and cpp testing, plus some more fixes

* [BOX32] Fix previous commit

* [BOX32] Better stack adjustment for 32bits processes

* [BOX32] Added getenv wrapped 32bits function and friends

* [BOX32] Don't look for box86 for a Box32 build

* [BOX32] Don't do 32bits cppThreads test for now on CI

* [BOX32] Enabled a few more 32bits tests

* [BOX32] For ld_lib_path for both CppThreads tests

* [BOX32] [ANDROID] Some Fixes for Android Build

* [BOX32] Still need to disable cppThread_32bits test on CI for some reason

* [BOX32] [ANDROID] Don't show PreInit Array Warning (#1751)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to … (#1752)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to push before

* [BOX32] [ANDROID] Try to Create __libc_init

* [BOX32] [ANDROID] Try to disable NEEDED_LIBS for now (libdl is not wrapped)

* [BOX32] Updated generated files

* [BOX32] Added 32bits context functions

* [BOX32] Added 32bits signal handling

* [BOX32] Added some missing 32bits elfloader functions

* [BOX32] Fix build on x86_64 machine

* [BOX32] Better fix for x86_64 build

* [BOX32] Actually added missing libs, and re-enabled cppThreads_32bits test

* [BOX32] Added wrapped 32bits libdl

* [BOX32] Try to re-enabled Box32 test on CI for ARM64 builds

* [BOX32] fine-tuning Box32 test on CI for ARM64 builds

* [BOX32] More fine-tuning to Box32 test on CI for ARM64 builds

* [BOX32] Enabled Box32 test on CI for LA64 and RV64 builds too

* [BOX32] re-Disabled Box32 test on CI for LA64 and RV64 builds, not working for now

* [BOX32] Temporarily disabled cppThreads_32bits test on CI

---------

Co-authored-by: KreitinnSoftware <[email protected]>
Co-authored-by: KreitinnSoftware <[email protected]>
2024-08-26 17:45:13 +02:00
WANG Guidong 9beb745765 [RV64_DYNAREC] Fix some typos in docs and dynarec/rv64 (#1758)
* [Typo] fix some typo in docs and dynarec/rv64

* [Typo] fix some typo in docs and dynarec/rv64

* [Typo] fix some typo in dynarec/rv64

* [Typo] fix some typo in dynarec/rv64

* [Typo] fix some typo in docs
2024-08-26 08:19:06 +02:00
KreitinnSoftware 0b1dd757be [EMU] [ARM64_DYNAREC] Fix Some Warnings on Clang Compilers (#1757) 2024-08-26 08:15:55 +02:00
KreitinnSoftware a7c61d8e20 [ANDROID] Not use 'libbsd.so' as needed lib and don't define NEEDED_LIBS_234 for Android Too, Use BOX64_LD_LIBRARY_PATH instead of LD_LIBRARY_PATH on CTEST (#1754)
* [ANDROID] Not use 'libbsd.so', 'libpthread.so' as needed libs and don't define NEEDED_LIBS_234 for Android Too

* [ANDROID] Use 'libpthread.so' again

* [CTEST] Try to use BOX64_LD_LIBRARY_PATH instead of LD_LIBRARY_PATH
2024-08-25 19:53:09 +02:00
Yang Liu 4988fb27dc [RV64_DYNAREC] Fixed more issues in the vector infrastructure (#1755)
* [RV64_DYNAREC] Fixed SEW transformation for vector

* more tweaks

* more fixes

* More fixes

* more fixes

* re-enable vector extension by default
2024-08-25 19:52:50 +02:00
ptitSeb db1f0825ce Merge pull request #1750 from ksco/fix
[RV64_DYNAREC] Fixed various issues in vector infra
2024-08-24 21:03:55 +02:00
Yang Liu c7b2a5f2df More fixes 2024-08-25 02:24:57 +08:00
Yang Liu b9cbd29bc4 Try to fix SSE type transformation 2024-08-24 19:27:57 +08:00
Yang Liu 84b53ecb42 [RV64,LA64_DYNAREC] Remove useless #if directives 2024-08-20 13:49:01 +08:00
ptitSeb 66da28a02f Merge pull request #1746 from ksco/disable_vector
[RV64_DYNAREC] Disable vector extension by default until it's ready
2024-08-19 14:36:26 +02:00
Yang Liu 15f6bbebe1 [RV64_DYNAREC] Disable vector extension by default until it's ready. 2024-08-19 20:10:02 +08:00
ptitSeb 2daef545dd Forgot to expose adx extension in cpuinfo virtual file 2024-08-19 10:57:03 +02:00
ptitSeb aac6b3d02d Forgot to expose f16c, xsave and randr extensions in cpuinfo virtual file 2024-08-19 10:46:13 +02:00
ptitSeb fda0e9a4cb Merge branch 'box32' into main 2024-08-18 16:02:27 +02:00
ptitSeb f1da5d433a [RV64_DYNAREC] Set the log level to Info for the LOCK CMPXCHG16B warning, to avoid breaking winetricks 2024-08-18 15:57:14 +02:00
ptitSeb dead2003fa [HACK] Patch Heroic 2.15.1 to avoid some internal memory manager test, until a better solution is found (heroic is still a bit unstable) 2024-08-18 10:46:15 +02:00
Yang Liu 44dfa53d45 warn only once 2024-08-18 10:46:15 +02:00
Yang Liu 769a9f65a9 Slightly improved LOCK CMPXCHG16B opcode 2024-08-18 10:46:15 +02:00
Yang Liu 5b78159cb5 [RV64_DYNAREC] Added a warning on LOCK CMPXCHG16B opcode 2024-08-18 10:46:15 +02:00
ptitSeb c384d53d75 [HACK] Patch Heroic 2.15.1 to avoid some internal memory manager test, until a better solution is found (heroic is still a bit unstable) 2024-08-18 10:16:38 +02:00
ptitSeb 683e44baf9 [BOX32] Added 32bits elf reloc type rel handling 2024-08-17 16:59:55 +02:00
ptitSeb c845d0cf81 [BOX32] Added 32bits elf alloc and load 2024-08-17 15:59:09 +02:00
Yang Liu 243a4deae7 warn only once 2024-08-17 15:57:48 +02:00
Yang Liu fe80d6305c Slightly improved LOCK CMPXCHG16B opcode 2024-08-17 15:57:48 +02:00
Yang Liu a0e7113397 [RV64_DYNAREC] Added a warning on LOCK CMPXCHG16B opcode 2024-08-17 15:57:48 +02:00
ptitSeb d47b1b0e56 [BOX32] Added 32bits elf header parser and dumper 2024-08-17 14:25:04 +02:00
ptitSeb fa87b0fcef [BOX32] prepare elfheader_t structure for 32bits elfs 2024-08-17 12:24:26 +02:00
Yang Liu 0f1bce0f32 [RV64_DYNAREC] Added more opcodes (#1740)
* [RV64_DYNAREC] Added more opcodes

* more opcodes

* more
2024-08-16 18:47:21 +02:00
Yang Liu bc0b5b1181 [LA64_DYNAREC] Port recent RV64 fixes (#1739) 2024-08-16 18:47:21 +02:00
Yang Liu 38833b9cf4 Added more curl function wrapper (#1738) 2024-08-16 18:47:21 +02:00
Yang Liu dda4f48397 [RV64_DYNAREC] Added 66 0F 3A 63 PCMPISTRI opcode (#1735) 2024-08-16 18:47:21 +02:00
Yang Liu bb712b1ad5 Added 1 more gtk3 function wrapper (#1737) 2024-08-16 18:47:21 +02:00
Yang Liu 6ddb5b3477 [RV64,LA64_DYNAREC] Small change when handling long CC INT 3 opcode (#1736) 2024-08-16 18:47:21 +02:00
Yang Liu c4253b73fa [RV64_DYNAREC] Added more opcodes (#1740)
* [RV64_DYNAREC] Added more opcodes

* more opcodes

* more
2024-08-16 18:16:20 +02:00
Yang Liu 3c1f6c2436 [LA64_DYNAREC] Port recent RV64 fixes (#1739) 2024-08-16 12:10:17 +02:00
Yang Liu 83484cfb60 Added more curl function wrapper (#1738) 2024-08-16 12:09:26 +02:00
Yang Liu a106082397 [RV64_DYNAREC] Added 66 0F 3A 63 PCMPISTRI opcode (#1735) 2024-08-16 12:09:00 +02:00
Yang Liu 6498248cef Added 1 more gtk3 function wrapper (#1737) 2024-08-16 12:08:53 +02:00
ptitSeb b2f94b274c [BOX32] Start differentiate 64bits from 32bits in elf parser 2024-08-16 10:56:47 +02:00
ptitSeb 34b85b3560 Detect 32bits elf before loading 2024-08-16 10:52:36 +02:00
Yang Liu 7bb30efb50 [RV64,LA64_DYNAREC] Small change when handling long CC INT 3 opcode (#1736) 2024-08-15 20:14:33 +02:00
ptitSeb 7df2b6b252 Added BOX32 option to CMakeList.txt 2024-08-15 15:50:16 +02:00
ptitSeb 017d13a7b0 [ARM64_DYNAREC] Small change when handling lone CC INT 3 opcode 2024-08-15 15:46:19 +02:00
ptitSeb 513647b272 Added syscalls 444-446 2024-08-15 15:45:50 +02:00
ptitSeb 280b1576c3 [ARM64_DYNAREC] Added AVX.66.0F38 A6 opcode 2024-08-15 14:07:51 +02:00
ptitSeb 2dfd449561 [ARM64_DYNAREC] Added 67 90..97 opcodes 2024-08-15 14:00:34 +02:00
ptitSeb 65b1b9256a Fixed falsly detection of needed memory hack 2024-08-15 14:00:02 +02:00
ptitSeb 7866f116df [TRACE] Better trace for libc syscall 2024-08-15 13:59:18 +02:00
ptitSeb 4544e1556a Added syscalls 122-124 2024-08-15 13:58:46 +02:00
Yang Liu 8c7d96ad63 [RV64_DYNAREC] Fixed extcacheUnwind regression (#1734) 2024-08-15 10:17:27 +02:00
ptitSeb bd23e1f7fc [RCFILE] Fine tuned profile for on of the EALauncher process 2024-08-12 21:23:30 +02:00
ptitSeb 99187a2d22 Added (fake) syscall 175 to libs syscall 2024-08-12 21:22:23 +02:00
Yang Liu 8974caf162 [RV64_DYNAREC] Fixed 0F BA /5 BTS opcode (#1733) 2024-08-12 21:09:19 +02:00
xctan f364c03964 [RV64_DYNAREC] More fixes (#1732)
* [RV64_DYNAREC] Fixed pending flag type in emit_sar16

* [RV64_DYNAREC] Fixed imm12 overflow in geted

* [SYSCALL] Added fake sys_init_module
2024-08-12 20:11:19 +02:00
ptitSeb 730eb1f472 [ARM64_DYNAREC] Some small improvments to ROR/ROL/RCR/RCL opcodes 2024-08-11 14:56:13 +02:00
ptitSeb 3760be946f [WRAPPER] Wrapped libdrm_amdgpu.so.1 2024-08-10 20:04:56 +02:00
Yang Liu 7db74b84cf [RV64_DYNAREC] Fixed flags for shrd/shld with constant 0 shift (#1730) 2024-08-10 10:51:56 +02:00
xctan 4c0a25db2a [RV64_DYNAREC] Fixed ROL/ROR RCX, CL (#1729) 2024-08-10 10:51:44 +02:00
ptitSeb 67af8c2bad Added 67.AVX.0F.66 D6 opcode ([ARM64_DYNAREC] too) 2024-08-10 09:58:42 +02:00
ptitSeb 92531929f3 Added 64bits 67 F3 0F 7F opcode ([ARM64_DYNAREC] too) 2024-08-10 09:50:11 +02:00
ptitSeb 0256a6332c [ARM64_DYNAREC] Fixed flags for surd/shld with constant 0 shift 2024-08-10 09:40:05 +02:00
ptitSeb bd4454d8ad [ARM64_DYNAREC] Fixed pending flags for large 8 & 16 bit const shifts 2024-08-10 09:34:09 +02:00
xctan 4187581be5 [RV64_DYNAREC] Fixed pending flags for large 8 & 16 bit const shifts (#1728) 2024-08-10 09:17:02 +02:00
Yang Liu 2a07636623 [RV64_DYNAREC] Fixed more register conflicts (#1726) 2024-08-09 20:16:52 +02:00
ptitSeb 8893344b76 Fix non-Dynarec build 2024-08-09 18:17:16 +02:00
ptitSeb f0ea65dc36 [DOCS] Added entry in USAGE.md for newly introduced BOX64_ARGS 2024-08-09 17:44:05 +02:00
ptitSeb 53756ee966 Improved Steam wine compatibility, not perfect, but better (thanks Hugo for the args) 2024-08-09 17:41:01 +02:00
xctan 8a2ee1ed59 [RV64_DYNAREC] Fixed OF generation in emit_sar16c (#1724) 2024-08-09 17:31:13 +02:00
ptitSeb 9bc9c10fb3 [ARM64_DYNAREC] Added AVX.66.0F38 9A opcode 2024-08-09 14:30:32 +02:00
Yang Liu 4407a17551 [RV64_DYNAREC] Fixed fpu_flags handling and enabled cosim in CI (#1722)
* [RV64_DYNAREC] Fixed fpu_flags handling

* repeat until-pass
2024-08-09 13:31:58 +02:00
xctan c7d6395aa6 [RV64_DYNAREC] Fixed misused BNE_NEXT in emit_ro{l,r}32 (#1723) 2024-08-09 13:29:37 +02:00
Yang Liu 649a65b8ee [RV64_DYNAREC] Fixed FNSTSW opcode (#1721) 2024-08-09 12:03:20 +02:00
Yang Liu 949b64ca53 [DYNAREC_RV64] Removed TODOs on GETEX and GETEM macros (#1720) 2024-08-09 12:02:14 +02:00
xctan cef906b24d [RV64_DYNAREC] Fixed register conflict in the GETSEB marco (#1719) 2024-08-09 09:25:27 +02:00
xctan 040c2c3d1b [RV64_DYNAREC] Fixed register conflict with GETEB macro (#1718) 2024-08-08 17:29:56 +02:00
Yang Liu 91ed6a83c1 [INTERP] Fixed some undefined behaviour (#1717) 2024-08-08 17:05:00 +02:00
Yang Liu d8ac8a5f1c [LA64_DYNAREC] Fixed flag generation in IMUL/MUL opcode (#1716) 2024-08-08 08:27:35 +02:00
xctan 18954abf54 [RV64_DYNAREC] Fixed flag generation in IMUL/MUL opcode (#1715) 2024-08-08 08:25:05 +02:00
ptitSeb ed7ee12e7e [GTK] Added wrapped GstVideoBufferPool 2024-08-07 15:11:31 +02:00
ptitSeb 42d99d2b2a [ARM64_DYNAREC] Added AVX.F3.0F38 F7 opcode 2024-08-07 10:26:17 +02:00
ptitSeb d24f13cd73 Small optimisation on xsave / xrstor helper 2024-08-07 10:13:43 +02:00
ptitSeb e8fad11128 [ARM64_DYNAREC] Added F0 20 opcode 2024-08-04 09:48:18 +02:00
ptitSeb 27a8d19f31 Added 3 syscalls 2024-07-30 16:00:32 +02:00
ptitSeb 387a3eeba3 [DYNAREC] Remove BARRIER_NEXT macro 2024-07-29 22:47:43 +02:00
Ilya114 3a3578aecc Update README_UK.md (#1709) 2024-07-28 09:21:46 +02:00
ptitSeb a8784eff9f [RCFILE] Added support for generic names in RCFiles 2024-07-25 15:10:40 +02:00
ptitSeb b26ae5886d Added 67 66 0F EF opcode ([ARM64_DYNAREC] too) 2024-07-23 17:40:56 +02:00
ptitSeb e6696f8d23 Added 67 66 0F FE opcode ([ARM64_DYNAREC] too) 2024-07-23 17:13:24 +02:00
Yang Liu 2989afdf84 [RV64_DYNAREC] Fixed more issues in the vector infrastructure (#1706) 2024-07-23 13:30:06 +02:00
Yang Liu 9c1b015689 [RV64_DYNAREC] Fixed vector infra (#1705) 2024-07-22 21:45:54 +02:00
Yang Liu 3b1fbef95c [DYNAREC] Fixed CI failures for RV64 and LA64 (#1702)
* [DYNAREC] Fixed CI failures for RV64 and LA64

* comment out android tests for now
2024-07-22 09:19:27 +02:00
ptitSeb 2e6acc86e1 Improved exception/int 3 handling 2024-07-21 20:32:17 +02:00
ptitSeb c6e981a363 Better X11 callback in list handling 2024-07-21 18:49:02 +02:00
ptitSeb 43de5afcf6 Improved TF handling 2024-07-21 10:52:58 +02:00
ptitSeb fb40035957 [ARM64_DYNAREC] Add a test about arm64 addresses in pass3, and abort if wrong 2024-07-21 09:39:07 +02:00
ptitSeb 93549259a0 [DYNAREC] Fixed a typo in an error message 2024-07-21 09:38:31 +02:00
ptitSeb f39d3ea43e Leave low memory for wine if it's loaded 2024-07-21 09:38:00 +02:00
Yang Liu 7ad169c7a8 [LA64_DYNAREC] Added more opcodes (#1701) 2024-07-20 14:19:24 +02:00
Yang Liu 052bba4578 [LA64_DYNAREC] Added more opcodes (#1700) 2024-07-20 10:04:07 +02:00
Yang Liu d1eb01e535 [RV64_DYNAREC] Added more 66 0F 38 opcodes for vector (#1699) 2024-07-19 16:05:52 +02:00
Yang Liu 3e20a60c37 [RV64_DYNAREC] Added vector SEW cache (#1698)
* [RV64_DYNAREC] Added vector SEW cache

* handling reset_n
2024-07-19 11:34:45 +02:00
ptitSeb 984c136349 [RCFILE] Re-organized box64.box64rc and add EA/Origin launcher progress profiles 2024-07-18 17:53:59 +02:00
Yang Liu 81f92d8f62 [RV64_DYNAREC] Added 66 0F 38 00 PSHUFB for vector (#1697) 2024-07-18 11:39:48 +02:00
Yang Liu 427051d04c [RV64_DYNAREC] Added more 66 0F opcodes for vector (#1696) 2024-07-18 08:58:05 +02:00
Yang Liu c1a14f93d8 [RV64_DYNAREC] Show missing opcodes in vector implementation (#1695) 2024-07-18 08:13:44 +02:00
Yang Liu f07ee85078 [RV64_DYNAREC] Added vlen detection (#1694) 2024-07-18 08:12:40 +02:00
Yang Liu 51b118d516 [LA64_DYNAREC] Added more opcodes and fixed more issues (#1692) 2024-07-17 19:50:13 +02:00
ptitSeb d5ec4692d3 [INTERPRETER] Fixed some issue with INT opcodes and STEP logic 2024-07-17 12:05:04 +02:00
ptitSeb a62336d433 Added 1 more wrapped function to gstaudio 2024-07-17 10:09:34 +02:00
Yang Liu abb2cbeeaa [LA64_DYNAREC] Added more opcodes (#1690) 2024-07-17 08:15:41 +02:00
ptitSeb 33381857ff Change (again) how Wine prereserved memory is allocated and freed 2024-07-16 22:53:47 +02:00
Yang Liu f1abd95ed0 [LA64_DYNAREC] Added more opcodes (#1688) 2024-07-16 22:50:02 +02:00
Yang Liu 43b155e8b4 [LA64_DYNAREC] Fixed CMPSD (#1687) 2024-07-16 22:49:14 +02:00
Yang Liu 6ee5415ea4 [LA64_DYNAREC] Fixed some opcodes (#1686) 2024-07-16 21:38:19 +02:00
ptitSeb 886ae378c5 Changed how TRAPNO 12 is triggered 2024-07-16 17:24:49 +02:00
Yang Liu 60d886c052 [RV64_DYNAREC] Fixed GETGXSS_empty on upper bits handling (#1685) 2024-07-16 12:57:14 +02:00
Yang Liu d700cc1f55 [RV64_DYNAREC] Clear high 32bits when write back as single (#1684) 2024-07-16 08:57:53 +02:00
Yang Liu 5c212e92c3 [LA64_DYNAREC] Remove xMASK and fixed 86 XCHG opcode (#1683) 2024-07-16 08:18:14 +02:00
Yang Liu 1dde4ee959 [ARM64_DYNAREC] Fixed OR Ew, Gw (#1682) 2024-07-16 08:16:01 +02:00
xctan 9fe450f2dc [RV64_DYNAREC] Fixed some bugs for VMP (#1679)
* [RV64_DYNAREC] Fixed reg x3 conflict with the GETEW macro

* [RV64_DYNAREC] Fixed (LOCK) XCHG Eb, Gb again

* [RV64_DYNAREC] Fixed register conflict in (LOCK) XCHG Eb, Gb
2024-07-16 08:15:33 +02:00
Panda b84e5f25f2 build: fix PKGBUILD-rk3xxx pkgname was set to box86 (#1681) 2024-07-16 08:10:35 +02:00
Yang Liu b52ff061b4 [LA64_DYNAREC] Added 2 more opcodes (#1680) 2024-07-15 23:44:56 +02:00
kaixindeken b7ae79514f Fix hidden error in PR 1677 (#1678)
* Fix most of tiff5 and ltdl7 functions

* Adding missing file

* delete libltdl7 wrapped

* re-wrapped libtiff5 and list all symbols
2024-07-15 18:32:27 +02:00
ptitSeb a90c7af708 Added BOX64_SHAEXT to hide sha cpu extension ([RCFILE] And added a profile using it) 2024-07-15 13:43:53 +02:00
ptitSeb 176e092a6c Added missing generated files 2024-07-15 10:42:04 +02:00
kaixindeken 94ccde160a Wrapped libtiff5 and libltdl7 (#1677)
* Wrapped libtiff5

* no types generated

* libtiff5 added missing defs types undefs files

* wrapped libltdl7

* rerun actions

* add more wrapped function for tiff5 and ltdl7

* remove unused functions
2024-07-15 08:23:14 +02:00
ptitSeb d8746c6c70 Something is wrong, emulated gnutls.so.30 doesn't seems to work fine for now 2024-07-14 15:35:02 +02:00
ptitSeb 4ff4ca72d3 Wrapped lots of new function t be abble to run emulated libgnutls.so.30 2024-07-14 11:18:08 +02:00
ptitSeb 47055f92df [RCFILE] Update a profile, with a workaround, until fixed 2024-07-14 11:17:20 +02:00
Yip Coekjan 7a4a44292c Wrap sqlite3_exec for libsqlite3 (#1674) 2024-07-13 12:52:24 +02:00
ptitSeb 98270a8601 Fix signal stack handling on reentrant signal when using SigAltStack 2024-07-13 11:35:42 +02:00
ptitSeb 182ca255f7 [TRACE] Fixed some issue with function name printing 2024-07-13 10:10:45 +02:00
ptitSeb 3d33713c2b Fixed some issue on tracking when protecting memory with PROT=0 2024-07-13 10:07:39 +02:00
ptitSeb ebf698fdb6 Removed debug leftover 2024-07-12 17:35:47 +02:00
ptitSeb 9d089f9b18 Fixed flaky signal handler on 32bits code (mainly for Wine with new Wow64) 2024-07-12 17:29:15 +02:00
ptitSeb c976833f46 Added 1 syscall (for #1672) 2024-07-12 09:58:34 +02:00
ptitSeb 1819b7563a Revert "[Wrapped] Added sqlite3_exec (#1671)" (#1673)
This reverts commit 548a21a5ec.
2024-07-12 08:52:07 +02:00
kaixindeken 548a21a5ec [Wrapped] Added sqlite3_exec (#1671) 2024-07-12 07:24:49 +02:00
Ivan Melnikov ad1dce7fb1 [RV64_DYNAREC] Cleanup for removed rv64_lock_cas_dq (#1670)
Since rv64_lock_cas_dq is removed, we should also remove its
global symbol declaration and its prototype. Otherwise, we
get and undefined symbol reference, which breaks ELF checks
that some distros employ.

Fixes: 9dbd7fc7e0
2024-07-11 16:57:56 +02:00
ptitSeb 302a358476 [ARM64_DYNAREC] Added handling of FASTNAN=0 to MULSS opcode 2024-07-11 16:47:24 +02:00
ptitSeb 74dd9f2778 Boosted number of X11 callback to 100 2024-07-11 16:18:26 +02:00
ptitSeb 495262f902 Fixed a nasty bug on memory permission tracking 2024-07-11 12:16:31 +02:00
ptitSeb d10a078473 [STATICBUILD] removed Android staticbuild 2024-07-10 16:37:46 +02:00
ptitSeb 8d9fd7cb0e [STATICBUILD] build 2024-07-10 16:09:21 +02:00
ptitSeb 8bd8a923ba [STATICBUILD] Go green now 2024-07-10 16:00:31 +02:00
ptitSeb 764a0c31e5 [STATICBUILD] This is getting old already, turn to green now! 2024-07-10 15:25:49 +02:00
ptitSeb 1ea0382055 [STATICBUILD] Removed libbsd build dependancy 2024-07-10 15:20:27 +02:00
ptitSeb bd673dc791 [STATICBUILD] Yet another attempt to fix CI build 2024-07-10 14:58:37 +02:00
ptitSeb 4fa00ba283 [STATICBUILD] Another attempt to fix CI build 2024-07-10 14:39:06 +02:00
ptitSeb deef011dbf [STATICBUILD] Attempt to fix CI build 2024-07-10 14:31:47 +02:00
ptitSeb afeecf9d9f [STATICBUILD] Fixed some more errors 2024-07-10 12:49:55 +02:00
ptitSeb e792f00363 This should fix regular build 2024-07-10 12:22:54 +02:00
ptitSeb f7d9dd4824 [STATICBUILD] Try to fix staticbuild and add it to the CI (for #1377) 2024-07-10 12:15:27 +02:00
josch dfc60e8bf1 fix some spelling (#1668) 2024-07-10 11:06:02 +02:00
ptitSeb 655e752c07 [STATICBUILD] Fixed a warning (for #1377) 2024-07-10 10:40:11 +02:00
rajdakin ebdbd1767a [DYNAREC] Fixed ymm0_purge for some instructions (#1664)
* [DYNAREC] Fixed `ymm0_purge` for the first instruction of a block

* [DYNAREC] Also consider barriers as having a pred with `ymm0_out = 0`
2024-07-10 09:45:57 +02:00
Yip Coekjan 4eca49697a Remove the flags adjustment in GO_TRACE for RISC-V 64 (#1663) 2024-07-10 09:45:40 +02:00
Yang Liu 7fa2371bbd [LA64_DYNAREC] Added more opcodes and a minor fix too (#1662)
* [LA64_DYNAREC] Added more opcodes and a minor fix too

* saturation is considered necessary
2024-07-10 09:45:27 +02:00
ptitSeb 60c41cadba Fixed some X11 wrapping (for Interrogation: You will be deceived linux version #1414) 2024-07-10 09:44:12 +02:00
ptitSeb 97769b63ad [RCFILE] Added profile for Death Stranding 2024-07-10 09:43:01 +02:00
ptitSeb bc482e29b0 Started a new dev. cycle 2024-07-10 09:42:00 +02:00
1693 changed files with 182974 additions and 42272 deletions

No files matched your search

+2 -1
View File
@@ -12,6 +12,7 @@ MaxEmptyLinesToKeep: 2
IndentCaseLabels: true
AlignConsecutiveMacros: true
WhitespaceSensitiveMacros: ['QUOTE']
IfMacros: ['IFX', '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
---
+187 -35
View File
@@ -27,16 +27,36 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RPI5ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, SD888, ADLINK, ARM64, ANDROID, TERMUX, LARCH64]
type: [Release, Trace]
os: [ubuntu-latest]
include:
- platform: TEGRAX1
type: Release
os: ubuntu-20.04
- platform: TEGRAX1
type: Trace
os: ubuntu-20.04
platform: [X64, RISCV, RK3588, ARM64, ANDROID, TERMUX, LARCH64, ANDROID_GLIBC]
type: [Release, Trace, StaticBuild, Box32]
os: [ubuntu-latest, ubuntu-22.04-arm]
exclude:
- platform: ANDROID
type: StaticBuild
- platform: TERMUX
type: StaticBuild
- platform: X64
type: StaticBuild
- platform: ANDROID
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:
@@ -46,9 +66,10 @@ jobs:
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' && ${{ matrix.platform }} != 'RISCV' && ${{ matrix.platform }} != 'LARCH64' ]]; then
sudo apt-get -y install git cmake make python3
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
@@ -57,13 +78,16 @@ jobs:
sudo cp -rf termux-docker/system/arm /system
sudo chown -R $(whoami):$(whoami) /system
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 -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
echo "BOX64_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
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
@@ -84,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
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 -
@@ -109,17 +133,63 @@ jobs:
if [[ ${{ matrix.type }} == 'Release' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
elif [[ ${{ matrix.type }} == 'StaticBuild' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=1 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
elif [[ ${{ matrix.type }} == 'Box32' ]]; then
echo BOX64_BUILD_TYPE=Release >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=0 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=1 >> $GITHUB_ENV
else
echo BOX64_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX64_HAVE_TRACE=1 >> $GITHUB_ENV
echo BOX64_STATICBUILD=0 >> $GITHUB_ENV
echo BOX64_BOX32=0 >> $GITHUB_ENV
fi
- name: "Get XuanTie QEMU Cache Key"
if: matrix.platform == 'RISCV'
id: get-xuantie-qemu-cache-key
run: |
echo "key=f2dfdd13014d51f957c7172acc2e791cb42dc400" >> $GITHUB_OUTPUT
- name: "Cache XuanTie QEMU"
if: matrix.platform == 'RISCV'
id: cache-xuantie-qemu
uses: actions/cache@v3
with:
path: ${{ github.workspace }}/xuantie_qemu_install
key: ${{ runner.os }}-${{ steps.get-xuantie-qemu-cache-key.outputs.key }}-xuantie-qemu
- name: "Checkout XuanTie QEMU"
if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true'
uses: actions/checkout@v3
with:
repository: revyos/qemu
path: xuantie_qemu
ref: f2dfdd13014d51f957c7172acc2e791cb42dc400
- name: "Build XuanTie QEMU for XTheadVector"
if: matrix.platform == 'RISCV' && steps.cache-xuantie-qemu.outputs.cache-hit != 'true'
run: |
cd xuantie_qemu
./configure --prefix=$GITHUB_WORKSPACE/xuantie_qemu_install --target-list=riscv64-linux-user --disable-system
make -j$(nproc)
make install
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX64_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX64_COMPILER }}"
echo "Build type: ${{ env.BOX64_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX64_HAVE_TRACE }}"
echo "StaticBuild Enabled: ${{ env.BOX64_STATICBUILD }}"
echo "Box32 Enabled: ${{ env.BOX64_BOX32 }}"
- name: "Build Box64"
run: |
@@ -130,46 +200,128 @@ jobs:
${{ env.BOX64_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\
-DSTATICBUILD=${{ env.BOX64_STATICBUILD }}\
-DBOX32=${{ env.BOX64_BOX32 }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON\
-DCI=${{ matrix.platform != 'ANDROID' }}
make -j$(nproc) VERBOSE=1
- name: "Test Box64"
if: ${{ matrix.platform != 'TEGRAX1' }}
run: |
if [[ ${{ matrix.platform }} != 'X64' ]]; then
mkdir qemu9.0.0
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-9.0.0-1-x86_64.pkg.tar.zst | tar -I zstd -C qemu9.0.0 -xf -
sudo cp qemu9.0.0/usr/bin/* /usr/bin/
mkdir qemu9
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-9.0.2-1-x86_64.pkg.tar.zst | tar -I zstd -C qemu9 -xf -
sudo cp qemu9/usr/bin/* /usr/bin/
fi
cd build
export CTEST_OPTIONS="-j$(nproc) --timeout 120 --output-on-failure --repeat until-pass:20"
if [[ ${{ matrix.platform }} == 'RISCV' ]]; then
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,v=false BOX64_DYNAREC=0 ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,v=false,xtheadba=true,xtheadba=true,xtheadbb=true,xtheadbs=true,xtheadcondmov=true,xtheadmemidx=true,xtheadmempair=true,xtheadfmemidx=true,xtheadmac=true,xtheadfmv=true ctest -j$(nproc) --output-on-failure
export INTERPRETER=qemu-riscv64-static
export QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/
ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=false BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS
QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS
QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=false,zba=true,zbb=true,zbc=true,zbs=true ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=128,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=rv64,v=true,vlen=256,vext_spec=v1.0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 QEMU_CPU=thead-c906 ctest $CTEST_OPTIONS -E nocosim
export INTERPRETER=$GITHUB_WORKSPACE/xuantie_qemu_install/bin/qemu-riscv64
QEMU_CPU=c910v ctest $CTEST_OPTIONS
BOX64_DYNAREC_TEST=1 QEMU_CPU=c910v ctest $CTEST_OPTIONS -E nocosim
elif [[ ${{ matrix.platform }} == 'LARCH64' ]]; then
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC_LA64NOEXT=1 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC_TEST=2 BOX64_DYNAREC_LA64NOEXT=1 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-loongarch64-static QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
export INTERPRETER=qemu-loongarch64-static
export QEMU_LD_PREFIX=/usr/loongarch64-linux-gnu/
BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS -E nocosim
BOX64_DYNAREC_TEST=1 BOX64_DYNAREC_LA64NOEXT=1 ctest $CTEST_OPTIONS -E nocosim
elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/system/lib64 BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/system/lib64 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
export INTERPRETER=qemu-aarch64-static
export QEMU_LD_PREFIX=/system/lib64
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
elif [[ ${{ matrix.platform }} == 'TERMUX' ]]; then
INTERPRETER=qemu-aarch64-static QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib BOX64_DYNAREC=0 ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib ctest -j$(nproc) --repeat until-pass:20 --output-on-failure
elif [[ ${{ matrix.platform }} != 'X64' ]]; then # AArch64
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC_TEST=2 ctest -j$(nproc) --output-on-failure
export INTERPRETER=qemu-aarch64-static
export QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
export QEMU_LD_PREFIX=/system/lib64:/data/data/com.termux/files/usr/lib
BOX64_DYNAREC=0 ctest $CTEST_OPTIONS
ctest $CTEST_OPTIONS
else
ctest -j$(nproc) --output-on-failure
ctest -j$(nproc)
fi
- name: "Get short Git commit"
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: |
cd build
cat <<EOF > profile.json
{
"type": "Box64",
"versionName": "latest-${SHORT_COMMIT}",
"versionCode": 1,
"description": "Box64-latest-${SHORT_COMMIT}. Built from [https://github.com/ptitSeb/box64].",
"files": [
{
"source": "box64",
"target": "\${localbin}/box64"
}
]
}
EOF
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:
name: box64-${{ matrix.platform }}-${{ matrix.type }}
path: build/box64
- name: "Upload WCP file"
if: matrix.platform == 'ANDROID_GLIBC' && matrix.type != 'StaticBuild'
uses: actions/upload-artifact@v4
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
+24 -5
View File
@@ -60,11 +60,30 @@ build*/
src/git_head.h
backup/
# LLVMprivateGenerator
/LLVMprivateGenerator/*
!/LLVMprivateGenerator/Makefile
!/LLVMprivateGenerator/main.cpp
!/LLVMprivateGenerator/registered_structs.cpp
# Wrapper helper
/wrapperhelper/bin
/wrapperhelper/makedir
/wrapperhelper/obj
/wrapperhelper/sanaddress
/wrapperhelper/sanleak
/wrapperhelper/sanundefined
/wrapperhelper/src/machine.gen
/wrapperhelper/*.h
!/wrapperhelper/example-libc.h
# macOS
.DS_Store
# Archives
*.7z
*.deb
*.eopkg
*.gz
*.rar
*.rpm
*.tar*
*.xbps
*.xz
*.zip
*.zst
*.zstd
+467 -53
View File
@@ -17,8 +17,10 @@ option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(SD8G2 "Set to ON if targeting a Snapragon 8 Gen 2 based device" ${SD8G2})
option(SDORYON1 "Set to ON if targeting a Snapdragon Oryon 1 (X1E80100/X1E78100) based device" ${SDORYON1})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(M1 "Set to ON if targeting a AppleM1 running on Asahi computer" ${M1})
option(LARCH64 "Set to ON if targeting an Loongarch64 based device" ${LARCH64})
@@ -28,15 +30,20 @@ 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})
option(SW64 "Set ON if targeting an SW64 based device" ${SW64})
option(CI "Set to ON if running in CI" ${CI})
option(WITH_MOLD "Set to ON to use with mold" ${WITH_MOLD})
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")
@@ -48,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 "")
@@ -63,7 +74,7 @@ if(PPC64LE)
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR M1 OR ARM64 OR ADLINK)
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR PHYTIUM OR SD845 OR SD865 OR SD888 OR SD8G2 OR SDORYON1 OR LX2160A OR M1 OR ARM64 OR ADLINK)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -81,10 +92,16 @@ if(SW64)
set(NOALIGN OFF CACHE BOOL "")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
set(TERMUX_PATH "/data/data/com.termux/files")
#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})
@@ -173,6 +190,11 @@ elseif(SD845)
add_definitions(-DSD845)
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55")
elseif(SD865)
add_definitions(-DSD865)
#note that cortex-a77.cortex-a55 is not supported, so fall back to a76 instead
add_definitions(-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55")
elseif(SD888)
add_definitions(-DSD888)
add_definitions(-pipe -march=armv8.4-a+simd+crypto)
@@ -181,6 +203,24 @@ elseif(SD8G2)
add_definitions(-DSD8G2)
add_definitions(-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2)
set(CMAKE_ASM_FLAGS "-pipe -march=armv9-a+i8mm+sm4+sha3+rcpc+crypto+nosve+nosve2")
elseif(SDORYON1)
add_definitions(-DSDORYON1)
# NOTE
#
# 1.
# GCC 14 and Clang 19 support oryon-1 as a -mcpu/-mtune argument,
# however it seems like fedora (the system I tested this on) does not work.
# see https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/AArch64-Options.html if you're interested
#
# 2.
# gcc/gcc/config/aarch64/aarch64-cores.def:157 defines oryon1 as
# AARCH64_CORE("oryon-1", oryon1, cortexa57, V8_6A, (CRYPTO, SM4, SHA3, F16), cortexa72, 0x51, 0x001, -1)
# where
# * the 3rd positional argument is represented as the "scheduler"
# * the 6th positional argument is represented as the "cost"
# I've chosen the a57 because I don't know if I should choose the a72
add_definitions(-pipe -march=armv8.6-a+crypto+sm4+sha3+fp16 -mtune=cortex-a57)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.6-a+crypto+sm4+sha3+fp16 -mtune=cortex-a57")
elseif(ADLINK)
add_definitions(-DADLINK)
add_definitions(-pipe -mcpu=neoverse-n1 -fuse-ld=gold -fuse-linker-plugin)
@@ -217,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()
@@ -231,10 +274,17 @@ if(STATICBUILD)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(HAVE_TRACE OFF)
endif()
if(BOX32)
add_definitions(-DBOX32)
add_definitions(-Wno-address-of-packed-member) #32bits might generated unaligned pointers
endif()
if(NOGIT)
add_definitions(-DNOGIT)
endif()
if(CI)
add_definitions(-Wno-pointer-type-mismatch)
endif()
if(HAVE_TRACE)
set(BOX64 box64)
@@ -298,6 +348,11 @@ include_directories(
"${BOX64_ROOT}/src"
"${BOX64_ROOT}/src/wrapped/generated"
)
if(BOX32)
include_directories(
"${BOX64_ROOT}/src/wrapped32/generated"
)
endif()
# git_head.h is a generated file
set_source_files_properties(
@@ -320,13 +375,13 @@ 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"
"${BOX64_ROOT}/src/emu/x64run_private.c"
"${BOX64_ROOT}/src/emu/x64shaext.c"
"${BOX64_ROOT}/src/emu/x64syscall.c"
"${BOX64_ROOT}/src/emu/x86syscall.c"
"${BOX64_ROOT}/src/emu/x64tls.c"
"${BOX64_ROOT}/src/emu/x64trace.c"
"${BOX64_ROOT}/src/librarian/librarian.c"
@@ -336,16 +391,18 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/signals.c"
"${BOX64_ROOT}/src/libtools/decopcode.c"
"${BOX64_ROOT}/src/libtools/threads.c"
"${BOX64_ROOT}/src/tools/bitutils.c"
"${BOX64_ROOT}/src/tools/box64stack.c"
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
"${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"
)
@@ -359,6 +416,35 @@ if(NOT STATICBUILD)
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
)
endif()
if(BOX32)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/box32.c"
"${BOX64_ROOT}/src/elfs/elfhash32.c"
"${BOX64_ROOT}/src/elfs/elfloader32.c"
"${BOX64_ROOT}/src/elfs/elfparser32.c"
"${BOX64_ROOT}/src/elfs/elfload_dump32.c"
"${BOX64_ROOT}/src/tools/box32stack.c"
"${BOX64_ROOT}/src/emu/x86int3.c"
"${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"
"${BOX64_ROOT}/src/libtools/sdl1align32.c"
"${BOX64_ROOT}/src/libtools/sdl2align32.c"
"${BOX64_ROOT}/src/libtools/my_x11_conv.c"
"${BOX64_ROOT}/src/libtools/my_x11_xevent.c"
"${BOX64_ROOT}/src/emu/x86syscall_32.c"
"${BOX64_ROOT}/src/wrapped32/generated/wrapper32.c"
"${BOX64_ROOT}/src/wrapped32/generated/converter32.c"
)
else()
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x86syscall.c"
)
endif()
if(NOT ANDROID)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/obstack.c"
@@ -412,7 +498,7 @@ set(INTERPRETER
if(STATICBUILD)
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
#"${BOX64_ROOT}/src/wrapped/wrappedlibbsd.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcmusl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
@@ -497,6 +583,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdrm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdrmamdgpu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibegl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.c"
@@ -538,6 +625,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxaw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
@@ -550,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"
@@ -590,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"
@@ -649,6 +739,8 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedicui18n73.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc75.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n75.c"
"${BOX64_ROOT}/src/wrapped/wrappedidn2.c"
"${BOX64_ROOT}/src/wrapped/wrappedanl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpsl5.c"
@@ -659,6 +751,9 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibunistring2.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibhogweed6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsqlite3.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtiff5.c"
"${BOX64_ROOT}/src/wrapped/wrappedbrotlidec.c"
"${BOX64_ROOT}/src/wrapped/wrappedzstd.c"
)
endif()
if(ANDROID)
@@ -692,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}
@@ -711,6 +806,93 @@ endif ()
add_custom_target(WRAPPERS DEPENDS "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt")
#add_custom_target(PRINTER DEPENDS "${BOX64_ROOT}/src/dynarec/last_run.txt")
if(BOX32)
if(STATICBUILD)
set(WRAPPEDS32
"${BOX64_ROOT}/src/wrapped32/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibrt.c"
)
else()
set(WRAPPEDS32
"${BOX64_ROOT}/src/wrapped32/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped32/wrappedcrashhandler.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped32/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped32/wrappedopenal.c"
"${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"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxi.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcomposite.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxcursor.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxrandr.c"
"${BOX64_ROOT}/src/wrapped32/wrappedlibxss.c"
"${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})
#set(WRAPPEDS32_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_genvate.h")
foreach(A ${WRAPPEDS32})
string(REPLACE ".c" "_private.h" C ${A})
string(REPLACE "${MODROOT}" "${BOX64_ROOT}" B ${C})
set(WRAPPEDS32_HEAD ${WRAPPEDS32_HEAD} ${B})
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
endforeach()
set(WRAPPER32 "${BOX64_ROOT}/src/wrapped32/generated/wrapper32.c" "${BOX64_ROOT}/src/wrapped32/generated/wrapper32.h")
if(NOT CI)
add_custom_command(
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" "WINLATOR_GLIBC" "STATICBUILD" "--"
${WRAPPEDS32_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers_32.py"
DEPENDS ${WRAPPEDS32} ${WRAPPEDS32_HEAD}
BYPRODUCTS ${WRAPPER32}
)
endif()
add_custom_target(WRAPPERS32 DEPENDS "${BOX64_ROOT}/src/wrapped32/generated/functions_list.txt")
else()
set(WRAPPEDS32)
endif()
if(DYNAREC)
set(DYNAREC_SRC
"${BOX64_ROOT}/src/dynarec/dynablock.c"
@@ -725,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"
@@ -776,6 +959,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f3a.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f38.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f3a.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f3_0f38.c"
)
endif()
@@ -784,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"
@@ -806,10 +991,12 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_2.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_3.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c"
#"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_65.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_32.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c"
@@ -821,13 +1008,18 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_df.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f38.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f30f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f30f_vector.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c"
)
endif()
@@ -856,20 +1048,32 @@ 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"
${DYNAREC_PASS}
"${BOX64_ROOT}/src/dynarec/dynarec_native_pass.c"
)
if(BOX32)
list(APPEND DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped32/generated/wrapper32.h"
)
endif()
add_library(dynarec_native OBJECT ${DYNAREC_SRC})
@@ -887,6 +1091,12 @@ if(DYNAREC)
add_dependencies(native_pass1 WRAPPERS)
add_dependencies(native_pass2 WRAPPERS)
add_dependencies(native_pass3 WRAPPERS)
if(BOX32)
add_dependencies(native_pass0 WRAPPERS32)
add_dependencies(native_pass1 WRAPPERS32)
add_dependencies(native_pass2 WRAPPERS32)
add_dependencies(native_pass3 WRAPPERS32)
endif()
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_native>
@@ -896,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
@@ -903,26 +1117,29 @@ if(DYNAREC)
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/git_head.h"
COMMAND sh -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX64_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS} ${WRAPPEDS32}
VERBATIM)
endif()
add_library(interpreter OBJECT ${INTERPRETER})
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} ${WRAPPEDS32} "${BOX64_ROOT}/src/git_head.h")
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
if(BOX32)
add_dependencies(${BOX64} WRAPPERS32)
endif()
#add_dependencies(${BOX64} PRINTER)
#target_link_libraries(${BOX64} c m dl rt pthread resolv)
if(STATICBUILD)
#set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-fuse-ld=gold -static -Wl,--no-relax -Wl,--allow-multiple-definition -ldl -lrt -lpthread -lresolv -lc -lutil -lm -Wl,-defsym,_DYNAMIC=0 -pthread")
target_link_libraries(${BOX64} c m dl pthread resolv util bsd c)
target_link_libraries(${BOX64} c m dl pthread resolv util c)
else()
if(ANDROID)
if(TERMUX)
@@ -931,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)
@@ -942,15 +1159,18 @@ 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 "-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()
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR WITH_MOLD)
if(WITH_MOLD) # --image-base requires -no-pie in mold!
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()
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
@@ -969,42 +1189,57 @@ endif()
if(NOT _x86 AND NOT _x86_64)
if(NOT TERMUX)
install(TARGETS ${BOX64}
RUNTIME DESTINATION bin)
install(TARGETS ${BOX64} RUNTIME DESTINATION bin)
if(NOT NO_LIB_INSTALL)
install(PROGRAMS ${CMAKE_SOURCE_DIR}/tests/box64-bash DESTINATION bin)
endif()
else()
install(TARGETS ${BOX64}
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
install(TARGETS ${BOX64} RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
if(NOT NO_LIB_INSTALL)
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)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
else()
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION /etc/)
if(BOX32_BINFMT)
configure_file(system/box32.conf.cmake system/box32.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box32.conf DESTINATION /etc/binfmt.d/)
endif()
else()
install(FILES ${CMAKE_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
if(BOX32_BINFMT)
configure_file(system/box32.conf.cmake system/box32.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box32.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
endif()
endif()
endif()
set(INSTALL_PATH "/usr/lib/x86_64-linux-gnu/")
set(INSTALL_PATH "/usr/lib/box64-x86_64-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.14 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${INSTALL_PATH})
else()
if(NOT TERMUX AND NOT ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.14 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${INSTALL_PATH})
elseif(TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
@@ -1020,8 +1255,36 @@ if(NOT _x86 AND NOT _x86_64)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.12 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.7 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedcrypto.so.3 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
elseif(ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x64android/libc++_shared.so DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
endif()
endif()
if(BOX32)
set(INSTALL_PATH "/usr/lib/box64-i386-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX AND NOT ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libcrypto.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libssl.so.1.0.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libz.so.1 DESTINATION ${INSTALL_PATH})
elseif(TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libcrypto.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libssl.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libz.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
elseif(ANDROID)
install(FILES ${CMAKE_SOURCE_DIR}/x86android/libc++_shared.so DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
endif()
endif()
endif()
endif()
if(NOT TARGET uninstall)
@@ -1129,11 +1392,13 @@ add_test(fork ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(cppThreads ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
add_test(cppThreads_nocosim ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(cppThreads_nocosim PROPERTIES ENVIRONMENT "BOX64_LD_LIBRARY_PATH=${CMAKE_SOURCE_DIR}/x64lib")
add_test(tlsData ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
@@ -1243,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}
@@ -1275,10 +1551,10 @@ add_test(threadsStart ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(trig ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07_android -D TEST_OUTPUT=tmpfile07.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(trig ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07_android -D TEST_OUTPUT=tmpfile07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(pi ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08_android -D TEST_OUTPUT=tmpfile08.txt
@@ -1330,10 +1606,10 @@ add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21_android -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# add_test(longjumpInSignals ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21_android -D TEST_OUTPUT=tmpfile21.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22_android -D TEST_OUTPUT=tmpfile22.txt
@@ -1410,3 +1686,141 @@ foreach(file ${extension_tests})
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endif()
if(BOX32)
add_test(NAME bootSyscall_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test01 -D TEST_OUTPUT=tmpfile32_01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME bootSyscallC_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test02 -D TEST_OUTPUT=tmpfile32_02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME printf_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test03 -D TEST_OUTPUT=tmpfile32_03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME args_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile32_04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME maths1_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile32_05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME threadsStart_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test06 -D TEST_OUTPUT=tmpfile32_06.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME trig_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test07 -D TEST_OUTPUT=tmpfile32_07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME pi_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test08 -D TEST_OUTPUT=tmpfile32_08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fork_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test09 -D TEST_OUTPUT=tmpfile32_09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT CI)
add_test(NAME cppThreads_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test10 -D TEST_OUTPUT=tmpfile32_10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(cppThreads_32bits PROPERTIES ENVIRONMENT "BOX64_LD_LIBRARY_PATH=${CMAKE_SOURCE_DIR}/x86lib")
endif()
add_test(NAME tlsData_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test11 -D TEST_OUTPUT=tmpfile32_11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fpu_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test12 -D TEST_OUTPUT=tmpfile32_12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME contexts_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test13 -D TEST_OUTPUT=tmpfile32_13.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT LD80BITS)
add_test(NAME conditionalThreads_32bits_nocosim COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test14 -D TEST_OUTPUT=tmpfile32_14.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
add_test(NAME linkingIndirectNoversion_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test15 -D TEST_OUTPUT=tmpfile32_15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME linkingIndirectVersion_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test16 -D TEST_OUTPUT=tmpfile32_16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME sse_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test17 -D TEST_OUTPUT=tmpfile32_17.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(NAME longjumpInSignals_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test18 -D TEST_OUTPUT=tmpfile32_18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME x87_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test19 -D TEST_OUTPUT=tmpfile32_19.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref19.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(x87_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
add_test(NAME idiv_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test20 -D TEST_OUTPUT=tmpfile32_20.txt
-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
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests32/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}_32bits" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/extensions/${testname} -D TEST_OUTPUT=tmpfile32_-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
#add_test(NAME sse_optimized_32bits COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test17_o2 -D TEST_OUTPUT=tmpfile32_17_o2.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref17_o2.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#set_tests_properties(sse_optimized_32bits PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(bswap_32bits ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests32/test23 -D TEST_OUTPUT=tmpfile32_23.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests32/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
-12
View File
@@ -1,12 +0,0 @@
all: dumpSigs
dumpSigs: main.o registered_structs.o
g++ -g3 -std=gnu++17 -fno-rtti main.o registered_structs.o -o dumpSigs "-L$(LLVM_install_dir)/lib" -lclang-cpp -lclangTooling -Wl,-rpath "-Wl,$(LLVM_install_dir)/lib"
main.o: main.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c main.cpp -Wfatal-errors "-I$(LLVM_install_dir)/include" -o main.o
registered_structs.o: registered_structs.cpp
g++ -g3 -std=gnu++17 -fno-rtti -c registered_structs.cpp -Wfatal-errors -o registered_structs.o
clean:
$(RM) dumpSigs main.o registered_structs.o
-458
View File
@@ -1,458 +0,0 @@
#include <algorithm>
#include <fstream>
#include <iostream>
#include <numeric>
#include <unordered_map>
#include <utility>
#include <vector>
#include <llvm/Support/raw_ostream.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/Decl.h>
#include <clang/AST/Mangle.h>
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Tooling/CommonOptionsParser.h>
#include <clang/Tooling/Tooling.h>
clang::MangleContext *mangler = nullptr;
std::unordered_map<std::string, std::pair<std::string, bool>> funMap;
std::vector<std::string> funList;
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig);
clang::QualType getPointedType(const clang::QualType q) {
if (const clang::PointerType *p = q->getAs<clang::PointerType>())
return getPointedType(p->getPointeeType());
else if (const clang::ReferenceType *r = q->getAs<clang::ReferenceType>())
return getPointedType(r->getPointeeType());
else
return q;
}
std::string record2name(const clang::RecordDecl &q, const clang::QualType *qorig) {
std::string s = q.getNameAsString();
if (s == "") {
if (!qorig) return "????.!";
if (const clang::TypedefType *tt = (*qorig)->getAs<clang::TypedefType>()) {
// Typedef
if (clang::TypedefNameDecl *td = tt->getDecl()) {
return td->getNameAsString();
} else {
return "<typedef with no declaration>";
}
} else {
return std::string("<unknown type ") + (*qorig)->getTypeClassName() + ">";
}
} else {
return s;
}
}
char ptr2char(const std::string &str) __attribute__((const));
const char *ptr2str(const std::string &str) __attribute__((const));
char type2char(const clang::QualType &qual /* Canonical */, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
switch (static_cast<const clang::BuiltinType&>(*qual).getKind()) {
case clang::BuiltinType::Kind::Void:
return 'v';
case clang::BuiltinType::Kind::Bool:
return 'i';
case clang::BuiltinType::Kind::Char_U:
return 'C';
case clang::BuiltinType::Kind::Char_S:
return 'c';
case clang::BuiltinType::Kind::Char8:
return 'c';
case clang::BuiltinType::Kind::UChar:
return 'C';
case clang::BuiltinType::Kind::SChar:
return 'c';
case clang::BuiltinType::Kind::WChar_U:
return 'W';
case clang::BuiltinType::Kind::UShort:
return 'W';
case clang::BuiltinType::Kind::WChar_S:
return 'w';
case clang::BuiltinType::Kind::Char16:
return 'w';
case clang::BuiltinType::Kind::Short:
return 'w';
case clang::BuiltinType::Kind::UInt:
return 'u';
case clang::BuiltinType::Kind::Char32:
return 'i';
case clang::BuiltinType::Kind::Int:
return 'i';
case clang::BuiltinType::Kind::ULong:
return 'L';
case clang::BuiltinType::Kind::Long:
return 'l';
case clang::BuiltinType::Kind::ULongLong:
return 'U';
case clang::BuiltinType::Kind::LongLong:
return 'I';
case clang::BuiltinType::Kind::UInt128:
return 'H';
case clang::BuiltinType::Kind::Int128:
return 'H';
case clang::BuiltinType::Kind::Float:
return 'f';
case clang::BuiltinType::Kind::Double:
return 'd';
case clang::BuiltinType::Kind::LongDouble:
return 'D';
case clang::BuiltinType::Kind::NullPtr:
return 'p'; // nullptr_t
case clang::BuiltinType::Kind::Half:
case clang::BuiltinType::Kind::BFloat16:
case clang::BuiltinType::Kind::ShortAccum:
case clang::BuiltinType::Kind::Accum:
case clang::BuiltinType::Kind::LongAccum:
case clang::BuiltinType::Kind::UShortAccum:
case clang::BuiltinType::Kind::UAccum:
case clang::BuiltinType::Kind::ULongAccum:
case clang::BuiltinType::Kind::ShortFract:
case clang::BuiltinType::Kind::Fract:
case clang::BuiltinType::Kind::LongFract:
case clang::BuiltinType::Kind::UShortFract:
case clang::BuiltinType::Kind::UFract:
case clang::BuiltinType::Kind::ULongFract:
case clang::BuiltinType::Kind::SatShortAccum:
case clang::BuiltinType::Kind::SatAccum:
case clang::BuiltinType::Kind::SatLongAccum:
case clang::BuiltinType::Kind::SatUShortAccum:
case clang::BuiltinType::Kind::SatUAccum:
case clang::BuiltinType::Kind::SatULongAccum:
case clang::BuiltinType::Kind::SatShortFract:
case clang::BuiltinType::Kind::SatFract:
case clang::BuiltinType::Kind::SatLongFract:
case clang::BuiltinType::Kind::SatUShortFract:
case clang::BuiltinType::Kind::SatUFract:
case clang::BuiltinType::Kind::SatULongFract:
case clang::BuiltinType::Kind::Float16:
case clang::BuiltinType::Kind::Float128:
case clang::BuiltinType::Kind::Overload:
case clang::BuiltinType::Kind::BoundMember:
case clang::BuiltinType::Kind::PseudoObject:
case clang::BuiltinType::Kind::Dependent:
case clang::BuiltinType::Kind::UnknownAny:
case clang::BuiltinType::Kind::ARCUnbridgedCast:
case clang::BuiltinType::Kind::BuiltinFn:
case clang::BuiltinType::Kind::ObjCId:
case clang::BuiltinType::Kind::ObjCClass:
case clang::BuiltinType::Kind::ObjCSel:
#define IMAGE_TYPE(it, id, si, a, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLImageTypes.def>
#undef IMAGE_TYPE
case clang::BuiltinType::Kind::OCLSampler:
case clang::BuiltinType::Kind::OCLEvent:
case clang::BuiltinType::Kind::OCLClkEvent:
case clang::BuiltinType::Kind::OCLQueue:
case clang::BuiltinType::Kind::OCLReserveID:
case clang::BuiltinType::Kind::IncompleteMatrixIdx:
case clang::BuiltinType::Kind::OMPArraySection:
case clang::BuiltinType::Kind::OMPArrayShaping:
case clang::BuiltinType::Kind::OMPIterator:
#define EXT_OPAQUE_TYPE(et, id, e) case clang::BuiltinType::Kind::id:
#include <clang/Basic/OpenCLExtensionTypes.def>
#define SVE_TYPE(n, id, si) case clang::BuiltinType::Kind::id:
#include <clang/Basic/AArch64SVEACLETypes.def>
#define PPC_VECTOR_TYPE(n, id, s) case clang::BuiltinType::Kind::id:
#include <clang/Basic/PPCTypes.def>
#undef EXT_OPAQUE_TYPE
#undef SVE_TYPE
#undef PPC_VECTOR_TYPE
return '!';
default:
return ':';
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return 'i';
} else {
return type2char(ed->getIntegerType().getCanonicalType(), qorig);
}
} else if (qual->isFunctionPointerType()) {
return '@';
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return 'p';
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '!';
} else if (!rc->isCompleteDefinition()) {
return 'p';
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
char ret = ptr2char(str);
if (ret) return ret;
else {
return '!';
}
}
} else {
return '!';
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return '?';
} else if (rc->getNameAsString() == "__builtin_va_list") {
// va_list
return 'A';
} else {
return '?';
}
} else {
return '?';
}
}
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
#define GO(chr) || (c == chr)
return (c == 'v')
GO('i') GO('u')
GO('I') GO('U')
GO('l') GO('L')
GO('f') GO('d')
GO('D') GO('K')
GO('0') GO('1')
GO('C') GO('c')
GO('W') GO('w')
GO('H')
GO('p');
#undef GO
}
bool isTypeValid(const clang::QualType &q, const clang::QualType *qorig) {
const char c = type2char(q, qorig);
if (c == 'A') return false;
if (c == 'V') return false;
return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
}
const std::string type2string(const clang::QualType &qual, const clang::QualType *qorig) {
if (qual->isBuiltinType()) {
return std::string("(builtin) ") + static_cast<const clang::BuiltinType&>(*qual).getName(clang::PrintingPolicy{{}}).data();
} else if (qual->isFunctionPointerType()) {
return "Callback (function pointer)";
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
std::string prefix = qual->isAnyPointerType() ? "Pointer to " : "Reference to ";
const clang::QualType &pointed = getPointedType(qual);
if (isTypeTrivial(pointed, qorig)) {
return prefix + "trivial object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return prefix + "unknown record";
} else if (!rc->isCompleteDefinition()) {
return prefix + "incomplete record " + rc->getNameAsString();
} else {
std::string str;
if (qorig) {
const clang::QualType qpted = getPointedType(*qorig);
str = record2name(*rc, &qpted);
} else {
str = record2name(*rc, nullptr);
}
const char *ret = ptr2str(str);
if (ret[0] != '\0') {
return prefix + ret;
} else {
if (mangler && mangler->shouldMangleDeclName(rc)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(rc, strstr);
}
return prefix + "unknown record " + str + " (=== " + mangled + ")";
} else {
return prefix + "unknown record " + str;
}
}
}
} else {
return prefix + "non-trivial or typedef'ed object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
//return "Pointer (maybe to callback)";
}
} else if (qual->isEnumeralType()) {
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
if (!ed) {
return "Enumeration with unknown underlying integer type (assuming int)";
} else {
return "Enumeration with underlying type " + type2string(ed->getIntegerType().getCanonicalType(), nullptr);
}
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
clang::RecordDecl *rc = rct->getDecl();
if (!rc) {
return "Unknown record";
} else if (rc->getNameAsString() == "__builtin_va_list") {
return "va_list";
} else {
return "Unknown record " + std::string(rc->getName().data());
}
} else {
return std::string("??? ") + qual->getTypeClassName();
}
}
class Visitor : public clang::RecursiveASTVisitor<Visitor> {
public:
clang::ASTContext &context;
bool shouldVisitTemplateInstantiations() const /* override */ { return true; }
Visitor(clang::CompilerInstance &ci) : context(ci.getASTContext()) {
if (!mangler) {
mangler = clang::ItaniumMangleContext::create(context, ci.getDiagnostics());
}
}
~Visitor() {
if (mangler) {
delete mangler;
mangler = nullptr;
}
}
bool VisitDecl(clang::Decl *decl) /* override */ {
std::cerr << std::flush;
if (!decl) return true;
if ((decl->getKind() >= clang::Decl::Kind::firstFunction) && (decl->getKind() <= clang::Decl::Kind::lastFunction)) {
clang::DeclaratorDecl *ddecl = static_cast<clang::DeclaratorDecl*>(decl);
std::cout << "Function detected!\n";
std::string funName{ddecl->getName()};
auto niceprint = [](const std::string &infotype, const auto &dat){ std::cout << " " << infotype << ": " << dat << "\n"; };
niceprint("Function name", funName);
if (mangler && mangler->shouldMangleDeclName(ddecl)) {
std::string mangled;
{
llvm::raw_string_ostream strstr{mangled};
mangler->mangleName(ddecl, strstr);
}
niceprint("Function mangled name", mangled);
funName = std::move(mangled);
}
bool valid;
std::string funTypeStr{""};
if (ddecl->getFunctionType()->isFunctionNoProtoType()) {
const clang::FunctionNoProtoType *funType = static_cast<const clang::FunctionNoProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType) +
" (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Is sugared", funType->isSugared());
if (funType->isSugared()) {
clang::QualType qft{funType, 0};
niceprint("Desugared", type2string(funType->desugar(), &qft));
}
funTypeStr = type2char(retType.getCanonicalType(), &retType) + std::string("Fv");
valid = isTypeValid(retType.getCanonicalType(), &retType);
} else {
const clang::FunctionProtoType *funType = static_cast<const clang::FunctionProtoType*>(ddecl->getFunctionType());
const auto &retType = funType->getReturnType();
niceprint("Function return type", type2string(retType, &retType));
niceprint("Canonical function return type",
type2string(retType.getCanonicalType(), &retType)
+ " (" + type2char(retType.getCanonicalType(), &retType) + ")");
niceprint("Parameter count", funType->getNumParams());
for (const clang::QualType &type : funType->getParamTypes()) {
niceprint(" " + type2string(type, &type),
type2string(type.getCanonicalType(), &type) + " (" + type2char(type.getCanonicalType(), &type) + ")");
}
niceprint("Variadic function", funType->isVariadic() ? "yes" : "no");
funTypeStr =
type2char(retType.getCanonicalType(), &retType) +
((funType->getNumParams() == 0)
? std::string("Fv") : std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), std::string("F"),
[](const std::string &acc, const clang::QualType &qual){ return acc + type2char(qual.getCanonicalType(), &qual); }));
if (funType->isVariadic()) funTypeStr += "V";
valid = !funType->isVariadic() &&
std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), isTypeValid(retType.getCanonicalType(), &retType),
[](bool acc, const clang::QualType &qual){ return acc && isTypeValid(qual.getCanonicalType(), &qual); });
}
niceprint("Conclusion", "");
niceprint("Function final name", funName);
niceprint("Function type", funTypeStr);
niceprint("Valid function type", valid ? "yes" : "no");
std::cout << "\n";
funMap[funName] = std::make_pair(funTypeStr, valid);
funList.push_back(funName);
}
return true;
}
};
class Consumer : public clang::ASTConsumer {
public:
Visitor visitor;
Consumer(clang::CompilerInstance &ci) : visitor(ci) {
}
void HandleTranslationUnit(clang::ASTContext &context) override {
visitor.TraverseDecl(context.getTranslationUnitDecl());
}
};
class Action : public clang::ASTFrontendAction {
public:
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef inFile) override {
return std::make_unique<Consumer>(ci);
}
};
int main(int argc, const char **argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " (filenames) -- [-I...]" << std::endl;
return 2;
}
/*int fakeargc = argc + 1;
const char **fakeargv = new const char*[fakeargc];
memcpy(fakeargv, argv, argc * sizeof(char*));
fakeargv[fakeargc - 1] = "--";*/
llvm::cl::OptionCategory opcat{""};
clang::tooling::CommonOptionsParser op{argc, argv, opcat};
std::vector<std::string> paths; for (int i = 1; i < argc; ++i) paths.push_back(argv[i]);
clang::tooling::ClangTool tool{op.getCompilations(), paths};
tool.run(clang::tooling::newFrontendActionFactory<Action>().get());
std::cout << "Done, outputing output.h" << std::endl;
std::sort(funList.begin(), funList.end());
std::fstream file{"output.h", std::ios_base::out};
for (const std::string &funName : funList) {
if (!funMap[funName].second) {
file << "//";
}
file << "GO(" << funName << ", " << funMap[funName].first << ")\n";
}
return 0;
}
-267
View File
@@ -1,267 +0,0 @@
#include <string>
#define ALL START() \
/* libc */ \
STRUCT("_IO_FILE", "a FILE") \
STRUCT("_G_fpos_t", "a file position") \
STRUCT("sockaddr", "a socket address") \
STRUCT("itimerspec", "an itimerspec") \
STRUCT("timespec", "a timespec") \
STRUCT("itimerval", "an itimerval") \
STRUCT("timeval", "a timeval") \
STRUCT("timex", "a timex") \
STRUCT("timezone", "a timezone") \
STRUCT("dirent", "a dirent") \
STRUCT("dirent64", "a dirent64") \
STRUCT("__dirstream", "a dir stream") \
STRUCT("tm", "a time structure (tm)") \
STRUCT("cmsghdr", "a cmsghdr") \
STRUCT("msghdr", "a msghdr") \
STRUCT("rpcent", "an rpcent") \
STRUCT("random_data", "a random_data structure") \
STRUCT("drand48_data", "a drand48_data structure") \
STRUCT("termios", "a termios") \
STRUCT("iovec", "an iovec") \
STRUCT("file_handle", "a file handle") \
STRUCT("lconv", "an lconv") \
STRUCT("__locale_struct", "a locale structure") \
STRUCT("aliasent", "an alias") \
STRUCT("fstab", "an fstab") \
STRUCT("group", "a group") \
STRUCT("hostent", "a hostent") \
STRUCT("protoent", "a protoent") \
STRUCT("passwd", "a password") \
STRUCT("spwd", "an spwd") \
STRUCT("ttyent", "a ttyent") \
STRUCT("utmp", "an utmp structure") \
STRUCT("utmpx", "an utmpx structure") \
STRUCT("ifaddrs", "an ifaddrs structure") \
STRUCT("statfs", "a statfs structure") \
STRUCT("statfs64", "a statfs64 structure") \
STRUCT("statvfs", "a statvfs structure") \
STRUCT("statvfs64", "a statvfs64 structure") \
STRUCT("timeb", "a timeb structure") \
STRUCT("_ftsent", "an _ftsent structure") \
STRUCT("sysinfo", "a sysinfo structure") \
STRUCT("rlimit", "an rlimit structure") \
STRUCT("rlimit64", "an rlimit64 structure") \
STRUCT("rusage", "an rusage structure") \
STRUCT("entry", "an entry structure") \
STRUCT("pollfd", "a pollfd structure") \
STRUCT("re_pattern_buffer", "a re_pattern_buffer structure") \
STRUCT("sembuf", "a sembuf structure") \
STRUCT("tms", "a tms structure") \
STRUCT("utsname", "an utsname structure") \
STRUCT("utimbuf", "an utimbuf structure") \
STRUCT2("__va_list_tag", "__va_list_tag (aka, a va_list)", 'A') \
/* ncurses */ \
STRUCT("_win_st", "a _win_st structure") \
STRUCT("MEVENT", "an MEVENT structure") \
TYPEDEF("cchar_t", "a cchar_t") \
/* zlib */ \
STRUCT("gz_header_s", "a gz_header_s structure") \
STRUCT("gzFile_s", "a gzFile_s structure") \
STRUCT("z_stream_s", "a z_stream_s structure") \
\
END()
#define START()
#define STRUCT(s, ret) if (str == s) { return 'p'; } else
#define STRUCT2(s, ret, c) if (str == s) { return c; } else
#define TYPEDEF(s, ret) if (str == s) { return 'p'; } else
#define END() { return 0; }
char ptr2char(const std::string &str) {
/*if ((str == "_IO_FILE")
|| (str == "_G_fpos_t")
|| (str == "sockaddr")
|| (str == "itimerspec")
|| (str == "timespec")
|| (str == "itimerval")
|| (str == "timeval")
|| (str == "timex")
|| (str == "timezone")
|| (str == "dirent")
|| (str == "dirent64")
|| (str == "__dirstream")
|| (str == "tm")
|| (str == "cmsghdr")
|| (str == "msghdr")
|| (str == "rpcent")
|| (str == "random_data")
|| (str == "drand48_data")
|| (str == "termios")
|| (str == "iovec")
|| (str == "file_handle")
|| (str == "lconv")
|| (str == "__locale_struct")
|| (str == "aliasent")
|| (str == "fstab")
|| (str == "group")
|| (str == "hostent")
|| (str == "protoent")
|| (str == "passwd")
|| (str == "spwd")
|| (str == "ttyent")
|| (str == "utmp")
|| (str == "utmpx")
|| (str == "ifaddrs")
|| (str == "statfs")
|| (str == "statfs64")
|| (str == "statvfs")
|| (str == "timeb")
|| (str == "_ftsent")
|| (str == "sysinfo")
|| (str == "rlimit")
|| (str == "rlimit64")
|| (str == "rusage")
|| (str == "entry")
|| (str == "pollfd")
|| (str == "re_pattern_buffer")
|| (str == "sembuf")
|| (str == "tms")
|| (str == "utsname")
|| (str == "utimbuf")
// ncurses
|| (str == "_win_st")
|| (str == "cchar_t")
) {
// FILE*, fpos_t*, ...
return 'p';
} else if (str == "__va_list_tag") {
return 'A';
} else {
return 0;
}*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
#define START()
#define STRUCT(s, ret) if (str == s) { return ret; } else
#define STRUCT2(s, ret, c) if (str == s) { return ret; } else
#define TYPEDEF(s, ret) if (str == s) { return ret; } else
#define END() return "";
const char *ptr2str(const std::string &str) {
/*if (str == "_IO_FILE") {
return "a FILE";
} else if (str == "_G_fpos_t") {
return "a file position";
} else if (str == "sockaddr") {
return "a socket address";
} else if (str == "itimerspec") {
return "an itimerspec";
} else if (str == "timespec") {
return "a timespec";
} else if (str == "itimerval") {
return "an itimerval";
} else if (str == "timeval") {
return "a timeval";
} else if (str == "timex") {
return "a timex";
} else if (str == "timezone") {
return "a timezone";
} else if (str == "dirent") {
return "a dirent";
} else if (str == "dirent64") {
return "a dirent64";
} else if (str == "__dirstream") {
return "a dir stream";
} else if (str == "tm") {
return "a time structure (tm)";
} else if (str == "cmsghdr") {
return "a cmsghdr";
} else if (str == "msghdr") {
return "a msghdr";
} else if (str == "rpcent") {
return "an rpcent";
} else if (str == "random_data") {
return "a random_data structure";
} else if (str == "drand48_data") {
return "a drand48_data structure";
} else if (str == "termios") {
return "a termios";
} else if (str == "iovec") {
return "an iovec";
} else if (str == "file_handle") {
return "a file handle";
} else if (str == "lconv") {
return "an lconv";
} else if (str == "__locale_struct") {
return "a locale structure";
} else if (str == "aliasent") {
return "an alias";
} else if (str == "fstab") {
return "an fstab";
} else if (str == "group") {
return "a group";
} else if (str == "hostent") {
return "a hostent";
} else if (str == "protoent") {
return "a protoent";
} else if (str == "passwd") {
return "a password";
} else if (str == "spwd") {
return "an spwd";
} else if (str == "ttyent") {
return "a ttyent";
} else if (str == "utmp") {
return "an utmp structure";
} else if (str == "utmpx") {
return "an utmpx structure";
} else if (str == "ifaddrs") {
return "an ifaddrs structure";
} else if (str == "statfs") {
return "a statfs structure";
} else if (str == "statfs64") {
return "a statfs64 structure";
} else if (str == "statvfs") {
return "a statvfs structure";
} else if (str == "statvfs64") {
return "a statvfs64 structure";
} else if (str == "timeb") {
return "a timeb structure";
} else if (str == "_ftsent") {
return "an _ftsent structure";
} else if (str == "sysinfo") {
return "a sysinfo structure";
} else if (str == "rlimit") {
return "an rlimit structure";
} else if (str == "rlimit64") {
return "an rlimit64 structure";
} else if (str == "rusage") {
return "an rusage structure";
} else if (str == "entry") {
return "an entry structure";
} else if (str == "pollfd") {
return "a pollfd structure";
} else if (str == "re_pattern_buffer") {
return "a re_pattern_buffer structure";
} else if (str == "sembuf") {
return "a sembuf structure";
} else if (str == "tms") {
return "a tms structure";
} else if (str == "utsname") {
return "an utsname structure";
} else if (str == "utimbuf") {
return "an utimbuf structure";
} else if (str == "__va_list_tag") {
return "__va_list_tag (aka, a va_list)";
// ncurses
} else if (str == "_win_st") {
return "a _win_st structure";
} else if (str == "cchar_t") {
return "a cchar_t";
} else return "";*/
ALL
}
#undef END
#undef TYPEDEF
#undef STRUCT2
#undef STRUCT
#undef START
+89 -104
View File
@@ -1,112 +1,96 @@
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
# Box64: Linux Userspace x86-64 Emulator with a Twist
[View changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an error](https://github.com/ptitSeb/box64/issues/new)
[Changelog](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an Error](https://github.com/ptitSeb/box64/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box64) ![forks](https://img.shields.io/github/forks/ptitSeb/box64) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![issues](https://img.shields.io/github/issues/ptitSeb/box64)
![Build Status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
---
Box64 enables running x86_64 Linux programs, including games, on non-x86_64 Linux systems such as Arm (64-bit little-endian host system required).
Check out Box64 in action on YouTube:
- [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
- [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
- [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
Box64 leverages native system libraries (libc, libm, SDL, OpenGL), offering ease of integration and surprising performance in many applications. For performance benchmarks, check [this analysis](https://box86.org/index.php/2021/06/game-performances/).
With DynaRec for ARM64, RV64 and LA64 platforms, Box64 achieves a speed boost 5-10x faster than the interpreter alone. For a deeper look at DynaRec, see [Inner workings](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
<img src="docs/img/Box64Icon.png" width="96" height="96" alt="Box64 Icon">
_Logo and icon by @grayduck - Thank you!_
---
## 📖 Usage
Box64 offers environment variables to control its behavior. For details, see [Usage Documentation](docs/USAGE.md).
---
## 🚀 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)
---
## 🔄 Version History
See the [Changelog](docs/CHANGELOG.md) for version updates.
---
## 🖥️ Platform Compatibility Notes
Box64 requires 64-bit libraries on the host system, as it directly translates x86_64 function calls. For 32-bit binaries, use Box86.
**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 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`.
---
## ⚙️ Configuration
Box64 has configuration files located in `/etc/box64.box64rc` and `~/.box64rc`, both formatted as `.ini` files. If you don’t want to use the default `/etc/box64.box64rc` file, copy it to `~/.box64rc` to ensure compatibility.
Settings priority: `~/.box64rc` > `/etc/box64.box64rc` > Command line.
---
## 📄 Additional Platform-Specific Notes
### Unity Game Emulation
- Many Unity games require OpenGL 3+, which may be challenging on ARM/RISC-V SBCs.
- **Tip for Pi4 and Pi5 Users**: Set `MESA_GL_VERSION_OVERRIDE=3.2` with `BOX64_DYNAREC_STRONGMEM=1` to prevent freezes and enable strong memory mode.
- **Using Panfrost**: For better compatibility on ARM, enable `PAN_MESA_DEBUG=gl3` to force higher OpenGL profiles. This can help if a game starts but quits unexpectedly before showing any content.
### GTK Programs
Box64 wraps GTK libraries, supporting both gtk2 and gtk3.
### Steam
Steam requires Box86 due to its 32-bit client app, but uses 64-bit local server binaries. Systems with less than 6GB RAM may need a swap file for optimal performance.
### Wine
Box64 supports Wine64 and Proton. For 32-bit components, Box86 is required. Systems with both Box64 and Box86 can run 32- and 64-bit Windows programs.
**Note**: You can use Wine WOW64 build to run x86 Windows programs in Box64-only environments, this is still experimental, but it works in most cases.
### Vulkan
Box64 wraps Vulkan libraries.
----
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).
You can find many Box64 videos on the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube channels.
Since Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates with DynaRec (dynamic recompiler) for the ARM64 and RV64 platform, providing a speed boost between 5 to 10 times faster than using only the interpreter. Some high level information on how DynaRec works can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Some x64 internal opcodes use parts of "Realmode X86 Emulator Library", see [x64primop.c](src/emu/x64primop.c) for copyright details
<img src="docs/img/Box64Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
----
Usage
----
There are a few environment variables to control the behaviour of Box64.
See [here](docs/USAGE.md) for all the environment variables and what they do.
Note: Box64's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
Compiling/Installation
----
> Compilation instructions can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md) \
> Instructions for installing Wine for Box64 can be found [here](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
----
Version history/Change log
----
The change log is available [here](docs/CHANGELOG.md).
----
Notes about 32-bit platforms
----
Because Box64 works by directly translating function calls from x86_64 to host system, the host system (the one Box64 is running on) needs to have 64-bit libraries. Box64 doesn't include any 64-bit <-> 32-bit translation.
So understand that box64 will only run 64-bit linux binaries. For 32-bit binaries, you need box86 (with all the multiarch or proot trickery it implies on a 64-bit OS).
Note that many installer (mojo setup based) will fall back to "x86" when detecting ARM64 OS, and so will try to use box86 for the setup, even if an x86_64 version exist. You can hack your way around with a fake "uname" that return "x86_64" when the argument is "-m"
An alternative solution is to use Wine with new WoW64, but you will be limited to 32bits windows apps and games.
----
Notes about Box64 configuration
----
Box64 now have configurations files. There are 2 files loaded. `/etc/box64.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](https://github.com/ptitSeb/box64/blob/main/docs/USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reason, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
Note that the priority is: `~/.box64rc` > `/etc/box64.box64rc` > command line
So, your settings in `~/.box64rc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games should just work, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers). Also many newer Unity3D (like KSP) games use the BC7 compressed textures, which is not supported on many ARM integrated GPU.
Hint: on Pi4 and Pi5 use `MESA_GL_VERSION_OVERRIDE=3.2`, with `BOX64_DYNAREC_STRONGMEM=1` to prevent freezes and enable strong memory mode, and use Panfrost `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
Notes about GTK programs
----
GTK libraries are now wrapped on box64, both gtk2 and gtk3.
----
Notes about Steam
----
Note that Steam is a hybrid 32-bit / 64-bit. You NEED box86 to run Steam, as the client app is a 32-bit binary. It also uses a 64-bit local server binaries, and that steamwebhelper process is now mandatory, even on the "small mode". And that process will eat lots of memory. So machine with less the 6Gb of RAM will need a swapfile to use Steam.
----
Notes about Wine
----
Wine64 is supported on box64. Proton too. Be aware that 64-bit Wine also includes 32-bit components, to be able to run 32-bit Windows programs. The 32-bit apps will need box86 and will not run without it. On a system where both box64 and box86 are present and working, a wine 64-bit setup can run both 32-bit and 64-bit Windows programs (just use `wine` and `wine64` respectively).
Note that the new 32-bit PE in 64-bit processes that the Wine team is currently implementing in Wine 7.+ is now supported. It's called "new WoW64" and it's working fine on box64, allowing the use of 32bits windows program on 64bits only system.
----
Notes about Vulkan
----
Box64 wraps Vulkan libraries, but note that it as mostly been tested with an AMD RX550 card and on the Freedreno driver, so some extensions may be missing depending on your graphics card.
----
Final word
----
@@ -114,7 +98,7 @@ I want to thank everyone who has contributed to box64 development.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery, ksco, xctan
* For their major financial contribution: [Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For their major financial contribution: [Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their hardware contribution: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* For their continuous advertisements for the box64 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
@@ -122,3 +106,4 @@ So, in no particular order, I want to thank:
And I also thank the many other people who participated even once in this project.
(If you use Box64 in your project, please don't forget to mention it!)
+50 -55
View File
@@ -1,97 +1,92 @@
# box64
![图标](docs/img/Box64Logo.png "图标")
![Official logo](docs/img/Box64Logo.png "Official Logo")
Linux 上用户空间的 x86_64 应用模拟器(支持运行原生库)
# Box64:Linux 用户空间 x86-64 模拟器(支持原生库)
----
![box64 build status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main)
[更新日志](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box64/blob/main/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Report an Error](https://github.com/ptitSeb/box64/issues/new)
[English](docs/README.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md)
![Build Status](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![Stars](https://img.shields.io/github/stars/ptitSeb/box64) ![Forks](https://img.shields.io/github/forks/ptitSeb/box64) ![Contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![Pull Requests](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![Issues](https://img.shields.io/github/issues/ptitSeb/box64)
Box64 可以在非 x86_64 Linux 系统(比如 ARM64)上运行 x86_64 Linux 程序(比如游戏),注意主机系统需要是 64 位小端。
---
您可以在 [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)、[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) 和 [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube 频道上找到许多 Box64 视频。
Box64 可以在非 x86_64 Linux 主机系统(比如 Arm)上运行 x86_64 Linux 程序(比如游戏),目前仅支持 64 位小端主机系统。
由于 Box64 使用一些“系统”库的原生版本,如 libc、libm、SDL 和 OpenGL 等,因此很容易与大多数应用程序集成和使用,并且在许多情况下性能会相当不错。可以在[这里](https://box86.org/index.php/2021/06/game-performances/)查看一些性能测试的样例。
在 YouTube 上查看 Box64 的运行效果:
- [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
- [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
- [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
Box64 集成了适用于 ARM64 和 RV64 平台的 DynaRec(动态重编译器),速度可以比纯解释模式快 5 到 10 倍。可以在[这里](https://box86.org/2021/07/inner-workings-a-high%E2%80%91level-view-of-box86-and-a-low%E2%80%91level-view-of-the-dynarec/)找到有关 DynaRec 工作原理的一些信息。
Box64 可以使用本机原生的系统库(libc、libm、SDL、OpenGL),有着易于集成的特性和令人惊讶的性能。如需性能基准测试,请查看[此分析](https://box86.org/index.php/2021/06/game-performances/)。
一些 x64 内部操作码使用 “Realmode X86 Emulator Library” 的部分内容,有关版权详细信息,请参见 [x64primop.c](../src/emu/x64primop.c)。
借助适用于 ARM64,RV64 以及 LA64 平台的 DynaRec,Box64 的速度比单独使用解释器快 5-10 倍。如需深入了解 DynaRec,请参考[此文章](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)。
<img src="docs/img/Box64Icon.png" width="96" height="96">
<img src="docs/img/Box64Icon.png" width="96" height="96" alt="Box64 Icon">
LOGO 由 @grayduck 制作,感谢!
_Logo 由 @grayduck 制作,感谢!_
----
---
使用方法
----
## 📖 使用方法
有若干环境变量可以控制 Box64 的行为。
Box64 提供了环境变量来控制其行为。有关详细信息请参阅[使用文档](docs/USAGE.md)。
可在[这里](docs/USAGE.md)查看所有环境变量及其作用。
---
注意:Box64 的 Dynarec 使用具有内存保护和段错误信号处理的机制来执行 JIT 代码。所以,如果想使用 GDB 调试使用 JIT 代码的程序(如 Mono/Unity3D),这会触发许多“正常”的段错误。建议在 GDB 中使用类似 `handle SIGSEGV nostop` 来防止它每个段错误处停止。如果你想捕获段错误,可以在 `signals.c` 的 `my_memprotectionhandler` 中设置断点。
## 🚀 编译和安装
----
- [编译说明](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md)
- [安装 Wine](https://github.com/ptitSeb/box64/blob/main/docs/X64WINE.md)
编译/安装
----
---
编译说明可以在[这里](docs/COMPILE.md)查看。
## 🔄 版本历史
----
请参阅[变更日志](docs/CHANGELOG.md)了解版本更新说明。
版本历史
----
---
版本日志在[这里](docs/CHANGELOG.md)。
## 🖥️ 平台兼容性说明
----
Box64 直接转换 x86_64 函数调用到本机原生库,因此需要主机系统上的 64 位库。对于 32 位二进制文​​件,请使用 Box86。
32位平台的注意事项
----
**注意事项**
因为 Box64 的工作原理是直接将函数调用从 x86_64 转换为主机系统,所以主机系统(运行 Box64 的系统)需要有 64 位库。Box64 不包含任何 64 位 <-> 32 位的转换。
1. Box32 模式正在制作中,旨在支持 Box64 上运行 32 位二进制文​​件,敬请期待!
2. 某些安装程序可能会将 64 位的主机操作系统判定为 x86 导致兼容性问题。解决方法:使用假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
所以 box64 只能运行 64 位的 Linux 二进制。对于 32 位二进制则需要使用 box86 来运行(它在 64 位操作系统上使用了 multiarch 和 proot 等技巧来实现运行)。请注意,许多(基于 mojo 的)安装程序在检测到 ARM64 操作系统时将回退到 “x86”,因此即使存在 x86_64 版本,也会尝试使用 box86。这时你可以使用一个假的 `uname` ,并使它在运行参数为 `-m` 时返回 `x86_64`。
---
----
## ⚙️ 配置
关于 Unity 游戏模拟的注意事项
----
Box64 的配置文件位于 `/etc/box64.box64rc` 和 `~/.box64rc`,均为 `.ini` 格式的文件。如果您不想使用默认的 `/etc/box64.box64rc` 文件,请将其复制到 `~/.box64rc` 以确保兼容性。
运行 Unity 游戏应该没什么问题,但还应该注意,许多 Unity3D 游戏需要 OpenGL 3+,这在 ARM SBC 上可能会比较棘手。同时许多较新的 Unity3D游戏(如 KSP)也使用 BC7 压缩纹理,很多 ARM 的集成显卡并不支持。
配置项的优先级:`~/.box64rc` > `/etc/box64.box64rc` > 命令行。
> 提示:如果游戏开始后没有显示任何东西就退出了,在 Pi4 上可以使用 `MESA_GL_VERSION_OVERRIDE=3.2`,在 Panfrost 上则可以使用 `PAN_MESA_DEBUG=gl3` 来使用更高的配置。
---
----
## 📄 特定平台的其他说明
关于GTK程序的注意事项
----
### Unity 游戏
- 许多 Unity 游戏需要 OpenGL 3+,这对 ARM/RISC-V SBC 来说可能具有挑战性。
- **对 Pi4 和 Pi5 用户的提示**:设置 `MESA_GL_VERSION_OVERRIDE=3.2` 和 `BOX64_DYNAREC_STRONGMEM=1` 以防止卡死并启用强内存模式。
- **Panfrost**:为了在 ARM 上实现更好的兼容性,启用 `PAN_MESA_DEBUG=gl3` 以强制更高的 OpenGL Profile。如果游戏可以启动但在显示任何内容之前意外退出,这个设置可能会有所帮助。
box64 封装了 GTK,包括 gtk2 和 gtk3。
### GTK 程序
----
Box64 包装了 GTK 库,支持 gtk2 和 gtk3。
关于 Steam 的注意事项
----
### Steam
请注意,Steam 是 32/64 位混合的应用,所以你需要 box86 才能运行,因为客户端应用程序是 32 位的。它还使用 64 位本地服务器,它的 steamwebhelper 无法被关闭(即使是在最小模式)而且会吃掉大量的内存。对于内存小于 6 GB 的机型,你将会需要创建 swapfile 来运行 Steam。
由于 Steam 客户端应用是 32 位的,需要使用 Box86,但其本地服务器是 64 位的二进制文件。对于内存少于 6GB 的系统,可能需要使用交换文件以获得最佳性能。
----
### Wine
关于 Wine 的注意事项
----
Box64 支持 Wine64 和 Proton。对于 32 位组件,需要 Box86。配备 Box64 和 Box86 的系统可以运行 32 位和 64 位的 Windows 程序。
box64 支持 Wine64,Proton 应该也能运行。请注意,64 位 Wine 包含有 32 位组件,以便能够运行 32 位 Windows 程序。32 位应用程序需要 box86,否则无法运行。在 box64 和 box86 都存在并工作的系统上,64 位的 Wine 可以同时运行 32 位和 64 位 Windows 程序(分别使用 `wine` 和 `wine64`)。请注意,目前在 Wine 7.+ 中实现的 Wine 时间在 64 位进程中的新 32bit PE 尚不支持。我测试了 Wine 7.5 64 位可以正常工作,但是更新的版本可能还不行。
**提示**:您可以使用 Wine WOW64 版本在仅限 Box64 的环境中运行 x86 Windows 程序,这项支持仍处于实验阶段,但在大多数情况下都可以工作。
----
### Vulkan
关于 Vulkan 注意事项
----
Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过测试,因此根据您的显卡,某些扩展可能会丢失。
Box64 包装了 Vulkan 库。
----
@@ -103,7 +98,7 @@ Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过
以下感谢不分先后:
* 代码贡献:rajdakin, mogery, ksco, xctan
* 财务帮助:[Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 财务支持:[Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* 硬件捐赠和 LoongArch 迁移:[xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* 硬件捐赠:[ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* 为本项目持续的宣传:salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS](https://twisteros.com/) team, [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+3 -4
View File
@@ -2,7 +2,7 @@
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [Українська](https://github.com/ptitSeb/box64/blob/main/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
[Дивитись журнал змін](https://github.com/ptitSeb/box64/blob/main/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box64/blob/main/README_CN.md) | [English](https://github.com/ptitSeb/box64/blob/main/README.md) | [Повідомити про помилку](https://github.com/ptitSeb/box64/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box64.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box64) ![forks](https://img.shields.io/github/forks/ptitSeb/box64) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box64) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box64) ![issues](https://img.shields.io/github/issues/ptitSeb/box64)
@@ -40,7 +40,6 @@ Box64 інтегрується з DynaRec (динамічний рекомпіл
> Інструкцію з встановлення Wine для Box64 можна знайти [тут](docs/X64WINE.md).
----
Історія версій/Журнал змін
----
@@ -68,7 +67,7 @@ Box64 інтегрується з DynaRec (динамічний рекомпіл
----
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
Підказка: на Pi4 і Pi5 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2` з `BOX64_DYNAREC_STRONGMEM=1`, щоб запобігти зависанням і ввімкнути режим сильної пам’яті, і використовуйте Panfrost `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра починається, а потім завершується, перш ніж щось показати.
----
@@ -108,7 +107,7 @@ Box64 використовує бібліотеки Vulkan, але зауваж
Є багато способів зробити внесок: внесок коду, фінансовий внесок, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, mogery, ksco, xctan
* За великий фінансовий внесок: [Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За великий фінансовий внесок: [Playtron](https://playtron.one), tohodakilla, FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
* За внесок у апаратне забезпечення: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [SOPHGO](https://www.sophon.ai/), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/), [AYANEO](https://ayaneo.com/), [jiangcuo](https://github.com/jiangcuo)
* За безперервну рекламу Box64: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/Команда [TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg), ekianjo ([Boilingsteam](https://boilingsteam.com/))
+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}"
+43
View File
@@ -1,3 +1,46 @@
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
* => Box32 is a build option for Box64, and is disabled by default
* => Optionnal binfmt integration available for Box32
* => Wrapped some basics libs, including graphics and sounds so a few games already works
* => Work In Progress, many issues remain to be fixed, but some Linux games are playable
* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default
* => Available on the 3 Dynarec backend, with different implementations
* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* +> Can lead to large speedup on certain cases
* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation
* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used!
* Some bugfix and improvment in the Signal handler and internal memory tracking
* Improvment to TRAP signal generation and Handling
* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data
* Improved some x87 operations, like long double handling and infinity comparisons...
* Dynarec: ARM64 fixes to a few opcodes
* Dynarec: RV64 fixes to many opcodes
* Dynarec: LA64 fixes to a few opcodes
* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes
* Dynarec: Many optimisation on some individual opcodes, an all 3 backends
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too
* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one
* ElfLoader: Improved object fetching
* New build profile for SD865 and ORYON
* Changed the installation folder of x86 libs to avoid conflict with linux distro
* Added a few syscalls
* Some more Vulkan extensions wrapped
* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational)
-- Sebastien Chevalier <[email protected]> Thu, 6 Dec 2024 10:30:33 -0100
box64 (0.3.0) unstable; urgency=low
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
+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.
+67
View File
@@ -1,3 +1,70 @@
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
=> Box32 is a build option for Box64, and is disabled by default
=> Optionnal binfmt integration available for Box32
=> Wrapped some basics libs, including graphics and sounds so a few games already works
=> Work In Progress, many issues remain to be fixed, but some Linux games are playable
* Introduced Native Flags. Can be controled with BOX64_DYNAREC_NATIVEFLAGS, but enabled by default
=> Available on the 3 Dynarec backend, with different implementations
=> ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
+> Can lead to large speedup on certain cases
* Improved Strong Memory Model emulation, with better default options and a more efficiant emulation
* Dynarec: RV64: using RVV (and XThreadVector) to implement SSEx opcodes, with some massive speedup when used!
* Some bugfix and improvment in the Signal handler and internal memory tracking
* Improvment to TRAP signal generation and Handling
* Improved CPUID opcodes again, and the various virtual file in /proc that represent those data
* Improved some x87 operations, like long double handling and infinity comparisons...
* Dynarec: ARM64 fixes to a few opcodes
* Dynarec: RV64 fixes to many opcodes
* Dynarec: LA64 fixes to a few opcodes
* Dynarec: RV64 fixes and improvments on LOCK prefixes opcodes
* Dynarec: Many optimisation on some individual opcodes, an all 3 backends
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too
* WREPPING: New wrapperhelper to help coding new wrapping & fixing/enhancing existing one
* ElfLoader: Improved object fetching
* New build profile for SD865 and ORYON
* Changed the installation folder of x86 libs to avoid conflict with linux distro
* Added a few syscalls
* Some more Vulkan extensions wrapped
* More work on build system, and github CI (generating WCP archive), with some fixes on the Android version (still not 100% operational)
v0.3.0
======
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
+82 -47
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 dosen'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
```
@@ -211,62 +215,62 @@ If you encounter some linking errors, try using `NOLOADADDR=ON` (`cmake -D NOLOA
### Use ccmake
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
Alternatively, you can **use the curses-based ccmake (or any other gui frontend for cmake)** to select which platform to use interactively.
### 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 staticaly 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 -389
View File
File diff suppressed because it is too large. Load diff
+565 -266
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."
+1 -1
View File
@@ -1,6 +1,6 @@
# Maintainer: Jai-JAP <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3xxx-git
pkgname=box64-rk3xxx-git
pkgver=r2431.60c6858
pkgrel=1
pkgdesc="Linux Userspace x86_64 Emulator with a twist, targeted at ARM64 Linux devices."
+338 -71
View File
@@ -150,14 +150,18 @@ class FunctionConvention(object):
self.ident = ident
self.name = convname
self.values = valid_chars
# Free letters: B FG J QR T YZa e gh jk mno qrst z
# Free letters: B FG JK QR T YZa e gh jk mno qrst yz
conventions = {
'F': FunctionConvention('F', "System V", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', 'Y', 'y', 'b']),
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'P', 'A'])
'F': FunctionConvention('F', "System V", ['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']),
'W': FunctionConvention('W', "Windows", ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'P', 'A'])
}
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', 'Y', 'y', 'b', '0', '1']
sortedvalues = ['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', '0', '1']
assert(all(all(c not in conv.values[:i] and c in sortedvalues for i, c in enumerate(conv.values)) for conv in conventions.values()))
# Some type depend on HAVE_LD80BITS; define this here so we can use it in readFiles and main
depends_on_ld: str = "DY"
assert(all(c in sortedvalues for c in depends_on_ld))
class FunctionType(str):
@staticmethod
def validate(s: str, post: str) -> bool:
@@ -359,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
@@ -369,7 +373,7 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
# typedefs is a list of all "*FE*" types for the current file
# mystructs is a map of all char -> (structure C name, replacement) for structures
typedefs : JumbledTypedefs = {}
typedefs : JumbledTypedefs = {}
mystructs : JumbledStructures = {}
mystructuses: JumbledStructUses = {}
filespec[filename[:-10]] = (typedefs, mystructs, mystructuses)
@@ -402,9 +406,11 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("libgl", "libegl") \
or match("libgl", "glesv2") \
or match("libegl", "glesv2") \
or match("softokn3", "p11kit") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
or match("libc", "androidshmem") \
or match("crypto", "libssl3") \
or match("tcmallocminimal", "tbbmallocproxy"):
continue
@@ -530,9 +536,22 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
if ln not in gbl[str(dependants)]:
gbl[str(dependants)].append(FunctionType(ln))
if any(c in origLine for c in depends_on_ld):
if (gotype != "GOM") and (gotype != "GOWM") and (gotype != "GOD") and (gotype != "GOWD"):
print("\033[91mError:\033[m type depends on HAVE_LD80BITS but the GO type doesn't support that ({0}:{1})"
.format(filename, line[:-1]))
halt_required = True
if (gotype == "GO2") or (gotype == "GOW2") or (gotype == "GOD") or (gotype == "GODW"):
altfun = line.split(',')[2].split(')')[0].strip()
if altfun == "":
print("\033[91mError:\033[m empty alt function ({0}:{1})".format(filename, line[:-1]))
halt_required = True
elif altfun == funname:
print("\033[91mError:\033[m alt function is the original function ({0}:{1})".format(filename, line[:-1]))
halt_required = True
if origLine[2] == "E":
if (gotype != "GOM") and (gotype != "GOWM"):
if (gotype != "GO2") or not (line.split(',')[2].split(')')[0].strip().startswith('my_')):
if ((gotype != "GO2") and (gotype != "GOW2")) or not (line.split(',')[2].split(')')[0].strip().startswith('my_')):
print("\033[91mThis is probably not what you meant!\033[m ({0}:{1})".format(filename, line[:-1]))
halt_required = True
if len(origLine) > 3:
@@ -823,36 +842,39 @@ 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 = "DK"
return_x87: str = "D"
# Sanity checks
forbidden_simple: Dict[str, str] = {"ARM64": "EDKVOSNMHPAxXYyb", "RV64": "EcwiDKVOSNMHPAxXYyb"}
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))
simple_wraps: Dict[str, Dict[ClausesStr, List[Tuple[FunctionType, int]]]] = {
k1: {} for k1 in forbidden_simple
}
def check_simple(v: FunctionType) -> Dict[str, int]:
regs_count: int = 0
fpr_count : int = 0
ret = {}
ret: Dict[str, int] = {}
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
if v[0] in forbidden_simple[k]:
@@ -864,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:
@@ -871,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
@@ -930,6 +956,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
return v;
{rbr}
static void* io_convert_back(void* v)
{lbr}
if(!v)
return v;
if(v == stdin)
return my__IO_2_1_stdin_;
if(v == stdout)
return my__IO_2_1_stdout_;
if(v == stderr)
return my__IO_2_1_stderr_;
return v;
{rbr}
#define ST0val ST0.d
int of_convert(int);
@@ -966,7 +1005,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
// o = stdout
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
// A = va_list
// 0 = constant 0, 1 = constant 1
// x = float complex
@@ -995,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 = {
@@ -1017,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}
"""
}
@@ -1033,20 +1099,59 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Rewrite the wrapper.c file:
# i and u should only be 32 bits
td_types = {
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t", "complexl_t", "complex_t", "void*"],
# E v c w i I C W u U f d K l L p V O S N M P A
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "void*", "void*"]
# 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
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t", "complexl_t", "void*"],
# E v c w i I C W u U f d l L p V O S N P A
'W': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "void*", "void*"]
}
td_types_nold = {
'F': {'D': "double", 'Y': "complex_t"},
'W': {}
}
td_types_ld = {
k: {t: td_types[k][conventions[k].values.index(t)] for t in td_types_nold[k]} for k in td_types_nold
}
assert(all(k in conventions for k in td_types))
assert(all(k in conventions for k in td_types_nold))
assert(all(t in depends_on_ld for k in td_types_nold for t in td_types_nold[k]))
for k in conventions:
if len(conventions[k].values) != len(td_types[k]):
raise NotImplementedError("len(values) = {lenval} != len(td_types) = {lentypes}".format(lenval=len(conventions[k].values), lentypes=len(td_types[k])))
def generate_typedefs(arr: Iterable[FunctionType], file) -> None:
any_depends_on_ld = False
for v in arr:
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + v + "_t)"
if any(c in v for c in depends_on_ld):
any_depends_on_ld = True
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
if any_depends_on_ld:
file.write("\n#if defined(HAVE_LD80BITS) || defined(ANDROID)\n")
for v in arr:
if all(c not in v for c in depends_on_ld):
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
file.write("#else // !HAVE_LD80BITS && !ANDROID\n")
for k in td_types_nold:
for t in td_types_nold[k]:
td_types[k][conventions[k].values.index(t)] = td_types_nold[k][t]
for v in arr:
if all(c not in v for c in depends_on_ld):
continue
name = v + "_t"
v = v[:-1] if v.endswith('NN') else v # FIXME
file.write("typedef " + td_types[v.get_convention().ident][v.get_convention().values.index(v[0])] + " (*" + name + ")"
+ "(" + ', '.join(td_types[v.get_convention().ident][v.get_convention().values.index(t)] for t in v[2:]) + ");\n")
for k in td_types_nold:
for t in td_types_ld[k]:
td_types[k][conventions[k].values.index(t)] = td_types_ld[k][t]
file.write("#endif\n")
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_header["wrapper.c"].format(lbr="{", rbr="}", version=ver))
@@ -1069,10 +1174,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
conventions['F']: [
"\n#error Invalid return type: emulator\n", # E
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=(int32_t)fn({0});", # i
"R_RAX=(int64_t)fn({0});", # I
"R_RAX=(uint8_t)fn({0});", # c
"R_RAX=(uint16_t)fn({0});", # w
"R_RAX=(uint32_t)fn({0});", # i
"S_RAX=(int64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint32_t)fn({0});", # u
@@ -1080,22 +1185,19 @@ def main(root: str, files: Iterable[Filename], ver: str):
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"R_RAX=(uintptr_t)io_convert_back(fn({0}));", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
'from_complexf(emu, fn({0}));', # x
'from_complex(emu, fn({0}));', # X
'from_complexl(emu, fn({0}));', # Y
'from_complexk(emu, fn({0}));', # y
"from_complexf(emu, fn({0}));", # x
"from_complex(emu, fn({0}));", # X
"from_complexl(emu, fn({0}));", # Y
"\n#error Invalid return type: xcb_connection_t*\n", # b
],
conventions['W']: [
@@ -1111,32 +1213,47 @@ def main(root: str, files: Iterable[Filename], ver: str):
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"R_RAX=io_convert_back(fn({0}));", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
]
}
vals_nold = {
conventions['F']: {
'D': "double db=fn({0}); fpu_do_push(emu); ST0val = db;",
'Y': "from_complexk(emu, fn({0}));",
},
conventions['W']: {}
}
vals_android = {
conventions['F']: {
"D": "long double ld=fn({0}); emu->xmm[0].u128=*(__uint128_t*)&ld;",
"Y": "from_complexl(emu, fn({0}));",
},
conventions['W']: {}
}
vals_ld = {
k: {t: vals[k][k.values.index(t)] for t in vals_nold[k]} for k in vals_nold
}
# vreg: value is in a general register
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1, 0, 0, 0, 0, 1]
# 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
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 0, 1, 0, 0, 0, 1]
# vxmm: value is in a XMM register
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0]
# 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
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]
# vother: value is elsewere
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# 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
vother = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# vstack: value is on the stack (or out of register)
# E v c w i I C W u U f d D K l L p V O S N M H P A x X Y y b
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1, 1, 1, 2, 4, 4, 1]
# 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
vstack = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 2, 4, 1]
arg_r = [
"", # E
"", # v
@@ -1151,7 +1268,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # f
"", # d
"", # D
"", # K
"(intptr_t){p}, ", # l
"(uintptr_t){p}, ", # L
"(void*){p}, ", # p
@@ -1159,14 +1275,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"of_convert((int32_t){p}), ", # O
"io_convert((void*){p}), ", # S
"(void*){p}, ", # N
"(void*){p}, ", # M
"\n#error Use pp instead\n", # H
"(unsigned __int128){p} + ((unsigned __int128){p2} << 64), ", # H
"", # P
"(void*){p}, ", # A
"", # x
"", # x
"", # X
"", # Y
"", # y
"", # Y
"aligned_xcb, ", # b
]
arg_x = [
@@ -1183,7 +1297,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
@@ -1191,14 +1304,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"to_complexf(emu, {p}), ", # x
"to_complex(emu, {p}), ", # X
"", # Y
"", # y
"", # Y
"", # b
]
arg_o = [
@@ -1215,7 +1326,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
@@ -1223,14 +1333,12 @@ def main(root: str, files: Iterable[Filename], ver: str):
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"", # x
"", # X
"", # Y
"", # y
"", # Y
"", # b
]
arg_s = [
@@ -1247,7 +1355,6 @@ def main(root: str, files: Iterable[Filename], ver: str):
"*(float*)(R_RSP + {p}), ", # f
"*(double*)(R_RSP + {p}), ", # d
"LD2localLD((void*)(R_RSP + {p})), ", # D
"FromLD((void*)(R_RSP + {p})), ", # K
"*(intptr_t*)(R_RSP + {p}), ", # l
"*(uintptr_t*)(R_RSP + {p}), ", # L
"*(void**)(R_RSP + {p}), ", # p
@@ -1255,16 +1362,36 @@ def main(root: str, files: Iterable[Filename], ver: str):
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
"io_convert(*(void**)(R_RSP + {p})), ", # S
"*(void**)(R_RSP + {p}), ", # N
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
"*(unsigned __int128*)(R_RSP + {p}), ", # H
"*(void**)(R_RSP + {p}), ", # P
"*(void**)(R_RSP + {p}), ", # A
"*(complexf_t*)(R_RSP + {p}), ", # x
"*(complex_t*)(R_RSP + {p}), ", # X
"to_complexl(emu, R_RSP + {p}), ", # Y
"to_complexk(emu, R_RSP + {p}), ", # y
"to_complexl(emu, R_RSP + {p}), ", # Y
"aligned_xcb, ", # b
]
arg_s_nold = {
'D': "FromLD((void*)(R_RSP + {p})), ", # K
'Y': "to_complexk(emu, R_RSP + {p}), ", # y
}
arg_s_android = {
'D': "*(long double*)(R_RSP + {p})], ",
'Y': "to_complexl(emu, R_RSP + {p}), ",
}
arg_s_ld = {
t: arg_s[conventions['F'].values.index(t)] for t in arg_s_nold
}
vxmm_noandroid = vxmm[:]
vxmm_android = vxmm[:]
vxmm_android[conventions['F'].values.index('D')] = 1
vxmm_android[conventions['F'].values.index('Y')] = 1
arg_x_android = {
'D': "*(long double*)&emu->xmm[{p}], ",
'Y': "to_complexl(emu, (uintptr_t)&emu->xmm[{p}]), ",
}
arg_x_ld = {
t: arg_x[conventions['F'].values.index(t)] for t in arg_x_android
}
# Asserts
for k in conventions:
@@ -1378,16 +1505,26 @@ def main(root: str, files: Iterable[Filename], ver: str):
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
if (r < len(reg_arg)) and (vreg[idx] > 0):
ret = ""
for _ in range(vreg[idx]):
# There may be values in multiple registers
if (vreg[idx] == 2) and ("{p2}" in arg_r[idx]):
if r < len(reg_arg):
# Value is in a general register
ret = ret + arg_r[idx].format(p=reg_arg[r])
r = r + 1
ret = ret + arg_r[idx].format(p=reg_arg[r], p2=reg_arg[r+1])
r = r + 2
else:
# Remaining is in the stack
ret = ret + arg_s[idx].format(p=d)
d = d + 8
else:
for _ in range(vreg[idx]):
# There may be values in multiple registers
if r < len(reg_arg):
# Value is in a general register
ret = ret + arg_r[idx].format(p=reg_arg[r])
r = r + 1
else:
# Remaining is in the stack
ret = ret + arg_s[idx].format(p=d)
d = d + 8
return ret + function_args_systemV(args[1:], d, r, x)
elif (x < 8) and (vxmm[idx] > 0):
# Value is in an XMM register
@@ -1445,22 +1582,128 @@ def main(root: str, files: Iterable[Filename], ver: str):
f.write(" }\n")
for k in gbls:
any_depends_on_ld = False
if k != str(Clauses()):
file.write("\n#if " + k + "\n")
for v in gbls[k]:
if any(c in v for c in depends_on_ld):
any_depends_on_ld = True
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
if any_depends_on_ld:
file.write("\n#if defined(ANDROID)\n")
for c in vals_android:
for t in vals_android[c]:
vals[c][c.values.index(t)] = vals_android[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_android[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_android[t]
vxmm = vxmm_android
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
file.write("#elif !defined(HAVE_LD80BITS)\n")
for c in vals_android:
for t in vals_ld[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_nold[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_nold[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_ld[t]
vxmm = vxmm_noandroid
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
file.write("#else // defined(HAVE_LD80BITS) && !defined(ANDROID)\n")
for v in gbls[k]:
if all(c not in v for c in depends_on_ld):
continue
if v == FunctionType("vFv"):
# Suppress all warnings...
file.write("void vFv(x64emu_t *emu, uintptr_t fcn) { vFv_t fn = (vFv_t)fcn; fn(); (void)emu; }\n")
else:
function_writer(file, v, v + "_t")
file.write("#endif\n")
if k != str(Clauses()):
file.write("#endif\n")
file.write("\n")
for k in redirects:
any_depends_on_ld = False
if k != str(Clauses()):
file.write("\n#if " + k + "\n")
for vr, vf in redirects[k]:
if any(c in vr for c in depends_on_ld):
any_depends_on_ld = True
continue
function_writer(file, vr, vf + "_t")
if any_depends_on_ld:
file.write("\n#if defined(ANDROID)\n")
for c in vals_android:
for t in vals_android[c]:
vals[c][c.values.index(t)] = vals_android[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_android[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_android[t]
vxmm = vxmm_android
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
file.write("#elif !defined(HAVE_LD80BITS)\n")
for c in vals_android:
for t in vals_ld[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_nold[c][t]
for t in arg_s_android:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_nold[t]
for t in arg_x_android:
arg_x[conventions['F'].values.index(t)] = arg_x_ld[t]
vxmm = vxmm_noandroid
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
for c in vals_nold:
for t in vals_nold[c]:
vals[c][c.values.index(t)] = vals_ld[c][t]
for t in arg_s_nold:
arg_s[conventions['F'].values.index(t)] = arg_s_ld[t]
file.write("#else // defined(HAVE_LD80BITS) && !defined(ANDROID)\n")
for vr, vf in redirects[k]:
if all(c not in vr for c in depends_on_ld):
continue
function_writer(file, vr, vf + "_t")
file.write("#endif\n")
if k != str(Clauses()):
file.write("#endif\n")
@@ -1468,7 +1711,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
inttext = ""
file.write("\n")
for k1 in simple_idxs:
file.write("#{inttext}if defined({k1})\nint isSimpleWrapper(wrapper_t fun) {{\n".format(inttext=inttext, k1=k1))
file.write("#{inttext}if defined({k1})\nint isSimpleWrapper(wrapper_t fun) {{\n\tif (box64_is32bits) return 0;\n".format(inttext=inttext, k1=k1))
inttext = "el"
for k in simple_idxs[k1]:
if k != str(Clauses()):
@@ -1478,9 +1721,10 @@ def main(root: str, files: Iterable[Filename], ver: str):
if k != str(Clauses()):
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
file.write("\n#else\nint isSimpleWrapper(wrapper_t fun) {\n\treturn 0;\n}\n#endif\n")
file.write("#else\nint isSimpleWrapper(wrapper_t fun) {\n\treturn 0;\n}\n#endif\n")
# Write the isRetX87Wrapper function
file.write("\nint isRetX87Wrapper32(wrapper_t fun)\n#ifndef BOX32\n{ return 0; }\n#else\n ;\n#endif\n")
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
for k in retx87_idxs:
if k != str(Clauses()):
@@ -1514,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"
@@ -1559,11 +1826,11 @@ def main(root: str, files: Iterable[Filename], ver: str):
return 0
if __name__ == '__main__':
limit = []
limit: List[int] = []
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.4.0.21") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.5.0.24") != 0:
exit(2)
exit(0)
+1655
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -19,10 +19,10 @@ set(ENV{BOX64_LOG} 0)
set(ENV{BOX64_NOBANNER} 1)
if( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
# we are inside box64 folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x64lib)
set(ENV{BOX64_LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x64lib)
else()
# we are inside build folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x64lib)
set(ENV{BOX64_LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x64lib)
endif( EXISTS ${CMAKE_SOURCE_DIR}/x64lib )
# run the test program, capture the stdout/stderr and the result var
+342
View File
@@ -0,0 +1,342 @@
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include "debug.h"
#include "box32.h"
#include "custommem.h"
#include "converter32.h"
#include "khash.h"
KHASH_MAP_INIT_INT64(to, ulong_t);
KHASH_MAP_INIT_INT(from, uintptr_t);
KHASH_MAP_INIT_STR(strings, ptr_t);
static kh_from_t* hash_from = NULL;
static kh_to_t* hash_to = NULL;
#define HASH_MSK 0xf000000f
#define HASH_VAL 0x00ffffff
#define HASH_SHIFT 4
static uint32_t hash_cnt = 1;
static pthread_rwlock_t hash_lock = {0};
static int hash_running = 0;
// locale
static kh_from_t* locale_from = NULL;
static kh_to_t* locale_to = NULL;
static kh_strings_t* const_strings = NULL;
void init_hash_helper() {
hash_from = kh_init(from);
hash_to = kh_init(to);
locale_from = kh_init(from);
locale_to = kh_init(to);
const_strings = kh_init(strings);
pthread_rwlock_init(&hash_lock, NULL);
hash_running = 1;
}
void fini_hash_helper() {
if(!hash_running)
return;
hash_running = 0;
kh_destroy(from, hash_from);
hash_from = NULL;
kh_destroy(to, hash_to);
hash_to = NULL;
hash_cnt = 1;
kh_destroy(from, locale_from);
locale_from = NULL;
kh_destroy(to, locale_to);
locale_to = NULL;
kh_destroy(strings, const_strings); //TODO: does not free memory correctly
const_strings = NULL;
pthread_rwlock_destroy(&hash_lock);
}
// Convert from hash key to original 64bits value
uintptr_t from_hash(ulong_t l) {
// easy case first
if((l&HASH_MSK)!=HASH_MSK) {
return (uintptr_t)l;
}
if(l==0xffffffff) {
return 0xffffffffffffffffll;
}
// get value from hash table second
uintptr_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, from_hash used but hash not running\n");
return ret;
}
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(from, hash_from, l);
if (k==kh_end(hash_from)) {
ret = (uintptr_t)l;
} else {
ret = kh_value(hash_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
// same as from_hash
uintptr_t from_hash_d(ulong_t l) {
return from_hash(l);
}
// Convert from 64bits to hash key, creating it if needed
ulong_t to_hash(uintptr_t p) {
if((p<0x100000000LL) && ((p&HASH_MSK)!=HASH_MSK))
return (ulong_t)p;
if(p==0xffffffffffffffffll) {
return 0xffffffff;
}
ulong_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_hash used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_rdlock(&hash_lock);
k = kh_get(to, hash_to, p);
if(k==kh_end(hash_to)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
ret = HASH_MSK | (((hash_cnt++)&HASH_VAL)<<HASH_SHIFT);
int r;
k = kh_put(to, hash_to, p, &r);
kh_value(hash_to, k) = ret;
k = kh_put(from, hash_from, ret, &r);
kh_value(hash_from, k) = p;
} else {
ret = kh_value(hash_to, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
// Convert from 64bits to hash key and delete the entry from both hash table
ulong_t to_hash_d(uintptr_t p) {
if((p<0x100000000LL) && ((p&HASH_MSK)!=HASH_MSK))
return (ulong_t)p;
if(p==0xffffffffffffffffll)
return 0xffffffff;
ulong_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_hash_d used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_wrlock(&hash_lock);
k = kh_get(to, hash_to, p);
if(k==kh_end(hash_to)) {
/// should this be an assert?
} else {
ret = kh_value(hash_to, k);
// delete both entries
//k = kh_get(to, hash_to, p);
kh_del(to, hash_to, k);
k = kh_get(from, hash_from, ret);
kh_del(from, hash_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
typedef struct struct_locale_s {
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]; //const char*
} struct_locale_t;
// not a real structure
#define LOCALE_SIGN 0x54abcd845412LL
typedef struct struct_locale_32_s {
ptr_t p0[13];
ptr_t p1;
ptr_t p2;
ptr_t p3;
ptr_t p4[13];
uint64_t sign;
struct_locale_t* org; // save the orginal locale
// copy of the array, in case some apps use them
unsigned short int type_b[384];
int tolower[384];
int tohigher[384];
} struct_locale_32_t;
void to_struct_locale(ptr_t d, const struct_locale_t *src) {
if (!src) return;
struct_locale_32_t* dest = from_ptrv(d);
// save the original locale
dest->sign = LOCALE_SIGN;
dest->org = (void*)src;
//copy the 2 arrays
for(int i=0; i<13; ++i) {
dest->p0[i] = to_hashv(src->p0[i]);
}
for(int i=0; i<13; ++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));
memcpy(dest->tolower, src->p2-128*sizeof(int), 384*sizeof(int));
memcpy(dest->tohigher, src->p3-128*sizeof(int), 384*sizeof(int));
dest->p1 = to_ptrv(dest->type_b)+128*sizeof(short);
dest->p2 = to_ptrv(dest->tolower)+128*sizeof(int);
dest->p3 = to_ptrv(dest->tohigher)+128*sizeof(int);
}
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) {
to_hash_d((uintptr_t)src->p4[i]);
}*/
}
// Convert from locale key to original 64bits value
void* from_locale(ptr_t l) {
// easy case first
if(l < 0x100) {
return from_ptrv(l);
}
if(l == 0xffffffff) {
return (void*)-1;
}
// get value from hash table second
void* ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, from_locale used but hash not running\n");
return ret;
}
struct_locale_32_t* loc = from_ptrv(l);
if(loc->sign==LOCALE_SIGN)
return loc->org;
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(from, locale_from, l);
if (k==kh_end(locale_from)) {
ret = from_ptrv(l);
} else {
ret = (void*)kh_value(locale_from, k);
}
pthread_rwlock_unlock(&hash_lock);
//from_struct_locale((struct_locale_t*)ret, l);
return ret;
}
// same as from_locale
void* from_locale_d(ptr_t l) {
return from_locale(l);
}
// Convert from 64bits to locale key, creating it if needed
ptr_t to_locale(void* p) {
if((uintptr_t)p < 0x100) {
return to_ptrv(p);
}
if(p == (void*)-1) {
return 0xffffffff;
}
ptr_t ret = 0;
if(!hash_running) {
//printf_log(LOG_INFO, "Warning, to_locale used but hash not running\n");
return ret;
}
khint_t k;
pthread_rwlock_rdlock(&hash_lock);
k = kh_get(to, locale_to, (uintptr_t)p);
int conv = 0;
if(k==kh_end(locale_to)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
// a locale_t is 5 pointer!
void* m = calloc(1, sizeof(struct_locale_32_t)); // the 3 ctype value are also inside the locale struct
ret = to_ptrv(m);
// add to hash maps
int r;
k = kh_put(to, locale_to, (uintptr_t)p, &r);
kh_value(locale_to, k) = ret;
k = kh_put(from, locale_from, ret, &r);
kh_value(locale_from, k) = (uintptr_t)p;
conv = 1;
} else {
ret = kh_value(locale_to, k);
}
pthread_rwlock_unlock(&hash_lock);
if(conv)
to_struct_locale(ret, (struct_locale_t*)p);
return ret;
}
// Convert from 64bits to hash key and delete the entry from both hash table
ptr_t to_locale_d(void* p) {
if((uintptr_t)p < 0x100)
return to_ptrv(p);
ptr_t ret = 0;
if(!hash_running)
return ret;
khint_t k;
pthread_rwlock_wrlock(&hash_lock);
k = kh_get(to, locale_to, (uintptr_t)p);
if(k==kh_end(locale_to)) {
/// should this be an assert?
} else {
ret = kh_value(locale_to, k);
// free the memory
free_struct_locale(p);
free(from_ptrv(ret));
// delete both entries
k = kh_get(to, locale_to, (uintptr_t)p);
kh_del(to, locale_to, k);
k = kh_get(from, locale_from, ret);
kh_del(from, locale_from, k);
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
char* from_cstring(ptr_t p) {
return (char*)from_ptrv(p);
}
ptr_t to_cstring(char* p) {
if((uintptr_t)p<0x100000000LL)
return to_ptrv(p);
ptr_t ret = 0;
pthread_rwlock_rdlock(&hash_lock);
khint_t k = kh_get(strings, const_strings, p);
if(k==kh_end(const_strings)) {
// create a new key, but need write lock!
pthread_rwlock_unlock(&hash_lock);
pthread_rwlock_wrlock(&hash_lock);
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;
} else
ret = kh_value(const_strings, k);
pthread_rwlock_unlock(&hash_lock);
return ret;
}
ptr_t to_cstring_d(char* p) {
if((uintptr_t)p<0x100000000LL)
return to_ptrv(p);
ptr_t ret = 0;
pthread_rwlock_wrlock(&hash_lock);
khint_t k = kh_get(strings, const_strings, p);
if(k==kh_end(const_strings)) {
// assert?
} else {
ret = kh_value(const_strings, k);
kh_del(strings, const_strings, k);
box32_free(from_ptrv(ret));
}
pthread_rwlock_unlock(&hash_lock);
return ret;
}
+38 -26
View File
@@ -19,10 +19,12 @@
#include "wrapper.h"
#include "x64emu.h"
#include "signals.h"
#include "rcfile.h"
#include "gltools.h"
#include "rbtree.h"
#include "dynarec.h"
#ifdef BOX32
#include "box32.h"
#endif
EXPORTDYN
void initAllHelpers(box64context_t* context)
@@ -31,6 +33,9 @@ void initAllHelpers(box64context_t* context)
if(inited)
return;
my_context = context;
#ifdef BOX32
init_hash_helper();
#endif
init_pthread_helper();
init_bridge_helper();
init_signal_helper(context);
@@ -43,10 +48,12 @@ void finiAllHelpers(box64context_t* context)
static int finied = 0;
if(finied)
return;
DeleteParams();
fini_pthread_helper(context);
fini_signal_helper();
fini_bridge_helper();
#ifdef BOX32
fini_hash_helper();
#endif
fini_custommem_helper(context);
finied = 1;
}
@@ -68,13 +75,14 @@ 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);
}
void x64Syscall(x64emu_t *emu);
void x86Syscall(x64emu_t *emu);
int unlockMutex()
{
@@ -128,7 +136,7 @@ void relockMutex(int locks)
#undef GO
}
static void init_mutexes(box64context_t* context)
void init_mutexes(box64context_t* context)
{
#ifndef DYNAREC
pthread_mutexattr_t attr;
@@ -171,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]);
}
@@ -184,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);
}
@@ -213,25 +221,27 @@ box64context_t *NewBox64Context(int argc)
init_custommem_helper(context);
#ifdef DYNAREC
x64test_init();
#endif
context->maplib = NewLibrarian(context);
context->local_maplib = NewLibrarian(context);
context->versym = NewDictionnary();
context->system = NewBridge();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, vFEv, x64Syscall, 0, NULL);
context->vsyscall = AddBridge(context->system, vFEv, box64_is32bits?x86Syscall:x64Syscall, 0, NULL);
// create the vsyscalls
context->vsyscalls[0] = AddVSyscall(context->system, 96);
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
if(box64_is32bits) {
#ifdef BOX32
addAlternate((void*)0xffffe400, from_ptrv(context->vsyscall));
#endif
} else {
context->vsyscalls[0] = AddVSyscall(context->system, 96);
context->vsyscalls[1] = AddVSyscall(context->system, 201);
context->vsyscalls[2] = AddVSyscall(context->system, 309);
// create the alternate to map at address
addAlternate((void*)0xffffffffff600000, (void*)context->vsyscalls[0]);
addAlternate((void*)0xffffffffff600400, (void*)context->vsyscalls[1]);
addAlternate((void*)0xffffffffff600800, (void*)context->vsyscalls[2]);
}
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
// get handle to box64 itself
@@ -275,7 +285,7 @@ box64context_t *NewBox64Context(int argc)
initAllHelpers(context);
#ifdef DYNAREC
context->db_sizes = init_rbtree();
context->db_sizes = rbtree_init("db_sizes");
#endif
return context;
@@ -291,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)
@@ -351,6 +361,8 @@ void FreeBox64Context(box64context_t** context)
#ifndef STATICBUILD
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
#ifdef BOX32
#endif
#endif
if(ctx->stack_clone)
@@ -377,7 +389,7 @@ void FreeBox64Context(box64context_t** context)
#ifdef DYNAREC
//dynarec_log(LOG_INFO, "BOX64 Dynarec at exit: Max DB=%d, righter=%d\n", ctx->max_db_size, rb_get_righter(ctx->db_sizes));
delete_rbtree(ctx->db_sizes);
rbtree_delete(ctx->db_sizes);
#endif
finiAllHelpers(ctx);
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 3
#define BOX64_REVISION 0
#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__
+597 -1321
View File
File diff suppressed because it is too large. Load diff
+807 -280
View File
File diff suppressed because it is too large. Load diff
+11 -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
@@ -13,23 +15,29 @@
#define EXPORTDYN
#endif
#ifndef MAP_32BIT
#define MAP_32BIT 0x40
#endif
typedef void x64emu_t;
extern void* mapallmem;
extern int box64_is32bits;
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&0x40)))
ret = my_mmap64(NULL, addr, length, prot, flags | 0x40, 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)
+125 -48
View File
@@ -60,6 +60,10 @@ p0-p3 are used to pass scalable predicate arguments to a subroutine and to retur
#define xFlags 26
#define xRIP 27
#define xSavedSP 28
// convert a x86 register to native according to the register mapping
#define TO_NAT(A) (xRAX + (A))
// 32bits version
#define wEAX xRAX
#define wECX xRCX
@@ -140,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)
@@ -178,38 +185,49 @@ int convert_bitmask(uint64_t bitmask);
// ADD / SUB
#define ADDSUB_REG_gen(sf, op, S, shift, Rm, imm6, Rn, Rd) ((sf)<<31 | (op)<<30 | (S)<<29 | 0b01011<<24 | (shift)<<22 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd))
#define ADDx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSx_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(1, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDz_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, lsl, Rn, Rd))
#define ADDxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDz_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.is32bits?0:1, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
#define ADDSUB_IMM_gen(sf, op, S, shift, imm12, Rn, Rd) ((sf)<<31 | (op)<<30 | (S)<<29 | 0b10001<<24 | (shift)<<22 | (imm12)<<10 | (Rn)<<5 | (Rd))
#define ADDx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSx_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(1, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 0, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define ADDz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 0, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 0, 0b00, Rm, 0, Rn, Rd))
#define SUBSx_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(1, 1, 1, 0b00, Rm, 0, Rn, Rd))
#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 SUBSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, 0, Rn, Rd))
#define SUBSw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 1, 1, 0b00, Rm, lsl, Rn, Rd))
#define 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) EMIT(ADDSUB_REG_gen(rex.w, 1, 1, 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);
@@ -218,12 +236,12 @@ int convert_bitmask(uint64_t bitmask);
#define NEGSxw_REG(Rd, Rm) SUBSxw_REG(Rd, xZR, Rm);
#define SUBx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSx_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(1, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSx_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(1, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(0, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(0, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBz_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.is32bits?0:1, 1, 0, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSxw_U12(Rd, Rn, imm12) EMIT(ADDSUB_IMM_gen(rex.w, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define SUBSxw_U12(Rd, Rn, imm12) FEMIT(ADDSUB_IMM_gen(rex.w, 1, 1, 0b00, (imm12)&0xfff, Rn, Rd))
#define CMPSx_U12(Rn, imm12) SUBSx_U12(xZR, Rn, imm12)
#define CMPSw_U12(Rn, imm12) SUBSw_U12(wZR, Rn, imm12)
#define CMPSxw_U12(Rn, imm12) SUBSxw_U12(xZR, Rn, imm12)
@@ -235,18 +253,22 @@ int convert_bitmask(uint64_t bitmask);
#define SBCx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 1, 0, Rm, Rn, Rd))
#define SBCw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 0, Rm, Rn, Rd))
#define SBCxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 0, Rm, Rn, Rd))
#define ADCSx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 0, 1, Rm, Rn, Rd))
#define ADCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 0, 1, Rm, Rn, Rd))
#define ADCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 0, 1, Rm, Rn, Rd))
#define SBCSx_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(1, 1, 1, Rm, Rn, Rd))
#define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
#define ADCSx_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(1, 0, 1, Rm, Rn, Rd))
#define ADCSw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(0, 0, 1, Rm, Rn, Rd))
#define ADCSxw_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(rex.w, 0, 1, Rm, Rn, Rd))
#define SBCSx_REG(Rd, Rn, Rm) FEMIT(ADDSUBC_gen(1, 1, 1, Rm, Rn, Rd))
#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) EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
#define CCMPw(Wn, Wm, nzcv, cond) FEMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) FEMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) FEMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
// ADR
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
@@ -283,13 +305,25 @@ int convert_bitmask(uint64_t bitmask);
#define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
#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))
@@ -301,6 +335,8 @@ 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))
@@ -371,12 +407,21 @@ int convert_bitmask(uint64_t bitmask);
#define STRx_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
#define STRx_REG_LSL3(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b011, 1, Rn, Rt))
#define STRx_REG_UXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b010, 0, Rn, Rt))
#define STRx_REG_SXTW(Rt, Rn, Rm) EMIT(STR_REG_gen(0b11, Rm, 0b110, 0, Rn, Rt))
#define STRw_REG(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b011, 0, Rn, Rt))
#define STRw_REG_LSL2(Rt, Rn, Rm) EMIT(STR_REG_gen(0b10, Rm, 0b011, 1, Rn, Rt))
#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))
@@ -476,12 +521,19 @@ int convert_bitmask(uint64_t bitmask);
// Data Memory Barrier
#define DMB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b01<<5 | 0b11111)
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#define DMB_ISHLD() EMIT(DMB_gen(0b1001))
#define DMB_ISHST() EMIT(DMB_gen(0b1010))
#define DMB_LD() EMIT(DMB_gen(0b1101))
#define DMB_ST() EMIT(DMB_gen(0b1110))
#define DMB_SY() EMIT(DMB_gen(0b1111))
// Data Synchronization Barrier
#define DSB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#define DSB_ISHLD() EMIT(DSB_gen(0b1001))
#define DSB_ISHST() EMIT(DSB_gen(0b1010))
#define DSB_LD() EMIT(DSB_gen(0b1101))
#define DSB_ST() EMIT(DSB_gen(0b1110))
#define DSB_SY() EMIT(DSB_gen(0b1111))
// Break
@@ -492,6 +544,7 @@ int convert_bitmask(uint64_t bitmask);
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
#define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
#define BLR(Rn) EMIT(BR_gen(0, 0b01, 0, 0, Rn, 0))
#define RET(Rn) EMIT(BR_gen(0, 0b10, 0, 0, Rn, 0))
#define CB_gen(sf, op, imm19, Rt) ((sf)<<31 | 0b011010<<25 | (op)<<24 | (imm19)<<5 | (Rt))
#define CBNZx(Rt, imm19) EMIT(CB_gen(1, 1, ((imm19)>>2)&0x7FFFF, Rt))
@@ -517,6 +570,10 @@ int convert_bitmask(uint64_t bitmask);
#define BL(imm26) EMIT(BL_gen(((imm26)>>2)&0x3ffffff))
#define NOP EMIT(0b11010101000000110010000000011111)
#define WFE EMIT(0b11010101000000110010000001011111)
#define WFI EMIT(0b11010101000000110010000001111111)
#define YIELD EMIT(0b11010101000000110010000000111111)
#define SEVL EMIT(0b11010101000000110010000010111111)
#define CSINC_gen(sf, Rm, cond, Rn, Rd) ((sf)<<31 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | 1<<10 | (Rn)<<5 | (Rd))
#define CSINCx(Rd, Rn, Rm, cond) EMIT(CSINC_gen(1, Rm, cond, Rn, Rd))
@@ -529,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))
@@ -556,9 +613,9 @@ int convert_bitmask(uint64_t bitmask);
#define ANDx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b00, N, immr, imms, Rn, Rd))
#define ANDw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b00, 0, immr, imms, Rn, Rd))
#define ANDxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b00, rex.w?(N):0, immr, imms, Rn, Rd))
#define ANDSx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b11, N, immr, imms, Rn, Rd))
#define ANDSw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b11, 0, immr, imms, Rn, Rd))
#define ANDSxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b11, rex.w?(N):0, immr, imms, Rn, Rd))
#define ANDSx_mask(Rd, Rn, N, immr, imms) FEMIT(LOGIC_gen(1, 0b11, N, immr, imms, Rn, Rd))
#define ANDSw_mask(Rd, Rn, immr, imms) FEMIT(LOGIC_gen(0, 0b11, 0, immr, imms, Rn, Rd))
#define ANDSxw_mask(Rd, Rn, N, immr, imms) FEMIT(LOGIC_gen(rex.w, 0b11, rex.w?(N):0, immr, imms, Rn, Rd))
#define ORRx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b01, N, immr, imms, Rn, Rd))
#define ORRw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b01, 0, immr, imms, Rn, Rd))
#define ORRxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b01, rex.w?(N):0, immr, imms, Rn, Rd))
@@ -574,9 +631,10 @@ int convert_bitmask(uint64_t bitmask);
#define ANDw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b00, 0b01, 0, Rm, lsr, Rn, Rd))
#define ANDxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSx_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(1, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSxw_REG(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 0, Rm, 0, Rn, Rd))
#define ANDSw_REG_LSL(Rd, Rn, Rm, lsl) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
#define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
@@ -627,10 +685,10 @@ int convert_bitmask(uint64_t bitmask);
#define BICx(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICw_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, lsl, Rn, Rd))
#define BICSx(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICxw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSxw(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSx(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(1, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(0, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICxw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b00, 0b00, 1, Rm, 0, Rn, Rd))
#define BICSxw(Rd, Rn, Rm) FEMIT(LOGIC_REG_gen(rex.w, 0b11, 0b00, 1, Rm, 0, Rn, Rd))
#define BICx_REG BICx
#define BICw_REG BICw
#define BICxw_REG BICxw
@@ -662,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)
@@ -806,9 +865,9 @@ int convert_bitmask(uint64_t bitmask);
#define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt))
// mrs x0, nzcv : 1101010100 1 1 1 011 0100 0010 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0010(2) op2=0
// MRS : from System register
#define MRS_nzvc(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
#define MRS_nzcv(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
// MSR : to System register
#define MSR_nzvc(Rt) EMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
#define MSR_nzcv(Rt) FEMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=0
#define MRS_fpcr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
#define MSR_fpcr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
@@ -835,6 +894,14 @@ int convert_bitmask(uint64_t bitmask);
#define FPSR_DZC 1
// NEON Invalid Operation Cumulative
#define FPSR_IOC 0
// NZCV N
#define NZCV_N 31
// NZCV Z
#define NZCV_Z 30
// NZCV C
#define NZCV_C 29
// NZCV V
#define NZCV_V 28
// FCSEL
#define FCSEL_scalar(type, Rm, cond, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | (cond)<<12 | 0b11<<10 | (Rn)<<5 | (Rd))
@@ -878,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))
@@ -896,18 +965,24 @@ int convert_bitmask(uint64_t bitmask);
#define VMEM_REG_gen(size, opc, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | 0b10<<10 | (Rn)<<5 | (Rt))
#define VLDR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR32_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b110, 0, Rn, Dt))
#define VLDR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 0, Rn, Dt))
#define VLDR64_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b110, 0, Rn, Dt))
#define VLDR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b01, Rm, 0b011, 1, Rn, Dt))
#define VLDR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 0, Rn, Qt))
#define VLDR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b011, 1, Rn, Qt))
#define VLDR128_REG_SXTW(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b11, Rm, 0b110, 0, Rn, Qt))
#define VSTR32_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR32_REG_LSL2(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR32_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b10, 0b00, Rm, 0b110, 0, Rn, Dt))
#define VSTR64_REG(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 0, Rn, Dt))
#define VSTR64_REG_LSL3(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b011, 1, Rn, Dt))
#define VSTR64_REG_SXTW(Dt, Rn, Rm) EMIT(VMEM_REG_gen(0b11, 0b00, Rm, 0b110, 0, Rn, Dt))
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Qt))
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Qt))
#define VSTR128_REG_SXTW(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b110, 0, Rn, Qt))
#define VLDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | 1<<26 | (imm19)<<5 | (Rt))
#define VLDR32_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b00, ((imm19)>>2)&0x7FFFF, Vt))
@@ -1095,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
@@ -1251,12 +1328,12 @@ 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) EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
#define FCMPD(Dn, Dm) EMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
#define FCMPS_0(Sn) EMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) EMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
#define FCMPS(Sn, Sm) FEMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
#define FCMPD(Dn, Dm) FEMIT(FCMP_scalar(0b01, Dn, Dm, 0b00))
#define FCMPS_0(Sn) FEMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) FEMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
// CVT
#define FCVT_scalar(sf, type, rmode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
@@ -1780,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)))
@@ -2182,7 +2259,7 @@ int convert_bitmask(uint64_t bitmask);
#define LDSETLH(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, Rt))
#define STSETH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 0, Rs, 0b011, Rn, 0b11111))
#define STSETLH(Rs, Rn) EMIT(ATOMIC_gen(0b01, 0, 1, Rs, 0b011, Rn, 0b11111))
// Atomic Signel Max
// Atomic Signed Max
#define LDSMAXxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 0, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXAxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 0, Rs, 0b100, Rn, Rt))
#define LDSMAXALxw(Rs, Rt, Rn) EMIT(ATOMIC_gen(0b10+rex.w, 1, 1, Rs, 0b100, Rn, Rt))
@@ -2298,23 +2375,23 @@ int convert_bitmask(uint64_t bitmask);
// FLAGM extension
// Invert Carry Flag
#define CFINV() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
#define CFINV() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b000<<5 | 0b11111)
#define RMIF_gen(imm6, Rn, mask) (0b10111010000<<21 | (imm6)<<15 | 0b00001<<10 | (Rn)<<5 | (mask))
// Rotate right reg and use as NZCV
#define RMIF(Xn, shift, mask) EMIT(RMIF_gen(shift, Xn, mask))
#define RMIF(Xn, shift, mask) FEMIT(RMIF_gen(shift, Xn, mask))
#define SETF_gen(sz, Rn) (0b00111010000<<21 | (sz)<<14 | 0b0010<<10 | (Rn)<<5 | 0b1101)
// Set NZVc with 8bit value of reg: N=bit7, Z=[0..7]==0, V=bit8 eor bit7, C unchanged
#define SETF8(Wn) EMIT(SETF_gen(0, Wn))
#define SETF8(Wn) FEMIT(SETF_gen(0, Wn))
// Set NZVc with 16bit value of reg: N=bit15, Z=[0..15]==0, V=bit16 eor bit15, C unchanged
#define SETF16(Wn) EMIT(SETF_gen(1, Wn))
#define SETF16(Wn) FEMIT(SETF_gen(1, Wn))
// FLAGM2 extension
// NZCV -> N=0 Z=C|V C=C&!V V=0
#define AXFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
#define AXFLAG() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b010<<5 | 0b11111)
// NZCV -> N=!C&!Z Z=Z&C C=C|Z V=!C&Z
#define XAFLAG() EMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
#define XAFLAG() FEMIT(0b1101010100<<22 | 0b0100<<12 | 0b001<<5 | 0b11111)
// FRINTTS extension
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
+84 -16
View File
@@ -124,6 +124,22 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "NOP");
return buff;
}
if(isMask(opcode, "11010101000000110010000001011111", &a)) {
snprintf(buff, sizeof(buff), "WFE");
return buff;
}
if(isMask(opcode, "11010101000000110010000001111111", &a)) {
snprintf(buff, sizeof(buff), "WFI");
return buff;
}
if(isMask(opcode, "11010101000000110010000000111111", &a)) {
snprintf(buff, sizeof(buff), "YIELD");
return buff;
}
if(isMask(opcode, "11010101000000110010000010111111", &a)) {
snprintf(buff, sizeof(buff), "SEVL");
return buff;
}
// --- LDR / STR
if(isMask(opcode, "f010100011iiiiiii22222nnnnnttttt", &a)) {
int offset = signExtend(imm, 7)<<(2+sf);
@@ -538,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);
@@ -573,6 +599,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "BIC %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, "f1101010hh1mmmmmiiiiiinnnnnddddd", &a)) {
const char* shifts[] = { "LSL", "LSR", "ASR", "ROR" };
if(shift==0 && imm==0)
snprintf(buff, sizeof(buff), "BICS %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
else
snprintf(buff, sizeof(buff), "BICS %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, "f01100100Nrrrrrrssssssnnnnnddddd", &a)) {
uint64_t i = DecodeBitMasks(a.N, imms, immr);
if(!sf) i&=0xffffffff;
@@ -719,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
@@ -744,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)) {
@@ -1300,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':'?');
@@ -1550,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))
@@ -1566,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
@@ -1613,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)) {
@@ -1643,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"};
@@ -1689,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
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+318 -173
View File
@@ -20,7 +20,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -78,9 +78,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, i16);
emit_add16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -102,7 +102,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
emit_or16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x0B:
@@ -117,10 +117,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
emit_or16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -155,9 +154,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
u16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, u16);
emit_adc16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -225,10 +224,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
emit_and16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -253,9 +251,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
MOV32w(x2, i16);
emit_sub16(dyn, ninst, x1, x2, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -281,10 +279,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
BFIz(xRAX, x1, 0, 16);
break;
@@ -307,10 +304,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
u16 = F16;
UXTHw(x1, xRAX);
if(i32) {
MOV32w(x2, i32);
if(u16) {
MOV32w(x2, u16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp16_0(dyn, ninst, x1, x3, x4);
@@ -326,11 +323,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x46:
case 0x47:
INST_NAME("INC Reg16 (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = TO_NAT (opcode&7);
UXTHw(x1, gd);
emit_inc16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x48:
case 0x49:
@@ -341,11 +338,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg16 (32bits)");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xRAX + (opcode&7);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = TO_NAT (opcode&7);
UXTHw(x1, gd);
emit_dec16(dyn, ninst, x1, x2, x3);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x50:
case 0x51:
@@ -356,7 +353,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x56:
case 0x57:
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if (gd==xRSP) {
MOVw_REG(x1, xRSP);
PUSH1_16(x1);
@@ -373,9 +370,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x5E:
case 0x5F:
INST_NAME("POP reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
POP1_16(x1);
BFIw(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0x60:
if(rex.is32bits) {
@@ -397,20 +394,20 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(rex.is32bits) {
INST_NAME("POPA 16bits (32bits)");
POP1_16(x1);
BFIw(xRDI, x1, 0, 16);
BFIz(xRDI, x1, 0, 16);
POP1_16(x1);
BFIw(xRSI, x1, 0, 16);
BFIz(xRSI, x1, 0, 16);
POP1_16(x1);
BFIw(xRBP, x1, 0, 16);
BFIz(xRBP, x1, 0, 16);
POP1_16(x1); // RSP ignored
POP1_16(x1);
BFIw(xRBX, x1, 0, 16);
BFIz(xRBX, x1, 0, 16);
POP1_16(x1);
BFIw(xRDX, x1, 0, 16);
BFIz(xRDX, x1, 0, 16);
POP1_16(x1);
BFIw(xRCX, x1, 0, 16);
BFIz(xRCX, x1, 0, 16);
POP1_16(x1);
BFIw(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
} else {
DEFAULT;
}
@@ -439,16 +436,43 @@ 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");
i16 = F8S;
MOV32w(x2, (uint16_t)i16);
PUSH1_16(x2);
break;
case 0x70:
@@ -488,8 +512,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
@@ -498,7 +521,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
MOVZw(x5, (uint16_t)i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -508,7 +531,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
MOVZw(x5, (uint16_t)i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
@@ -517,8 +540,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
@@ -535,8 +557,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
@@ -575,8 +596,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICH) {
TSTx_mask(ed, 1, 0, 0); // mask=1
B_MARK(cNE);
TBNZ_MARK(ed, 0);
}
if(arm64_atomics) {
SWPALH(gd, x1, ed);
@@ -613,7 +633,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIz(ed, gd, 0, 16);
}
@@ -628,7 +648,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD; // don't need GETGW neither
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIz(gd, ed, 0, 16);
}
@@ -644,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
BFIz(xRAX+(nextop&7)+(rex.b<<3), x3, 0, 16);
} else { // mem <= seg
if (MODREG) {
BFIz(TO_NAT((nextop & 7) + (rex.b << 3)), x3, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x3, wback, fixedaddress);
SMWRITE2();
@@ -657,8 +677,8 @@ 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) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if (MODREG) {
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
@@ -672,8 +692,8 @@ 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) {
wback = xRAX+(nextop&7)+(rex.b<<3);
if (MODREG) {
wback = TO_NAT((nextop & 7) + (rex.b << 3));
BFIz(wback, x1, 0, 16);
} else {
SMREAD();
@@ -689,7 +709,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if(gd==xRAX) {
INST_NAME("NOP");
} else {
@@ -706,13 +726,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x99:
INST_NAME("CWD");
SXTHw(x1, xRAX);
BFXILx(xRDX, x1, 16, 16);
SXTHw(x1, xRAX); // sign extend ax to x1
BFXILx(xRDX, x1, 16, 16); // insert high 16bits of x1 as low DX
break;
case 0x9C:
INST_NAME("PUSHF");
READFLAGS(X_ALL);
WILLWRITE();
PUSH1_16(xFlags);
SMWRITE();
break;
@@ -720,21 +739,21 @@ 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 Interpretor only
// go to epilog, TF should trigger at end of next opcode, so using Interpreter only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
INST_NAME("MOV AX,Od");
if(rex.is32bits)
u64 = F32;
else
@@ -747,14 +766,13 @@ 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
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
WILLWRITELOCK(lock);
lock = isLockAddress(u64);
STRH_U12(xRAX, x1, 0);
SMWRITELOCK(lock);
break;
@@ -764,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");
@@ -821,8 +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");}
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
@@ -860,13 +917,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
UBFXx(x1, xRAX, 0, 16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
emit_test16c(dyn, ninst, x1, u16, x3, x4, x5);
break;
case 0xAB:
WILLWRITE();
if(rep) {
INST_NAME("REP STOSW");
CBZx_NEXT(xRCX);
@@ -922,8 +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");}
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);
@@ -965,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 = xRAX+(opcode&7)+(rex.b<<3);
BFIz(gd, x1, 0, 16);
gd = TO_NAT((opcode & 7) + (rex.b << 3));
if(u16) {
MOV32w(x1, u16);
BFIz(gd, x1, 0, 16);
} else
BFCz(gd, 0, 16);
break;
case 0xC1:
@@ -975,9 +1036,9 @@ 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_CF | X_OF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = (F8)&0x1f;
emit_rol16c(dyn, ninst, x1, u8, x4, x5);
@@ -989,8 +1050,8 @@ 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) {
SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);
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;
emit_ror16c(dyn, ninst, x1, u8, x4, x5);
@@ -1002,11 +1063,11 @@ 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);
u8 = F8;
u8 = (F8)&0x1f;
emit_rcl16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
@@ -1016,11 +1077,11 @@ 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);
u8 = F8;
u8 = (F8)&0x1f;
emit_rcr16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
@@ -1075,15 +1136,22 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Ew, Iw");
nextop = F8;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
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;
@@ -1093,14 +1161,14 @@ 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, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
emit_rol16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
emit_ror16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
@@ -1151,61 +1219,70 @@ 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 {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
ANDw_mask(x2, xRCX, 0, 0b00011); //mask=0x00000000f
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
CMPSw_U12(x2, 15);
B_MARK(cNE);
ADDxw_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 {
TSTw_mask(xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
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
CMPSw_U12(x2, 1);
B_MARK(cNE);
LSRxw(x2, ed, 14); // x2 = d>>14
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFIw(xFlags, x2, F_OF, 1);
MARK;
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);
@@ -1214,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);
@@ -1227,14 +1306,14 @@ 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 {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4);
@@ -1242,14 +1321,14 @@ 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 {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
CBZw_NEXT(x2);
}
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4);
@@ -1257,14 +1336,15 @@ 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 {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
B_NEXT(cEQ);
CBZw_NEXT(x2);
} else {
ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4);
@@ -1272,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) {
@@ -1281,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);}
@@ -1301,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);}
@@ -1309,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);}
@@ -1333,14 +1413,19 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
emit_test16c(dyn, ninst, x1, u16, x3, x4, x5);
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");
@@ -1351,34 +1436,74 @@ 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");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
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);
@@ -1392,14 +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();
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);
SET_DFNONE(x1);
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);
@@ -1415,19 +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);
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;
@@ -1436,14 +1581,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4);
EWBACK;
File diff suppressed because it is too large. Load diff
+47 -38
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
@@ -58,11 +58,13 @@ 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);
VLDR64_REG(v1, ed, x4);
VLD64(v1, ed, fixedaddress);
}
FCMPD(v0, v1);
FCOMI(x1, x2);
@@ -77,10 +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();
VLDR128_REG(v0, ed, x4);
ADDz_REG(x4, x4, ed);
ed = x4;
VLD128(v0, ed, fixedaddress);
}
break;
@@ -92,9 +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);
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;
@@ -108,9 +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);
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;
@@ -126,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);
@@ -136,18 +144,17 @@ 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;
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
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);
@@ -158,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);
@@ -168,17 +175,16 @@ 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;
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
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);
@@ -188,17 +194,16 @@ 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;
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
grab_segdata(dyn, addr, ninst, x1, seg, (MODREG));
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
@@ -215,7 +220,7 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(ed, gd);
} else {
@@ -224,23 +229,25 @@ 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 {
STRH_REG(gd, ed, x4);
STH(gd, ed, fixedaddress);
}
SMWRITE();
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
INST_NAME("MOV Gw, FS:Ew");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(rex.w) {
MOVx_REG(gd, ed);
} else {
@@ -249,13 +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 {
LDRH_REG(x1, ed, x4);
LDH(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
}
}
+107 -79
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -30,7 +30,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int16_t i16;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
@@ -55,7 +55,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -85,7 +85,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -120,7 +120,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGD;
UXTHw(x6, xRAX);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
wback = 0;
UXTHw(x1, ed);
CMPSxw_REG(x6, x1);
@@ -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);
@@ -177,10 +179,10 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("LOCK XADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
UXTHx(x5, gd);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BFIx(gd, ed, 0, 16);
emit_add16(dyn, ninst, x5, gd, x3, x4);
BFIx(ed, x5, 0, 16);
@@ -216,7 +218,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -237,7 +239,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, gd, x3, x4);
BFIx(ed, x6, 0, 16);
@@ -274,16 +276,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
if(!ALIGNED_ATOMICH) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -295,57 +297,68 @@ 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
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
emit_or16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(!i64) {MOV32w(x5, i16);}
if(arm64_atomics) {
UFLAG_IF {
LDSETALH(x5, x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
emit_or16c(dyn, ninst, x1, i16, x3, x4);
} else {
STSETLH(x5, wback);
}
} else {
i64 = convert_bitmask_w(i16);
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_or16c(dyn, ninst, x1, i16, x3, x4);
} else {
emit_or16(dyn, ninst, x1, x5, x3, x4);
}
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
@@ -357,16 +370,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MARKLOCK;
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
@@ -380,16 +393,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MARKLOCK;
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
@@ -402,29 +415,37 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, x5, x3, x4);
emit_and16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
if(arm64_atomics) {
MOV32w(x5, ~i32);
MOV32w(x5, ~i16);
UFLAG_IF {
LDCLRALH(x5, x1, wback);
MVNw_REG(x5, x5);
emit_and16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_and16c(dyn, ninst, x1, i16, x3, x4);
} else {
MVNw_REG(x5, x5);
emit_and16(dyn, ninst, x1, x5, x3, x4);
}
} else {
STCLRLH(x5, wback);
}
} else {
MOV32w(x5, i32);
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
if(i64) {
emit_and16c(dyn, ninst, x1, i16, x3, x4);
} else {
emit_and16(dyn, ninst, x1, x5, x3, x4);
}
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
@@ -435,16 +456,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV32w(x5, i16);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
if(!ALIGNED_ATOMICH) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
@@ -459,57 +480,64 @@ 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
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_xor16(dyn, ninst, x6, x5, x3, x4);
emit_xor16c(dyn, ninst, x6, i16, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
i64 = convert_bitmask_w(i16);
if(arm64_atomics) {
UFLAG_IF {
LDEORALH(x5, x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
} else {
STEORLH(x5, wback);
}
} else {
if(!i64) {MOV32w(x5, i16);}
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
if(i64)
emit_xor16c(dyn, ninst, x1, i16, x3, x4);
else
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
@@ -522,9 +550,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEW(x6, (opcode==0x81)?2:1);
(void)wb1;
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(i32) {
MOV32w(x5, i32);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x5, i16);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
@@ -539,9 +567,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
{
case 0: // INC Ew
INST_NAME("LOCK INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_inc16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
@@ -567,9 +595,9 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
break;
case 1: //DEC Ew
INST_NAME("LOCK DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UXTHw(x6, ed);
emit_dec16(dyn, ninst, x6, x5, x3);
BFIx(ed, x6, 0, 16);
+1 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
+75 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "emu/x64compstrings.h"
uintptr_t dynarec64_66F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
@@ -55,7 +55,81 @@ 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();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
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?
}
GWBACK;
break;
default:
DEFAULT;
+333 -81
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -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;
@@ -55,10 +56,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
return addr;
}
GETREX();
while(opcode==0x67) opcode = F8;
// reset rex after 67
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3) || (opcode>=0x40 && opcode<=0x4F)) {
if((opcode==0xF2) || (opcode==0xF3))
@@ -220,6 +223,39 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x38: /* MAP 0F38 */
opcode = F8;
switch(opcode) {
case 0xF6:
switch(rep) {
case 2:
INST_NAME("ADOX Gd, Ed");
nextop = F8;
READFLAGS(X_OF);
SETFLAGS(X_OF, SF_SUBSET);
GETED32(0);
GETGD;
MRS_nzcv(x3);
LSRw(x4, xFlags, F_OF);
BFIx(x3, x4, 29, 1); // set C
MSR_nzcv(x3); // load CC into ARM CF
IFX(X_OF) {
ADCSxw_REG(gd, gd, ed);
CSETw(x3, cCS);
BFIw(xFlags, x3, F_OF, 1);
} else {
ADCxw_REG(gd, gd, ed);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x6F:
switch(rep) {
case 0:
@@ -271,6 +307,19 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMWRITE();
}
break;
case 2:
INST_NAME("MOVDQU Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VST128(v0, ed, fixedaddress);
SMWRITE();
}
break;
default:
DEFAULT;
}
@@ -282,11 +331,11 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
UBFXxw(gd, eb1, eb2*8, 8);
@@ -301,7 +350,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
UBFXxw(gd, ed, 0, 16);
} else {
SMREAD();
@@ -634,13 +683,32 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_cmp32_0(dyn, ninst, rex, xRAX, x3, x4);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0x63:
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
GETGD;
if(rex.w) {
if(MODREG) { // reg <= reg
SXTWx(gd, xRAX+(nextop&7)+(rex.b<<3));
SXTWx(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
@@ -648,7 +716,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
if(MODREG) { // reg <= reg
MOVw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
MOVw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
@@ -665,6 +733,46 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x0F:
nextop = F8;
switch(nextop) {
case 0x6F:
INST_NAME("MOVDQA Gx,Ex");
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
VLD128(v0, ed, fixedaddress);
}
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
GETGX(v0, 0);
if(rex.w) {
if(MODREG) {
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVQDto(ed, v0, 0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
} else {
if(MODREG) {
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVSto(ed, v0, 0);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(v0, ed, fixedaddress);
SMWRITE2();
}
}
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
@@ -673,13 +781,20 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
WILLWRITE2();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xFE:
INST_NAME("PADDD Gx,Ex");
nextop = F8;
GETGX(v0, 1);
GETEX32(v1, 0, 0);
VADDQ_32(v0, v0, v1);
break;
default:
DEFAULT;
}
@@ -703,8 +818,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
emit_or16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 2: //ADC
@@ -732,8 +846,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
emit_and16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 5: //SUB
@@ -750,8 +863,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
emit_xor16c(dyn, ninst, x1, i16, x2, x4);
EWBACK;
break;
case 7: //CMP
@@ -772,13 +884,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGD; // don't need GETGW here
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << 1, 1, rex, &lock, 0, 0);
STH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -806,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);
@@ -817,9 +932,17 @@ 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);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
SET_DFNONE();
IFX(X_CF | X_OF) {
CMPSx_REG_ASR(x3, gd, 63);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x1, F_OF, 1);
}
}
} else {
MULxw(gd, ed, x4);
}
@@ -827,17 +950,51 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// 32bits imul
UFLAG_IF {
SMULL(gd, ed, x4);
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
MOVw_REG(gd, gd);
SET_DFNONE();
IFX(X_CF | X_OF) {
CMPSw_REG_ASR(x3, gd, 31);
CSETw(x1, cNE);
IFX(X_CF) {
BFIw(xFlags, x1, F_CF, 1);
}
IFX(X_OF) {
BFIw(xFlags, x1, F_OF, 1);
}
}
} else {
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:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F:
// just use regular conditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0x81:
case 0x83:
nextop = F8;
@@ -922,10 +1079,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
gd = ((nextop&0x38)>>3)+(rex.r<<3);
if(rex.rex) {
gb2 = 0;
gb1 = xRAX + gd;
gb1 = TO_NAT(gd);
} else {
gb2 = ((gd&4)<<1);
gb1 = xRAX+(gd&3);
gb1 = TO_NAT(gd & 3);
}
if(gb2) {
gd = x4;
@@ -936,16 +1093,15 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = (nextop&7) + (rex.b<<3);
if(rex.rex) {
eb1 = xRAX+ed;
eb1 = TO_NAT(ed);
eb2 = 0;
} else {
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
}
BFIx(eb1, gd, eb2*8, 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
STB(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -955,10 +1111,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
MOVxw_REG(TO_NAT((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff << (2 + rex.w), (1 << (2 + rex.w)) - 1, rex, &lock, 0, 0);
STxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -967,21 +1122,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("MOV Gb, Eb");
nextop = F8;
if(rex.rex) {
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gb1 = gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
gb2=0;
} else {
gd = (nextop&0x38)>>3;
gb1 = xRAX+(gd&3);
gb1 = TO_NAT(gd & 3);
gb2 = ((gd&4)<<1);
}
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
wback = TO_NAT(wback & 3);
}
if(wb2) {
UBFXw(x4, wback, wb2*8, 8);
@@ -1002,7 +1157,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
GETGD;
if(MODREG) {
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
MOVxw_REG(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
SMREADLOCK(lock);
@@ -1018,18 +1173,51 @@ 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;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = TO_NAT((opcode & 0x07) + (rex.b << 3));
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG EAX, Reg");
MOVxw_REG(x2, xRAX);
MOVxw_REG(xRAX, gd);
MOVxw_REG(gd, x2);
}
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);
i64 = F32S;
emit_test32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5);
break;
case 0xC1:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4);
@@ -1037,7 +1225,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4);
@@ -1064,11 +1252,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
case 6:
INST_NAME("SHL Ed, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
if(u8) { //should create the geted32_ib utility function for that
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4);
WBACK;
}
break;
case 5:
INST_NAME("SHR Ed, Ib");
@@ -1147,10 +1337,10 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = F8;
if(!rex.rex) {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
}
MOV32w(x3, u8);
@@ -1163,7 +1353,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = x3;
} else
ed = xZR;
WILLWRITELOCK(lock);
STB(ed, wback, fixedaddress);
SMWRITELOCK(lock);
}
@@ -1173,13 +1362,12 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);
i64 = F32S;
MOV64xw(x3, i64);
WILLWRITELOCK(lock);
STxw(x3, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -1201,21 +1389,23 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
Bcond(YES, i32); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (32bits)");
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
@@ -1224,9 +1414,9 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
READFLAGS(X_ZF);
i8 = F8S;
MOVw_REG(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 32);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
@@ -1259,8 +1449,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED32H(x1, 4);
i64 = F32S;
MOV64xw(x2, i64);
emit_test32(dyn, ninst, rex, ed, x2, x3, x4, x5);
emit_test32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
break;
case 2:
INST_NAME("NOT Ed");
@@ -1277,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_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;
@@ -1289,13 +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_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w?d_mul64:d_mul32);
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);
}
}
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;
@@ -1307,14 +1519,28 @@ 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");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
GETED32(0);
MOVw_REG(x3, xRAX);
@@ -1348,12 +1574,25 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
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);
SET_DFNONE(x2);
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);
@@ -1385,6 +1624,13 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(xRAX, x2);
}
}
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;
@@ -1393,21 +1639,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETED32(0);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
WBACK;
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETED32(0);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
WBACK;
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)
{
@@ -1416,16 +1662,15 @@ 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);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
GETIP_(addr);
if(box64_dynarec_callret) {
if(BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
@@ -1434,15 +1679,22 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
STPx_S7_preindex(x4, xRIP, xSP, -16);
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
if(BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
BR(x4);
}
break;
default:
DEFAULT;
+24 -20
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -66,11 +66,12 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
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;
@@ -79,11 +80,12 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
GETGD;
if(MODREG) { // reg => reg
MOVxw_REG(gd, xRAX+(nextop&7)+(rex.b<<3));
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;
@@ -92,19 +94,20 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
nextop=F8;
if(MODREG) { // reg <= reg
POP1_32(x1);
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), 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;
+10 -8
View File
@@ -18,7 +18,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGm gd = ((nextop&0x38)>>3)
@@ -80,21 +80,23 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size);\
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
Bcond(YES, i32); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
@@ -103,9 +105,9 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
SUBw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
CBZw_NEXT(x1); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
+51 -9
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
@@ -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;
@@ -103,10 +109,46 @@ uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
}
}
else if((vex.m==VEX_M_0F) && (vex.p==VEX_P_66)) {
switch(opcode) {
case 0xD6:
INST_NAME("VMOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOV(v1, v0);
YMM0((nextop&7)+(rex.b<<3));
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xfff<<3, 7, rex, NULL, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0x6E:
INST_NAME("VMOVD Gx, Ed");
nextop = F8;
GETGX_empty(v0);
GETED(0);
VEORQ(v0, v0, v0); // RAZ vector
if(rex.w) {
FMOVDx(v0, ed);
} else {
FMOVSw(v0, ed);
}
YMM0(gd);
break;
default:
DEFAULT;
}
}
else {DEFAULT;}
if((*ok==-1) && (box64_dynarec_log>=LOG_INFO || box64_dynarec_dump || box64_dynarec_missing)) {
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__
+6 -3
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
@@ -67,10 +67,13 @@ uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = dynarec64_AVX_F2_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_F2))
addr = dynarec64_AVX_F2_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F3))
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)) {
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
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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;
+173 -17
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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,7 +69,33 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
GETGD;
GETED(0);
GETVD;
BICxw(gd, ed, vd);
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) {
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_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw_IMM(x1, gd, rex.w?63:31);
BFIw(xFlags, x1, F_SF, 1);
}
}
break;
case 0xF3:
nextop = F8;
@@ -84,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;
}
@@ -116,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:
+91 -55
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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) */
@@ -295,6 +292,29 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
BFIx(gd, x2, 3, 1);
}
break;
case 0x51:
INST_NAME("VSQRTPD Gx, Ex");
nextop = F8;
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(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFCMEQQD(d0, v1, v1); // 0 if NAN, 1 if not NAN
VFSQRTQD(v0, v1);
VFCMEQQD(d1, v0, v0); // 0 => out is NAN
VBICQ(d1, d0, d1); // forget it in any input was a NAN already
VSHLQ_64(d1, d1, 63); // only keep the sign bit
VORRQ(v0, v0, d1); // NAN -> -NAN
} else {
VFSQRTQD(v0, v1);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x54:
INST_NAME("VANDPD Gx, Vx, Ex");
@@ -339,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
@@ -363,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
@@ -387,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) {
if(BOX64ENV(dynarec_fastround)==2) {
FCVTXN(v0, v1);
} else {
u8 = sse_setround(dyn, ninst, x1, x2, x4);
@@ -398,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) {
if(BOX64ENV(dynarec_fastround)==2) {
FCVTXN2(v0, v1);
} else {
FCVTN2(v0, v1);
@@ -411,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 {
@@ -434,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);
}
@@ -447,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
@@ -471,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
}
@@ -488,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
@@ -512,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) {
@@ -520,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
}
@@ -1105,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);
@@ -1120,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
@@ -1136,7 +1156,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
GETGX(v0, 0);
if(rex.w) {
if(MODREG) {
ed = xRAX + (nextop&7) + (rex.b<<3);
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVQDto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
@@ -1145,7 +1165,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
}
} else {
if(MODREG) {
ed = xRAX + (nextop&7) + (rex.b<<3);
ed = TO_NAT((nextop & 0x07) + (rex.b << 3));
VMOVSto(ed, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
@@ -1166,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();
}
@@ -1216,7 +1236,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(v0!=v2) VMOVQ(v0, v2);
if(MODREG) {
u8 = (F8)&7;
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
VMOVQHfrom(v0, u8, ed);
} else {
SMREAD();
@@ -1231,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 {
@@ -1373,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
@@ -1597,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
@@ -1773,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);
@@ -1788,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);
@@ -1803,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);
@@ -1858,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;
+573 -149
View File
@@ -22,7 +22,12 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
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)
{
@@ -94,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;
@@ -121,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;
@@ -201,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;
@@ -238,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);
@@ -250,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);
@@ -269,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);
@@ -305,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);
@@ -315,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:
@@ -332,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:
@@ -391,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);
@@ -430,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);
@@ -454,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);
@@ -492,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;
@@ -520,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:
@@ -554,38 +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 {
WILLWRITE2();
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);
// check if mask as anything, else scipt the whole read/write to avoid a SEGFAULT.
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;
@@ -593,44 +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 {
WILLWRITE2();
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 scipt the whole read/write to avoid a SEGFAULT.
// 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;
@@ -638,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);
@@ -680,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);
@@ -706,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);
@@ -806,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);
@@ -994,54 +1266,138 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
break;
case 0x8C:
INST_NAME("VMASKMOVD/Q Vx, Ex, Gx");
INST_NAME("VPMASKMOVD/Q Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_VXEX(v0, v2, v1, 0);
if(MODREG) {
if(!l) {
GETGX_empty_VXEX(v0, v2, v1, 0);
} else {
GETGY_empty_VYEY(v0, v2, v1);
}
if(rex.w)
VSSHRQ_64(q0, v2, 63);
else
VSSHRQ_32(q0, v2, 31);
VANDQ(v0, v1, q0);
} else {
GETGY_empty_VYEY(v0, v2, v1);
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);
}
unscaled = 0;
// 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!
VEORQ(v1, v1, v1);
if(rex.w) {
VSSHRQ_64(q0, v2, 63);
VMOVQDto(x4, q0, 0);
CBZx(x4, 4+1*4);
VLD1_64(v1, 0, ed);
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, 8);
} else {
VSSHRQ_32(q0, v2, 31);
VMOVSto(x4, q0, 0);
CBZx(x4, 4+1*4);
VLD1_32(v1, 0, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 1);
CBZx(x4, 4+1*4);
VLD1_32(v1, 1, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 2);
CBZx(x4, 4+1*4);
VLD1_32(v1, 2, ed);
ADDx_U12(ed, ed, 4);
VMOVSto(x4, q0, 3);
CBZx(x4, 4+1*4);
VLD1_32(v1, 3, ed);
if(!l && vex.l)
ADDx_U12(ed, ed, 4);
}
VMOVQ(v0, v1);
}
if(rex.w)
VSSHRQ_64(q0, v2, 63);
else
VSSHRQ_32(q0, v2, 31);
VANDQ(v0, v1, q0);
}
if(!vex.l) YMM0(gd);
break;
case 0x8E:
INST_NAME("VMASKMOVD/Q Ex, Vx, Gx");
INST_NAME("VPMASKMOVD/Q Ex, Vx, Gx");
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;
@@ -1057,7 +1413,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
MOV64x(x5, F32S64);
eb1 = x5;
} else
eb1 = xRAX + (u8&0x7)+(rex.b<<3); // base
eb1 = TO_NAT((u8 & 0x7) + (rex.b << 3)); // base
eb2 = ((u8>>3)&7)+(rex.x<<3); // index
if(nextop&0x40)
i32 = F8S;
@@ -1116,7 +1472,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
MOV64x(x5, F32S64);
eb1 = x5;
} else
eb1 = xRAX + (u8&0x7)+(rex.b<<3); // base
eb1 = TO_NAT((u8 & 0x7) + (rex.b << 3)); // base
eb2 = ((u8>>3)&7)+(rex.x<<3); // index
if(nextop&0x40)
i32 = F8S;
@@ -1208,7 +1564,18 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
}
YMM0(gd);
break;
case 0x9A:
INST_NAME("VFNMSUB132PS/D Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_VXEX(v0, v2, v1, 0); } else { GETGY_VYEY(v0, v2, v1); }
if(rex.w) VFNEGQD(q0, v2); else VFNEGQS(q0, v2);
if(rex.w) VFMLAQD(q0, v0, v1); else VFMLAQS(q0, v0, v1);
VMOVQ(v0, q0);
}
if(!vex.l) YMM0(gd);
break;
case 0x9B:
INST_NAME("VFMSUB132SS/D Gx, Vx, Ex");
nextop = F8;
@@ -1233,7 +1600,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(!l && v0!=v2) q0 = fpu_get_scratch(dyn, ninst);
if(v0!=v2) VMOVQ(q0, v2); else q0 = v2;
if(rex.w) VFMLSQD(q0, v0, v1); else VFMLSQS(q0, v0, v1);
VMOVQ(v0, q0);
if(q0!=v0) VMOVQ(v0, q0);
}
if(!vex.l) YMM0(gd);
break;
@@ -1271,6 +1638,27 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
YMM0(gd);
break;
case 0xA6:
INST_NAME("VFMADDSUB213PS/D Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
TABLE64(x2, (rex.w)?((uintptr_t)&addsubpd):((uintptr_t)&addsubps));
VLDR128_U12(q0, x2, 0);
q1 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_VXEX(v0, v2, v1, 0); } else { GETGY_VYEY(v0, v2, v1); }
if(rex.w) {
VFMULQD(q1, v1, q0);
VFMLAQD(q1, v0, v2);
} else {
VFMULQS(q1, v1, q0);
VFMLAQS(q1, v0, v2);
}
VMOVQ(v0, q1);
}
if(!vex.l) YMM0(gd);
break;
case 0xA8:
INST_NAME("VFMADD213PS/D Gx, Vx, Ex");
nextop = F8;
@@ -1404,9 +1792,6 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
INST_NAME("VFMADDSUB231PS/D Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
static float addsubps[4] = {-1.f, 1.f, -1.f, 1.f};
static double addsubpd[2] = {-1., 1.};
MAYUSE(addsubps); MAYUSE(addsubpd);
TABLE64(x2, (rex.w)?((uintptr_t)&addsubpd):((uintptr_t)&addsubps));
VLDR128_U12(q0, x2, 0);
for(int l=0; l<1+vex.l; ++l) {
@@ -1426,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;
@@ -1513,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;
+86 -29
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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); }
@@ -368,7 +374,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 1);
@@ -385,7 +391,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 1);
@@ -402,7 +408,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 1);
@@ -423,7 +429,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
@@ -490,7 +496,6 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x3, (nextop&7)+(rex.b<<3));
} else {
WILLWRITE2();
v1 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<(3+vex.l), vex.l?15:7, rex, NULL, 0, 1);
}
@@ -593,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;
@@ -771,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;
}
+110 -40
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -88,7 +88,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(v1!=v2) VMOVeD(v1, 1, v2, 1);
YMM0((nextop&7)+(rex.b<<3));
} else {
WILLWRITE2();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
@@ -114,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);
@@ -141,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) {
@@ -162,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);
@@ -172,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) {
@@ -189,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
@@ -212,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");
@@ -241,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);
}
@@ -252,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:
@@ -280,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:
@@ -323,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);
@@ -361,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");
@@ -390,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);
@@ -413,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)
+41 -6
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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;
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F3A(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
+111 -33
View File
@@ -22,7 +22,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
@@ -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) {
@@ -215,39 +215,72 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
VMOVeS(v0, 0, d0, 0);
YMM0(gd);
break;
case 0x53:
INST_NAME("VRCPSS Gx, Vx, Ex");
nextop = F8;
GETGX(v0, 1);
GETVX(v2, 0);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn, ninst);
FMOVS_8(d0, 0b01110000); //1.0f
FDIVS(d0, d0, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d0, 0);
YMM0(gd);
break;
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:
@@ -271,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
@@ -299,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:
@@ -326,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:
@@ -380,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 {
@@ -432,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();
}
@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "my_cpuid.h"
#include "emu/x87emu_private.h"
#include "emu/x64shaext.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
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;
GETGD;
GETED(0);
GETVD;
ANDx_mask(x3, vd, 1, 0, rex.w?5:4); // mask 0x3f/0x1f
ASRxw_REG(gd, ed, x3);
break;
default:
DEFAULT;
}
return addr;
}
+50 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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:
@@ -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]");
@@ -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;
+69 -33
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -161,21 +161,21 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
ADDw_U12(x5, x5, i2);
}
ANDw_mask(x5, x5, 0, 3); // (emu->top + i)&7
ANDw_mask(x5, x5, 0, 2); // (emu->top + i)&7
}
// load tag
LDRH_U12(x3, xEmu, offsetof(x64emu_t, fpu_tags));
if(i2<0) {
LSLw_IMM(x3, x3, -i2*2);
} else if(i2>0) {
ORRw_mask(x3, x3, 0b010000, 0b001111); // 0xffff0000
LSRw_IMM(x3, x3, i2*2);
}
TSTw_mask(x3, 0, 1); // 0b11
B_MARK3(cNE); // empty: C3,C2,C0 = 101
// load x2 with ST0 anyway, for sign extraction
ADDx_REG_LSL(x1, xEmu, x5, 3);
LDRx_U12(x2, x1, offsetof(x64emu_t, x87));
// load tag
if(i2>=0) {
LDRH_U12(x3, xEmu, offsetof(x64emu_t, fpu_tags));
if(i2>0) {
ORRw_mask(x3, x3, 0b010000, 0b001111); // 0xffff0000
LSRw_IMM(x3, x3, i2*2);
}
TSTw_mask(x3, 0, 1); // 0b11
B_MARK3(cNE); // empty: C3,C2,C0 = 101
}
}
} else {
// simply move from cache reg to x2
@@ -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,13 +288,17 @@ 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 emiting 1\n");
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emitting 1\n");
u8 = F8;
u8 = F8;
} else {
@@ -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) {
+26 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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;
@@ -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");
@@ -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;
+75 -68
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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;
@@ -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;
+50 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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:
@@ -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]");
@@ -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;
+8 -7
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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);}
+26 -1
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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:
@@ -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:
+30 -23
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
#include "dynarec_arm64_functions.h"
@@ -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);
+369 -294
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
@@ -27,25 +27,43 @@ 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) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int 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) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -55,33 +73,51 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
// emit OR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or32c(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) {
MOV64xw(s3, c);
emit_or32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_xw(c);
if(mask) {
ORRxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
ORRxw_REG(s1, s1, s3);
SET_DFNONE();
}
ORRxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int 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) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -94,25 +130,43 @@ 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) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int 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) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -122,33 +176,55 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// emit XOR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
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 && !((!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);
}
int mask = convert_bitmask_xw(c);
if(mask) {
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
EORxw_REG(s1, s1, s3);
SET_DFNONE();
}
if(!mask) {
MVNxw_REG(s1, s1);
} else {
EORxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
int 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) TSTxw_REG(s1, s1);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -161,10 +237,10 @@ 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) {
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_REG(s1, s1, s2);
} else {
ANDxw_REG(s1, s1, s2);
@@ -172,17 +248,30 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -192,40 +281,49 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// emit AND32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and32c(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) {
MOV64xw(s3, c);
emit_and32(dyn, ninst, rex, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, rex.w?d_and64:d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_xw(c);
if(mask) {
IFX(X_ALL) {
ANDSxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
} else {
MOV64xw(s3, c);
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
} else {
ANDxw_REG(s1, s1, s3);
}
SET_DFNONE();
}
IFX(X_ZF|X_SF|X_CF|X_OF) {
ANDSxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDxw_mask(s1, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -237,9 +335,9 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_or8);
} else {
SET_DFNONE();
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -256,20 +354,20 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit OR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c);
emit_or8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c&0xff);
ORRw_REG(s1, s1, s3);
SET_DFNONE();
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -288,9 +386,9 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_xor8);
} else {
SET_DFNONE();
}
EORx_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -307,20 +405,20 @@ void emit_xor8(dynarec_arm_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_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c&0xff);
emit_xor8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c&0xff);
EORw_REG(s1, s1, s3);
SET_DFNONE();
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -339,9 +437,9 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_and8);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
@@ -355,13 +453,19 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw_REG(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 8)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -369,27 +473,23 @@ void emit_and8(dynarec_arm_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_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, uint8_t c, int s3, int s4)
{
int mask = convert_bitmask_w(c);
if(!mask) {
MOV32w(s3, c);
emit_and8(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int mask = convert_bitmask_w(c);
if(mask) {
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
} else {
MOV32w(s3, c&0xff);
IFX(X_ZF) {
ANDSw_REG(s1, s1, s3);
} else {
ANDw_REG(s1, s1, s3);
}
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -398,28 +498,33 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 8)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 7);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_or16);
} else {
SET_DFNONE();
}
ORRw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -436,59 +541,41 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit OR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_or16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// ORRS_IMM8(s1, s1, c, 0);
// } else {
// ORR_IMM8(s1, s1, c, 0);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// ORR_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s4);
// }
//}
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_or16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_or16);
} else {
SET_DFNONE();
}
ORRw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_xor16);
} else {
SET_DFNONE();
}
EORw_REG(s1, s1, s2);
IFX(X_PEND) {
@@ -505,61 +592,44 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit XOR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_xor16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// XORS_IMM8(s1, s1, c);
// } else {
// XOR_IMM8(s1, s1, c);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// XORS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// XOR_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s4);
// }
//}
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_xor16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_xor16);
} else {
SET_DFNONE();
}
EORw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit AND16 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_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
SET_DF(s3, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
SET_DF(s4, d_and16);
} else {
SET_DFNONE();
}
IFX(X_ALL) {
IFX(X_ZF) {
ANDSw_REG(s1, s1, s2);
} else {
ANDw_REG(s1, s1, s2);
@@ -571,13 +641,19 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw_REG(xFlags, xFlags, s3);
}
IFX(X_ZF) {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
if(arm64_flagm) {
COMP_ZFSF(s1, 16)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -585,47 +661,46 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// emit AND16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// SET_DF(s4, d_and16);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c>=0 && c<256) {
// IFX(X_ALL) {
// ANDS_IMM8(s1, s1, c);
// } else {
// AND_IMM8(s1, s1, c);
// }
// } else {
// IFX(X_PEND) {} else {MOVW(s3, c);}
// IFX(X_ALL) {
// ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
// } else {
// AND_REG_LSL_IMM5(s1, s1, s3, 0);
// }
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_CF | X_AF | X_ZF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF)|(1<<F_ZF), 0);
// }
// IFX(X_OF) {
// BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 15);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s4);
// }
//}
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int16_t c, int s3, int s4)
{
int mask = convert_bitmask_w((uint16_t)c);
if(!mask) {
MOV32w(s3, (uint16_t)c);
emit_and16(dyn, ninst, s1, s3, s3, s4);
return;
}
IFX(X_PEND) {
SET_DF(s4, d_and16);
} else {
SET_DFNONE();
}
IFX(X_ZF) {
ANDSw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
ANDw_mask(s1, s1, mask&0x3F, (mask>>6)&0x3F);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
if(arm64_flagm) {
COMP_ZFSF(s1, 16)
} else {
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s3, cEQ);
BFIw(xFlags, s3, F_ZF, 1);
}
}
IFX(X_SF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+392 -92
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
@@ -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
@@ -47,21 +47,31 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s5, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s5, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
@@ -78,22 +88,37 @@ 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
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_OF|X_AF|X_CF) {
MOV32w(s4, (1<<F_OF)|(1<<F_AF)|(1<<F_CF));
BICw(xFlags, xFlags, s4);
IFX(X_CF) {
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s3, s1, (rex.w)?63:31);
BFIw(xFlags, s3, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
@@ -109,33 +134,62 @@ 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();
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
BICw(s4, s2, s1); // s4 = ~op1 & op2
}
COMP_ZFSF(s5, 16)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVNw_REG(s4, s1); // s4 = ~d
ORRw_REG(s4, s4, s2); // s4 = ~d | s
ANDw_REG(s4, s4, s5); // s4 = res & (~d | s)
BICw_REG(s3, s2, s1); // s3 = s & ~d
ORRw_REG(s3, s4, s3); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
LSRw(s4, s3, 15);
BFIw(xFlags, s4, F_CF, 1); // CF : bc & 0x8000
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
SUBSw_REG_LSL(s5, s5, s2, 16);
IFX(X_AF) {
ANDw_REG_LSR(s3, s3, s5, 16); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
LSRw(s4, s3, 14);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_AF) {
ANDw_REG(s3, s3, s5); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
@@ -152,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) {
@@ -171,34 +225,64 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
IFX_PENDOR0 {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp8);
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s4);
SET_DFNONE();
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
IFX(X_AF) {
ORNw_REG(s3, s2, s1); // s3 = ~op1 | op2
BICw(s4, s2, s1); // s4 = ~op1 & op2
}
COMP_ZFSF(s5, 8)
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
ORNw_REG(s4, s2, s1); // s4 = ~d | s
ANDw_REG(s4, s4, s5); // s4 = res & (~d | s)
BICw_REG(s3, s2, s1); // s3 = s & ~d
ORRw_REG(s3, s4, s3); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
LSRw(s4, s3, 7);
BFIw(xFlags, s4, F_CF, 1); // CF : bc & 0x80
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
SUBSw_REG_LSL(s5, s5, s2, 24);
IFX(X_AF) {
ANDw_REG_LSR(s3, s3, s5, 24); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
// inverted carry
IFNATIVE(NF_CF) {
GEN_INVERTED_CARRY();
} else {
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
}
IFX(X_OF) {
LSRw(s4, s3, 6);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
IFNATIVE(NF_VF) {} else {
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_AF) {
ANDw_REG(s3, s3, s5); // s3 = (~op1 | op2) & res
ORRw_REG(s3, s3, s4); // s3 = (~op1 & op2) | ((~op1 | op2) & res)
LSRw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
@@ -214,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) {
@@ -234,23 +318,85 @@ 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 | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSxw_REG(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s5);
}
}
// emit TEST32 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
int mask = convert_bitmask_xw(c);
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE();
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {
BFCw(xFlags, F_CF, 1);
}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
if(mask) {
ANDSxw_mask(s3, s1, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV64xw(s3, c);
ANDSxw_REG(s3, s1, s3); // res = s1 & s2
}
IFX_PENDOR0 {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s5);
@@ -264,23 +410,100 @@ 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_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
ANDSw_REG_LSL(s5, s5, s2, 16);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
ANDw_REG(s5, s1, s2); // res = s1 & s2
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
}
IFX(X_SF) {
LSRw(s4, s5, 15);
BFIw(xFlags, s4, F_SF, 1);
}
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
MAYUSE(s1);
int mask = 0;
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 16);
mask = convert_bitmask_w(c<<16);
if(mask) {
ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c);
ANDSw_REG_LSL(s5, s5, s3, 16);
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 16);
}
} else {
mask = convert_bitmask_w(c);
if(mask) {
ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s5, c);
ANDw_REG(s5, s1, s5); // res = s1 & s2
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
@@ -294,24 +517,101 @@ 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_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
ANDSw_REG_LSL(s5, s5, s2, 24);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
ANDw_REG(s5, s1, s2); // res = s1 & s2
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
}
}
// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4, int s5)
{
MAYUSE(s1);
int mask = 0;
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE();
}
IFX(X_CF|X_ZF|X_SF|X_OF) {
LSLw(s5, s1, 24);
mask = convert_bitmask_w(c<<24);
if(mask) {
ANDSw_mask(s5, s5, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s3, c);
ANDSw_REG_LSL(s5, s5, s3, 24);
}
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {} else {BFCw(xFlags, F_CF, 1);}
}
IFX(X_OF) {
IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);}
}
IFX(X_SF) {
IFNATIVE(NF_SF) {} else {
CSETw(s4, cMI);
BFIw(xFlags, s4, F_SF, 1);
}
}
IFX(X_PF|X_PEND) {
LSRw(s5, s5, 24);
}
} else {
mask = convert_bitmask_w(c);
if(mask) {
ANDw_mask(s5, s1, mask&0x3F, (mask>>6)&0x3F);
} else {
MOV32w(s5, c);
ANDw_REG(s5, s1, s5); // res = s1 & s2
}
}
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRw(s4, s5, 7);
BFIw(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s4);
}
File diff suppressed because it is too large. Load diff
+73 -33
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -31,6 +31,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t wback, wb1, wb2;
uint8_t u8;
uint64_t u64, j64;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1;
int q0;
int d0, d1;
@@ -71,7 +73,6 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
d0 = sse_get_reg(dyn, ninst, x1, ed, 1);
VMOVeD(d0, 0, v0, 0);
} else {
WILLWRITE2();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v0, ed, fixedaddress);
SMWRITE2();
@@ -99,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;
@@ -112,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) {
@@ -133,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);
@@ -143,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) {
@@ -205,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:
@@ -226,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
@@ -248,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
@@ -270,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;
@@ -280,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
@@ -318,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
@@ -388,32 +405,55 @@ 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);
VFSUBQS(v0, d0, v0);
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
i32_ = F32S; \
if(rex.is32bits) \
j64 = (uint32_t)(addr+i32_); \
else \
j64 = addr+i32_; \
BARRIER(BARRIER_MAYBE); \
JUMP(j64, 1); \
GETFLAGS; \
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, 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); \
SKIP_SEVL(i32); \
B(i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address-(dyn->native_size); \
SKIP_SEVL(i32); \
Bcond(YES, i32); \
}
GOCOND(0x80, "J", "Id");
#undef GO
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
@@ -455,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;
@@ -473,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);
+114 -38
View File
@@ -19,7 +19,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -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) {
@@ -184,10 +184,14 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_OF, SF_SUBSET);
GETED(0);
GETGD;
MRS_nzvc(x3);
LSRw(x4, xFlags, F_OF);
BFIx(x3, x4, 29, 1); // set C
MSR_nzvc(x3); // load CC into ARM CF
MRS_nzcv(x3);
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);
CSETw(x3, cCS);
@@ -242,20 +246,46 @@ 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");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn, ninst);
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FMULS(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
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
VORR(v1, v1, q0); // NAN -> -NAN
} else {
FMULS(v1, d1, d0); // the high part of the vector is erased...
}
VMOVeS(d1, 0, v1, 0);
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
@@ -271,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);
@@ -294,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");
@@ -312,18 +355,31 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cLS); //Less than or equal
B_NEXT(cCC); //Less than
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
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");
@@ -337,7 +393,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
FCMPS(v0, v1);
B_NEXT(cGE); //Greater than or equal
B_NEXT(cGT); //Greater than
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
@@ -404,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;
@@ -441,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;
@@ -465,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;
@@ -497,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;
+430 -77
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)
@@ -143,6 +144,7 @@ int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg)
// found a slot!
dyn->n.neoncache[reg].t=t;
dyn->n.neoncache[reg].n=ymm;
dyn->n.news |= (1<<reg);
return reg;
}
return -1;
@@ -285,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)
@@ -302,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);
}
}
@@ -330,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)
@@ -358,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)
@@ -493,7 +495,7 @@ void neoncacheUnwind(neoncache_t* cache)
}
if(cache->news) {
// remove the newly created neoncache
for(int i=0; i<24; ++i)
for(int i=0; i<32; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
cache->news = 0;
@@ -598,7 +600,7 @@ void neoncacheUnwind(neoncache_t* cache)
#define F8 *(uint8_t*)(addr++)
#define F32S64 (uint64_t)(int64_t)*(int32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
// Get if ED will have the correct parity. Not emitting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
{
(void)dyn; (void)ninst;
@@ -657,81 +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), %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].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].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 (!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].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)
@@ -794,4 +919,232 @@ void fpu_reset_ninst(dynarec_native_t* dyn, int ninst)
int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st)
{
return (dyn->n.tags&(0b11<<(st*2)))?1:0;
}
}
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;
//}
} else {
if(before)
dyn->insts[ninst].use_nat_flags_before |= flag;
else
dyn->insts[ninst].use_nat_flags |= flag;
}
return flag;
}
uint8_t flag2native(uint8_t flags)
{
uint8_t ret = 0;
#ifdef ARM64
if(flags&X_ZF) ret|=NF_EQ;
if(flags&X_SF) ret|=NF_SF;
if(flags&X_OF) ret|=NF_VF;
if(flags&X_CF) ret|=NF_CF;
#else
// no native flags on rv64 or la64
#endif
return ret;
}
int flagIsNative(uint8_t flags)
{
if(flags&(X_AF|X_PF)) return 0;
return 1;
}
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
{
// propagate and check wich flags are actually used
uint8_t used_flags = 0;
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 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) {
// check if the gen flags are compatible
if(dyn->insts[ninst].use_nat_flags_before&~flags)
return 0;
nat_flags_used = 1;
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 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 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) {
// check if the gen flags are compatible
if(dyn->insts[ninst].use_nat_flags&~flags)
return 0;
nat_flags_used = 1;
used_flags |= dyn->insts[ninst].use_nat_flags&flags;
}
if(ninst!=start && dyn->insts[ninst].x64.use_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)) {
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after))
return 0; // partial covert, not supported for now (TODO: this might be fixable)
else
return nat_flags_used?used_flags:0; // full covert... End of propagation
}
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&flags))
return nat_flags_used?used_flags:0;
// check if flags are destroyed, cancel the use then
if(dyn->insts[ninst].nat_flags_op && (start!=ninst))
return 0;
// update used 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
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.jmp && (jmp!=-1) && (getNominalPred(dyn, jmp)==ninst))
ninst = jmp;
else
return nat_flags_used?used_flags:0;
} else
++ninst;
}
return nat_flags_used?used_flags:0;
}
static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
{
int ninst = start;
// those are the flags generated by the opcode and used later on
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after);
//check if they are actualy used before starting
//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.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
int nc = dyn->insts[ninst].gen_inverted_carry?0:1;
int carry = used_flags&NF_CF;
// propagate
while(ninst<dyn->size) {
// check if this is an opcode that generate flags but consume flags before
if((start!=ninst) && dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH) {
if(dyn->insts[ninst].use_nat_flags_before) {
dyn->insts[ninst].before_nat_flags |= used_flags;
if(carry) dyn->insts[ninst].normal_carry_before = nc;
}
// if the opcode generate flags, return
return;
}
// 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))
return;
// mark the opcode
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after);
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags); // should not change anything
//printf_log(LOG_INFO, " marking ninst=%d with %x | %x&%x => %x\n", ninst, dyn->insts[ninst].need_nat_flags, used_flags, use_flags, dyn->insts[ninst].need_nat_flags | (used_flags&use_flags));
dyn->insts[ninst].need_nat_flags |= used_flags&use_flags;
if(carry) dyn->insts[ninst].normal_carry = nc;
if(carry && dyn->insts[ninst].invert_carry) nc = 0;
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&used_flags))
return;
// 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
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(dyn->insts[ninst].x64.jmp && (jmp!=-1) && (getNominalPred(dyn, jmp)==ninst))
ninst = jmp;
else
return;
} else
++ninst;
}
}
void updateNativeFlags(dynarec_native_t* dyn)
{
if(!BOX64ENV(dynarec_nativeflags))
return;
// 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);
}
}
void rasNativeState(dynarec_arm_t* dyn, int ninst)
{
dyn->insts[ninst].nat_flags_op = dyn->insts[ninst].set_nat_flags = dyn->insts[ninst].use_nat_flags = dyn->insts[ninst].need_nat_flags = 0;
}
int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst)
{
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return 0;
if(!dyn->insts[ninst].x64.need_after || !dyn->insts[jmp].x64.need_before)
return 0;
if(dyn->insts[ninst].set_nat_flags)
return 0;
uint8_t flags_before = dyn->insts[ninst].need_nat_flags;
uint8_t nc_before = dyn->insts[ninst].normal_carry;
if(dyn->insts[ninst].invert_carry)
nc_before = 0;
uint8_t flags_after = dyn->insts[jmp].need_nat_flags;
uint8_t nc_after = dyn->insts[jmp].normal_carry;
if(dyn->insts[jmp].nat_flags_op==NAT_FLAG_OP_TOUCH) {
flags_after = dyn->insts[jmp].before_nat_flags;
nc_after = dyn->insts[jmp].normal_carry_before;
}
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
flags_x86 &= ~flags_after;
if((flags_before&NF_CF) && (flags_after&NF_CF) && (nc_before!=nc_after))
return 1;
// all flags_after should be present and none remaining flags_x86
if(((flags_before&flags_after)!=flags_after) || (flags_before&flags_x86))
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));
}
+14 -1
View File
@@ -51,14 +51,27 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with
// Do not allow i64 type
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
// transform x86 flags to native flags
uint8_t flag2native(uint8_t flags);
// mark a instruction as using/generating flags. return flag
uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before);
// propage the use of nativeflags or not (done between step 0 and step 1)
void updateNativeFlags(dynarec_arm_t* dyn);
// raz arm speicifc state when an opcode is unused
void rasNativeState(dynarec_arm_t* dyn, int ninst);
// check if natives flags needs some tranform to/from x86 flags
int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst);
// FPU Cache transformation (for loops) // Specific, need to be written by backend
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
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 emiting anything. Parity is 2 for DWORD or 3 for QWORD
// 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);
const char* getCacheName(int t, int n);
+281 -85
View File
@@ -23,7 +23,7 @@
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
#include "../dynarec_helper.h"
static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, int* l, int s);
@@ -59,12 +59,12 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV64x(scratch, tmp);
ADDx_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDx_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
} else {
if(sib>>6) {
LSLx(ret, xRAX+sib_reg, (sib>>6));
LSLx(ret, TO_NAT(sib_reg), (sib>>6));
} else
ret = xRAX+sib_reg;
ret = TO_NAT(sib_reg);
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
*fixaddress = tmp;
@@ -78,9 +78,9 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
} else {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDx_REG_LSL(ret, TO_NAT((sib&0x7)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
ret = xRAX+(sib&0x7)+(rex.b<<3);
ret = TO_NAT((sib&0x7)+(rex.b<<3));
}
}
} else if((nextop&7)==5) {
@@ -112,7 +112,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
ret = TO_NAT((nextop & 7) + (rex.b << 3));
}
} else {
int64_t i64;
@@ -132,24 +132,24 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDx_REG_LSL(ret, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
ret = xRAX+(sib&0x07)+(rex.b<<3);
ret = TO_NAT((sib&0x07)+(rex.b<<3));
}
} else
ret = xRAX+(nextop&0x07)+(rex.b<<3);
ret = TO_NAT((nextop & 0x07) + (rex.b << 3));
} else {
int64_t sub = (i64<0)?1:0;
if(sub) i64 = -i64;
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDx_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDx_REG_LSL(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), TO_NAT(sib_reg), (sib>>6));
} else {
scratch = xRAX+(sib&0x07)+(rex.b<<3);
scratch = TO_NAT((sib&0x07)+(rex.b<<3));
}
} else
scratch = xRAX+(nextop&0x07)+(rex.b<<3);
scratch = TO_NAT((nextop & 0x07) + (rex.b << 3));
if(sub) {
SUBx_U12(ret, scratch, i64);
} else {
@@ -160,13 +160,13 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBx_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
SUBx_REG(scratch, TO_NAT((sib&0x07)+(rex.b<<3)), scratch);
} else {
ADDx_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
ADDx_REG(scratch, scratch, TO_NAT((sib&0x07)+(rex.b<<3)));
}
ADDx_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDx_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib>>6));
} else {
PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
PASS3(int tmp = TO_NAT(sib & 0x07) + (rex.b << 3));
if(sub) {
SUBx_REG(ret, tmp, scratch);
} else {
@@ -174,7 +174,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3)));
if(sub) {
SUBx_REG(ret, tmp, scratch);
} else {
@@ -214,9 +214,9 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV32w(scratch, tmp);
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
LSLw(ret, TO_NAT(sib_reg), (sib >> 6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
@@ -230,9 +230,9 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
}
} else {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x7), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, TO_NAT(sib & 0x7), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = xRAX+(sib&0x7);
ret = TO_NAT(sib & 0x7);
}
}
} else if((nextop&7)==5) {
@@ -243,7 +243,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
case 2: if(isLockAddress(tmp)) *l=1; break;
}
} else {
ret = xRAX+(nextop&7);
ret = TO_NAT(nextop & 7);
if(ret==hint) {
MOVw_REG(hint, ret); //to clear upper part
}
@@ -266,12 +266,12 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x07), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, TO_NAT(sib & 0x07), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = xRAX+(sib&0x07);
ret = TO_NAT(sib & 0x07);
}
} else {
ret = xRAX+(nextop&0x07);
ret = TO_NAT(nextop & 0x07);
}
} else {
int64_t sub = (i32<0)?1:0;
@@ -279,12 +279,12 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
if(i32<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(scratch, xRAX+(sib&0x07), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(scratch, TO_NAT(sib & 0x07), TO_NAT(sib_reg), (sib >> 6));
} else {
scratch = xRAX+(sib&0x07);
scratch = TO_NAT(sib & 0x07);
}
} else
scratch = xRAX+(nextop&0x07);
scratch = TO_NAT(nextop & 0x07);
if(sub) {
SUBw_U12(ret, scratch, i32);
} else {
@@ -295,13 +295,13 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBw_REG(scratch, xRAX+(sib&0x07), scratch);
SUBw_REG(scratch, TO_NAT(sib & 0x07), scratch);
} else {
ADDw_REG(scratch, scratch, xRAX+(sib&0x07));
ADDw_REG(scratch, scratch, TO_NAT(sib & 0x07));
}
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
PASS3(int tmp = xRAX+(sib&0x07));
PASS3(int tmp = TO_NAT(sib & 0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
@@ -309,7 +309,7 @@ static uintptr_t geted_32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07));
PASS3(int tmp = TO_NAT(nextop & 0x07));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
@@ -350,9 +350,9 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if (sib_reg!=4) {
if(tmp && ((!((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask))) || !(unscaled && (tmp>-256) && (tmp<256)))) {
MOV64x(scratch, tmp);
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
LSLw(ret, TO_NAT(sib_reg), (sib >> 6));
*fixaddress = tmp;
if(unscaled && (tmp>-256) && (tmp<256))
*unscaled = 1;
@@ -366,9 +366,9 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
} else {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, TO_NAT((sib & 0x7) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = xRAX+(sib&0x7)+(rex.b<<3);
ret = TO_NAT((sib & 0x7)) + (rex.b << 3);
}
}
} else if((nextop&7)==5) {
@@ -381,7 +381,7 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
case 2: if(isLockAddress(addr+delta+tmp)) *l=1; break;
}
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
ret = TO_NAT((nextop & 7) + (rex.b << 3));
if(ret==hint) {
MOVw_REG(hint, ret); //to clear upper part
}
@@ -404,12 +404,12 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
*unscaled = 1;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, TO_NAT((sib & 0x07) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
ret = xRAX+(sib&0x07)+(rex.b<<3);
ret = TO_NAT((sib & 0x07) + (rex.b << 3));
}
} else {
ret = xRAX+(nextop&0x07)+(rex.b<<3);
ret = TO_NAT((nextop & 0x07) + (rex.b << 3));
}
} else {
int64_t sub = (i64<0)?1:0;
@@ -417,12 +417,12 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(scratch, TO_NAT((sib & 0x07) + (rex.b << 3)), TO_NAT(sib_reg), (sib >> 6));
} else {
scratch = xRAX+(sib&0x07)+(rex.b<<3);
scratch = TO_NAT((sib & 0x07) + (rex.b << 3));
}
} else
scratch = xRAX+(nextop&0x07)+(rex.b<<3);
scratch = TO_NAT((nextop & 0x07) + (rex.b << 3));
if(sub) {
SUBw_U12(ret, scratch, i64);
} else {
@@ -433,13 +433,13 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBw_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
SUBw_REG(scratch, TO_NAT((sib & 0x07) + (rex.b << 3)), scratch);
} else {
ADDw_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
ADDw_REG(scratch, scratch, TO_NAT((sib & 0x07) + (rex.b << 3)));
}
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
ADDw_REG_LSL(ret, scratch, TO_NAT(sib_reg), (sib >> 6));
} else {
PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
PASS3(int tmp = TO_NAT((sib & 0x07) + (rex.b << 3)));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
@@ -447,7 +447,7 @@ uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3)));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
@@ -569,6 +569,9 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Jump to next\n");
if(is32bits)
ip &= 0xffffffffLL;
SMEND();
if(reg) {
if(reg!=xRIP) {
@@ -577,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);
@@ -596,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);
}
@@ -606,8 +609,14 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32
CLEARIP();
#ifdef HAVE_TRACE
//MOVx(x3, 15); no access to PC reg
#endif
BLR(x2); // save LR...
#else
if (dyn->insts[ninst].x64.has_callret) {
BLR(x2); // save LR...
} else {
BR(x2);
}
#endif
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
@@ -617,12 +626,12 @@ 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(x2, x6, xSP, 16);
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
BLR(x2);
RET(xLR);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
SUBx_U12(xSP, xSavedSP, 16);
}
@@ -643,7 +652,11 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex)
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
LDRx_REG_LSL3(x2, x2, x3);
BLR(x2); // save LR
#ifdef HAVE_TRACE
BLR(x2);
#else
BR(x2);
#endif
CLEARIP();
}
@@ -660,12 +673,12 @@ 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(x2, x6, xSP, 16);
LDPx_S7_postindex(xLR, x6, xSP, 16);
SUBx_REG(x6, x6, xRIP); // is it the right address?
CBNZx(x6, 2*4);
BLR(x2);
RET(xLR);
// not the correct return address, regular jump
SUBx_U12(xSP, xSavedSP, 16);
}
@@ -686,17 +699,23 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n)
LDRx_REG_LSL3(x2, x2, x3);
UBFXx(x3, xRIP, JMPTABL_START0, JMPTABL_SHIFT0);
LDRx_REG_LSL3(x2, x2, x3);
BLR(x2); // save LR
#ifdef HAVE_TRACE
BLR(x2);
#else
BR(x2);
#endif
CLEARIP();
}
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits)
{
int64_t j64;
//#warning TODO: is64bits
MAYUSE(ninst);
MAYUSE(j64);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
SMEND();
SET_DFNONE(x2);
SET_DFNONE();
// POP IP
NOTEST(x2);
if(is64bits) {
@@ -715,7 +734,13 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, 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
CMPSw_U12(x2, 0x23);
B_MARKSEG(cEQ);
}
// POP RSP
if(is64bits) {
POP1(x3); //rsp
@@ -729,6 +754,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
// set new RSP
MOVx_REG(xRSP, x3);
MARKSEG;
// Ret....
MOV64x(x2, (uintptr_t)arm64_epilog); // epilog on purpose, CS might have changed!
BR(x2);
@@ -738,6 +764,9 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
{
MAYUSE(fnc);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
if(savereg==0)
savereg = 7;
if(saveflags) {
@@ -780,9 +809,48 @@ 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);
#if STEP == 0
dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE;
#endif
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
fpu_pushcache(dyn, ninst, x3, 1);
// x9..x15, x16,x17,x18 those needs to be saved by caller
@@ -826,24 +894,25 @@ 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 t1 = x1, t2 = x4;
if(reg==t1) ++t1;
int t2 = x4;
if(reg==t2) ++t2;
LDRw_U12(t2, xEmu, offsetof(x64emu_t, segs_serial[segment]));
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
if(segment==_GS) {
/*if(segment==_GS) {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
CBNZw_MARKSEG(t2); // fast check
} else {
LDRx_U12(t1, xEmu, offsetof(x64emu_t, context));
LDRw_U12(t1, t1, offsetof(box64context_t, sel_serial));
SUBw_REG(t1, t1, t2);
CBZw_MARKSEG(t1);
} else*/ {
LDRx_U12(reg, xEmu, offsetof(x64emu_t, context));
LDRw_U12(reg, reg, offsetof(box64context_t, sel_serial));
SUBw_REG(t2, reg, t2);
LDRx_U12(reg, xEmu, offsetof(x64emu_t, segs_offs[segment]));
CBZw_MARKSEG(t2);
}
MOVZw(x1, segment);
call_c(dyn, ninst, GetSegmentBaseEmu, t2, reg, 1, 0);
@@ -1156,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
@@ -1216,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;
@@ -2185,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;
@@ -2201,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)
@@ -2322,7 +2425,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->f.dfnone || (dyn->insts[jmp].f_exit.dfnone_here && !dyn->insts[jmp].x64.use_flags)) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone && !dyn->insts[jmp].df_notneeded)?1:0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
@@ -2332,8 +2435,17 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
case SF_SET_PENDING:
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
&& dyn->f.pending!=SF_PENDING
) {
// only sync if some previous flags are used or if all flags are not regenerated at the instuction
if(dyn->insts[jmp].x64.use_flags || (dyn->insts[jmp].x64.set_flags!=X_ALL))
go = 1;
else if(go) {
// just clear df flags
go = 0;
STRw_U12(xZR, xEmu, offsetof(x64emu_t, df));
}
}
break;
case SF_PENDING:
if(dyn->f.pending!=SF_SET
@@ -2350,16 +2462,100 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
j64 = (GETMARKF2)-(dyn->native_size);
CBZw(s1, j64);
}
CALL_(UpdateFlags, -1, 0);
if(dyn->insts[ninst].need_nat_flags)
MRS_nzcv(s1);
CALL_(UpdateFlags, -1, s1);
if(dyn->insts[ninst].need_nat_flags)
MSR_nzcv(s1);
MARKF2;
}
}
static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
{
int j64;
int jmp = dyn->insts[ninst].x64.jmp_insts;
if(jmp<0)
return;
uint8_t flags_before = dyn->insts[ninst].need_nat_flags;
uint8_t nc_before = dyn->insts[ninst].normal_carry;
if(dyn->insts[ninst].invert_carry)
nc_before = 0;
uint8_t flags_after = dyn->insts[jmp].need_nat_flags;
uint8_t nc_after = dyn->insts[jmp].normal_carry;
if(dyn->insts[jmp].nat_flags_op==NAT_FLAG_OP_TOUCH) {
flags_after = dyn->insts[jmp].before_nat_flags;
nc_after = dyn->insts[jmp].normal_carry_before;
}
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
flags_x86 &= ~flags_after;
MESSAGE(LOG_DUMP, "\tNative Flags transform ---- ninst=%d -> %d %hhx -> %hhx/%hhx\n", ninst, jmp, flags_before, flags_after, flags_x86);
// flags present in before and missing in after
if((flags_before&NF_EQ) && (flags_x86&NF_EQ)) {
CSETw(s1, cEQ);
BFIw(xFlags, s1, F_ZF, 1);
}
if((flags_before&NF_SF) && (flags_x86&NF_SF)) {
CSETw(s1, cMI);
BFIw(xFlags, s1, F_SF, 1);
}
if((flags_before&NF_VF) && (flags_x86&NF_VF)) {
CSETw(s1, cVS);
BFIw(xFlags, s1, F_OF, 1);
}
if((flags_before&NF_CF) && (flags_x86&NF_CF)) {
if(nc_before) // might need to invert carry
CSETw(s1, cCS);
else
CSETw(s1, cCC);
BFIw(xFlags, s1, F_CF, 1);
}
// flags missing and needed later
int mrs = 0;
#define GO_MRS(A) if(!mrs) {mrs=1; MRS_nzcv(s2); }
if(!(flags_before&NF_EQ) && (flags_after&NF_EQ)) {
GO_MRS(s2);
UBFXw(s1, xFlags, F_ZF, 1);
BFIx(s2, s1, NZCV_Z, 1);
}
if(!(flags_before&NF_SF) && (flags_after&NF_SF)) {
GO_MRS(s2);
UBFXw(s1, xFlags, F_SF, 1);
BFIx(s2, s1, NZCV_N, 1);
}
if(!(flags_before&NF_VF) && (flags_after&NF_VF)) {
GO_MRS(s2);
UBFXw(s1, xFlags, F_OF, 1);
BFIx(s2, s1, NZCV_V, 1);
}
if(!(flags_before&NF_CF) && (flags_after&NF_CF)) {
GO_MRS(s2);
BFIx(s2, xFlags, NZCV_C, 1); // F_CF is bit 0
if(!nc_after)
EORx_mask(s2, s2, 1, 35, 0); //mask=1<<NZCV_C
}
// special case for NF_CF changing state
if((flags_before&NF_CF) && (flags_after&NF_CF) && (nc_before!=nc_after)) {
if(arm64_flagm && !mrs) {
CFINV();
} else {
GO_MRS(s2);
EORx_mask(s2, s2, 1, 35, 0); //mask=1<<NZCV_C
}
}
#undef GL_MRS
if(mrs) MSR_nzcv(s2);
MESSAGE(LOG_DUMP, "\t---- Native Flags transform\n");
}
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) {
if(cacheupd&1)
flagsCacheTransform(dyn, ninst, s1);
if(cacheupd&2)
fpuCacheTransform(dyn, ninst, s1, s2, s3);
if(cacheupd&4)
nativeFlagsTransform(dyn, ninst, s1, s2);
}
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
@@ -2379,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)
@@ -2484,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)
File diff suppressed because it is too large. Load diff
+6 -2
View File
@@ -2,10 +2,14 @@
#include "arm64_emitter.h"
#define EMIT(A) *block = (A); ++block
#define EMIT(A) \
do { \
*block = (A); \
++block; \
} while (0)
void CreateJmpNext(void* addr, void* next)
{
uint32_t* block = (uint32_t*)addr;
LDRx_literal(x2, (intptr_t)next - (intptr_t)addr);
BR(x2);
}
}
+42 -18
View File
@@ -6,19 +6,19 @@
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
#define BARRIER_NEXT(A) dyn->insts[ninst].x64.barrier_next = A
#define SET_HASCALLRET() dyn->insts[ninst].x64.has_callret = 1
#define NEW_INST \
++dyn->size; \
@@ -31,20 +31,44 @@
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
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) {\
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))
#define IFX(A) if((dyn->insts[ninst].x64.set_flags&(A)))
#define IFX2(A, B) if((dyn->insts[ninst].x64.set_flags&(A)) B)
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.set_flags&(X_PEND) || !dyn->insts[ninst].x64.set_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.set_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.set_flags==(A) || dyn->insts[ninst].x64.set_flags==(B) || dyn->insts[ninst].x64.set_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x64.set_flags&(A) && !(dyn->insts[ninst].x64.set_flags&(B))))
#define IFXNATIVE(X, N) if((dyn->insts[ninst].x64.set_flags&(X)) && mark_natflag(dyn, ninst, N, 0))
#define GEN_INVERTED_CARRY() dyn->insts[ninst].gen_inverted_carry = 1
#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)))
+10
View File
@@ -2,6 +2,16 @@
#define FINI
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define SET_NODF() \
if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \
propagate_nodf(dyn, ninst); \
dyn->f.dfnone = 0
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0; \
if(!BOX64ENV(dynarec_df)) {dyn->f.dfnone=1; dyn->f.pending=0; }
#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)
+4 -3
View File
@@ -1,20 +1,21 @@
#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; \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4); \
dyn->insts[ninst].ymm0_pass3 = dyn->ymm_zero; \
}
+36 -5
View File
@@ -9,6 +9,20 @@ typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
#define NF_EQ (1<<0)
#define NF_SF (1<<1)
#define NF_VF (1<<2)
#define NF_CF (1<<3)
// Nothing happens to the native flags
#define NAT_FLAG_OP_NONE 0
// Native flags are touched on this opcode
#define NAT_FLAG_OP_TOUCH 1
// Native flags are destroyed and unusable
#define NAT_FLAG_OP_UNUSABLE 2
// Native flags usaged are canceled here
#define NAT_FLAG_OP_CANCELED 3
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
#define NEON_CACHE_ST_F 2
@@ -89,11 +103,26 @@ typedef struct instruction_arm64_s {
uint16_t ymm0_in; // bitmap of ymm to zero at purge
uint16_t ymm0_add; // the ymm0 added by the opcode
uint16_t ymm0_sub; // the ymm0 removed by the opcode
uint16_t ymm0_out; // the ymmm0 at th end of the opcode
uint16_t ymm0_out; // the ymm0 at th end of the opcode
uint16_t ymm0_pass2, ymm0_pass3;
uint8_t barrier_maybe;
uint8_t will_write;
uint8_t last_write;
uint8_t will_write:2; // [strongmem] will write to memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t wfe:1; // opcode uses sevl + wfe
uint8_t set_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags_before; // 0 or combinaison of native flags define
uint8_t nat_flags_op:4;// what happens to native flags here
uint8_t nat_flags_op_before:4;// what happens to native flags here
uint8_t before_nat_flags; // 0 or combinaison of native flags define
uint8_t need_nat_flags;
unsigned gen_inverted_carry:1;
unsigned normal_carry:1;
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
@@ -132,11 +161,11 @@ typedef struct dynarec_arm_s {
int forward_ninst; // ninst at the forward point
uint16_t ymm_zero; // bitmap of ymm to zero at purge
uint8_t smwrite; // for strongmem model emulation
uint8_t smread;
uint8_t doublepush;
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);
@@ -154,9 +183,11 @@ void CreateJmpNext(void* addr, void* next);
#define GO_TRACE(A, B, s0) \
GETIP(addr); \
MOVx_REG(x1, xRIP); \
MRS_nzcv(s0); \
STORE_XEMU_CALL(xRIP); \
MOV32w(x2, B); \
CALL(A, -1); \
CALL_(A, -1, s0); \
MSR_nzcv(s0); \
LOAD_XEMU_CALL(xRIP)
#endif //__DYNAREC_ARM_PRIVATE_H_
+14 -3
View File
@@ -19,6 +19,7 @@
#include "dynarec_private.h"
#include "elfloader.h"
#include "bridge.h"
#include "signals.h"
#include "dynarec_native.h"
#include "native_lock.h"
@@ -198,12 +199,16 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
{
if(hasAlternate((void*)addr))
return NULL;
const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ;
dynablock_t* block = getDB(addr);
if(block || !create)
if(block || !create) {
if(block && getNeedTest(addr) && (getProtection(addr)&req_prot)!=req_prot)
block = NULL;
return block;
}
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
@@ -211,11 +216,17 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
}
block = getDB(addr); // just in case
if(block) {
if(block && getNeedTest(addr) && (getProtection_fast(addr)&req_prot)!=req_prot)
block = NULL;
mutex_unlock(&my_context->mutex_dyndump);
return block;
}
}
if((getProtection_fast(addr)&req_prot)!=req_prot) {// cannot be run, get out of the Dynarec
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
block = AddNewDynablock(addr);
// fill the block
+6 -3
View File
@@ -10,17 +10,20 @@ typedef struct dynablock_s {
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
struct dynablock_s* previous; // a previous block that might need to be freed
int size;
void* x64_addr;
uintptr_t x64_size;
int size;
uint32_t hash;
uint8_t done;
uint8_t gone;
uint8_t always_test;
uint8_t dirty; // if need to be tested as soon as it's created
uint8_t always_test:1;
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_
+54 -29
View File
@@ -34,17 +34,25 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
#ifdef HAVE_TRACE
if(!addr) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
printf_log(LOG_INFO, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p/%s)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, db?getAddrFunctionName(getX64Address(db, (uintptr_t)x2-4)):"(nil)");
} else if(addr<0x10000) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to low address %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)");
printf_log(LOG_INFO, "Warning, jumping to low address %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)");
#ifdef BOX32
} else if(emu->segs[_CS]==0x23 && addr>0x100000000LL) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_INFO, "Warning, jumping to high address %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)");
} else if(!memExist(addr)) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_INFO, "Warning, jumping to an unmapped address %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)");
#endif
}
#endif
void * jblock;
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!
@@ -55,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 {
@@ -71,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)");
}
@@ -95,25 +103,24 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
uint64_t old_rsi = R_RSI;
uint64_t old_rbp = R_RBP;
uint64_t old_rip = R_RIP;
x64flags_t old_eflags = emu->eflags;
// save defered flags
deferred_flags_t old_df = emu->df;
multiuint_t old_op1 = emu->op1;
multiuint_t old_op2 = emu->op2;
multiuint_t old_res = emu->res;
multiuint_t old_op1_sav= emu->op1_sav;
multiuint_t old_res_sav= emu->res_sav;
deferred_flags_t old_df_sav= emu->df_sav;
// uc_link
x64_ucontext_t* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
PushExit(emu);
#ifdef BOX32
if(box64_is32bits)
PushExit_32(emu);
else
#endif
PushExit(emu);
R_RIP = addr;
emu->df = d_none;
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
@@ -123,10 +130,8 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
emu->op1 = old_op1;
emu->op2 = old_op2;
emu->res = old_res;
emu->op1_sav = old_op1_sav;
emu->res_sav = old_res_sav;
emu->df_sav = old_df_sav;
// and the old registers
emu->eflags = old_eflags;
R_RBX = old_rbx;
R_RDI = old_rdi;
R_RSI = old_rsi;
@@ -137,6 +142,10 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
}
int my_setcontext(x64emu_t* emu, void* ucp);
#ifdef BOX32
int my32_setcontext(x64emu_t* emu, void* ucp);
#endif
extern int running32bits;
void DynaRun(x64emu_t* emu)
{
// prepare setjump for signal handling
@@ -147,7 +156,7 @@ void DynaRun(x64emu_t* emu)
uintptr_t old_savesp = emu->xSPSave;
#endif
emu->flags.jmpbuf_ready = 0;
int is32bits = (emu->segs[_CS]==0x23);
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
@@ -163,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;
@@ -175,28 +184,48 @@ void DynaRun(x64emu_t* emu)
emu->flags.need_jmpbuf = 0;
#ifdef DYNAREC
if(!box64_dynarec)
if(!BOX64ENV(dynarec))
#endif
Run(emu, 0);
#ifdef DYNAREC
else {
int is32bits = (emu->segs[_CS]==0x23);
int newis32bits = (emu->segs[_CS]==0x23);
if(newis32bits!=is32bits) {
is32bits = newis32bits;
if(is32bits) {
// Zero upper part of the 32bits regs
R_RAX = R_EAX;
R_RBX = R_EBX;
R_RCX = R_ECX;
R_RDX = R_EDX;
R_RSP = R_ESP;
R_RBP = R_EBP;
R_RSI = R_ESI;
R_RDI = R_EDI;
running32bits = 1;
}
}
dynablock_t* block = (skip)?NULL:DBGetBlock(emu, R_RIP, 1, is32bits);
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
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);
extern int running32bits;
if(emu->segs[_CS]==0x23)
running32bits = 1;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -204,10 +233,6 @@ void DynaRun(x64emu_t* emu)
emu->fork = 0;
emu = x64emu_fork(emu, forktype);
}
if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
+44 -6
View File
@@ -5,22 +5,36 @@
#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);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2; \
if (nativeFlagsNeedsTransform(dyn, ninst)) ret|=4;
#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)
#define RAZ_SPECIFIC(A, N) rasNativeState(A, N)
#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);
@@ -33,22 +47,46 @@
#include "la64/dynarec_la64_functions.h"
// Limit here is unconditionnal jump, that is signed 28bits
#define MAXBLOCK_SIZE ((1 << 27) - 200)
#define RAZ_SPECIFIC(A, N)
#define UPDATE_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);
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst); \
int sewNeedsTransform(dynarec_rv64_t* dyn, int ninst);
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=2;
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret |= 2; \
if (sewNeedsTransform(dyn, ninst)) ret |= 4;
#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
+186 -1
View File
@@ -1,6 +1,191 @@
#ifndef __DYNAREC_HELPER__H_
#define __DYNAREC_HELPER__H_
/* Box64 Strong Memory Model Emulation
*
* Definition of a SEQ:
* A SEQ is a sequence of opcodes that writes to guest memory, terminated by JMP, RET, CALL, etc.
*
* Memory barriers are added in the following cases to emulate the strong memory model:
* 1. End of a SEQ:
* - Scalar operations (a1)
* - SIMD operations (a2)
* 2. Start of a SEQ:
* - Scalar operations (b1)
* - SIMD operations (b2)
* 3. Right before the last guest memory store in a SEQ:
* - Scalar operations (c1)
* - SIMD operations (c2)
* 4. After every third guest memory store in a SEQ (d)
*
* STRONGMEM levels (coarse-grained):
* 1: Includes a1, b1, c1
* 2: Includes LEVEL1, plus a2, b2, c2
* 3: Includes LEVEL2, plus d
*
* WEAKBARRIER levels (fine-grained):
* 1: Use dmb.ishld and dmb.ishst over dmb.ish for more performance
* 2. All 1. Plus disabled the last write barriers (c1, c2)
*/
#define STRONGMEM_SIMD_WRITE 2 // The level of SIMD memory writes will be tracked
#define STRONGMEM_LAST_WRITE 1 // The level of a barrier before the last guest memory store will be put
#define STRONGMEM_SEQ_WRITE 3 // The level of a barrier at every third memory store will be put
#if STEP == 1
#define SMWRITE() \
do { \
/* Mark that current sequence writes to guest memory. */ \
/* This will be used in SMEND for last_write. */ \
dyn->smwrite = 1; \
/* Mark that current opcode writes to guest memory. */ \
dyn->insts[ninst].will_write = 1; \
} while (0)
#define SMWRITELOCK(lock) \
do { \
dyn->insts[ninst].lock = lock; \
SMWRITE(); \
} while (0)
#define SMWRITE2() \
do { \
if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SIMD_WRITE) { \
dyn->smwrite = 1; \
dyn->insts[ninst].will_write = 2; \
} \
} while (0)
#define SMREAD()
#define SMREADLOCK(lock)
#define WILLWRITE()
#define WILLWRITELOCK(lock)
#define SMSTART() \
do { \
/* Clear current state at the start of a potential SEQ. */ \
dyn->smwrite = 0; \
} while (0)
#define SMEND() \
do { \
/* If there is any guest memory write, which is a SEQ, then compute the last_write. */ \
if (dyn->smwrite && (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_LAST_WRITE)) { \
int i = ninst; \
while (i >= 0 && !dyn->insts[i].will_write) \
--i; \
if (i >= 0) { dyn->insts[i].last_write = 1; } \
} \
dyn->smwrite = 0; \
} while (0)
#define SMDMB()
#else
// An opcode writes guest memory, this need to be put after the STORE instruction manually.
#define SMWRITE() \
do { \
/* Put a barrier at every third memory write. */ \
if (BOX64DRENV(dynarec_strongmem) >= STRONGMEM_SEQ_WRITE) { \
if (++dyn->smwrite >= 3 /* Every third memory write */) { \
DMB_ISH(); \
dyn->smwrite = 1; \
} \
} else { \
/* Mark that current sequence writes to guest memory. */ \
dyn->smwrite = 1; \
} \
} while (0)
// Similar to SMWRITE, but checks lock.
#define SMWRITELOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
SMWRITE(); \
} \
} while (0)
// Similar to SMWRITE, but for SIMD instructions.
#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.
#define SMREAD()
// Similar to SMREAD, but checks lock.
#define SMREADLOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
SMREAD(); \
} \
} while (0)
// An opcode will write memory, this will be put before the STORE instruction automatically.
#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.
#define WILLWRITELOCK(lock) \
do { \
if (lock) { \
DMB_ISH(); \
} else { \
WILLWRITE(); \
} \
} while (0)
// Used to clear the state at the start of a SEQ
#define SMSTART() \
do { \
dyn->smwrite = 0; \
} while (0)
// Will be put at the end of the SEQ
#define SMEND() \
do { \
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 (BOX64ENV(dynarec_weakbarrier)) \
DMB_ISHST(); \
else \
DMB_ISH(); \
} \
} \
dyn->smwrite = 0; \
} while (0)
// The barrier.
#define SMDMB() DMB_ISH()
#endif
int is_addr_unaligned(uintptr_t addr);
#ifdef ARM64
#include "arm64/dynarec_arm64_helper.h"
#elif defined(LA64)
@@ -11,4 +196,4 @@
#error Unsupported architecture
#endif
#endif //__DYNAREC_HELPER__H_
#endif //__DYNAREC_HELPER__H_
+134 -43
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)
@@ -121,6 +123,8 @@ int is_nops(dynarec_native_t *dyn, uintptr_t addr, int n)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0xF3 && PK(1)==0x90)
return is_nops(dyn, addr+2, n-2);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
if(n>2 && PK(0)==0x8d && PK(1)==0x76 && PK(2)==0x00) // lea esi, [esi]
@@ -229,6 +233,14 @@ int next_instruction(dynarec_native_t *dyn, uintptr_t addr)
case 0xBE:
case 0xBF:
return 5;
case 0xF3:
nextop = PK(1);
switch(nextop) {
case 0x90:
return 2;
default: break;
}
break;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7) {
@@ -367,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);
@@ -409,25 +422,29 @@ 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 (ninst && dyn->insts[ninst].pred_sz && dyn->insts[ninst].x64.alive) {
uint16_t ymm0_union = 0, ymm0_inter = (uint16_t)-1; // The union of the empty set is empty, the intersection is the universe
if (dyn->insts[ninst].pred_sz && dyn->insts[ninst].x64.alive) {
// The union of the empty set is empty (0), the intersection is the universe (-1)
// The first instruction is the entry point, which has a virtual pred with ymm0_out = 0
// Similarly, float barriers reset ymm0s
uint16_t ymm0_union = 0;
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;
@@ -449,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)
@@ -463,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 {
@@ -489,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)
@@ -510,7 +558,7 @@ uintptr_t native_pass1(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
uintptr_t native_pass2(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
uintptr_t native_pass3(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits);
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr, int is32bits) {
block->isize = 0;
block->done = 0;
size_t sz = 4*sizeof(void*);
@@ -525,11 +573,12 @@ void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
block->is32bits = is32bits;
*(dynablock_t**)actual_p = block;
*(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;
}
@@ -545,11 +594,12 @@ 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);
return CreateEmptyBlock(block, addr, is32bits);
}
if(current_helper) {
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock at %p as another one is going on\n", (void*)addr);
@@ -559,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;
@@ -574,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;
}
@@ -582,7 +636,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
if(!helper.size) {
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock64(0);
return CreateEmptyBlock(block, addr);
return CreateEmptyBlock(block, addr, is32bits);
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
@@ -637,6 +691,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
if(k!=-1) {
if(!helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
// special case, loop on itself with some nop in between
if(k<i && !helper.insts[i].x64.has_next && is_nops(&helper, helper.insts[k].x64.addr, helper.insts[i].x64.addr-helper.insts[k].x64.addr)) {
helper.always_test = 1;
k = -1;
}
helper.insts[i].x64.jmp_insts = k;
}
}
@@ -649,7 +708,9 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
helper.predecessor = (int*)alloca(alloc_size*sizeof(int));
fillPredecessors(&helper);
int pos = helper.size;
PREUPDATE_SPECIFICS(&helper);
int pos = helper.size-1;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// remove fpu stuff on non-executed code
@@ -659,6 +720,7 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
while(ii<helper.size && !helper.insts[ii].pred_sz) {
fpu_reset_ninst(&helper, ii);
helper.insts[ii].ymm0_in = helper.insts[ii].ymm0_sub = helper.insts[ii].ymm0_add = helper.insts[ii].ymm0_out = helper.insts[ii].purge_ymm = 0;
RAZ_SPECIFIC(&helper, ii);
++ii;
}
i = ii;
@@ -672,15 +734,16 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// NULL block after removing dead code, how is that possible?
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block after trimming dead code (%p)\n", (void*)addr);
CancelBlock64(0);
return CreateEmptyBlock(block, addr);
return CreateEmptyBlock(block, addr, is32bits);
}
updateYmm0s(&helper, 0, 0);
UPDATE_SPECIFICS(&helper);
// 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;
}
@@ -688,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;
}
@@ -696,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);
@@ -719,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;
@@ -733,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 pass1\n");
if(BOX64DRENV(dynarec_dump) || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Abort dynablock on pass3\n");
CancelBlock64(0);
return NULL;
}
@@ -751,32 +819,45 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
block->jmpnext = next+sizeof(void*);
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((block->hash != hash)) {
if((helper.abort || (block->hash != hash))) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
CancelBlock64(0);
return NULL;
}
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu, %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");
@@ -787,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);
@@ -805,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));
}
+85 -15
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,19 +50,32 @@ 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)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
int tmp32s;
if(isnan(ST1.d)) {
ST0.d = ST1.d;
} else if(isinf(ST1.d)) {
ST0.d = ST1.d;
ST1.d = INFINITY;
} else if(ST1.d==0.0) {
ST0.d = ST1.d;
ST1.d = -INFINITY;
} else {
// LD80bits doesn't have implicit "1" bit, so need to adjust for that
ST0.d = frexp(ST1.d, &tmp32s)*2;
ST1.d = tmp32s-1;
}
}
void native_fprem(x64emu_t* emu)
{
@@ -87,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;
}
@@ -100,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;
}
@@ -164,15 +184,22 @@ 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;
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0);
emit_signal(emu, SIGSEGV, (void*)R_RIP, 0xbad0);
}
void native_int(x64emu_t* emu, int num)
@@ -188,13 +215,13 @@ void native_singlestep(x64emu_t* emu)
void native_int3(x64emu_t* emu)
{
emit_signal(emu, SIGTRAP, (void*)R_RIP, 128);
emit_signal(emu, SIGTRAP, NULL, 3);
}
void native_div0(x64emu_t* emu)
{
emu->test.test = 0;
emit_div0(emu, (void*)R_RIP, 0);
emit_div0(emu, (void*)R_RIP, 1);
}
void native_fsave(x64emu_t* emu, uint8_t* ed)
@@ -513,7 +540,7 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone && !dyn->insts[jmp].df_notneeded)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
@@ -584,7 +611,7 @@ uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
return addr;
}
// return Ib on a mod/rm opcode without emiting anything
// return Ib on a mod/rm opcode without emitting anything
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
addr = fakeed(dyn, addr, ninst, nextop);
@@ -592,9 +619,11 @@ uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
#undef F8
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, uint16_t* retn)
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn)
{
(void)dyn;
if(is32bits)
addr &= 0xFFFFFFFFLL;
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
@@ -608,7 +637,7 @@ int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress,
if(!addr || !getProtection(addr))
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver64) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
@@ -646,3 +675,44 @@ void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero &= ~(1<<reg);
}
void propagate_nodf(dynarec_native_t* dyn, int ninst)
{
while(ninst>=0) {
if(dyn->insts[ninst].df_notneeded)
return; // already flagged
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
return; // flags are use, so maybe it's needed
dyn->insts[ninst].df_notneeded = 1;
--ninst;
}
}
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);
}
+12 -2
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);
@@ -61,6 +62,8 @@ void native_div0(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
// propagete defererd to unknow, as state is not needed
void propagate_nodf(dynarec_native_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_native_t* dyn, int ninst, int pred);
@@ -68,11 +71,11 @@ int getNominalPred(dynarec_native_t* dyn, int ninst);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// return Ib on a mod/rm opcode without emiting anything
// return Ib on a mod/rm opcode without emitting anything
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, uint16_t* retn);
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn);
// AVX utilities
void avx_mark_zero(dynarec_native_t* dyn, int ninst, int reg);
@@ -81,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__
+40 -29
View File
@@ -55,19 +55,19 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#endif
fpu_reset(dyn);
ARCH_INIT();
int reset_n = -1;
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
uintptr_t cur_page = (addr)&~box64_pagesize;
uintptr_t cur_page = (addr)&~(box64_pagesize-1);
#endif
while(ok) {
#if STEP == 0
if(cur_page != ((addr)&~box64_pagesize)) {
cur_page = (addr)&~box64_pagesize;
if(!(getProtection(addr)&PROT_READ)) {
if(cur_page != ((addr)&~(box64_pagesize-1))) {
cur_page = (addr)&~(box64_pagesize-1);
if(!(getProtection(addr)&PROT_READ) || checkInHotPage(addr)) {
need_epilog = 1;
break;
}
@@ -89,6 +89,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
ARCH_RESET();
} else {
fpu_reset_cache(dyn, ninst, reset_n);
dyn->f = dyn->insts[reset_n].f_exit;
@@ -110,28 +111,33 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
#endif
dyn->f.dfnone_here = 0;
NEW_INST;
MESSAGE(LOG_DUMP, "New Instruction x64:%p, native:%p\n", (void*)addr, (void*)dyn->block);
#if STEP == 0
if(ninst && dyn->insts[ninst-1].x64.barrier_next) {
BARRIER(dyn->insts[ninst-1].x64.barrier_next);
}
#endif
MESSAGE(LOG_DUMP, "New Instruction %s:%p, native:%p\n", is32bits?"x86":"x64",(void*)addr, (void*)dyn->block);
if(!ninst) {
GOTEST(x1, x2);
}
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
#if STEP > 1
if (dyn->insts[ninst].lock) {
WILLWRITELOCK(dyn->insts[ninst].lock);
} else if (dyn->insts[ninst].will_write) {
WILLWRITE();
}
#endif
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");
@@ -173,7 +179,14 @@ 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) {
#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; }
fpu_purgecache(dyn, ninst, 0, tmp1, tmp2, tmp3);
#else
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
#endif
}
if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
dyn->f.pending = 0;
@@ -218,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;
@@ -237,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;
@@ -248,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 && (
@@ -263,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;
@@ -313,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
{
@@ -331,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) {
+4 -4
View File
@@ -29,6 +29,9 @@
#define SF_NODF 16
#define SF_SET_NODF (SF_SET|SF_NODF)
#define NAT_FLAGS_FUSION 0
#define NAT_FLAGS_NOFUSION 1
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
@@ -36,10 +39,9 @@ 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 barrier_next; // next instruction needs a barrier
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
@@ -49,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
+505 -155
View File
@@ -24,7 +24,7 @@
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
@@ -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;
}
@@ -93,15 +94,19 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LOAD_XEMU_CALL();
TABLE64(x3, addr); // expected return address
BNE_MARK(xRIP, x3);
LD_W(w1, xEmu, offsetof(x64emu_t, quit));
CBZ_NEXT(w1);
LD_W(x1, xEmu, offsetof(x64emu_t, quit));
CBZ_NEXT(x1);
MARK;
LOAD_XEMU_REM();
jump_to_epilog(dyn, 0, xRIP, ninst);
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);
@@ -110,6 +115,17 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
*need_epilog = 0;
*ok = 0;
break;
case 0x0D:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 1:
INST_NAME("PREFETCHW");
FAKEED;
break;
default: //???
DEFAULT;
}
break;
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
@@ -160,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 {
@@ -205,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) {
@@ -234,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;
@@ -292,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);
@@ -325,6 +340,20 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
SPILL_EFLAGS();
}
break;
case 0x31:
INST_NAME("RDTSC");
NOTEST(x1);
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);
}
SRLI_D(xRDX, x3, 32);
ZEROUP2(xRDX, x3);
break;
case 0x38:
// SSE3
nextop = F8;
@@ -388,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_LA64((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");
@@ -503,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");
@@ -524,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);
@@ -546,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);
@@ -565,74 +698,89 @@ 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) \
if (box64_dynarec_test == 2) { NOTEST(x1); } \
READFLAGS(F); \
i32_ = F32S; \
BARRIER(BARRIER_MAYBE); \
JUMP(addr + i32_, 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, addr + i32_, 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) \
READFLAGS(F); \
if (la64_lbt) { \
X64_SETJ(x3, I); \
} else { \
GETFLAGS; \
S##YES(x3, x1); \
} \
nextop = F8; \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_LA64((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_LA64(ed & 3); \
} \
BSTRINS_D(eb1, x3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(x3, ed, fixedaddress); \
SMWRITE(); \
}
#define GO(GETFLAGS, NO, YES, NATNO, NATYES, F, I) \
READFLAGS(F); \
tmp1 = x1; \
tmp3 = x3; \
if (la64_lbt) { \
X64_SETJ(x3, I); \
} else { \
GETFLAGS; \
S##YES(x3, x1); \
} \
nextop = F8; \
if (MODREG) { \
if (rex.rex) { \
eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); \
eb2 = 0; \
} else { \
ed = (nextop & 7); \
eb2 = (ed >> 2) * 8; \
eb1 = TO_NAT(ed & 3); \
} \
BSTRINS_D(eb1, x3, eb2 + 7, eb2); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
ST_B(x3, ed, fixedaddress); \
SMWRITE(); \
}
GOCOND(0x90, "SET", "Eb");
#undef GO
#undef GO
case 0xA2:
INST_NAME("CPUID");
@@ -645,12 +793,12 @@ 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;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, x1, &fixedaddress, rex, NULL, 1, 0);
@@ -659,33 +807,82 @@ 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");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
FAKEED;
F8;
}
break;
case 0xAB:
INST_NAME("BTS Ed, Gd");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGD;
u8 = F8;
emit_shld32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
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);
SRAI_D(x1, gd, 5 + rex.w);
ALSL_D(x3, x1, wback, 2 + rex.w);
LDxw(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
ANDI(x2, gd, rex.w ? 0x3f : 0x1f);
IFX (X_CF) {
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);
OR(ed, ed, x4);
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED(1);
GETGD;
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
if (geted_ib(dyn, addr, ninst, nextop)) {
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
GETED(1);
GETGD;
u8 = F8;
u8 &= (rex.w ? 0x3f : 0x1f);
emit_shrd32c(dyn, ninst, rex, ed, gd, u8, x3, x4);
WBACK;
} else {
FAKEED;
F8;
}
break;
case 0xAE:
nextop = F8;
@@ -718,14 +915,23 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL(rex.w ? ((void*)fpu_fxsave64) : ((void*)fpu_fxsave32), -1);
CALL(rex.is32bits ? ((void*)fpu_fxsave32) : ((void*)fpu_fxsave64), -1);
}
break;
case 1:
INST_NAME("FXRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x1);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL(rex.is32bits ? ((void*)fpu_fxrstor32) : ((void*)fpu_fxrstor64), -1);
break;
case 2:
INST_NAME("LDMXCSR Md");
GETED(0);
ST_W(ed, xEmu, offsetof(x64emu_t, mxcsr));
if (box64_sse_flushto0) {
if (BOX64ENV(sse_flushto0)) {
// TODO
}
break;
@@ -735,17 +941,42 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LD_WU(x4, xEmu, offsetof(x64emu_t, mxcsr));
ST_W(x4, wback, fixedaddress);
break;
case 4:
INST_NAME("XSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
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);
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, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
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, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
if (ed != x1) { MV(x1, ed); }
CALL_(native_clflush, -1, 0);
break;
default:
DEFAULT;
}
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);
}
@@ -813,18 +1044,50 @@ 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;
GETGD;
if (MODREG) {
if (rex.rex) {
eb1 = TO_LA64((nextop & 7) + (rex.b << 3));
eb1 = TO_NAT((nextop & 7) + (rex.b << 3));
eb2 = 0;
} else {
ed = (nextop & 7);
eb1 = TO_LA64(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 {
@@ -838,7 +1101,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
BSTRPICK_D(gd, ed, 15, 0);
} else {
SMREAD();
@@ -851,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;
@@ -864,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;
@@ -879,12 +1142,13 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} 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;
@@ -898,22 +1162,79 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETED(1);
u8 = F8;
u8 &= rex.w ? 0x3f : 0x1f;
BSTRPICK_D(x3, ed, u8, u8);
BSTRINS_D(xFlags, x3, 0, 0);
if (u8 <= 10) {
XORI(ed, ed, (1LL << u8));
} else {
MOV64xw(x3, (1LL << u8));
XOR(ed, ed, x3);
}
if (wback) {
SDxw(ed, wback, fixedaddress);
SMWRITE();
} else if (!rex.w) {
ZEROUP(ed);
}
MARK;
break;
default:
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);
GETGD;
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ZEROUP2(x4, ed);
ed = x4;
}
BNE_MARK(ed, xZR);
@@ -933,19 +1254,18 @@ 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);
GETGD;
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ZEROUP2(x4, ed);
ed = x4;
}
BNE_MARK(ed, xZR);
@@ -960,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);
@@ -976,12 +1295,12 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
if (MODREG) {
if (rex.rex) {
wback = TO_LA64((nextop & 7) + (rex.b << 3));
wback = TO_NAT((nextop & 7) + (rex.b << 3));
wb2 = 0;
} else {
wback = (nextop & 7);
wb2 = (wback >> 2) * 8;
wback = TO_LA64(wback & 3);
wback = TO_NAT(wback & 3);
}
BSTRPICK_D(gd, wback, wb2 + 7, wb2);
EXT_W_B(gd, gd);
@@ -997,7 +1316,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
ed = TO_NAT((nextop & 7) + (rex.b << 3));
EXT_W_H(gd, ed);
} else {
SMREAD();
@@ -1023,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;
@@ -1038,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:
@@ -1047,7 +1397,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xCE:
case 0xCF:
INST_NAME("BSWAP Reg");
gd = TO_LA64((opcode & 7) + (rex.b << 3));
gd = TO_NAT((opcode & 7) + (rex.b << 3));
REVBxw(gd, gd);
break;
default:
Loaded 100 of 1693 files, more files were not shown because too many files have changed in this diff. Show more