Compare commits

..
1034 Commits
Author SHA1 Message Date
ptitSeb 62695ceed4 Bumped version to v0.3.0 2024-07-09 11:02:43 +02:00
rajdakin 605d5a29c0 Fixes (#1659)
* Replaced some tabs with spaces

* Fixed some signedness warnings

* Added more debug info

* Fixed an improper alignment

* [WRAPPEDWAYLAND] Added return statements to wrappers

* [EMU] [AVX] Fixed some issues

* [ARM DYNAREC] Fixed some minor warnings

* [ARM DYNAREC] Removed unused macro arguments

* [EMU] Fixed a noisy warning

* [ARM DYNAREC] Removed "empty body" warnings

* [EMU] Fixed an opcode in dynarec, non-cosim builds

* [LA64 DYNAREC] Minor warning fixes

* [LA64 DYNAREC] Fixed empty body warnings

* [LA64 DYNAREC] Added parenthesis around assignments in if statements

* [LA64 DYNAREC] Fixed missing parenthesis in macro definitions

* [RV64 DYNAREC] Fixed minor warnings

* [RV64 DYNAREC] Fixed wrong/missing parentheses

* [WRAPPER] Fixed the WaylandClient callback signatures
2024-07-09 08:21:21 +02:00
Yang Liu fdc7e9d1e4 [LA64_DYNAREC] Fixed ADC/SBC usage (#1658) 2024-07-08 21:46:46 +02:00
ptitSeb dcc7ad45bc Added x64 version of libcrypto.so.1.0.0 and libssl.1.0.0 2024-07-08 18:18:04 +02:00
rajdakin 265f153449 [WRAPPED] Added NSS_Init (#1657) 2024-07-08 17:48:23 +02:00
ptitSeb ba9aa3657c Fixed wrapping of some rare opengl functions 2024-07-08 17:45:28 +02:00
ptitSeb 115d666fff [ARM64_DYNAREC] Small optim on some ROL/ROR opcodes 2024-07-08 17:45:27 +02:00
Yang Liu 42ce1a3b61 [LA64_DYNAREC] Added more opcodes (#1656) 2024-07-08 15:17:16 +02:00
Yang Liu a7b912393c [LA64_DYNAREC] Added more opcodes (#1654) 2024-07-08 14:26:28 +02:00
Yip Coekjan e82f17842e Mask rs2 when using bext instruction if rex.w is not set (#1653) 2024-07-08 13:55:32 +02:00
ptitSeb 4838c86ca9 Fixed deb packaging 2024-07-08 10:33:15 +02:00
ptitSeb d6b9fd2860 [VULKAN] Added 1 more extension 2024-07-07 20:17:19 +02:00
Yang Liu 60dac1aa29 Set last_ip to an unclean state at the end of CALL (#1650) 2024-07-07 17:39:54 +02:00
ptitSeb 8dd071bcfa [ARM64_DYNAREC] Fixed a warning 2024-07-07 17:30:35 +02:00
ptitSeb d92d693df3 [ARM64_DYNAREC] Added AVX.66.0F38 B6 opcode 2024-07-07 11:45:02 +02:00
ptitSeb d16bd5104e [ARM64_DYNAREC] Added AVX.F2.0F D0 opcode 2024-07-07 11:29:17 +02:00
ptitSeb d7e8da6321 [ARM64_DYNAREC] Fixed reflect cache for ymm0 2024-07-07 11:28:54 +02:00
ptitSeb aec3fd524a [VULKAN] Added 1 more extension 2024-07-07 10:39:35 +02:00
ptitSeb 14b0323bf6 [ARM64_DYNAREC] Reworked ymm0 propagation 2024-07-07 10:37:51 +02:00
Haichen Wu b482847779 [INTERPRETER] Added 64 66 8D opcode (#1648) 2024-07-06 08:12:16 +02:00
ptitSeb 8c5752de23 [ARM64_DYNAREC] Made AVX/AVX2 enabled by default, but only for ARM64 Dynarec configs 2024-07-05 21:57:20 +02:00
ptitSeb 267bffb0ec [ARM64_DYNAREC] More improvment on YMM handling 2024-07-05 18:53:32 +02:00
ptitSeb 0546216228 [ARM64_DYNAREC] Added Calling Convention as comment in emitter, for reference 2024-07-05 17:21:20 +02:00
ptitSeb a46ea2c07f Cosmetic change 2024-07-05 17:20:48 +02:00
ptitSeb ed4e1ee0ba Put a limit on how much the hardware counter can be shifted 2024-07-05 17:19:11 +02:00
Yip Coekjan 6ac3716594 Should not follow symlinks on file path resolution (#1644) 2024-07-05 11:02:09 +02:00
ptitSeb 42bad3ea6b Added 1 more wrapped funciton to libcups (for #1629) 2024-07-05 09:53:39 +02:00
ptitSeb f9c4eda1fc [VULKAN] Fixed a typo 2024-07-05 09:08:07 +02:00
KreitinnSoftware 688665e730 [VULKAN] Add Wrapped VK_KHR_android_surface (#1643) 2024-07-05 00:23:45 +02:00
ptitSeb a676255231 [VULKAN] Added 1 more extension 2024-07-04 22:48:04 +02:00
ptitSeb d227edeefd Cosmetic change 2024-07-04 20:09:02 +02:00
ptitSeb 34c3e2dab3 [ARM64_DYNAREC] Improved 0F C7 /6 opcode 2024-07-04 20:08:11 +02:00
Yang Liu 2c0bbc06b7 [DYNAREC] Fixed IMUL sign extension issue (#1639) 2024-07-04 18:47:45 +02:00
Yip Coekjan 299551428f Impl sys_getpgrp & sys_getpgid (#1637) 2024-07-04 18:42:22 +02:00
ptitSeb d0ac9c2a5a Fixed 2 warning 2024-07-04 16:36:16 +02:00
Yip Coekjan a69368e855 Wrap some functions for libc (#1635) 2024-07-04 16:31:26 +02:00
Yang Liu 84b0e2f113 [LA64_DYNAREC] Fixed F2 0F 70 PSHUFLW opcode (#1634) 2024-07-04 12:39:57 +02:00
Yang Liu eb695d5553 [RV64_DYNAREC] Added preliminary RVV infra and PXOR opcode for demonstration (#1632)
* [RV64_DYNAREC] Added preliminary RVV infra and PXOR opcode for demonstration

* keep sse_cache_s uint8_t as suggested

* use xor to do the wrap

* revert

* better fallback
2024-07-04 12:39:05 +02:00
LiZhuoheng b5946f3752 [RV64_DYNAREC] modify DF default /4 opcode (#1633)
* [RV64_DYNAREC] modify DF default /4 opcode

* [RV64_DYNAREC] added DF default /4 opcode
2024-07-04 07:59:54 +02:00
LiZhuoheng 371435afd0 [RV64_DYNAREC] Added DF default /4 opcode (#1631)
* [RV64_DYNAREC] Added DF default /4 opcode

* replace tabs to spaces
2024-07-03 14:44:47 +02:00
ptitSeb 0ba46403c6 Detect UnityPlayer.dll to apply strongmem=1 automatically (can be disabled with BOX64_UNITYPLAYER=0) 2024-07-03 11:19:55 +02:00
Diego q cac43a1f5f Updated box64.box64rc (#1630)
added two baldi games, one horror game, 2d superhot, and one game i had to fix for a friend
2024-07-03 08:18:27 +02:00
Yip Coekjan 7771a67abe Add missing func declarations: get_first_jump_addr (#1627) 2024-07-02 15:59:45 +02:00
Yip Coekjan 9cd8812d8b Handle .relr.dyn section (#1626) 2024-07-02 13:47:48 +02:00
ptitSeb 4b0b3fc98a [DYNAREC] Improved cache coherency and internal jump handling, [ARM64_DYNAREC] Improved YMM register tracking 2024-07-02 10:34:37 +02:00
ptitSeb c6afd44c1c Added one more wrapped function to gnutls 2024-07-02 09:29:14 +02:00
Yang Liu dbb84245a0 Wrapped libsqlite3 (#1625)
* Wrapped libsqlite3

* More functions
2024-07-01 18:58:17 +02:00
ptitSeb 15a7c4d8dd [DYNAREC] Reset fpu scratch after Instruction epilog 2024-07-01 15:21:51 +02:00
Yang Liu a842938cfe Wrapped more functions (#1624)
* Wrapped more gtk functions

* Wrapped 1 more gdk3 function

* Wrapped more gnutls functions

* Added generated files
2024-07-01 14:39:54 +02:00
ptitSeb 3f83038061 [DYNAREC] Keep internal jmp table to the end 2024-07-01 10:39:30 +02:00
ptitSeb 01568f8fd3 [ARM64_DYNAREC] Fixed some regression on internal jumps 2024-07-01 10:33:41 +02:00
ptitSeb 1ee4d5aaf4 [ARM64_DYNAREC] Added 64/65 70-7F/EB opcodes 2024-06-30 15:50:16 +02:00
ptitSeb f9b74642a2 {ARM64_DYNAREC] Small optimisation on F3 0F BC/BD opcodes 2024-06-28 18:51:16 +02:00
ptitSeb 401e3a7282 [ARM64_DYNAREC] Fixed printer for DUP opcode 2024-06-28 18:49:32 +02:00
ptitSeb 32b2b388c8 [ARM64_DYNAREC] Added AVX.66.0F38 91/93 opcodes 2024-06-28 10:35:59 +02:00
ptitSeb 013643782f [ARM64_DYNAREC] Fixed AVX.66.0F3A 06/46/21 opcodes 2024-06-28 10:35:11 +02:00
Yang Liu cb064f9e5a [RV64_DYNAREC] Added vector instructions emitter (#1621) 2024-06-27 08:44:11 +02:00
Yang Liu 52c97c47ab [RV64_DYNAREC] Detect vector extension (#1619) 2024-06-27 08:43:49 +02:00
ptitSeb 5f06d066e7 [ARM64_DYNAREC] Improved comment 2024-06-26 11:10:44 +02:00
liuli a7a211fc85 small fix for ROR and ROL (#1618) 2024-06-26 07:23:13 +02:00
KreitinnSoftware 5540601918 Compile Dynarec With ARMv8-A ASM Flags without Hardware Profile on Android Builds Too (#1617) 2024-06-26 07:22:11 +02:00
ptitSeb 22f99601d9 [INTERPRETER] Added 64/65 F3 0F 58 opcode 2024-06-25 18:12:32 +02:00
ptitSeb 2fe2e52249 [ARM64_DYNAREC] Small fixes to 0F C7 /6 opcode 2024-06-25 14:48:03 +02:00
Yang Liu 6caa598dd7 [RV64_DYNAREC] Fixed regression on D9 E5 FXAM opcode (#1616) 2024-06-25 14:19:17 +02:00
ptitSeb aeeb9b719a [COSIM] Added range handling in BOX64_DYNAREC_TEST ([RCFILE] too) 2024-06-24 20:32:16 +02:00
ptitSeb 36f1808615 [INTERPRETER] opcode F1 is valid alson in 64bits 2024-06-24 18:41:10 +02:00
ptitSeb 0ce5f34f8c [INTERPRETER] Added 32bits F1 opcode 2024-06-24 17:58:40 +02:00
ptitSeb 579ae99d1b [ARM64_DYNAREC] Added 0F C7 /6 opcode, with hardware support if present 2024-06-24 17:34:02 +02:00
ptitSeb fa702c0240 Improved CPUID a bit more, adding RDRAND (helps geekbench6 avx2 version) 2024-06-24 16:07:10 +02:00
ptitSeb 34bc807bd5 [ARM64_DYNAREC] Fixed AVX.66.0F38 90/92 opcodes 2024-06-24 16:05:57 +02:00
ptitSeb 71d49badcc Fixed AVX.66.0F38 90-93 opcodes (certain special cases) 2024-06-24 16:05:26 +02:00
ptitSeb 3dfcc278e0 [ARM64_DYNAREC] Minor fix on printer for SMOV/UMOV 2024-06-24 16:04:29 +02:00
ptitSeb e312fa392d [ARM64_DYNAREC] Reworked ymm_zero handling on internal jump 2024-06-23 20:38:54 +02:00
ptitSeb bda28e5882 [TRACE] Print offset in function in hex 2024-06-23 20:38:11 +02:00
ptitSeb 68c2abc429 [DYNAREC] Try to limit UpdateFlags on internal jumps 2024-06-23 20:26:43 +02:00
ptitSeb b0727d6f2b [ARM64_DYNAREC] Some small optims to a few AVX opcodes 2024-06-23 20:23:04 +02:00
ptitSeb c66be063aa Small improvment to 0F BC/BD opcodes ([ARM64_DYNAREC] too) 2024-06-23 20:22:02 +02:00
ptitSeb 1f0165f895 [ARM64_DYNAREC] Fixed printer for MOVI_64 2024-06-23 20:20:58 +02:00
ptitSeb b1ae5dc2b6 [ARM64_DYNAREC] Small optim on 0F BC/BD opcodes 2024-06-23 12:04:42 +02:00
ptitSeb df228f8829 [ARM64_DYNAREC] Fixed an issue with fpuCacheTransform (possible regression) 2024-06-22 20:33:06 +02:00
ptitSeb dc2d54edf2 Added 66 F2/F3 A4 opcode ({DYNAREC] too) 2024-06-22 18:05:03 +02:00
ptitSeb d39c554541 [ARM64_DYNAREC] Small improvement to 0F 5D/5F opcodes 2024-06-22 13:26:58 +02:00
ptitSeb 314b2a5583 [COSIM] Imprroved F2 0F prefixed opcodes 2024-06-22 13:26:14 +02:00
ptitSeb ce30c1179e Improved handling of cpuid leaf 0x80000006 2024-06-22 11:40:35 +02:00
ptitSeb cbb3126b28 [COSIM] Improved handling of AVX.66.0F38 3E/2F opcodes 2024-06-22 11:40:11 +02:00
ptitSeb a3413ba96d [ARM64_DYNAREC] Improved AVX.66.0F38 2E/2F to avoid segfault when mask is null 2024-06-21 21:22:43 +02:00
ptitSeb 2b625e4aa5 Small fix for a signature of a gnutls function 2024-06-21 21:18:49 +02:00
ptitSeb df74626ca2 [RCFILE] Improved hendling of BOX64_NODYNAREC 2024-06-21 21:17:49 +02:00
Yang Liu 10373ca6fc [RCFILE] Added Goat Simulator profile (#1609) 2024-06-21 14:03:25 +02:00
Yang Liu 3dcd08bd4a Wrapped pthread_cond_signal with aligned cond like others (#1608) 2024-06-21 13:08:53 +02:00
Yang Liu a945daf96d [RV64_DYNAREC] Added unaligned support for F0 /5 LOCK SUB opcode (#1607) 2024-06-20 16:20:36 +02:00
Michael Büchler 22116dabc3 Add missing wrappings for winewayland.so (#1599)
* Add missing wrappings for winewayland.so

These were missing on wine-9.9 built with `--enable-win64` and
`--with-wayland=yes` on Ubuntu 24.04 "noble".

Does not work at this point! Now there is a SIGILL during/after mapping
winewayland.so due to a missing zxdg_output_v1 listener.

* wrappedwaylandclient: add zxdg_output_v1 listener

This is used by wine's waylandclient.so. Tested with wine-9.9 regedit
and winecfg.
2024-06-20 08:24:48 +02:00
ptitSeb 5494d95b6b Added a few more symbols, used by latest steam for linux (for #1603) 2024-06-19 21:30:20 +02:00
theofficialgman 9ab686b3e0 switch to maintained Pi-Apps-Coders apt repo (#1605)
closes https://github.com/ptitSeb/box64/issues/1576
2024-06-19 18:39:03 +02:00
ptitSeb 5b24440e8c [ARM64_DYNAREC] Fixed AVX.F2.0F3A F0 opcode 2024-06-19 10:33:49 +02:00
salt431 44deff987c Update arm64_immenc.c (#1602)
combine if (!bitmask || !~bitmask) to (bitmask == 0 || bitmask == ~0ULL) to reduce overhead.

use bitwise operators instead of + operators.
2024-06-19 08:55:01 +02:00
Yang Liu 7273ac0d34 [RV64_DYNAREC] Fixed potential issue of jump_to_next (#1600) 2024-06-18 18:35:35 +02:00
ptitSeb ceb9834a27 [RCFILE] Better profile for Kingdom Rush Origin linux version 2024-06-18 18:23:31 +02:00
ptitSeb 4eebf25f1c Added BOX64_RESERVE_HIGH in rcfile handling 2024-06-18 17:25:32 +02:00
ptitSeb 865ef2ff6e Added 1 more wrapped symbol to libmpg123 2024-06-18 16:59:54 +02:00
ptitSeb 8138ba6ecb [ARM64_DYNAREC] Added a warning if allocating a scratch register after some YMM 2024-06-18 16:23:32 +02:00
ptitSeb f1c0b52677 [ARM64_DYNAREC] Fixed AVX.66.0F 6B opcode 2024-06-18 16:22:57 +02:00
ptitSeb a4cb62d6d6 [ARM64_DYNAREC] Restaured a better way to handle ymm register, now that the traking is improved 2024-06-18 15:58:57 +02:00
ptitSeb e4062c6031 [ARM64_DYNAREC] Fixed AVX.66.0F3A 19/39 opcodes 2024-06-18 15:24:30 +02:00
ptitSeb 08844f31c9 [ARM64_DYNAREC] Better tracking of used ymm (seems redundent with ymm0_sub) 2024-06-18 15:23:46 +02:00
ptitSeb 4dfdba001b [TRACE] Cosmetic change on ymm printout 2024-06-18 15:22:52 +02:00
LiZhuoheng 8dbf982ebe Added more wrapped functions to gmp and idn2 (#1598) 2024-06-18 11:35:09 +02:00
Yang Liu 031255a946 [RV64_DYNAREC] Improved 0F AE opcodes (#1596) 2024-06-18 10:01:54 +02:00
Yang Liu 8dfbe80b41 [LA64_DYNAREC] Added more opcodes (#1597) 2024-06-18 10:01:12 +02:00
Yang Liu 2bcc997e4b [RV64_DYNAREC] Fixed and refined F0 81,83 LOCK prefix opcodes (#1595) 2024-06-18 09:59:33 +02:00
LiZhuoheng 263e79be53 Added more wrapped functions (#1593) 2024-06-18 07:21:25 +02:00
ptitSeb d031a8b423 [ARM64_DYNAREC][COSIM] Do not test atomic operatin, they don't support double execution very well by nature 2024-06-17 22:15:48 +02:00
ptitSeb 7bec96e4b2 [COSIM] Some improvment to avoid segfault in edge cases 2024-06-17 22:15:03 +02:00
Yang Liu 6bb1bacfba Fixed some symbols not found error for libc and libresolv wrapping (#1591) 2024-06-17 18:40:16 +02:00
Yang Liu 95a4aaf8fd [LA64_DYNAREC] Added more opcodes (#1590) 2024-06-17 18:39:01 +02:00
ptitSeb 387c64b74c Fixed usage of getcpu, only enablign that for recent enough glibc (should help #1586) 2024-06-17 16:02:26 +02:00
ptitSeb 4d068eee26 This should fix slatest steam on linux not starting 2024-06-15 09:58:00 +02:00
Yang Liu ece732ba41 [DYNAREC_RV64] Fixed 16bit LOCK ADD issue (#1584) 2024-06-15 09:02:16 +02:00
Yang Liu 8f40dc1a8c Fixed some vulkan wrapper functions (#1585)
* Fixed some vulkan wrapper functions

* Forgot to submit generated files
2024-06-15 09:01:33 +02:00
ptitSeb c9a6d4c05a [ARM64_DYNAREC] Added AVX.66.0F38 8C/9C/9F/BE opcodes 2024-06-14 11:26:49 +02:00
ptitSeb a66b4e257a [ARM64_DYNAREC] Added AVX.F2.0F 7C/F0 opcodes 2024-06-14 11:25:50 +02:00
ptitSeb 3796805d98 [ARM64_DYNAREC] Added faked F3 0F AE /5 unsupported opcode 2024-06-14 11:24:59 +02:00
ptitSeb a3d09e95d5 Fixed an issue with BOX64_RDTSC_1GHZ being always active 2024-06-13 15:51:15 +02:00
ptitSeb 626846c37b [ANDROID] This should fix android build 2024-06-13 11:32:58 +02:00
ptitSeb 8bf1ac6577 [ARM64_DYNAREC] Added AVX.66.0F 7C opcode 2024-06-13 10:49:49 +02:00
ptitSeb 58c0bce4cf More work on RDTSC emulation 2024-06-13 10:22:33 +02:00
LiZhuoheng 3a82dc6aad Added more wrapped function to libunistring2 (#1582)
* Added more wrapped function to libunistring2

* add wrapper.c
2024-06-13 07:46:27 +02:00
ptitSeb e42b9e2866 [WAYLAND] Wrapped one more listener 2024-06-12 20:10:46 +02:00
ptitSeb 8a85acff32 Better wrapping for libwayland-client, removed the x64 versions of the libs, using wrapped one instead 2024-06-12 19:41:06 +02:00
ptitSeb b450ea24a2 Added the new x64 libs 2024-06-12 16:05:47 +02:00
ptitSeb 4fa92dc069 Removed wrapped libwayland-client and libwayland-cursor, the wrapping is wrong, and use native libs instead 2024-06-12 16:01:01 +02:00
LiZhuoheng 61a80c9b2d Wrapped libhogweed6 (#1579) 2024-06-12 15:27:37 +02:00
ptitSeb bcfd0f7ea3 Added one structure to libwayland-clinet and auto bridges all current interfaces 2024-06-11 18:02:02 +02:00
ptitSeb c404b3e0ab Fixed libudev.so.0 wrapping, removed functions from libudev.so.1 2024-06-11 16:41:44 +02:00
ptitSeb b246133b3b [ARM64_DYNAREC] Added AVX.0F 77 256bits opcode 2024-06-11 15:07:10 +02:00
ptitSeb 5b28d7bc03 [INTERPRETER] Added AVX.0F 77 256bits opcode 2024-06-11 15:06:50 +02:00
ptitSeb 8adaefcdb9 Remove and obsolete comment 2024-06-11 15:06:19 +02:00
ptitSeb e64b4d5c04 [ARM64_DYNAREC] Fixed AVX.66.0F E1-E3 opcodes and Added AVX.66.0F C6 and AVX.0F 17 opcodes 2024-06-11 13:33:24 +02:00
ptitSeb 59caccfeae [ARM64_DYNAREC] Added AVX.66.0F38 02/0B opcodes 2024-06-11 10:32:53 +02:00
ptitSeb bbd3333b5f [ARM64_DYNAREC] Fixed another issue with Ymm value when updating flags on internal jump 2024-06-11 10:21:52 +02:00
ptitSeb 1ce7f32b5d [ARM64_DYNAREC] Added AVX.66.0F38 5A opcode 2024-06-11 10:12:24 +02:00
ptitSeb 95f18dbf15 [ARM64_DYNAREC] Fixed another issue with Ymm0 mask and reset_cache on internal jump 2024-06-11 10:11:55 +02:00
LiZhuoheng 9ed2e3bbf2 Wrapped libunistring2 (#1577) 2024-06-11 08:02:11 +02:00
ptitSeb 8b3cd23045 [ARM64_DYNAREC] Added AVX.66.0F38 90/92 opcodes and added AVX.66.0F38 04 opcode 2024-06-10 15:18:06 +02:00
ptitSeb 072241eb10 [ARM64_DYNAREC] Fixed AVX.66.0F3A 00/01 opcodes 2024-06-10 15:17:03 +02:00
ptitSeb 84a8500323 [ARM64_DYNAREC] Fixed 256bits version of AVX.66.0F D1/D2/D3 opcodes 2024-06-10 15:15:57 +02:00
ptitSeb a8911fc979 [ARM64_DYNAREC] Cosmetic change 2024-06-10 15:14:55 +02:00
Diego q 04ba0b2f67 Update README.md (#1573)
Added Strong memory mode to the hint under unity games because freezing is also a common issue on PI-4 and PI-5 for games, also added the mention of PI-5 on the hint because the issues aren't limited to the PI-4 and also apply to the Pi-5
2024-06-09 22:49:35 +02:00
Diego q d1e5bc5c19 Update README.md (#1572)
Usage link was broken so i fixed it
2024-06-09 21:23:36 +02:00
ptitSeb 38364ef07f [COSIM] Fixed 66 48 xx type of opcodes 2024-06-09 17:45:36 +02:00
ptitSeb b25d8db994 [ARM64_DYNAREC] Fixed an issue when not purging Ymm0 on internal jump with less Ymm0 2024-06-09 17:12:06 +02:00
ptitSeb 989ed95891 [ARM64_DYNAREC] Fixed AVX.66.0F38 28 opcode 2024-06-09 17:05:33 +02:00
ptitSeb d15ffc48a3 [ARM64_DYNAREC] Fixed AVX.66.0F 7F opcode 2024-06-09 16:56:15 +02:00
ptitSeb 06df8c7bed [DYNAREC] Another fix for YMM Zero'd upper reg tracking 2024-06-09 14:51:41 +02:00
ptitSeb 950241d52f [ARM64_DYNAREC] Added AVX.66.0F38 41/8E/9B, AVX.66.0F3A 06 and AVX.66.0F F6 opcodes 2024-06-08 21:31:11 +02:00
ptitSeb a147c12f72 [ARM64_DYNAREC] Another fix for YMM selection on High registry pressure cases 2024-06-08 16:51:51 +02:00
ptitSeb 874828c2ac [ARM64_DYNAREC] Added AVX.66.0F 50/C2, AVX.66.0F3A 0D, AVX.66.0F38 16/28/29/2B/36/AC/BA and AVX.F2.0F 51 opcodes 2024-06-08 15:21:55 +02:00
ptitSeb 3369e5e755 Remove a warning on known unhandled arch_prctl commands 2024-06-08 15:19:46 +02:00
ptitSeb 9b3930ea62 [ARM64_DYNAREC] Small optim on 66 0F 50 opcode 2024-06-08 15:19:01 +02:00
ptitSeb 987d0db806 [INTERPRETER] Fixed AVX.66.0F 50 opcode not handling vex.l 2024-06-08 15:18:34 +02:00
ptitSeb 97530e4095 [ARM64_DYNAREC] Added AVX.66.0F E6, AVX.66.0F38 98 and fixed AVX.F2.0F E6 opcodes 2024-06-08 11:53:35 +02:00
ptitSeb 4c285d4d8a [ARM64_DYNAREC] Fixed an issue when purging an YMM that is used in the same opcode 2024-06-08 11:52:00 +02:00
ptitSeb cd5fbc1492 Added 2 wrapped function to libglib2 2024-06-08 09:50:10 +02:00
ptitSeb 2e379300a6 [RCFILE] Added a few more profiles 2024-06-07 20:02:57 +02:00
ptitSeb 65c19d073c Only expose xsave extension if avx is used 2024-06-07 17:04:14 +02:00
ptitSeb eb013f3492 [DYNAREC] This should fix RV64 and LA64 builds 2024-06-07 14:30:36 +02:00
ptitSeb b2fd651abe [ARM64_DYNAREC] Fixed YMM cache handling, espcially in high pressure regs cases 2024-06-07 13:34:22 +02:00
xctan d4b02e6a3f [RV64_DYNAREC] Fixed sign extension of 8-bit immediate in 66 opcodes (#1568) 2024-06-07 11:37:29 +02:00
ptitSeb 537cb65f26 [ARM64_DYNAREC] Added BMI.0F38 F2, F3/1 opcodes 2024-06-07 10:25:14 +02:00
ptitSeb f61367fc9a [ARM64_DYNAREC] That's just cosmetic... 2024-06-07 10:24:15 +02:00
LiZhuoheng 46e0505336 Wrapped libnettle8 (#1567) 2024-06-07 10:22:03 +02:00
xctan 75004d0b56 [RV64_DYNAREC] Fixed some opcodes caught by cosim (#1561)
* [RV64_DYNAREC] Fixed emit_shrd16c

* [RV64_DYNAREC] Fixed BSWAP Gw

* [RV64_DYNAREC] Fixed 32 bit RCL/RCR Ed, 1

* [RV64_DYNAREC] Fixed 32 bit BTR

* [RV64_DYNAREC] Fixed 32 bit SHLD

* [RV64_DYNAREC] Fixed 32 bit SHLD again

* [RV64_DYNAREC] Fixed 16 bit constant SHLD again

* [RV64_DYNAREC] Fixed 16-bit BTC

* [RV64_DYNAREC] Fixed 32-bit rotates using Zbb extension

* [RV64_DYNAREC] Fixed 16-bit SHLD opcode

* [RV64_DYNAREC] Fixed the mask of LAHF opcode

* [RV64_DYNAREC] Fixed LAHF again and handled OF2 before cosim

* [RV64_DYNAREC] Fixed XADD Eb, Gb when Eb == Gb

* [RV64_DYNAREC] Fixed XADD Ew, Gw when Ew == Gw

* [RV64_DYNAREC] Fixed zero extension of 32 bit Ed operand

* [RV64_DYNAREC] Fixed XADD Eb, Gb again for AH, BH, CH, DH

* [RV64_DYNAREC] Fixed various 16-bit immediate extension
2024-06-06 17:32:49 +02:00
ptitSeb 0dc5761ca6 [INTERPRETER] Added suport for F16C extension (linked to AVX flag) ([ARM64_DYNAREC] too) 2024-06-06 16:48:05 +02:00
ptitSeb df47fb5be8 Disable F16C for now, it's not ready yet 2024-06-06 13:59:09 +02:00
ptitSeb 0cedc70eb3 [ARM64_DYNAREC] Added a new small batch of AVX/BMI2 opcodes 2024-06-06 13:47:47 +02:00
ptitSeb 1612687acf [ARM64_DYNAREC] Fixed VCMPSS opcode 2024-06-06 13:47:14 +02:00
LiZhuoheng 67d587cd9b Wrapped libtasn1-6 (#1563) 2024-06-06 09:48:31 +02:00
LiZhuoheng 9e97e96b87 Wrapped libp11-kit (#1562) 2024-06-06 08:12:34 +02:00
ptitSeb 79c1ad1431 [ARM64_DYNAREC] Added a few more AVX opcodes 2024-06-05 20:40:26 +02:00
ptitSeb c0ebe09521 Added an AVX test (not on Android, needs to be build there) 2024-06-05 19:44:25 +02:00
ptitSeb b568cc529e [ARM64_DYNAREC] Added a bunch of AVX ocpodes and some fixes too 2024-06-05 19:44:02 +02:00
ptitSeb dc8e24c7b7 [INTERPRETER] Fixed VCMP opcode familly, that needs more cases on than con-vex CMP familly 2024-06-05 15:03:44 +02:00
ptitSeb ba411303e9 [DYNAREC] Improved handling of the Ymm0 attribute 2024-06-05 10:44:31 +02:00
ptitSeb 8848bc2e7f [ARM64_DYNAREC] Small optim for AVX.66.0F D7 opcode 2024-06-05 09:51:03 +02:00
Yang Liu f7798f361a [LA64_DYNAREC] Fixed LOCK DEC opcode (#1560) 2024-06-04 18:53:32 +02:00
ptitSeb 6a25427cb6 [DYNAREC] Small improvment to Dynarec infrastructure 2024-06-04 11:11:17 +02:00
ptitSeb a6c283f4ce [ARM64_DYNAREC] Added AVX.0F 16/50/53/C2 opcodes 2024-06-03 22:11:12 +02:00
Yang Liu 48bb907d2d [LA64_DYNAREC] Added more opcodes (#1558) 2024-06-03 22:04:28 +02:00
Yang Liu c2ce5d5557 [LA64_DYNAREC] Fixed emit_or16 (#1559) 2024-06-03 22:04:12 +02:00
ptitSeb 0d30fe90f8 [ARM64_DYNAREC] Added AVX.66.0F 5A/5C-5F/D0-D3 2024-06-03 21:29:14 +02:00
ptitSeb c434cef45e [ARM64_DYNAREC] Cosmetic change 2024-06-03 21:28:16 +02:00
ptitSeb d01970f731 [ARM64_DYNAREC] Added AVX.66.0F3A 02/08-09/0E/14/20/40/4A-4B opcodes 2024-06-03 20:28:32 +02:00
ptitSeb bb9beb75d1 [INTERPRETER] Fixed name in comment of an opcode 2024-06-03 20:28:32 +02:00
xctan ad3a9e6c55 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1557)
* [RV64_DYNAREC] Added 0F 38 0B PMULHRSW opcode

* [RV64_DYNAREC] Added 0F E4 PMULHUW opcode

* [RV64_DYNAREC] Added 0F F4 PMULUDQ opcode

* [RV64_DYNAREC] Added 0F F6 PSADBW opcode

* [RV64_DYNAREC] Added 0F 38 08 PSIGNB opcode

* [RV64_DYNAREC] Optimized 66 0F 38 08 PSIGNB opcode

* [RV64_DYNAREC] Added 0F 38 0A PSIGND opcode

* [RV64_DYNAREC] Optimized 66 0F 38 0A PSIGND opcode

* [RV64_DYNAREC] Added 0F 38 09 PSIGNW opcode

* [RV64_DYNAREC] Optimized 66 0F 38 09 PSIGNW opcode

* [RV64_DYNAREC] Added 0F F2 PSLLD opcode

* [RV64_DYNAREC] Added 0F F3 PSLLQ opcode

* [RV64_DYNAREC] Added 0F F1 PSLLW opcode

* [RV64_DYNAREC] Fixed 0F F1/F2 PSLLW/PSLLD opcode

* [RV64_DYNAREC] Added 0F E1 PSRAW opcode

* [RV64_DYNAREC] Added 0F D2 PSRLD opcode

* [RV64_DYNAREC] Added 0F D3 PSRLQ opcode

* [RV64_DYNAREC] Added 0F D1 PSRLW opcode

* [RV64_DYNAREC] Added 0F F8 PSUBB opcode

* [RV64_DYNAREC] Added 0F FA PSUBD opcode

* [RV64_DYNAREC] Added 0F FB PSUBQ opcode

* [RV64_DYNAREC] Added 0F E8 PSUBSB opcode and optimized 0F E9 PSUBSW opcode

* [RV64_DYNAREC] Added 0F D8 PSUBUSB opcode
2024-06-03 17:42:23 +02:00
ptitSeb 9a30b65180 [ARM64_DYNAREC] Added AVX.66.0F38 17/20-25/29/37-40/45-47/78-79/99/AA/AE-AF/BB-BD/F7 opcodes 2024-06-03 17:33:55 +02:00
ptitSeb cb548fe1fa [INTERPRETER] Fixed name in comment of an opcode 2024-06-03 17:31:17 +02:00
ptitSeb 0a8f049ced [ARM64_DYNAREC] Added AVX.66.0F38 19/1A and AVX.66.0F3A 22 opcodes 2024-06-03 14:43:21 +02:00
ptitSeb 890809069e [ARM64_DYNAREC] Fixed AVX.F2/F3.0F 5D/5F opcodes 2024-06-03 14:42:21 +02:00
ptitSeb ca9a6fe019 [ARM64_DYNAREC] Empty regs needs to be fetched last (again) 2024-06-03 13:54:49 +02:00
ptitSeb 94ccae727b [ARM64_DYNAREC] Fixed AVX Cache transform between internal jump points 2024-06-03 13:46:30 +02:00
ptitSeb 001e77952e [COSIM] Added more helpers to avoid segfault on rare cases 2024-06-03 13:45:55 +02:00
ptitSeb ac6a453833 [ARM64_DYNAREC] Empty register needs to be fetched last 2024-06-03 12:45:33 +02:00
ptitSeb 307915130c [INTERPRETER] Fixed VZEROUPPER opcode 2024-06-03 12:45:05 +02:00
Romain TISSERAND 3d225ef908 Try to fix mmap64 already defined error in custommem.c (#1552) 2024-06-03 08:07:11 +02:00
ptitSeb 1c9123637a [ARM64_DYNAREC] Added AVX.F3.0F 52, AVX.66.0F E4 and AVX.0F 52 opcodes 2024-06-02 20:31:32 +02:00
ptitSeb f1f690552f [ARM64_DYNAREC] Added AVX.66.0F38 08-0A/1C-1E/30-35/58/59/90/92/A8/A9/B8/B9 opcodes 2024-06-02 20:10:00 +02:00
ptitSeb 57dcf3401c [ARM64_DYNAREC] Remove parasite typo to fix build 2024-06-02 18:41:17 +02:00
ptitSeb 9e5df7957e [INTERPRETER] Added missing FMA opcodes, and fixed some existing ones 2024-06-02 17:26:26 +02:00
ptitSeb ca63389ea3 [INTERPRETER] Fixed opcode name in comment 2024-06-02 16:45:35 +02:00
ptitSeb 7b7ee070b9 [ARM64_DYNAREC] Added AVX.66.0F D6/E5/E7/F5 opcodes 2024-06-02 16:32:16 +02:00
ptitSeb 3aee16e9a0 [ARM64_DYNAREC] Added AVX.66.0F3A 00/01/04/05/0A/0B/46 opcodes 2024-06-02 15:18:04 +02:00
ptitSeb 06cb3624e2 [ARM64_DYNAREC] Fixed handling of YMM0 on forward jump 2024-06-02 13:56:13 +02:00
ptitSeb a1f83418b9 [COSIM] Fixed YMM handling in cosim, seems to work better now 2024-06-02 13:44:38 +02:00
ptitSeb e5a32ea129 [ARM64_DYNAREC] Added AVX.66.0F 60-63/67-6A/71 opcodes 2024-06-02 13:13:01 +02:00
ptitSeb eb209abe62 [ARM64_DYNAREC] Don't use fix scratch for x87 conversion, it might conflict with YMM handling 2024-06-02 13:12:06 +02:00
ptitSeb 13551fd410 [INTERPRETER] Small cosmetic changes on raz of ymm 2024-06-02 13:11:13 +02:00
ptitSeb 2493706315 [COSIM] Improved reliability with AVX (but there is still something wrong there) 2024-06-02 13:10:50 +02:00
ptitSeb b49273c079 [INTERPRETER] Added FMA cpu extension (linked to BOX64_AVX=2) 2024-06-02 11:26:16 +02:00
ptitSeb 7c1b161277 [ARM64_DYNAREC] Fixed YMM COSIM refreshing on each steps 2024-06-02 11:26:16 +02:00
ptitSeb d8a1dcc1b4 [COSIM] Fixed issue with YMM printing on difference 2024-06-02 11:26:16 +02:00
Yang Liu f44d60c58f [LA64_DYNAREC] Added more opcodes (#1549)
* [LA64_DYNAREC] Added more opcodes

* fastnan handling and fixed PALIGNR...
2024-06-02 10:25:57 +02:00
ptitSeb dc71840a5a [ARM64_DYNAREC] Added AVX.66.0F3A 21 and fixed a bunch of issues 2024-06-02 09:15:37 +02:00
ptitSeb 07b17cd0f6 [INTERPRETER] Small fixes for some rare case of AES with serc==dest 2024-06-02 08:41:29 +02:00
Yang Liu cf37e8ea83 [LA64_DYNAREC] Added more opcodes and fixed ADC opcode (#1548) 2024-06-01 20:08:33 +02:00
ptitSeb 5384489702 [ARM64_DYNAREC] Added AVX.F2.0F 58-5A/5C-5F opcodes 2024-06-01 19:38:28 +02:00
ptitSeb 1ad69d785f [ARM64_DYNAREC] Added AVX.66.0F C4/C5/D7 opcodes 2024-06-01 19:22:39 +02:00
ptitSeb ef3acd9f33 [ARM64_DYNAREC] Added BMI.F2.0F38 F7 opcode 2024-06-01 19:12:18 +02:00
ptitSeb 083b42fead [ARM64_DYNAREC] Added AVX.66.0F 10-17/29/29/2B/2E/2F/54-59/74-76/7E opcodes 2024-06-01 19:04:50 +02:00
ptitSeb c6814a6f97 [ARM64_DYNAREC] Added AVX.0F 28/29/2B/2E/2F/54-56/5A-5F opcodes, plus various small fixes 2024-06-01 18:03:24 +02:00
Yang Liu 9dbd7fc7e0 [INTERP] Rework on the 16b emulation for LA64 (#1547)
* [INTERP] Rework on the 16b emulation for LA64

* fix compiler issue
2024-06-01 17:14:23 +02:00
ptitSeb a79eff3b0d [ARM64_DYNAREC] Added AVX.F3.0F 10-12/16/2A/2C/2D/58-5F opcodes, plus a few other fixes 2024-06-01 15:32:37 +02:00
ptitSeb a89d7a2e2a [ARM64_DYNAREC] Added AVX.F2.0F 10-12/2A/2C/2D opcodes 2024-06-01 14:28:32 +02:00
ptitSeb 0336f6a987 [ARM64_DYNAREC] Added a few 67 prefixed opcodes 2024-06-01 13:33:20 +02:00
ptitSeb 6d68975ba5 [ARM64_DYNAREC] Added ADX RORX opcode 2024-06-01 13:17:50 +02:00
ptitSeb 2b07fd7c6a [ARM64_DYNAREC] Added AVX.66.0F3A 38/39 opcodes 2024-06-01 13:10:53 +02:00
ptitSeb f8cc423f3d [ARM64_DYNAREC] Added AVX.66.0F 72/7F/F8-FE 2024-06-01 12:37:37 +02:00
ptitSeb f4667fa3cf [ARM64_DYNAREC] Added AVX.F3.0F 7E opcode 2024-06-01 12:05:38 +02:00
Yang Liu d8f929755a Detects extensions even if dynarec is disable at runtime (#1546) 2024-06-01 11:55:45 +02:00
ptitSeb 031685e0a7 [ARM64_DYNAREC] Added AVX.66.0F38 00/DC-DF opcodes 2024-06-01 11:48:09 +02:00
ptitSeb 9f260eb86c [ARM64_DYNAREC] Fix issue with 66 0F 38 DC-DF when rare case of dest==src 2024-06-01 11:38:32 +02:00
ptitSeb 75878b24cd [ARM64_DYNAREC] Added AVX.F3.0F 7F opcode 2024-06-01 10:35:24 +02:00
ptitSeb fe0425eb80 [ARM64_DYNAREC] Added a couple of AVX.66.0F3A opcodes, and fixed some sse/avx function helpers 2024-06-01 09:49:35 +02:00
ptitSeb 453003da23 [ARM64_DYNAREC] Added some AVX.66.0F opcodes 2024-06-01 09:02:54 +02:00
Yang Liu eec08973bf [LA64_DYNAREC] Added LOCK CMPXCHG unaligned version (#1545) 2024-06-01 08:12:25 +02:00
Yang Liu c65f8da90f [RV64_DYNAREC] Fixed LOCK CMPXCHG unaligned version (#1544) 2024-06-01 07:52:03 +02:00
Yang Liu 2970ed5bfd [LA64_DYNAREC] Fixed 0F C2 CMPPS opcode (#1543) 2024-05-31 23:27:02 +02:00
ptitSeb bfebcba431 [ARM64_DYNAREC] Added a bunch of AVX/BMI2/ADX opcodes 2024-05-31 22:33:12 +02:00
ptitSeb dde85b761b [INTERPRETER] Added BMI1, BMI2 and ADX extensions 2024-05-31 15:59:11 +02:00
ptitSeb 34809e48d8 [ARM64_DYNAREC] Some fixes to AVX opcodes 2024-05-31 15:51:07 +02:00
xctan 6749c2d1a6 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1542)
* [RV64_DYNAREC] Added 0F 38 06 PHSUBD opcode

* [RV64_DYNAREC] Added 0F 38 07 PHSUBSW opcode

* [RV64_DYNAREC] Added 0F 38 05 PHSUBW opcode

* [RV64_DYNAREC] Added 0F C4 PINSRW opcode

* [RV64_DYNAREC] Added 0F 38 04 PMADDUBSW opcode

* [RV64_DYNAREC] Added 0F EE PMAXSW opcode

* [RV64_DYNAREC] Optimized SSE packed min/max

* [RV64_DYNAREC] Added 0F DE PMAXUB opcode

* [RV64_DYNAREC] Added 0F EA PMINSW opcode

* [RV64_DYNAREC] Added 0F DA PMINUB opcode

* [RV64_DYNAREC] Optimized 0F D9 PSUBUSW opcode

* [RV64_DYNAREC] Added 0F D7 PMOVMSKB opcode

* [RV64_DYNAREC] Optimized (66) 0F D7 PMOVMSKB opcode

* [RV64_DYNAREC] Switched to the simpler implementation for PMOVMSKB
2024-05-31 14:09:10 +02:00
ptitSeb 7eb24ff514 [ARM64_DYNBAREC] Added AVX.66.0F38 2C-2F opcodes 2024-05-30 21:26:10 +02:00
ptitSeb e367a2bcc9 [ARM64_DYNAREC] Added AVX.66.0F 64-66 opcodes 2024-05-30 20:25:01 +02:00
ptitSeb a02283264a [ARM64_DYNAREC] Fixed AVX.0F 12/13 opcodes 2024-05-30 20:24:34 +02:00
ptitSeb 7a7e9ee9af [ARM64_DYNAREC] Added AVX.0F 10-13 opcodes 2024-05-30 20:07:29 +02:00
ptitSeb b7f25a48c2 [ARM64_DYNAREC] Added AVX.0F 14/15/77/AE opcodes 2024-05-30 19:00:41 +02:00
ptitSeb 4477aa3159 [ARM64_DYNAREC] Added AVX.66.0F3A 15/16/17 opcodes 2024-05-30 18:40:07 +02:00
ptitSeb 4fd23c752c [ARM64_DYNAREC] Added AVX.66.0F 6B opcode 2024-05-30 18:21:16 +02:00
ptitSeb 60b625bc0f [ARM64_DYNAREC] Added AVX.66.F3A 19 opcodes and some various avx helper fixes 2024-05-30 18:13:01 +02:00
ptitSeb d1703b9bc0 [ARM64_DYNAREC] Added AVX.66.0F 5B/6F opcodes 2024-05-30 17:39:46 +02:00
ptitSeb eb9da7417f [RV64_DYNAREC] Fixed build 2024-05-30 17:16:28 +02:00
ptitSeb 782f497b20 [ARM64_DYNAREC] Added AVX.0F 58-59 opcodes, and fixed AVX.66.0F3A 18 opcode 2024-05-30 17:14:05 +02:00
ptitSeb 003a83b40b [ARM64_DYNAREC] Added AVX.66.0F38 18 and AVX.66.0F3A 0C opcodes 2024-05-30 16:53:39 +02:00
ptitSeb 2f8d28e7da [ARM64_DYNAREC] Added AVX.0F 57 opcode 2024-05-30 16:08:20 +02:00
ptitSeb fa591589c7 [ARM64_DYNAREC] Added AVX.66.0F3A 18 opcode 2024-05-30 15:47:19 +02:00
ptitSeb f0ea459c57 [ARM64_DYNAREC] That first avx opcode now is 256bits enabled 2024-05-30 15:17:13 +02:00
xctan f3d733c3ff [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1539)
* [RV64_DYNAREC] Added 0F DF PANDN opcode

* [RV64_DYNAREC] Added 0F E0 PAVGB opcode

* [RV64_DYNAREC] Added 0F E3 PAVGW opcode

* [RV64_DYNAREC] Added 0F 74 PCMPEQB opcode

* [RV64_DYNAREC] Added 0F 76 PCMPEQD opcode

* [RV64_DYNAREC] Added 0F 64 PCMPGTB opcode

* [RV64_DYNAREC] Added 0F 66 PCMPGTD opcode and optimized 66 0F 66 PCMPGTD opcode

* [RV64_DYNAREC] Added 0F 65 PCMPGTW opcode

* [RV64_DYNAREC] Added 0F C5 PEXTRW opcode

* [RV64_DYNAREC] Added 0F 38 02 PHADDD opcode

* [RV64_DYNAREC] Optimized packed saturate add/sub

* [RV64_DYNAREC] Added 0F 38 03 PHADDSW opcode

* [RV64_DYNAREC] Added 0F 38 01 PHADDW opcode
2024-05-30 14:35:27 +02:00
LiZhuoheng 19ca78769f Wrapped libssh2 (#1538)
* Wrapped libssh2

* Add more libssh2 wrapped functions
2024-05-30 14:34:08 +02:00
ptitSeb 3e5784cbc5 [ARM64_DYNAREC] Added a fisrt 128bits only AVX opcode 2024-05-30 12:12:45 +02:00
xctan 98d9f36f9c Added more MMX opcodes and some optimizations too (#1537)
* [RV64_DYNAREC] Added 0F DD PADDUSW opcode and optimized 66 0F DD PADDUSW opcode

* [RV64_DYNAREC] Added 0F 3A 0F PALIGNR opcode

* [RV64_DYNAREC] Optimized 66 0F 3A 0F PALIGNR opcode
2024-05-30 10:54:48 +02:00
ptitSeb 22bc6872f4 [INTERPRETER] Last batch of avx/avx2 opcode 2024-05-29 16:36:43 +02:00
ptitSeb f6fe84afad [INTERPRETER] Added more avx/avx2 opcodes, and fixed vpxor 2024-05-29 15:14:26 +02:00
ptitSeb 4744534fc9 [INTERPRETER] Moar avx/avx2 opcodes 2024-05-29 12:09:21 +02:00
ptitSeb af05d7439f [INTERPRETER] yet more avx/avx2 opcodes 2024-05-29 10:53:38 +02:00
ptitSeb 6e22f4fd6d Added one xslt wrapped constant (for #1534) 2024-05-29 08:39:52 +02:00
ptitSeb 0e3d92148b Added a few libc wrapped function (for #1517 and #1531) 2024-05-29 08:26:18 +02:00
ptitSeb 06cf6d2ecc [INTERPRETER] and a bit more avx/avx2 opcodes 2024-05-28 22:42:12 +02:00
ptitSeb 7b5654eea4 [INTERPRETER] still more avx/avx2 opcodes 2024-05-28 22:09:50 +02:00
ptitSeb 503eb41939 [INTERPRETER] more and more avx/avx2 opcodes 2024-05-28 19:55:15 +02:00
ptitSeb a77db3c6a5 [INTERPRETER] Even more avx/avx2 opcodes, all the mov and more 2024-05-28 18:27:32 +02:00
ptitSeb 4e0889469a [INTERPRETER] Even more avx/avx2 opcodes, and a fix for android builds 2024-05-28 16:50:51 +02:00
xctan 7c5bf62fc0 [RV64_DYNAREC] Added more MMX opcodes and some optimizations too (#1535)
* [RV64_DYNAREC] Added 0F F7 MASKMOVQ opcode

* [RV64_DYNAREC] Added 0F 38 1C PABSB opcode

* [RV64_DYNAREC] Added 0F 38 1E PABSD opcode

* [RV64_DYNAREC] Added 0F 38 1D PABSW opcode

* [RV64_DYNAREC] Added 0F 63 PACKSSWB opcode

* [RV64_DYNAREC] Added 0F FC PADDB opcode

* [RV64_DYNAREC] Added 0F D4 PADDQ opcode

* [RV64_DYNAREC] Added 0F EC PADDSB opcode and optimized 66 0F EC PADDSB opcode

* [RV64_DYNAREC] Added 0F DC PADDUSB opcode and optimized 66 0F DC PADDUSB opcode
2024-05-28 15:04:41 +02:00
ptitSeb b79f86b8d1 [INTERPRETER] More avx/avx2 opcodes 2024-05-28 14:55:17 +02:00
ptitSeb b9f5929439 [INTERPRETER] More avx, avx2 and vaes opcodes 2024-05-28 10:42:41 +02:00
ptitSeb 3dc396a647 Fixed cpuid leaf d, component 2 (fixes wine 9.6+ not booting) 2024-05-27 16:50:26 +02:00
ptitSeb c358bf448f Fixed a warning 2024-05-27 14:58:34 +02:00
ptitSeb abd1d56d7f Correct hadnlign of upper 32bits value of mask for xsave/xrstor 2024-05-27 14:57:05 +02:00
ptitSeb 22b9c16351 [ARM64_DYNAREC] Added faked 0F C7 /4 opcode to get bigger dynablock 2024-05-27 14:56:27 +02:00
ptitSeb 0131958136 [INTERPRETER] Added more avx opcodes 2024-05-27 14:51:08 +02:00
ptitSeb 9f70767acf [ARM64_DYNAREC] Fixed some SHA1 opcode when source is same as dest 2024-05-27 13:45:35 +02:00
ptitSeb bdeb8d7ee2 [ARM64_DYNAREC] Some fixes to opcode when src is same as dest 2024-05-27 13:14:22 +02:00
ptitSeb de831ee5ac [INTERPRETER] Some fixes when opcode use with same reg as src and dest 2024-05-27 13:13:52 +02:00
ptitSeb da1cb42f2a [ARM64_DYNAREC] Fixed some pcmp[ei]stri flags 2024-05-27 13:07:01 +02:00
ptitSeb 2c366ef4bd Just clear AF flags on pcmp[i/e]stri helper 2024-05-27 13:06:28 +02:00
ptitSeb bc0f31407f [INTERPRETER] Added some more avx opcodes 2024-05-27 12:48:05 +02:00
ptitSeb 0d755e610b More avx infrastructure 2024-05-27 12:21:57 +02:00
ptitSeb 55ee7fcc33 [INTERPRETER] Some fixes and small refactor on avx handling 2024-05-27 11:13:15 +02:00
ptitSeb 10200d7b55 [INTERPRETER] Added avx (66 0F 38) 00 opcode 2024-05-27 10:23:56 +02:00
ptitSeb 1eab6a0c8e [INTERPRETER] Added avx (66 0F 3A) 0F opcode 2024-05-27 10:08:46 +02:00
ptitSeb fc2d50c7d3 [INTERPRETER] Added avx (F3 0F) 7F opcode 2024-05-27 10:02:33 +02:00
ptitSeb aaed0364bd [INTERPRETER] Added avx (66 0F 3A) 44 opcode 2024-05-27 09:53:49 +02:00
ptitSeb 9e0139f3c3 Small cleanup in my_cpuid 2024-05-27 09:53:29 +02:00
ptitSeb ec3c3b7eed [INTERPRETER] Added avx (66 0F) 6F ocpode 2024-05-27 09:11:50 +02:00
ptitSeb c67632722b [INTERPRETER] Added avx (66 0F) 6C/6D opcode and even more fixes to some avx opcodes 2024-05-26 16:48:26 +02:00
ptitSeb 580fbf47b2 [INTERPRETER] Added avx (66 0F) DB opcode and more fixes to some avx opcodes 2024-05-26 16:11:26 +02:00
ptitSeb 4bffdce8af [INTERPRETER] Added avx (66 0F) EB opcode and fixed other avx opcodes 2024-05-26 15:50:43 +02:00
ptitSeb f22e9bf1d2 [INTERPRETER] Added avx (66 0F) 64/65/66/72/73/EF opcodes 2024-05-26 15:20:52 +02:00
ptitSeb 95b516127a [INTERPRETER] Added avx (F3 0F) 6F and (66 0F) 70 2024-05-26 12:57:59 +02:00
ptitSeb da7474b1de Added 67 66 83 opcodes ([ARM64_DYNAREC] too) 2024-05-26 11:03:32 +02:00
ptitSeb 27aa9011ce Fixed xrstor helper 2024-05-26 10:42:16 +02:00
ptitSeb d09a48fd03 [INTERPRETER] my first avx opcode 2024-05-26 09:21:04 +02:00
Yip Coekjan b5c0a857ca Fix typo on box64 config file (#1533) 2024-05-25 15:02:32 +02:00
Yip Coekjan ab9f848dcd Fix unclosed item list (#1532) 2024-05-25 13:57:35 +02:00
ptitSeb 1b3350437c Added 67 66 0F D6 ([ARM64_dynarec] too) 2024-05-25 11:46:31 +02:00
ptitSeb 03749788e8 [TRACE] Group trace member of x64emu_t 2024-05-24 22:45:11 +02:00
ptitSeb 9a571cfb72 [RV64_DYNAREC] Fix dynarec build for RV64 2024-05-24 22:44:47 +02:00
ptitSeb 39303611ef more avx infrastructure 2024-05-24 20:17:35 +02:00
ptitSeb fcf0cf00d0 Added support for XSAVE/XRSTOR ([ARM64_DYNAREC] too) 2024-05-24 15:01:46 +02:00
Yang Liu 2ee846f48e Workaround on a race condition on SDL_GetThreadID (#1530) 2024-05-24 10:14:49 +02:00
Yang Liu 9c846a3e40 Redirect pthread_yield to sched_yield (#1529) 2024-05-24 09:40:31 +02:00
Yang Liu 712e8315f8 [LA64_DYNAREC] Added more opcodes (#1528) 2024-05-23 22:21:56 +02:00
ptitSeb 604ab22526 [ARM64_DYNAREC] Added 66 D9 /6 and 66 DD /4 /6 opcodes 2024-05-23 16:32:04 +02:00
ptitSeb 85d09df938 Some more x87 adjustment, but it still off a bit 2024-05-23 16:32:04 +02:00
Yang Liu 5ae93f8431 [LA64_DYNAREC] Added CMPXCHG8B and CMPXCHG16B opcodes (#1527) 2024-05-23 15:57:58 +02:00
ptitSeb 3aab8dd332 More fixes to x87 handling 2024-05-23 15:55:28 +02:00
Yang Liu bf9d297dcd [RV64_DYNAREC] Fixed LOCK XCHG byte opcode (#1526) 2024-05-23 12:04:09 +02:00
Yang Liu 080cc77208 [LA64_DYNAREC] Added more opcodes (#1525) 2024-05-23 10:51:07 +02:00
ZoHan 7ebd92be7d Wrapped libpsl5 (#1523)
* Wrapped libpsl5

* Recover files
2024-05-23 07:49:52 +02:00
ptitSeb 22b2f63917 [ARM64_DYNAREC] Small potential fix to D9 E5 opcode 2024-05-22 23:51:54 +02:00
ptitSeb 5bcfa34bea Fixed some x87 handling issues 2024-05-22 23:50:45 +02:00
Yang Liu 48c47423a4 [LA64_DYNAREC] Fixed more issues here and there (#1521)
* [LA64_DYNAREC] Fixed more issues here and there

* minor optim

* minor change
2024-05-22 23:00:13 +02:00
Yang Liu 229cae16d1 [LA64_DYNAREC] Fixed some non-lbt flags comutation issues (#1520) 2024-05-22 20:00:22 +02:00
Yang Liu 9edb89fc22 [LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path (#1519)
* [LA64_DYNAREC] Fixed LOCK XCHG byte opcode fallback path

* fix
2024-05-22 18:22:08 +02:00
Yang Liu 3faabb478d [DYNAREC] Simplified emit_pf helper (#1518)
* [DYNAREC] Simplified emit_pf helper

* Remove unused function and outdated comments
2024-05-22 13:06:43 +02:00
ptitSeb 2c127fe69c [ARM64_DYANREC] Simplified emit_pf helper 2024-05-22 11:08:07 +02:00
ptitSeb 3765d9e6f7 Start of a new dev. cycle 2024-05-22 10:18:32 +02:00
ptitSeb 8545d0505f Bumped version to v0.2.8 2024-05-21 17:33:16 +02:00
Yang Liu 28b101aaf7 [RV64] Made Zba and Xthead* detection mutually exclusive (#1514) 2024-05-21 15:35:48 +02:00
ptitSeb 24d1250e66 [ARM64_DYNAREC] Some small fixes to D9 E5 opcode 2024-05-21 14:35:45 +02:00
ptitSeb 706ca3649e [RV64_DYNAREC] Fixed a bunch of x87 opcodes 2024-05-21 13:34:31 +02:00
Yang Liu bb537e4dd5 [RV64_DYNAREC] Fixed some MMX opcodes (#1513)
* Fixed MOVD opcode

* Fixed PSHUFW opcode
2024-05-21 11:54:08 +02:00
Yang Liu eb59ff2ebd [ARM64_DYNAREC] Fixed PSLLD/PSLLQ opcodes (#1512) 2024-05-21 10:27:13 +02:00
Yang Liu 7842c9e34d [INTERPRETER] Added more opcodes and fixed some opcodes too (#1511) 2024-05-21 09:55:59 +02:00
ptitSeb 3882a98755 [RV64_DYNAREC] Fixed a few more opcodes 2024-05-20 23:11:30 +02:00
ptitSeb 14c9dc5bdb [RV64_DYNAREC] Fixed some bit manipulation opcodes 2024-05-20 22:34:23 +02:00
ptitSeb 181457b69f [RV64_DYNAREC] Fixed some issue with shld/shrd emitter 2024-05-20 22:01:46 +02:00
ptitSeb 0b6f543bbd [RV64_DYNAREC] Fixed some rotation emiters 2024-05-20 21:06:42 +02:00
ptitSeb 01a386445c [RV64_DYNAREC] Fixed some math emiter issues 2024-05-20 18:50:40 +02:00
Yang Liu 3fce669f6e [LA64_DYNAREC] Fixed 66 0F 67 PACKUSWB opcode (#1508) 2024-05-20 18:12:38 +02:00
Yang Liu 8a701755d8 [LA64_DYNAREC] Fixed LOCK ADD opcode (#1507) 2024-05-20 14:08:52 +02:00
Yang Liu aead503f02 [INTERPRETER] Fixed CMPXCHG16B opcode for la64 (#1506)
it's not the best we can do, but it fixes things. Will came up something better with scq extension later.
2024-05-20 12:04:31 +02:00
ptitSeb 7ef2af2549 Wrapped another __isoc23 function 2024-05-20 10:12:28 +02:00
ptitSeb 1e44a93c87 Removed all traces of PAGE8K, PAGE16K and PAGE64K as it's now detected in runtime 2024-05-20 10:08:27 +02:00
ptitSeb 2e55dec949 Updated Wine details on README 2024-05-20 09:45:17 +02:00
ptitSeb c80a83485d Updated contributors 2024-05-20 09:42:28 +02:00
ptitSeb 8915484251 Wrapped one more __isoc23 function 2024-05-20 09:26:49 +02:00
ptitSeb ed3450388b [ARM64_DYNAREC] Some various fixes after double-check of code 2024-05-19 19:22:01 +02:00
ptitSeb a2d580e926 [ARM64_DYNAREC] Use optimized rcl/rcr emiter for remaining opcodes with 64/65/67 prefixes 2024-05-19 19:21:08 +02:00
ptitSeb 47085bb9c9 [INTERPRETER] Added unaligned handling for 32bits F0 83 /0 opcode 2024-05-19 19:19:57 +02:00
ptitSeb 73619f4d75 [ARM64_DYNAREC] Small optimisation for edge case on a few shift emiter 2024-05-18 08:03:16 +02:00
ptitSeb 5228338f97 Added 2 new syscalls 2024-05-17 21:25:12 +02:00
ptitSeb 71c0aff78f Added 2 wrapped function libsdl2mixer ('two months' works now) 2024-05-17 14:55:45 +02:00
ptitSeb 4d7e106088 Added empty wrapped libdecor-0.so.0 2024-05-17 14:46:22 +02:00
ptitSeb d7127ccc3d [ARM64_DYNAREC] Improved stability of RCL/RCR and added 32/64 bits with constant emiter 2024-05-17 14:29:58 +02:00
ptitSeb 04e960b0da [TARCE] Better trace for neverclean mmaps 2024-05-17 10:49:53 +02:00
ptitSeb 8d199cfc6c [ARM64_DYNAREC] Minor adjustments to a few complex x87 opcodes 2024-05-17 10:09:59 +02:00
ptitSeb ffa58e23f1 Added 1 more gstreamer symbol 2024-05-16 21:40:43 +02:00
ptitSeb 289f94599d [ARM64_DYNAREC] Small improvment to DD /1 opcode 2024-05-15 19:48:51 +02:00
ptitSeb d0b51ae18f [ARM64_DYNAREC] Added 64/65 13 opcode 2024-05-15 19:47:26 +02:00
ptitSeb cea459d1e3 [COSIM] Small change for D9 /6 opcode 2024-05-15 17:02:22 +02:00
ptitSeb f6cd825ab9 [ARM64_DYNAREC] Fixed a potential issue with 0F B1 opcode 2024-05-15 16:47:49 +02:00
ptitSeb f8fa438728 [COSIM] Fixed issue with 0F C7 opcode 2024-05-15 16:47:04 +02:00
ptitSeb 07aacc9b08 [DYNAREC] Small fixes to when to stop a block (fixes regression on EALauncher) 2024-05-15 14:45:27 +02:00
ptitSeb 50325785f5 [ARM64_DYNAREC] Small optim of 0F B1 opcode 2024-05-15 12:32:44 +02:00
Yang Liu ef49b97c75 Added more symbols for libcrypto (#1504) 2024-05-15 12:28:52 +02:00
Yang Liu 75110ac028 [LA64_DYNAREC] Added more opcodes (#1503) 2024-05-15 11:22:03 +02:00
ptitSeb 57bfa38328 Removed the export WINEFSYNC=0 at start, use BOX64_FUTEX_WAITV=0 to disable instead 2024-05-14 16:15:27 +02:00
ptitSeb 2c00386e99 [INTERPRETER] Added 1 unligned case for F0 83 group 2024-05-13 17:58:04 +02:00
ptitSeb 3b03b7aee6 Added some more wrapped functions 2024-05-13 16:31:39 +02:00
kaixindeken 1491270f1d [RV64_DYNAREC] Fix SIGABRT handling in x87cache testing (#1498) 2024-05-13 12:38:04 +02:00
Yang Liu 46dfaab639 [DYNAREC_LA64] Added more opcodes (#1496) 2024-05-11 10:49:16 +02:00
ptitSeb ff755facc0 [ARM64_DYNAREC] Fix and improvments on rcl/rcr helper 2024-05-09 22:03:25 +02:00
ptitSeb d38f659f42 Changed the workaround for MiniMetro/Steam, using rcfile now (for #1311) 2024-05-09 21:59:32 +02:00
ptitSeb 6d95a64412 Added some virtual files (if missing) to allow wine to compute cache size and coherency (for #1381 on Snapdragon, but BG3 still not working, probably a graphic driver issue now) 2024-05-07 21:20:13 +02:00
ptitSeb 21336c527a Small fix on a libc wrapped function signature 2024-05-07 20:02:15 +02:00
ptitSeb 3db2362c86 [ELFLOADER] Small change in the parser (for #1493) 2024-05-05 17:35:48 +02:00
ptitSeb 99b7ef0c92 [VULKAN] Added VK_AMDX_shader_enqueue extension 2024-05-05 14:23:16 +02:00
ptitSeb ff030fcbec [ELFLOADER] Added a fix for Uniengine Heaven linux crashing at load, but might need something more generic at some point 2024-05-05 12:39:27 +02:00
ptitSeb ecf19029f5 [ARM64] Add 1 more case of unaligned device memory access handling, plus better tracking 2024-05-04 14:33:42 +02:00
Yang Liu 9494801d0b [DYNAREC] Small improvements to atomic functions (#1492)
* [DYNAREC] Small improvements to atomic functions

* Support older version of gcc
2024-05-04 13:11:45 +02:00
Yang Liu 1501592fa8 [LA64_DYNAREC] Added more opcodes (#1491) 2024-05-03 21:18:42 +02:00
ptitSeb 12467916a4 [DYNAREC] Re-introduce a simple HotPage handling, to speedup heavily obfuscated program loading 2024-05-03 18:42:03 +02:00
ptitSeb 6f0eb56621 [LA64_DYNAREC] Fixed another typo (should fix Celeste) 2024-05-03 13:24:55 +02:00
Yang Liu 31dabf51ae [LA64_DYNAREC] Added more opcodes (#1490) 2024-05-03 12:41:49 +02:00
ptitSeb 22fd100b04 [LA64_DYNAREC] Fixed some typos 2024-05-03 11:05:24 +02:00
Yang Liu 20092ef1ac [RV64_DYNAREC] Fixed OF flag computation (#1489) 2024-05-03 10:35:44 +02:00
Yang Liu aad6a16984 [LA64_DYNAREC] Added more opcodes (#1488) 2024-05-03 09:42:25 +02:00
ptitSeb 9b00df93c2 [LA64_DYNAREC] Fixing the fix, and leave a comment for future me in case I want to fix that again 2024-05-03 00:01:30 +02:00
ptitSeb f1da71a8fe [DYNAREC] Stop a block when a unimplemented opcode is found 2024-05-02 23:27:18 +02:00
ptitSeb efd182971a [LA64_DYNAREC] Fixed some lock assembly helper 2024-05-02 22:24:26 +02:00
Yang Liu 40c5125a92 Added wrapping of libicuuc64 and libicui18n64 (#1487) 2024-05-02 22:08:06 +02:00
Yang Liu 0f6654bf95 [LA64_DYNAREC] Added more opcodes (#1486) 2024-05-02 21:42:41 +02:00
ptitSeb fa27ddecc5 [TRACE] Remove a trace that might crash when tracing 2024-05-02 21:38:55 +02:00
Yang Liu e5be67b005 [DYNAREC][32BITS] Fixed and improved 66 prefix opcodes (#1485)
* [DYNAREC][32BITS] Improved 66 prefix opcodes

* more fixes

* Removed some unintentional changes

* removed unnecessary improvements
2024-05-02 19:44:50 +02:00
ptitSeb 85458d1f20 [ARM64_DYNAREC] Added rcr16 / rcl16 emitter, plus some tiny fixes to other rotate operations 2024-05-02 15:44:14 +02:00
ptitSeb 5b5723c5a5 [ARM64_DYNAREC] Some small fixes to rcl8 / rcr8 emitters 2024-05-02 14:31:26 +02:00
Yang Liu e148e89091 [RV64_DYNAREC] Remove useless code (#1484) 2024-05-02 10:15:02 +02:00
Yang Liu 1d0614f0f3 [RV64_DYNAREC] Added some missing fastnan handling (#1483) 2024-05-02 10:14:36 +02:00
Yang Liu 2405e6c8e8 [LA64_DYNAREC] Added more opcodes (#1482) 2024-05-01 21:37:41 +02:00
Yang Liu 817408d247 [LA64_DYNAREC] Added more opcodes (#1481) 2024-05-01 18:09:44 +02:00
ptitSeb 8d77e39f4a Added 1 more wrapped function to waylandclient lib 2024-05-01 15:15:35 +02:00
Yang Liu 0fe7e7a88d [LA64_DYNAREC] Added more opcodes (#1480) 2024-05-01 11:04:50 +02:00
Yang Liu 08bc57045a [LA64_DYNAREC] Fixed dynarec infra (#1479) 2024-05-01 11:03:58 +02:00
ptitSeb ee58b6a734 [RV64_DYNAREC] Optimized F0 0F C7 32bits opcode 2024-04-30 21:43:09 +02:00
ptitSeb 2907e5a0bd [RV64_DYNAREC] Fixed adc32 helper 2024-04-30 21:42:33 +02:00
ptitSeb 4f229629c0 [RV64_DYNAREC] Improved/fixed flag handling (ported from ARM64_DYNAREC) 2024-04-30 17:50:11 +02:00
ptitSeb f0fd2bc30c [RV64_DYNAREC] Fix some x87 flags issue 2024-04-30 16:38:54 +02:00
Yang Liu 86e9a38384 [COSIM] Added thread-safe tests (#1477)
* [COSIM] Added thread-safe tests

* Added more notest

* Run cosim in CI

* Disable tests for RISC-V for now

* Simplify

* Initialize notest
2024-04-30 16:36:48 +02:00
ptitSeb 322f97ddbc Fixed wrapped function signature for xcb_image_put (should help #1450) 2024-04-30 15:22:06 +02:00
ptitSeb 695865f408 [ARM64_DYNAREC] Added CE opcode 2024-04-30 15:02:34 +02:00
ptitSeb 1f9834dc6b [RCFILE] More aggressive profile for FlatOut and FlatOut 2 2024-04-29 22:51:00 +02:00
ptitSeb d1555a4c78 [ARM64_DYNAREC] Fixed some more issue on x87 handling 2024-04-29 22:50:24 +02:00
ptitSeb 5fc4477a94 [DYNAREC] Allocate Dynarec memory by 2Mb batch, and advise for hugepage if available 2024-04-29 12:12:40 +02:00
ptitSeb a5753ec0b5 This should fix non-dynarec build 2024-04-29 12:11:10 +02:00
ptitSeb f256c48505 Fixed non-dynarec build by introducing BOX64_JVM to replace BOX64_DYNAREC_JVM 2024-04-29 11:23:35 +02:00
ptitSeb 71c5447b8a Added a way to hide SSE 4.2, as it might slow down things using the string opcodes. Also, looks like some java program have issue with current implementation of pcmp[ei]str[im] somehow, so diabling automaticaly when detecting libjvm.so (for SlayTheSpire in particular) 2024-04-29 10:57:19 +02:00
ptitSeb a9a338ff42 [INTERPRETER] Fixed pcmp[ei]strm opcodes 2024-04-28 23:05:45 +02:00
ptitSeb 06a21d490b [ARM64_DYNAREC] Some fixes to pcmp[ei]strm opcodes 2024-04-28 22:16:29 +02:00
ptitSeb ef0c9bd429 [DYNAREC] Change method to detect dead code in block (fixes Spintires on Wow64, maybe some other too) 2024-04-28 17:20:52 +02:00
ptitSeb f619df2773 [ARM64_DYNAREC] Cosmetic change on FCOM helper macro 2024-04-28 17:20:13 +02:00
xctan 41ae74757e [RV64_DYNAREC] Fixed DIV and IDIV for zero divisor (#1476)
* [RV64_DYNAREC] Fixed DIV Ed and IDIV Ed for zero divisor

* [RV64_DYNAREC] Fixed DIV Ew and IDIV Ew for zero divisor

* [LA64_DYNAREC] Added todos for zero divisor
2024-04-28 15:27:10 +02:00
ptitSeb 2304738336 [ARM64_DYNAREC] Added some comment on ARM64 jump condition 2024-04-28 15:18:56 +02:00
ptitSeb e70a9ba485 Added some comment to x87 sw flags 2024-04-28 15:18:28 +02:00
ptitSeb 61a759f802 [TRACE] Added C3..C0 to x87 trace 2024-04-28 15:18:04 +02:00
ptitSeb 3cb61ff840 Added 3 more functions on wrapped sdl2 (for VVVVVV) 2024-04-27 19:24:07 +02:00
Yang Liu b7a07c3816 Fixed my_prepare_thread in dynarec build (#1474) 2024-04-27 18:34:56 +02:00
Yang Liu ae386b3a7d [LA64_DYNAREC] Added more opcodes (#1473)
* Added 66 0F PSHUFB opcode

* Added 66 0F PHADDW opcode

* Added 66 0F 38 02 PHADDD opcode

* Added 66 0F 38 03 PHADDSW opcode

* Added 66 0F 38 04 PMADDUBSW opcode

* Added 66 0F 38 05..0A opcodes

* Upgrade QEMU
2024-04-27 18:33:58 +02:00
ptitSeb 2b8a8314c5 Changed how wine prereserve is handled on box64 2024-04-27 17:07:33 +02:00
ptitSeb eb28edbe58 [DYNAREC] Fix some flag propagation with partial SF_SET/SF_SET_DF 2024-04-27 15:24:36 +02:00
Yang Liu 8d683fc19c [LA64_DYNAREC] Added more opcodes and fixes (#1472)
* Fixed SHUFPS again

* Added 0F 28 MOVAPS opcode

* Added 0F 2E/2F [U]COMISS opcodes

* Added F3 0F 5A CVTSS2SD opcode

* Added 66 0F 7E MOVD opcode

* Added 66 0F 28 MOVAPD opcode

* fastnan handling

* Added F3 0F 5D MINSS opcode

* Added F3 0F 5F MAXSS opcode

* Added F3 0F C2 CMPSS opcode
2024-04-27 12:14:46 +02:00
ptitSeb 0c50f724e6 [RCFILE] Added 2 more optimized profile for wine new wow64 games 2024-04-27 12:10:10 +02:00
ptitSeb d406946c2d [ARM64_DYNAREC] Improved x87 stack handling on transformCache helper (helps callret and bigblock on 32bits wow64 games) 2024-04-27 12:10:10 +02:00
Yang Liu 1c7e620a86 [LA64_DYNAREC] Added more useful extensions detection (#1469) 2024-04-26 19:34:14 +02:00
Yang Liu c40096e128 [LA64_DYNAREC] Added more opcodes (#1468)
* Added 0F BF MOVSX opcode

* Added F7 /5 IMUL opcode

* Added 86 XCHG opcode

* Added 66 0F PADDQ opcode

* Added 0F C6 SHUFPS opcode

* Added 66 0F 69 PUNPCKHWD opcode

* Added 66 0F DB PAND opcode

* Test

* Review

* Review
2024-04-26 19:13:06 +02:00
ptitSeb 43d2817407 [DYNAREC] Fixed an issue with flags when using SF_SET_NODF (fixed regression with Freedom Planet 2 Wine/Wow64, probably a few other too) 2024-04-26 18:17:42 +02:00
ptitSeb ff14ccc0a5 [DYNAREC] More fixes on BIGBLOCK 2024-04-26 17:50:16 +02:00
ptitSeb 1222fee0d0 [ARM64_DYNAREC] Added 0F B1 opcode 2024-04-26 15:41:11 +02:00
ptitSeb b184a184c4 [DYNAREC] Stop building a block if opcode is garbbage or not redeable (should help BIGBLOCK=2) 2024-04-26 15:20:35 +02:00
ptitSeb e5dcb3f100 [RCFILE] Added a profile for beyond-all-reason (for #1412) 2024-04-26 14:03:45 +02:00
Yang Liu 411fe19ee5 [RCFILE] Update weixin profile (#1467) 2024-04-25 23:28:30 +02:00
Yang Liu 1c040117ec [DYNAREC] Fixed emit_shift functions and more (#1466)
* [LA64_DYNAREC] Fixed emit_shift functions

* [RV64_DYNAREC] Fixed emit_shift functions and more

* Fixed la64 build
2024-04-25 20:17:36 +02:00
ptitSeb 856d2653bc [DYNAREC] Fix for some rare (or less rare depending on the backend) case of jump incorectly computed (regression from previous commit) 2024-04-24 18:12:15 +02:00
ptitSeb 2a79b60454 Changed x87 way of handling FFREE opcode ([DYNAREC] too, improving x87 robustness overall) 2024-04-24 15:34:54 +02:00
ptitSeb db32e49879 Made minimum rdtsc frequency to 2GHz (seems 1GHz is not enough for Horizon Zero Dawn) 2024-04-23 13:16:19 +02:00
ptitSeb 65d83bb6f4 Autocalibrate RDTSC clock to 1GHz minimum, instead of 500MHz (helps HorizonZeroDawn speed) 2024-04-22 19:19:31 +02:00
ptitSeb 17b7ec6358 [ARM64_DYNAREC] Small optim on flags handling 2024-04-22 18:59:57 +02:00
ptitSeb 73c3190c86 [ANDROID] Need to regen test27 based on latest sources, disabling for now 2024-04-22 17:31:00 +02:00
ptitSeb b6f58caf24 [ARM64_DYNAREC] Improved some specific cases of pcmpestri opcode 2024-04-22 17:14:53 +02:00
ptitSeb 8c19c3a72c [INTERPRETER] Improved SSE4.2 String opcodes, and improved test27 2024-04-22 17:14:13 +02:00
ptitSeb c017d3e894 [ANDROID] Fix doesn't work, disabling test07 again 2024-04-22 15:57:17 +02:00
ptitSeb 35696508fb [ANDOIRD] Fix build 2024-04-22 15:52:25 +02:00
ptitSeb 7e3996b0d9 [TRACE] Fixed some dumpreg when x87stack is incoherent 2024-04-22 15:50:44 +02:00
ptitSeb a7ec8e7c55 [ANDROID] Try to fix test 07 2024-04-22 15:49:19 +02:00
ptitSeb dfaa6896c1 [ARM64_PRINTER] Added SHL printer 2024-04-22 10:03:24 +02:00
ptitSeb b64e6bdbba [RCFILE] Added 2 more profiles 2024-04-20 18:42:03 +02:00
ptitSeb e0ef248943 [ARM64_PRINTER] Fix some case of DecodeBit not working for 64bits values 2024-04-20 15:10:24 +02:00
Lily cdcb0a46dc [RCFILE] Added Yandare Simulator Profile (#1459) 2024-04-20 12:04:54 +02:00
ptitSeb e82e1f9905 Added 1 more sdl2 function (for #1458) 2024-04-19 08:15:33 +02:00
ptitSeb cb6616bba1 Added 2 wrapped functions to sdl2 2024-04-18 09:57:04 +02:00
Yang Liu e0f0afdf91 Wrapped 1 more function for mpg123 (#1454) 2024-04-17 19:23:38 +02:00
ptitSeb 5120e74b36 Added 66 68 opcode ([ARM64_DYNAREC] too) 2024-04-17 17:14:19 +02:00
Yang Liu 8f5fa863bf [DYNAREC] Fixed CF flag computation (#1453) 2024-04-17 16:43:59 +02:00
ZoHan d4e32fdbc0 [RV64_DYNAREC] Added more opcodes (#1451)
* [RV64_DYNAREC] Added more opcodes

* modify the format
2024-04-17 09:27:50 +02:00
Yang Liu 067cf75c65 [LA64_DYNAREC] Added more opcodes (#1447)
* Added B4..B7 MOV opcode

* Added 66 81,83 /5 SUB opcode

* Added 30 XOR opcode

* Added F0 01 LOCK ADD opcode

* Added 66 81,83 /0 ADD opcode

* Added 66 39 CMP opcode

* Added 66 0F D6 MOVQ opcode

* Added 0F 57 XORPS opcode

* Fix

* Added 66 0F 61 opcode
2024-04-14 20:39:31 +02:00
Yang Liu 7f16ddacf7 [LA64_DYNAREC] Added 1 more opcode and some fixes too (#1444)
* Added D3 /0 ROL opcode

* Refined emit_sub32c

* Fixed BSF and BSR
2024-04-14 12:47:42 +02:00
Yang Liu d936c072ea [DYNAREC] Fixed shift xw macros (#1443) 2024-04-14 09:26:42 +02:00
ptitSeb 7dee075c10 Fixed a few warning here and there... 2024-04-13 14:43:30 +02:00
Yang Liu b9ea2408c2 [LA64_DYNAREC] Added more opcodes (#1441)
* Added 66 C7 MOV opcode

* Added B0..B3 MOV opcode

* Added F0 87 LOCK XCHG opcode

* Added 35 XOR opcode

* Added F7 /7 IDIV opcode

* Added BC BSF opcode

* Added BD BSR opcode
2024-04-12 21:58:05 +02:00
ptitSeb 6ce570f4a5 Revert some cpuid changes, they are more wrong then right it seems 2024-04-12 18:14:51 +02:00
Yang Liu b95b99b3c9 [RV64_DYNAREC] Fixed 66 C7 MOV opcode (#1440) 2024-04-12 17:51:55 +02:00
Yang Liu 139197230d [LA64_DYNAREC] Added more opcodes and fixed more issues (#1439)
* Added F3 0F 10 MOVSS opcodes

* Added F3 0F 2A CVTSI2SS opcode

* Added F3 0F 5E opcode

* Added F3 0F 11 MOVSS opcode

* Added 0C OR opcode

* Added F3 0F 59 MULSS opcode

* Added 81,83 /3 SBB opcode

* Fixed 2 typos
2024-04-12 13:55:46 +02:00
Yang Liu 1d0e0307c4 [LA64_DYNAREC] Made the CALLRET optimization complete (#1438) 2024-04-12 13:13:30 +02:00
kaixindeken f94ab1be6f [RV64_DYNAREC] Implementation of some CRC32 instructions (#1435)
* [RV64_Dynarec] Implementation of some CRC32 instructions

* Use BEXTI to detect the lowest bit

* Prefer ANDI for lowest bit checking
2024-04-12 08:06:45 +02:00
Yang Liu 05c7596acb [LA64_DYNAREC] Small fix on emit_or32c LBT path (#1436) 2024-04-11 18:55:35 +02:00
Yang Liu b38d51ce37 [LA64_DYNAREC] Added more opcodes to the printer (#1433)
* Use ROTR

* Added more opcodes to the printer

* Added even more opcode to the printer

* Fixed typos

* More
2024-04-10 18:25:57 +02:00
Hypothalamus 5c0d765f59 Add Oxygen Not Included to box64rc based on https://github.com/ptitSeb/box86-compatibility-list/issues/298 (#1431)
Reported-by: ricoazzurro
2024-04-10 17:56:02 +02:00
Yang Liu db35542706 [LA64_DYNAREC] Refined MOV64 macros (#1430) 2024-04-09 18:33:41 +02:00
ptitSeb eda857cb10 Added 1 more function to icuucXX wrapped libs (for #1428) 2024-04-08 23:19:06 +02:00
ptitSeb b77c8fe5f1 [DYNAREC] Enabled larger dynablock 2024-04-07 19:23:44 +02:00
ptitSeb 0d864ed848 [ARM64_DYNAREC] Small change to stay in sync with other backend 2024-04-07 17:00:41 +02:00
Yang Liu 7c613198ce Fixed 0F A3 BT opcode (#1427) 2024-04-07 13:29:38 +02:00
xctan 1ca68a58fd [RV64_DYNAREC] Fixed various bugs in shift instructions (#1426)
* [RV64_DYNAREC] Optimized 8-bit constant shifts

* [RV64_DYNAREC] Fixed shl8c when c > 8

* [RV64_DYNAREC] Optimized 16-bit constant shifts

* [RV64_DYNAREC] Optimized 8-bit CL shifts

* [RV64_DYNAREC] Fixed SF generation of 32-bit SHL Ed, CL

* [RV64_DYNAREC] Optimized 16-bit CL shifts

* [RV64_DYNAREC] Fixed typo in 8-bit CL SHL and SHR

* [RV64_DYNAREC] Fixed the wrong mask in 8-bit SHL Eb, CL

* [RV64_DYNAREC] Fixed typo in SAR Ew, CL
2024-04-07 10:39:58 +02:00
Yang Liu b96139274f [LA64_DYNAREC] Added more opcodes (#1425)
* Added 0B OR opcode

* Added D3 /7 SAR opcode

* Added D3 /5 SHR opcode

* Added 80 /1 OR opcode

* Addeded  66 0F BE MOVSX opcode

* Fixed SRAxw

* Fix

* Added 0F C8..CF BSWAP opcode

* Added more opcodes
2024-04-06 14:45:22 +02:00
Yang Liu d84faf57ab [LA64_DYNAREC] Added more opcodes (#1424)
* [LA64_DYNAREC] Added 66 C1 /5 SHR opcode

* Added 69 IMUL opcode

* Added F7 /6 DIV opcode

* Added 6B IMUL opcode

* Added C1 /1 ROR opcode

* [LA64_DYNAREC] Added 87 XCHG opcode
2024-04-06 12:46:14 +02:00
Yang Liu 89f0c494e4 [LA64_DYNAREC] Added more opcode and fixes (#1423)
* Fixed F2 0F MOVSD opcode

* Added F3 0F 6F MOVDQU opcode

* Added F2,F3 A5 MOVSD opcode

* Added 80 /5 SUB opcode

* Fixed a typo in .clang-format

* Added 66 85 TEST opcode and a fix
2024-04-06 11:38:04 +02:00
Yang Liu 24f9263fa4 [LA64_DYNAREC] Added more opcodes (#1422)
* Added 1C SBB opcode

* Added 3A CMP opcode

* Added 38 CMP opcode

* Added 81,83 /6 XOR opcode

* Added F7 /4 MUL opcode
2024-04-06 10:50:10 +02:00
Haichen Wu 5f4f9337cd [LA64_DYNAREC] Added more SSE/SSE2 instructions (#1421)
* [LA64_DYNAREC] Added more SSE/SSE2 instructions

* [LA64_DYNAREC] Added more SSE/SSE2 instructions
2024-04-06 10:46:45 +02:00
Yang Liu 2a75d28386 [LA64_DYNAREC] Fixed missing LBT path and more (#1419)
* [LA64_DYNAREC] Fixed missing LBT path and more

* Fixed D3 /4/6 SHL opcode

* LA64 qemu is not stable too
2024-04-06 08:49:37 +02:00
Yang Liu 3e41289167 [DYNAREC] Fixed REP opcodes for correct register state recovery (#1420) 2024-04-06 08:48:00 +02:00
Yang Liu 9cf5373724 [LA64_DYNAREC] Added more opcodes (#1418)
* Added 0F A3 BT opcode

* Added 3C CMP opcode

* Added C0 /4/5/6/7 opcodes

* Added 6A PUSH opcode

* Added F2,F3 A6 CMPSB opcode
2024-04-05 20:11:09 +02:00
Yang Liu 6c5d35df6b [LA64_DYNAREC] Added more opcodes (#1417)
* Added 64 8B MOV opcode

* Added 64 33 XOR opcode

* Added 19 SBB opcode

* Smol fix
2024-04-05 17:56:24 +02:00
Yang Liu 4d26021705 [LA64_DYNAREC] Added more opcodes (#1416)
* [LA64_DYNAREC] Added 0F AF IMUL opcode

* Update clang-format rules

* Added 08 OR opcode

* Added F7 /3 NEG opcode and fixed some potential bugs
2024-04-05 16:34:59 +02:00
Yang Liu 2e9b8eff59 [LA64_DYNAREC] Fixed SSE issues (#1415)
* [LA64_DYNAREC] Fixed SSE issues

* Fixed MOVSD modreg
2024-04-05 11:55:41 +02:00
Haichen Wu a4142f68ce [LA64_DYNAREC] Added more SSE/SSE2 instructions (#1410) 2024-04-04 13:43:30 +02:00
ptitSeb 4a889e39ad Wrapped some more functions to gstreamer-1.0 and friends (for #1397) 2024-04-03 17:20:29 +02:00
ptitSeb d206d69b25 Wrapped 2 more functionto gstreamer-1.0 (for #1397) 2024-04-03 17:06:01 +02:00
ptitSeb 83e92d6298 Wrapped GstAudioFilter (for #1397) 2024-04-03 16:55:56 +02:00
ptitSeb e080551d54 [RCFILE] Make sure strdup is coherent with free 2024-04-03 16:43:01 +02:00
ptitSeb b40195d26d [INTERPRETER] Added aligned path to F0 0F C7 opcode 2024-04-03 16:43:01 +02:00
Yang Liu 316abec693 [RV64_DYNAREC] Added 0F 70 PSHUFW opcode (#1408) 2024-04-03 12:09:57 +02:00
ZoHan af685a263b [RV64_DYNAREC] Add 1E/1F opcode (#1407)
* [RV64_DYNAREC] Add 1E/1F opcode

* modify the format

* modify the format
2024-04-03 12:04:07 +02:00
ZoHan 31e8afa622 [RV64_DYNAREC] Add more opcodes (#1405)
* [RV64_DYNAREC] Add more opcodes

* modify the format
2024-04-03 08:01:49 +02:00
Yang Liu 1d500ad965 Force the use of spaces in .clang-format (#1406) 2024-04-03 07:38:31 +02:00
ptitSeb a8866c3f41 [ARM64_DYNAREC] Better fix for #1366, that should help #1383) 2024-04-02 23:21:21 +02:00
ptitSeb f64eca5d9b [DYNAREC] Small fixed on dynarec block protection 2024-04-02 23:21:21 +02:00
Yang Liu bdd5e7018a Create libssl/libcrypto symlinks (#1402) 2024-04-02 18:44:47 +02:00
ptitSeb 3d211143e0 [ELFLOADER] Fixed some residual issue with elfloader (espacially on non-4K pagesize) (should help #1398 #1271 maybe help #939 and probably others) 2024-04-02 15:49:51 +02:00
ptitSeb c1c11d8daa [DYNAREC] Improved CancelBlock function (might help #1383) 2024-04-02 15:42:00 +02:00
Yang Liu 0505b19378 [RV64_DYNAREC] Fixed some issue with x87 stack managment (ported from ARM64) (#1401) 2024-04-02 15:34:49 +02:00
ptitSeb e18e532846 Added wrapped libicuuc73 and libicui18n73 2024-04-02 15:16:26 +02:00
Yang Liu 10cec3de2f [LA64_DYNAREC] Added more SSE/SSE2 instructions (#1400)
* [LA64_DYNAREC] Added more SSE/SSE2 instructions

* Thank you test16
2024-04-02 13:44:40 +02:00
Yang Liu 76c0992d02 [LA64_DYNAREC] Fixed EBBACK (#1399) 2024-04-02 09:24:12 +02:00
ptitSeb e32a78a944 Added a couple of symbols to wrapped libcms2 and libgstaudio-1.0 2024-04-01 08:27:01 +02:00
ptitSeb 68d710cd94 [ARM64_DYNAREC] Fixed some issue with x87 stack managment 2024-03-29 11:05:53 +01:00
olegos2 da64a3eeab Add BOX64_RCFILE variable (#1392)
* Implement BOX64_RCFILE

* Update USAGE.md

* Should fix tests
2024-03-28 21:08:53 +01:00
Yang Liu 912622bf1f [LA64_DYNAREC] Added basic SSE infra and 66 0F 6E MOVD opcode (#1391) 2024-03-28 14:17:26 +01:00
Jiarui Wang 70fec208d8 update clang-format for IFX and QUOTE (#1390)
* update clang-format

* refactor: add more ifmacros
2024-03-28 12:44:33 +01:00
ptitSeb e1f69b9c61 Improve memory handling for wine, again 2024-03-27 15:01:16 +01:00
ptitSeb 81f25b219f Added some path for termux/glibc builds 2024-03-27 11:16:26 +01:00
ptitSeb d191b8c090 [ARM64_DYNAREC] More check to abort a block if x87 stack cache is incoherent 2024-03-26 16:24:17 +01:00
ptitSeb d53ff127ed Fixed some warning 2024-03-25 18:18:09 +01:00
howard97andhoward 50caca8fdc [REFACTOR] Refactor main.c (#1362)
Co-authored-by: howard <[email protected]>
2024-03-25 17:42:01 +01:00
ptitSeb 1dca97b4d3 Added 66 0F BF opcode 2024-03-21 04:08:14 +01:00
Yang Liu 14cf474167 [LA64_DYNAREC] Added CMOVcc opcodes and some fixes too (#1375) 2024-03-20 17:32:28 +01:00
Yang Liu 47b1203805 [LA64_DYNAREC] Added some FP/LSX/LASX instructions to the emitter (#1374)
* [LA64_DYNAREC] Added FP instructions to the emitter

* [LA64_DYNAREC] Added some LSX/LASX instructions to the emitter
2024-03-20 17:29:47 +01:00
ptitSeb 81ca016581 [DYNAREC] This should fix some issue with dynarec, like #1366 (but should be revisited soon, to many bytes writen there) 2024-03-19 02:30:22 +01:00
ptitSeb cd8bda7a29 Changed, again, RDTSC and Hardware counter, introducing auto calibration when hardware counter is too slow for modern standard (and removed BOX64_RDTSC env. var.) 2024-03-14 11:01:40 +01:00
ptitSeb 8115b47051 Added 64 66 83 opcodes ([ARM64_DYNAREC] too) 2024-03-14 10:01:00 +01:00
Tristan Morgan 6384cc6e86 Update GH-Actions workflows to remove Node.js deprecation warning. (#1359) 2024-03-14 08:36:53 +01:00
ptitSeb 2f68df2b5f [ARM64_DYNAREC] Try to improve strongmem=4 method, with a completly different approach 2024-03-13 18:17:37 +01:00
ptitSeb ed2697d6ad [RCFILE] Fixed some issues with wine program detection 2024-03-12 16:43:10 +01:00
ptitSeb df928fd2d0 [RCFILE] Added 2 new rcfile only option, and try to apply wine program parameter earlier, before wien load to be able to change command line and maxcpu 2024-03-12 11:39:11 +01:00
ptitSeb 52c50a2fd4 Changed in commented code, for more internal use 2024-03-12 11:36:31 +01:00
ptitSeb 666d051806 Changed how cpu cores are reported in cpuid for large number (>64) 2024-03-12 11:33:44 +01:00
Yang Liu 1e80316a7d [LA64_DYNAREC] Added more LBT instructions to the printer (#1356) 2024-03-11 15:35:43 +01:00
ptitSeb 65404cba33 Do not expose FMA cpu extension, it's associated to AVX by some engines 2024-03-11 15:22:08 +01:00
Yang Liu ac0519a046 [LA64_DYNAREC] Added more opcodes and some fixes (#1355)
* Added F0 B1 /0 LOCK CMPXCHG opcode

* Added 0F BE MOVSX opcode

* Added 81/83 /7 CMP opcodes

* Fixed emit_shl32c

* Added missing default

* Added A0 MOV opcode
2024-03-11 12:27:52 +01:00
Yang Liu 90a6306bbe [LA64_DYNAREC] Added more opcodes (#1354)
* Added 38 CMP opcode

* Added 0F B6 MOVZX opcode

* Added 88 MOV opcode

* Fixed 0F B6 MOVZX opcode

* Added 81/83 LOCK ADD opcodes

* Added 98 CWDE opcode

* Rebase
2024-03-11 09:05:10 +01:00
ptitSeb a5a7d9382e [DYNAREC] Limit temporary memory allocation on FillBlock64 2024-03-10 20:45:26 +01:00
ptitSeb bc770d908a [VULKAN] Added 1 more NV extension 2024-03-10 15:23:13 +01:00
ptitSeb 20724ceb17 [ELFLOADER] small change on free elf memory 2024-03-10 13:52:21 +01:00
ptitSeb 6ae6ac0272 [TRACE] Slighlty better log when emiting SIGILL 2024-03-10 13:51:38 +01:00
ptitSeb 5aa5015348 [TRACE] slignthly better log for ExitEmulation bridge 2024-03-10 13:50:52 +01:00
ptitSeb 411aecde6f Don't expose BMI1 for now, it's not really supported 2024-03-10 13:49:58 +01:00
ptitSeb e89b93285e [ARM64_DYNAREC] Added 64/65 0B opcode 2024-03-10 13:49:13 +01:00
ptitSeb 4e702cfeda [ARM64_DYNAREC] Fixed printer for MVN with shift 2024-03-10 13:48:40 +01:00
ptitSeb 33846405d8 Improved unload of libs (help wine when dlopen / dlclose is supposed to unload the lib so it can be dlopen again) 2024-03-09 14:10:09 +01:00
ptitSeb 378eb79ad3 Put back 8 slots for xcb_connection_t wrapping 2024-03-09 14:08:51 +01:00
ptitSeb da71b81d01 Don't try to load libstdc++ when loaing libGL if it's wine (helps mobox, maybe other android version of box64 too) 2024-03-09 08:57:16 +01:00
ptitSeb 35d734e6ac [TRACE] Better trace for (f)getxattr 2024-03-08 18:35:32 +01:00
ptitSeb 3937fc4b71 [DYNAREC] Small changeon the critical section handling of custommem 2024-03-08 18:17:08 +01:00
ptitSeb 5debac4c98 Change wrapping of _exit to just exit immediatly as expected 2024-03-08 18:16:36 +01:00
ptitSeb 3737abe081 [ARM64_DYNAREC][RV64_DYNAREC] Fixed some case where MOVS/B/W/D/Q is used on a protected page of code, and SI gets wrongly incremented (for #1347) 2024-03-08 18:01:33 +01:00
ptitSeb d0013c0700 [INTERPRETER] Added 64 EB opcode (for #1347) 2024-03-08 16:59:48 +01:00
ptitSeb 460277289b POPF opcode should not overwrite IF bit 2024-03-08 16:47:00 +01:00
ptitSeb 35ed305718 [ARM64_DYNAREC] Added 66 64 0F 6F opcode (for #1349) 2024-03-08 15:01:17 +01:00
ptitSeb d3c57eecbc [INTERPRETER] Added 66 64 0F 6F opcode (for #1349) 2024-03-08 15:00:47 +01:00
ptitSeb ad75da8502 [ARM64_DYNAREC] Added 67 64 8B opcode 2024-03-08 14:03:55 +01:00
ptitSeb c7c6880a01 [ARM64_DYNAREC] Added 67 64 8F opcode 2024-03-08 13:55:00 +01:00
ptitSeb 5ed3ef918d [INTERPRETER] Added 67 64 8F opcodes, and fixed 67 64 89/8B opcodes 2024-03-08 13:54:34 +01:00
ptitSeb c0f78342e1 [ARM64_DYNAREC] Improved MOV32w and MOV64x with a funciton with more speciall cases 2024-03-08 12:05:09 +01:00
Yang Liu 75494978ad [DYNAREC] Revert some fasly changes to the shift opcodes (#1346)
* [DYNAREC] Revert some fasly changes to the shift opcodes

* Prefer ZEROUP

* More fixes

* Fixed one more typo

* Should not revert this

* Fix fix fix
2024-03-08 11:51:39 +01:00
Yang Liu 602c015321 [DYNAREC] Made shift operations handle count==0 more uniformly (#1345) 2024-03-08 10:34:28 +01:00
Yang Liu 55c2c9ee59 [ARM64_DYNAREC] Fixed a falsy optimization on PSHUFHW (#1344)
* [ARM64_DYNAREC] Reverted a falsy optimization on PSHUFHW

* Fix it instead of a lazy revert
2024-03-08 08:39:05 +01:00
ptitSeb 8fef5f2c69 [ARM64_DYNAREC] Use convert_bitmask in logic emitters and in MAX32w and MOV64x 2024-03-07 21:25:11 +01:00
ptitSeb 9a4a62ff2d [ARM64_DYNAREC] Added 0F E1 opcode 2024-03-07 18:51:53 +01:00
ptitSeb 4ebc462e23 Added 1 more syscall 2024-03-07 18:49:25 +01:00
Haichen Wu 08e93a0fe9 [LA64_DYNAREC] Added C1 /4 and /6 opcodes and some fix (#1341)
* [LA64_DYNAREC] Added C1 /4 and /6 opcodes

* [LA64_DYNAREC] Some fix of C1 opcodes
2024-03-07 17:49:24 +01:00
rajdakin 4096869c50 [ARM] Added immediate encoding (#1340) 2024-03-07 17:48:35 +01:00
ptitSeb 3cd87e68c7 [RCFILE] Added profile for Capcom Arcade Statium 2024-03-07 17:48:17 +01:00
ptitSeb 7165ff7b84 More work on X11 wrapping, allowing gtk to run fully emulated 2024-03-07 17:31:40 +01:00
ptitSeb 81d906fd3b More wrapped functions on libs harfbuzz and fontconfig 2024-03-07 14:55:05 +01:00
ptitSeb b51bdf3d5e [NOGTK] libpangoft2 is also part of the gtk family 2024-03-07 14:41:59 +01:00
ptitSeb c8ca7876c3 [ARM64_DYNAREC] Slightly better trace when dynarec log unknown opcode 2024-03-07 14:41:28 +01:00
ptitSeb c181a6dcc8 [INTERPRETER] Generate a SIGILL when executing 3F opcode in 64bits 2024-03-07 14:40:43 +01:00
ptitSeb b763c22ef4 [TRACE] Improved logs on NULL-sized block 2024-03-07 14:40:02 +01:00
ptitSeb 5c83475c95 [VULKAN] Added one more vulkan extension 2024-03-07 14:15:23 +01:00
ptitSeb 1d1670864b [ARM64_DYNAREC] Fixed F0 0F AB opcode 2024-03-07 14:14:48 +01:00
ptitSeb 5e980767b9 [ARM64] Added 1 more special case of SIGBUS when accessing device memory (Help Planet Coaster on NVidia) 2024-03-07 13:42:36 +01:00
ptitSeb 2b3c9b95af Some work on gtk and co wrapping 2024-03-07 11:11:47 +01:00
ptitSeb 09232ad0b6 [ARM64_DYNAREC] A bot more work on shift opcodes 2024-03-07 10:17:39 +01:00
ptitSeb 2533197a3c [ARM64_DYNAREC] Small optim to SAHF & more cosmetics stuffs 2024-03-06 16:46:33 +01:00
ptitSeb 71c43b0de7 Added 1 more function to libpng16 2024-03-06 16:45:50 +01:00
ptitSeb 6606b7b097 Add more slot to gobject2 callbacks 2024-03-06 16:45:36 +01:00
Lily 5c994ff222 some gcrypt wrapping (#1338)
* some gcrypt wrapping (needed to check sign)

* little more wrapping in gcrypt

* correcting sign
2024-03-06 16:12:16 +01:00
ptitSeb 9372b96e47 Some more improvment to xcb wrapping 2024-03-06 15:20:31 +01:00
ptitSeb 24e133e006 Added back full handling of winepreloader prereserve memory 2024-03-06 12:41:39 +01:00
Yang Liu 995fa013a6 Fixed a warning (#1335)
* Fixed some warnings

* Revert
2024-03-06 11:14:01 +01:00
ptitSeb 4af1f56713 Improved wrapping of xcb (xcb_XXX_iterator_t and xcb_contection_t) 2024-03-06 11:11:36 +01:00
Yang Liu 584b258241 [RV64_DYNAREC] Added 66 0F 38 61 PCMPESTRI opcode and some refactors too (#1337) 2024-03-06 09:58:04 +01:00
Yang Liu fb13ce2baf [ARM64_DYNAREC] Fixed some typos (#1336) 2024-03-06 09:56:12 +01:00
Lily f910a70c8a Added 2 pthread wraps (#1334) 2024-03-05 19:52:14 +01:00
Yang Liu fedb8bd816 [LA64_DYNAREC] Added more opcodes and more instructions in emitter and printer (#1332) 2024-03-05 17:59:15 +01:00
Yang Liu c3f97dd730 [LA64_DYNAREC] Added more opcodes and some fixes too (#1331)
* [LA64_DYNAREC] Added 66 90..97 NOP/XCHG opcodes

* Added AB REP STOSD opcode

* Fixed a bug in emit_sar32c

* [LA64_DYNAREC] Added 0F B7 MOVZX opcode

* Why I keep forgetting the TO_LA64 thing?!

* Added 20..24 AND opcodes
2024-03-05 16:29:52 +01:00
ptitSeb b1ebf9dc79 Added 1 more function to libXrandr (should fix VampireSurvivors 1.9+) 2024-03-05 16:07:25 +01:00
ptitSeb d07ea96570 Adjusted dependancies for some X11 libs 2024-03-05 15:59:51 +01:00
ptitSeb dc3bdd89c1 Added a few more flags on of_convert to limit warnings 2024-03-05 15:59:27 +01:00
Yang Liu 7e92c912b2 [LA64_DYNAREC] Added more opcodes and some fixes in the printer (#1330)
* Added 90..97 NOP/XCHG opcodes

* More instructions and fixes to the emitter and printer

* Added F0 0F C1 LOCK XADD opcode

* Fix

* Fix
2024-03-05 12:03:41 +01:00
Yang Liu 5d5c3aec3c [LA64_DYNAREC] Made eflags synchronization lazy (#1329)
* [LA64_DYNAREC] Made eflags synchronization lazy

* A smol optim

* Fixed CLEAR_FLAGS
2024-03-05 09:49:19 +01:00
Yang Liu 0ba63ea272 [LA64_DYNAREC] Added more opcodes (#1327)
* [LA64_DYNAREC] Added F7 /2 NOT opcode

* [LA64_DYNAREC] Added 09 OR opcode

* [LA64_DYNAREC] Added 64 MOVSXD opcode

* [LA64_DYNAREC] Added more instructions to the emitter and printer, and fixed typos

* Remove unused code

* [LA64_DYNAREC] Added  D3 /4 /6 SHL opcode

* [LA64_DYNAREC] Added 0D OR opcode

* [LA64_DYNAREC] Fixed a bug when LBT is present

* Revert
2024-03-04 22:07:11 +01:00
Yang Liu a242a8e277 [LA64_DYNAREC] Added more and more opcodes (#1326)
* [LA64_DYNAREC] Added 81/83 /1 OR opcode

* [LA64_DYNAREC] Added F6 /0 /1 TEST opcode

* Added A9 TEST opcode

* Added A8 TEST opcode

* [LA64_DYNAREC] Added 80 /4 AND opcode

* [LA64_DYNAREC] Added 0F 90..9F SETcc opcodes

* [LA64_DYNAREC] Added 84 TEST opcode

* [LA64_DYNAREC] Added 0F 01 XGETBV opcode

* [LA64_DYNAREC] Added E0..E3 opcodes
2024-03-04 19:35:37 +01:00
Yang Liu cc86e94cd5 [LA64] Detect the existence of LBT extension (#1325) 2024-03-04 17:49:57 +01:00
Yang Liu 1c10ae443d [LA64_DYNAREC] Utilizing bitmanip instructions because they're great (#1324)
* [LA64_DYNAREC] Added bitmanip instructions to emitter and printer

* [LA64_DYNAREC] Utilizing bitmanip instructions because they're great

* Review
2024-03-04 17:48:59 +01:00
ptitSeb d44f3d9bae [ARM64_DYNAREC] Small optims for SSE/SSE2 & strongmem>1 2024-03-04 17:20:56 +01:00
ptitSeb d71e5f968a Added DF D0..D7 ([ARM64_DYNAREC] too) 2024-03-04 16:21:44 +01:00
ptitSeb 4aa9fba4fa [ARM64_DYNAREC] Stop a block on CC opcode (unless they are ignored) 2024-03-04 16:21:22 +01:00
xctan 8aaaddde03 [WRAPPER] Fixed a typo in the signature of my___libc_start_main (#1323) 2024-03-04 15:16:20 +01:00
Haichen Wu d5176ba278 [LA64_DYNAREC] Added more opcodes (#1322) 2024-03-04 15:15:22 +01:00
ptitSeb 13a8108e1e Added 2 more symbols to wrapped libicuuc 2024-03-04 15:08:53 +01:00
ptitSeb 82b19f6f69 Added a few more libc wrapped functions 2024-03-04 13:52:36 +01:00
ptitSeb 9e37dd008d [ELFLOADER] Fixes some issue with symbol version matching and unload of failled libs (for #1311, probably other too) 2024-03-04 13:40:57 +01:00
ptitSeb 5b1057fe08 [TRACE] Better trace when trying to run on very low address 2024-03-04 13:40:57 +01:00
ptitSeb 460fa3f3d7 Added libstdc++ when loading libGL (only if libgcc_s is already loaded), helps some linux Unity games 2024-03-04 13:40:57 +01:00
Yang Liu 61de3532c2 [LA64_DYNAREC] Added more opcodes (#1321)
* [LA64_DYNAREC] Added 0F 80..8F Jcc opcodes

* [LA64_DYNAREC] Added 31/33 XOR opcodes

* [LA64_DYNAREC] Added 0F A2 CPUID opcode

* [LA64_DYNAREC] Added 81/83 /4 AND opcode

* [LA64_DYNAREC] Added 25 AND opcode

* [LA64_DYNAREC] Added F7 /0 /1 TEST opcodes

* Fix
2024-03-04 11:36:27 +01:00
ptitSeb ddfc699809 Added 64 66 0F 7F opcode ([ARM64_DYNAREC] too) (for #1320) 2024-03-04 09:43:43 +01:00
Yang Liu d0edf2e8dd [LA64_DYNAREC] Added more opcodes and more fixes, SuperHexagon is working (#1319)
* Made printer slightly better

* [SIGNAL] Fixed a typo

* Removed useless comma

* Another typo

* Keep'em in order

* Added more opcodes and more fixes

* A big fix of GOCOND macro

* [LA64_DYNAREC] Added E8 CALL opcode

* [LA64_DYNAREC] Added C6 MOV opcode

* [LA64_DYNAREC] Added 39 CMP opcode

* [LA64_DYNAREC] Added 0F 1F NOP opcode

* BEWARE: shift instructions are NOT sign-extended!

* More fixes

* Try to be safe

* Fixed printer

* Fixed emitter & printer for B, briing superhexagon back
2024-03-03 21:41:31 +01:00
Yang Liu a159cb5efe [LA64_DYNAREC] Enable co-simulation and fixed an important issue (#1317) 2024-03-03 08:50:48 +01:00
Yang Liu 26371bb9dd Added a warning on interpreter only build when DynaRec is available (#1316) 2024-03-03 08:49:45 +01:00
Yang Liu de4ffcc8bc [LA64_DYNAREC] Added more and more opcodes (#1314)
* [LA64_DYNAREC] Added C1 /5 SHR opcode

* [LA64_DYNAREC] Added C1 /7 SAR opcode

* [LA64_DYNAREC] Added D1 /7 SAR opcode

* [LA64_DYNAREC] Added D1 /5 SHR opcode

* [LA64_DYNAREC] Added FF /4 JMP opcode

* [LA64_DYNAREC] Added 66 0F 1F NOP opcode

* [LA64_DYNAREC] Added B8..BF MOV opcodes

* [LA64_DYNAREC] Added C7 MOV opcode

* [LA64_DYNAREC] Added 0F 05 SYSCALL opcode
2024-03-02 20:10:04 +01:00
Yang Liu ebaedca708 [LA64_DYNAREC] Added more opcodes (#1313)
* [LA64_DYNAREC] Added F30F 1E NOP opcode

* [LA64_DYNAREC] Added E9/EB JMP opcodes
2024-03-02 18:26:07 +01:00
Yang Liu a86f597239 [LA64_DYNAREC] Added CC native call support, fixed call_c (#1312) 2024-03-02 18:10:44 +01:00
ptitSeb b72d3a77e9 [ARM64_DYNAREC] More fixes and optim on IMUL flags 2024-03-02 17:31:47 +01:00
ptitSeb 64fdf54156 [ARM64_DYNAREC] Fixed flags for 69 opcode, and small optim for 0F AF opcode 2024-03-02 16:36:54 +01:00
ptitSeb 463e31251f [ARM64_DYNAREC] Small optim on some cases of F2 0F 70 opcode 2024-03-02 14:09:31 +01:00
ptitSeb 9032f24a56 [ARM64_DYNAREC] Small optim on flag computation for 69 opcode 2024-03-02 14:05:17 +01:00
Yang Liu c5828803c6 [LA64_DYNAREC] Added more opcodes with CALL/RET optimization (#1310)
* [LA64_DYNAREC] Added FF /2 CALL Ed opcode

* [LA64_DYNAREC] Added 81/83 /0 ADD opcode

* [LA64_DYNAREC] Added C3 RET opcode
2024-03-02 13:11:20 +01:00
Yang Liu 9883c6464e [LA64_DYNAREC] Adopt to ARM64 way of CALL/RET optim since there is a dedicated register (#1309) 2024-03-02 11:14:48 +01:00
ptitSeb 67006f2809 [LA64_DYNAREC] Added xSavedSP to emitter for later use 2024-03-02 10:10:42 +01:00
ptitSeb e49728aa82 Added more hardware contributor, thanks! 2024-03-02 10:00:37 +01:00
Yang Liu 829c254b1f [LA64_DYNAREC] Added 70-7F Jcc opcodes, refine printer and some fixes too (#1307)
* [LA64_DYNAREC] Added 70-7F Jcc opcodes and some fixes too

* [LA64_DYNAREC] Added more instructions to the printer and made the format prettier

* Make LBT truely optional

* Do not test LBT in CI

* Format

* Optimize

* Fixed printer format

* Fixed CLEAR_FLAGS macro

* Fixed xMASK

* Use $r22 ($sp) in the prolog/epilog for better semantics

* Fixed la64_next
2024-03-02 09:45:55 +01:00
ptitSeb 8bf54eda56 Added 66 F8/F9 ([ARM64_DYNAREC] too) 2024-03-01 20:35:15 +01:00
Yang Liu c58adce8f6 [LA64_DYNAREC] Added 1 more opcode and more fixes (#1305)
* Fixed printer name mapping

* Fixed emit_sub32c

* Remove a useless macro

* Added 85 TEST opcode
2024-02-29 19:33:36 +01:00
Yang Liu 92532b0fd1 [LA64_DYNAREC] Added more opcodes and fixed more things (#1304)
* [LA64_DYNAREC] Fixed GETED macro

* [LA64_DYNAREC] Added 81/83 /5 SUB opcode

* Use xMASK when possible

* Added 8B MOV opcode

* Fix
2024-02-29 17:48:23 +01:00
Yang Liu 8cba5d55ce [LA64_DYNAREC] Added LBT support to all implemented emit functions and fixed some typos (#1303) 2024-02-29 17:10:47 +01:00
Yang Liu da1ac7beee [LA64_DYNAREC] Added basic LBT support, setup xMASK (#1302)
* [LA64] Added basic LBT support, setup xMASK

* [CI] Run tests without LBT
2024-02-29 16:11:52 +01:00
Yang Liu 28b79626d9 [LA64_DYNAREC] Removed F_OF2 trick as it's unnecessary (#1300) 2024-02-29 15:13:35 +01:00
Yang Liu 867059dfae [LA64_DYNAREC] Added some LBT instructions (#1299) 2024-02-29 14:05:52 +01:00
ptitSeb 50250bd2ca Added wrapped support for EGL/GLESv2 2024-02-29 12:55:57 +01:00
Yang Liu 0e71c3a2ac [CI] Added loongarch64 (#1298) 2024-02-29 08:49:47 +01:00
Haichen Wu db01a92edf [LONGAARCH_DYNAREC] Added 00...05 and 28...2D opcodes (#1297)
* [LONGAARCH] More renamed arch to LA64

* [LONGAARCH_DYNAREC] Added 00...05 and 28...2D opcodes
2024-02-29 08:16:40 +01:00
ptitSeb 6a9836912d [LONGAARCH] Renamed arch to LA64, as LA464 is code name for 3a5000, so that way it's more generic (and sorry about that late minute change) 2024-02-28 16:37:18 +01:00
Haichen Wu bdcfd69795 LARCH64 dynarec (#1295)
* LARCH64_DYNAREC dynarec

* [LARCH64_DYNAREC] Change mapping for the registers
2024-02-28 16:10:13 +01:00
ptitSeb dbe1bb0ec4 Added all wrapped function to libpci 2024-02-28 14:11:03 +01:00
ptitSeb d76841bdc1 Even more slot for X11 callbacks 2024-02-28 12:25:42 +01:00
ptitSeb 0251a29841 Small change on steam-pressure-vessel emulation 2024-02-28 12:25:21 +01:00
ptitSeb 32b0c173f0 [ELFLOADER] Fixed another warning 2024-02-28 10:28:41 +01:00
ptitSeb 90167afc2b [ELFLOADER] Fixed a warning 2024-02-28 10:27:36 +01:00
Yang Liu 6a4a58185e [RV64_INTERP] Added TSC freq support (#1293)
* [RV64_INTERP] Added TSC freq support

* Simplify
2024-02-28 10:10:30 +01:00
Yang Liu 6cffabacb3 [CI] Repeat until-pass for unstable platform (#1292)
* [CI] Repeat until-pass for unstable platform

Also removes useless --rerun-failed

* Fix
2024-02-28 08:11:29 +01:00
Yang Liu d658c47cd0 [RV64_DYNAREC] Fixed RDTSC handling (#1291)
* [LIBWRAP] Fixed a typo in the clocksource wrapping

* [RV64_DYNAREC] Added hardware timer support for RDTSC

* [INTERP] Optmize RV64 ReadTSC using rdtime

* [RV64_DYNAREC] Added 0F 01 F9 RDTSCP opcode

* Fixed typo

* Fixed another typo
2024-02-27 20:44:34 +01:00
ptitSeb 21b06ace43 [ANDROID] Small change on my___libc_init signature 2024-02-27 20:02:31 +01:00
ptitSeb 7a27b95df7 Added some more wrapped libm functions 2024-02-27 18:23:01 +01:00
ptitSeb a730935e6e Added 1 more syscall 2024-02-27 18:22:37 +01:00
ptitSeb ef705ed494 Added empty command 14 to CPUID 2024-02-27 17:44:09 +01:00
ptitSeb fb6915b059 [ARM64_DYNAREC] Added FF /3 opcode 2024-02-27 15:52:51 +01:00
ptitSeb 20d675ea48 [ARM64_DYNAREC] copied code for F0 87 to 87 opcode, as they should behavee the same way 2024-02-27 15:40:47 +01:00
ptitSeb 900dbc2a47 [32BITS][ARM64_DYNAREC] Added 67 E0..E3 opcodes 2024-02-27 15:40:47 +01:00
xctan d8affd8564 [RV64_DYNAREC] Optimized XOR Ew, Gw when Ew == Gw (#1289) 2024-02-27 15:13:00 +01:00
ptitSeb f3d4a1e1c3 Added some more vulkan extensions 2024-02-27 14:05:55 +01:00
ptitSeb d5ebea7928 [ARM64_DYNAREC] Added C8 opcode (for CP2077) 2024-02-27 14:05:42 +01:00
ptitSeb bd95c7a366 [ARM64_DYNAREC] Added 66 F0 01 opcode (for CP2077) 2024-02-27 14:05:20 +01:00
ptitSeb 20fc160230 [ARM64_DYNAREC] Fixed a potential issue with F0 87 opcode 2024-02-27 14:04:07 +01:00
ptitSeb c786e6d576 Added some more slots for X11 callbacks (help Cyberpunk 2077) 2024-02-27 14:03:33 +01:00
Yang Liu e9ce6a4f80 [RV64_INTERP] Comply CMPXCHG16B with dynarec (#1288) 2024-02-27 10:29:55 +01:00
ptitSeb 0024e4b970 [ANDROID] BBBBUUUIIIIILLLLDDDD 2024-02-26 21:18:39 +01:00
ptitSeb cf8ea5953e [ANDROID] Now build, stop complaining 2024-02-26 21:16:06 +01:00
ptitSeb 65ddcdeabb Fix Android tests 2024-02-26 21:00:12 +01:00
ptitSeb 6576686b36 Fix Android build 2024-02-26 19:47:03 +01:00
ptitSeb 13404ed090 Added ability to staticaly build box64 (for #1045 and #310, maybe a few others tickets) 2024-02-26 19:22:53 +01:00
ptitSeb ff6cc84482 Added CA opcode 2024-02-25 14:34:59 +01:00
ptitSeb 02caee0c02 Added some hack to rename wine binary process too (help mesa pick up the correct binary being run) 2024-02-24 14:12:36 +01:00
ptitSeb 7260da63af Fixed a warning 2024-02-24 12:27:59 +01:00
ptitSeb ec0d333d81 Improve emulation of clocksource 2024-02-24 12:10:08 +01:00
ptitSeb d3eb6b8a11 Small memory leak fixed with PRELOAD library 2024-02-24 12:09:32 +01:00
ptitSeb cc0ce73d39 This should improve stability when unloading libs 2024-02-24 12:09:09 +01:00
ptitSeb 2eb92951af [32BITS] Added 0E opcode ([ARM64_DYNAREC] too) 2024-02-24 12:08:16 +01:00
ptitSeb f8202096f1 Added 0F 01 F9 opcode ([ARM64_DYNAREC] too 2024-02-24 12:07:37 +01:00
ptitSeb f470d552cf Small changes in signal safe function handling 2024-02-24 09:56:04 +01:00
ptitSeb be50bbc149 [ARM64_DYNAREC] Handling of EB FF hacky jump 2024-02-24 09:55:26 +01:00
ptitSeb 50c49a1692 [RCFILE] Adjusted settings for windows steam 2024-02-24 09:54:29 +01:00
ptitSeb 70496c9bde Improved cpu detection for cpuid 2024-02-24 09:23:12 +01:00
ptitSeb f7f7c1c9af Fixed a typo in readme 2024-02-24 09:23:12 +01:00
Yang Liu f02d5fc28f [RV64_DYNAREC] Added missing 0F 38 00 PSHUFB opcode for test23 (#1282) 2024-02-23 19:33:33 +01:00
Yang Liu 422a982917 [RV64_DYNAREC] Added all missing 66 0F opcodes for test17 (#1281)
* Added 66 0F 38 14 PBLENDVPS opcode

* Added 66 0F 3A 40 DPPS opcode

* Added 66 0F 38 20 PMOVSXBW opcode

* Added 66 0F 38 21 PMOVSXBD opcode

* Added 66 0F 38 22 opcode

* Added 66 0F 38 23/24 opcodes
2024-02-23 19:06:00 +01:00
ptitSeb ce60a8cfa2 Fix Android build 2024-02-23 18:59:51 +01:00
ptitSeb f0026927e3 Added some various wrapped function (for rpcs3, but still not working) 2024-02-23 18:09:18 +01:00
ptitSeb d1388dd7eb Fix Android builds 2024-02-23 17:40:34 +01:00
ptitSeb ffda782c3d Better handling of Hardware counter for rdtsc emulation (ARM64 only for now), more cpuid leafs, and introduce BOX64_RDTSC env.var. with a profile that use it 2024-02-23 16:41:44 +01:00
ptitSeb 3a6df996dc Added 67 FF /2 opcode ([ARM64_DYNAREC] too) 2024-02-22 19:59:09 +01:00
Yang Liu 6141376977 [RV64_DYNAREC] Added 2 more 66 0F opcodes for test17 (#1278)
* Added 66 0F 38 03 PHADDSW opcode

* Added 66 0F 38 05 PHSUBW opcode
2024-02-22 19:10:56 +01:00
Yang Liu 3ec2ebabfc [RV64_DYNAREC] Added more opcodes (#1277)
* Added 66 0F 38 25 PMOVSXDQ opcode

* Added 0F 3A CC opcode

* Added 67 F7 /4 MUL opcode

* Added 67 C1 /5 SHR opcode
2024-02-22 13:37:46 +01:00
ptitSeb 77dcb025fd Hardened the my_sigaltstack wrapped function 2024-02-22 11:15:38 +01:00
ptitSeb bbaa01af79 [INTERPRETER] Added CB opcode 2024-02-22 11:15:02 +01:00
ptitSeb d033f34a45 [ARM64_DYNAREC] Added 0F E2 opcode 2024-02-22 10:39:59 +01:00
Yang Liu f2eb5326af [RV64_DYNAREC] Added more opcodes (#1276)
* Added 66 9C/9D PUSHF/POPF opcodes

* Added 0F E2 PSRAD opcode

* Fix

* More readable
2024-02-22 10:39:33 +01:00
ptitSeb f09b541ab7 [ARM64_DYNAREC] Added RCR 8bits with constant optimisation, and fixed RCL 8bit with const 2024-02-21 18:13:49 +01:00
ptitSeb e71df7eb67 [ARM64_DYNAREC] Optimized rcl 8bits with constant 2024-02-21 15:31:09 +01:00
ptitSeb 9d1e6b9b96 [INTERPRETER] SHRD/SHLD with cnt==0 should not change flags 2024-02-21 15:14:55 +01:00
ptitSeb 0d43b16fd5 [ARM64] Used Hardware counter for RDTSC emulation ([ARM64_DYNAREC] too) 2024-02-21 12:27:53 +01:00
Yang Liu b179bd2415 [DYNAREC_RV64] Minor OF flag fixes and optimizations for emit shift utils (#1275)
* Minor OF flag fixes and optimizations for emit shift utils

* original operand
2024-02-21 11:34:44 +01:00
ptitSeb 64fbd3db46 [ARM64_DYNAREC] Fixed some inf/nan detection for FXAM opcode 2024-02-21 11:25:31 +01:00
ptitSeb ea096cd593 [ARM64_DYNAREC] Adjusted some FLAGS productions of AAA/AAS/DAA/DAS ocpodes 2024-02-21 11:12:13 +01:00
ptitSeb 7934e3ad5c Small adjustment to flags computation on the AAA/AAS/AAD/AAM/DAA/DAS opcodes 2024-02-21 11:08:27 +01:00
ptitSeb 52a5335770 Small adjustment to one flags computation 2024-02-21 11:07:40 +01:00
Yang Liu f3d1ffbe01 [LIBTOOL] Fixed my_pthread_attr_init (#1274) 2024-02-21 09:00:23 +01:00
ptitSeb b40a17fc51 [ARM64_DYNAREC] Fixed some case of ROL/ROR 8/16bits not computing CF flag correctly 2024-02-20 16:32:41 +01:00
ptitSeb 02fadef9e7 [INTERPRETER] Fix shl/sar/shr for large shft value on 8 and 16bits operations 2024-02-20 16:31:44 +01:00
ptitSeb 6e4d2470d2 [TRACE] Slightly better trace for dynarec block writing on own page 2024-02-20 16:30:19 +01:00
ptitSeb 8e4faa3de2 Added 1 more profile for wine/new wow64 2024-02-20 16:29:09 +01:00
Yang Liu 4f3b9f19a7 [DYNAREC_RV64] Added more opcodes and some minor optimizations (#1272)
* Added DD /1 FISTTP i64 opcode

* Some small optimizations

* Added 0F AD SHRD opcode and some minor optimizations on the CF flag computation
2024-02-20 12:06:38 +01:00
ptitSeb e562baf30b Added some more symbol to wrapped libgnutls 2024-02-18 11:18:54 +01:00
ptitSeb efefd13bf5 Added VK_KHR_calibrated_timestamps extension to wrapped vulkan (for #1256) 2024-02-18 09:32:06 +01:00
ptitSeb 4314ef1ca8 [DYNAREC] Adjusted the PUSH/POP x87 macro (and fix RV64 test infinite loop) 2024-02-17 20:12:50 +01:00
KreitinnSoftware 477e531af9 [ANDROID] Fix Build When Compiling with NDK 26b, [CI] Download Basic Android Libs from 'termux-docker' and update NDK to 26b (#1270)
* [CI] Download Basic Android Libs from termux-docker for speed-up CI build

* [ANDROID] Fix 'SHT_CHECKSUM' error when compiling on NDK 26b

* [CI] Update NDK for 26b
2024-02-17 19:26:49 +01:00
ptitSeb 47b8e2a983 [INTERPRETER] Added a few unaligned path for some F0 math opcodes 2024-02-17 15:14:26 +01:00
ptitSeb cc01018223 [ARM64_DYNAREC] Added F0 31 opcode 2024-02-17 14:02:05 +01:00
ptitSeb 7a28084b63 [ARM64_DYNAREC] Added unligned path for F0 01 and F0 39 2024-02-17 13:46:16 +01:00
ptitSeb ea86b0e32f [RV64_DYNAREC] Fix build 2024-02-17 12:57:50 +01:00
ptitSeb 96169af71e [DYNAREC] Try to fix some issue with x87 stack and skipped code being incoherent 2024-02-17 12:54:45 +01:00
ptitSeb 4633817374 Small optim to speedup mmap64 2024-02-17 12:44:18 +01:00
ptitSeb a190910cbf [ARM64_DYNAREC] Fixed D9 E4 opcode 2024-02-17 11:45:10 +01:00
ptitSeb 6170fc8e43 Removed some debug leftover (at least change from LOG_INFO to LOG_DEBUG) 2024-02-17 11:10:31 +01:00
ptitSeb aa279c332d Better handling of 26/2E/36/3E prefix on F0 prefixed opcode ([ARM64_DYNAREC] too) 2024-02-17 09:37:50 +01:00
ptitSeb a79e1be034 Added 67 C6 opcode ([ARM64_DYNAREC] too) 2024-02-17 09:25:00 +01:00
ptitSeb 5924a8eca1 [ARM64_DYNAREC] Fixed 8C opcode 2024-02-16 18:38:21 +01:00
ptitSeb fc920b0838 Show box64 version inside trace file 2024-02-16 18:36:26 +01:00
ptitSeb e33d51641f [ARM64_DYNAREC][32BITS] Added C4 /m and C5 /m opcodes 2024-02-16 16:58:26 +01:00
ptitSeb 4b979bf206 [ARM64_DYNAREC] Added 0F A0/A1/A8/A9 opcodes 2024-02-16 16:31:05 +01:00
ptitSeb bc5afbea89 [ARM64_DYNAREC] Added better handling for DD C0 D9 F7 sequence 2024-02-16 14:22:05 +01:00
ptitSeb 65f75b0cc0 [ELFLOADER] Better handling of STB_GNU_UNIQUE binded symbol (prevent dlclose) 2024-02-16 13:44:54 +01:00
ptitSeb c50b0ef9e8 Added a few more function to libicuuc.so.* 2024-02-16 13:44:12 +01:00
ptitSeb 10c479034f Added some more wrapped function to libc, libXt and libX11 2024-02-16 12:41:13 +01:00
ptitSeb 3c95826c5c Added wrapped libanl 2024-02-16 11:40:19 +01:00
ptitSeb fa11368599 [ELFLOADER] Improved inter-library dependancie managment 2024-02-16 11:35:13 +01:00
ptitSeb f4fd01c777 [ANDROID][TERMUX] Fix build 2024-02-15 19:03:55 +01:00
ptitSeb 96941c9978 Fixe builds (non trace and android/termux) 2024-02-15 18:23:48 +01:00
ptitSeb c5a6875de9 [ELFLOADER] Huge refactor of elfloader and symbol resolution. Some more cleaning need to be done, but that's a first step (should help #422, #360, #1046 and probably others) 2024-02-15 18:11:57 +01:00
KreitinnSoftwareandPablo Carlos 549e042e67 [CI] Add Android Tests (#1263)
* [CI] Add Android Tests

* Remove a Build of Box64 that I placed and forgot to remove before

* Fix some tests checking

* Disable Test07 and Test17 for now

* Comment set_tests_proprieties (I have forgotten)

* Add mmx test and benchfloat for Android

* Fix build for Clang-17 on non-Termux

* Update NDK to 26b and add Termux Build/Testing

* Revert to NDK 25b, something is wrong

* Add -DTERMUX=1 to Termux Build

* Add LD_LIBRARY_PATH for Termux Testing

* Set LD_LIBRARY_PATH on QEMU_SET_ENV

* Move data folder to current dir before testing on Termux

* Copy Termux Data Libs for /data

* Try to set QEMU_SET_ENV on GITHUB_ENV

---------

Co-authored-by: Pablo Carlos <[email protected]>
2024-02-14 09:14:01 +01:00
ptitSeb c70581abc9 Added support for RTLD_DEEPBIND flag on dlopen 2024-02-11 16:46:21 +01:00
ptitSeb 5e6af37532 [ARM64_DYNAREC] Improved FFREE handling (fixing gameplay of Serious Sam 2, probably some other game too) 2024-02-11 16:12:46 +01:00
ptitSeb c0184f926d Small fix for FindNearestSymbolName 2024-02-11 15:39:25 +01:00
ptitSeb a69e81f034 [ARM64_DYNAREC] Improved FFREE/FXAM opcodes (helps 32bits games like SeriousSam2) 2024-02-11 11:52:58 +01:00
ptitSeb 5c01fbabac [INTERPRETER] Improved FXAM handling 2024-02-11 11:31:31 +01:00
Coreforge fed47bea4a more wrapped functions in libxcb-randr and libcap (#1260)
* wrapped a few xcbrandr functions for steamvr

* wrapped parts of libcap for vrcompositor-launcher
2024-02-10 19:15:06 +01:00
ptitSeb 213c063895 Fixed previous wrapped lib refactor when ALTMY macro is used 2024-02-10 18:20:16 +01:00
KreitinnSoftwareandPablo Carlos 632af46137 [ANDROID] BOX64_SHOWBT Now show Emulated BT on Android (#1258)
Co-authored-by: Pablo Carlos <[email protected]>
2024-02-10 16:44:28 +01:00
rajdakin b527ebbf5b Wrapped libraries refactor (#1257)
* [MISC] Removed a warning caused by tab/space mismatch

* [WRAPPED] Factored out `getMy` and `freeMy` calls

* [WRAPPED] Small cleanup of the init header

* [WRAPPED] Factored out `SETALT`

* [WRAPPED] Factored out needed libs
2024-02-10 15:06:08 +01:00
ptitSeb ad55cfde7f Added 0F 01 E0..E7 opcodes ([ARM64_DYNAREC] too) 2024-02-10 13:10:33 +01:00
ptitSeb 44e77de620 Increased default size for number of elf in the tls dts zone 2024-02-09 18:40:34 +01:00
ptitSeb 40de8e16ec Simplified (and improved?) handling of phtread_attr_t 2024-02-09 17:43:35 +01:00
ptitSeb d36f9e4dbb [ELFLOADER] Do not memset the remaining of page when mmap'ing, it's already done (and might not be possible depending on the protection) 2024-02-09 17:33:00 +01:00
ptitSeb a65f448856 Added some more libc wrapped functions 2024-02-09 15:58:40 +01:00
ptitSeb 8cba593882 Added 1 syscall 2024-02-09 15:47:19 +01:00
ptitSeb 0715dd145f Added some wrapped function to libxml2 2024-02-09 15:47:08 +01:00
ptitSeb 5a20322251 [WRAPPING] Added supot for the 'long double complex' type 2024-02-09 15:19:05 +01:00
ptitSeb 89b5e1163d Added some more symbols to wrapped libm 2024-02-09 14:37:07 +01:00
ptitSeb 6a9dbe3d89 Prefer emulated version tbbmalloc.so.2 if present 2024-02-09 13:59:01 +01:00
ptitSeb 8e6ae3aa01 Hack to add some paramter when launching steam under wine to easy memory and cpu load 2024-02-08 18:28:21 +01:00
ptitSeb e46707750b [ARM64_DYNAREC] Added F0 21 opcode 2024-02-08 18:27:21 +01:00
ptitSeb b1f6ea8ae6 More work on libcurl and friends (and set to used emulated version of curl if possible) 2024-02-08 16:49:02 +01:00
ptitSeb 82ae65f477 Added wrapped (empty) libpam.so.0 2024-02-07 21:58:38 +01:00
ptitSeb 4a3595133a [ARM64_DYNAREC] Improved stability when USCAT extention is supported, qn d improved reliqbility of unaligned fallback for LOCK CMPXCHG8B/CMPXCHG16B opcodes 2024-02-07 19:31:35 +01:00
ptitSeb 4c9a6a5d98 [DYNAREC] Jumptable now use custom Malloc instead of regular one 2024-02-07 18:02:07 +01:00
ptitSeb a2e01c36ba [ARM64_DYNAREC] 32bits Shift with 0 amount still wipe upper part of register on 64bits 2024-02-07 18:02:07 +01:00
ptitSeb 774d872f41 [DYNAREC] Tests for emited coded size limit (usefull for DYNAREC_TEST for example) 2024-02-07 18:02:07 +01:00
ptitSeb fa19435d24 [DYNAREC_TEST] Have a proper TestEw that only copy/tests 2 bytes instead of 4 2024-02-07 18:02:07 +01:00
factfinding 902186bdff [DYNAREC_RV64] f23 and f24 are save in a same place (#1251) 2024-02-07 17:27:35 +01:00
ptitSeb 6996c06909 TEGRAX1 config also have BOX64_MMAP32 activated by default 2024-02-07 16:42:13 +01:00
ptitSeb 315068b111 [ARM64_DYNAREC] Added 0F C7 /1 opcode 2024-02-07 14:13:05 +01:00
ptitSeb 4047d1ba3c [ARM64_DYNAREC] More fixes to F0 0F C7 opcode 2024-02-07 13:56:45 +01:00
ptitSeb d74bee3596 Disabling WINEFSYNC for now, that seems to be not working fine 2024-02-07 12:39:02 +01:00
ptitSeb aea1049223 Fixed a warning 2024-02-07 11:24:59 +01:00
ptitSeb 3548195fbe [ARM64_DYNAREC] Fixed F0 0F C7 opcode that was broken on previous commit 2024-02-06 22:02:13 +01:00
ptitSeb 8d0cc15eb0 [ARM64_DYNAREC] Reworked, again, strongmem emulation 2024-02-06 18:21:37 +01:00
ptitSeb ee2580a57f Reworked, again, exit process 2024-02-06 18:20:11 +01:00
ptitSeb 255d5c661e Do not force mmap alginement if wine not detected (shoudl help #1249) 2024-02-06 18:16:42 +01:00
ptitSeb a60d945968 [ARM64_DYNAREC] Added an unaligned path for F0 0F C7 /1 opcode 2024-02-06 16:13:36 +01:00
ptitSeb f8fa53aa3b Changed a bit how SGDT/SIDT are faked ([ARM64_DYNAREC] too) 2024-02-06 14:42:51 +01:00
KreitinnSoftware 1642327015 [ANDROID] Fix GLib and GObject Library Names (#1247)
* [ANDROID] Fix GLib and GObject Library Names

* [ANDROID] Fix gdk3, gdkpixbuf2, gio2, gmodule2, gtkx112, gdkx112, pangocairo Library Names
2024-02-06 12:26:50 +01:00
ptitSeb 399478d635 [ARM64_DYNAREC] Added BOX64_DYNAREC_DIV0 option to check/trigger Divide by 0 when needed 2024-02-05 20:35:31 +01:00
ptitSeb 608c13ebba Added curl_url api to wrapped libcurl 2024-02-04 20:46:27 +01:00
ptitSeb 99694d67ca Added some more function to wrapped libcrypto.so.3 and libssl.so.3 2024-02-04 20:39:35 +01:00
ptitSeb bde279f2fa [ARM64_DYANREC] Try to fix DD /1 opcode with FRINT extension 2024-02-04 19:50:00 +01:00
ptitSeb e4f56f0b23 [INTERPRETER] CE opcode is only for 32bits 2024-02-04 16:49:34 +01:00
ptitSeb 3e8da0cc1a [RV64_DYNAREC] Fixed build 2024-02-04 14:43:20 +01:00
ptitSeb ca0e12d93f [RV64_DYNAREC][32BITS] Added optim for 32bits jumptable and fix build 2024-02-04 12:31:58 +01:00
ptitSeb 0c41d9810f [ARM64_DYNAREC][32BITS] Small optim on jump table for 32bits access (1 less read, or 2 in SAVE_MEM configuration) 2024-02-04 11:34:29 +01:00
ptitSeb 165961f27e [ARM64_DYNAREC] Small D8..DF opcodes refactor 2024-02-04 10:39:25 +01:00
ptitSeb 81386b7a56 [INTERPRETER] Small D8..DF opcodes refactor 2024-02-04 10:32:42 +01:00
ptitSeb 5bf2a7d51b Updated wrapped SDL2 (will help #1225) 2024-02-04 10:24:14 +01:00
ptitSeb 3fa527b45b [ARM64_DYNAREC] Reworked STRONGMEM 2 & 3 2024-02-03 18:03:26 +01:00
ptitSeb 121d986b11 [DYNAREC] Reworked a bit the Strange SEGSIGV handling 2024-02-03 18:01:13 +01:00
ptitSeb f18f5c9b85 [DYNAREC_TEST] Force enabled x87double when using DYNAREC_TEST to limit false positive 2024-02-03 17:59:18 +01:00
ptitSeb d5808f6be3 [ARM64_DYNAREC] Improved 0F AE opcodes 2024-02-03 17:57:16 +01:00
ptitSeb 2984d30118 [INTERPRETER] Improved 0F AE opcodes 2024-02-03 17:56:45 +01:00
ptitSeb efbb5a2ae5 [ARM64_DYNAREC] DD /6 opcode also perform x87 init 2024-02-03 17:56:04 +01:00
ptitSeb 31aafe23b7 [ARM64_DYNAREC] Use frint extension for DD /1 opcode 2024-02-03 17:35:03 +01:00
ptitSeb 09779e294c [RCFILE] Adjested/Added profiles 2024-02-03 17:00:56 +01:00
Lily 2fe872de3d [X64EMU] Fix for linux clang (#1243) 2024-02-02 21:19:11 +01:00
ptitSeb 153d8d2cf0 Block signals while traicking memory protection 2024-02-02 16:44:50 +01:00
ptitSeb 1b07a10b5d Refactored a bit protection traking to avoid re-entrance 2024-02-02 15:59:12 +01:00
ptitSeb d743c8235f Fixed a warning on non-dynarec build 2024-02-02 10:40:58 +01:00
ptitSeb 7781bfcbac Added 0F 0E opcode support ([ARM64_DYNAREC] too) 2024-02-01 20:09:22 +01:00
rajdakin 0fd81e067f [WRAPPER] Regenerated the wrapper files (#1241) 2024-02-01 19:04:55 +01:00
ptitSeb acc2f2e3d5 [32BITS] Added 67 64 89 opcode ([ARM64_DYNAREC] too) 2024-02-01 18:58:01 +01:00
ptitSeb a2be60cce8 [32BITS] Added 67 64 A1 opcode ([ARM64_DYNAREC] too) 2024-02-01 18:42:37 +01:00
ptitSeb 1344b18379 [DYNAREC] Handling of memfd_create backed mmap on dynarec (help #1234 but doesn't solve it completly) 2024-02-01 16:42:16 +01:00
ptitSeb 1deec05f3d [DYNAREC] Improved trace a bit 2024-02-01 16:42:16 +01:00
Lily 2ee5bcf933 [DOCS] Fix a typo in temrux building (#1240) 2024-02-01 15:46:48 +01:00
ptitSeb 5f57de017c [INTERPRETER] Added CE opcode 2024-01-31 18:38:52 +01:00
josch 508a153973 When BOX64_VERSION is set, just print the version and exit (#1238)
When set, box64 will only print its version and then exit. This option
is analogous to QEMU_VERSION used by binfmt_misc emulation of qemu-user.
Its purpose is the same: provide a way to soft-disable binfmt_misc
emulation as well as for identifying box64 as the registered binfmt_misc
emulator.

This commit enables adding support for box64 to the arch-test utility.
With this change, arch-test is able to soft-disable box64 as the x86_64
emulator in the same way as it does this for qemu and wine already.
Without this change, arch-test will report an architecture as natively
executable by the processor, disregarding that it actually gets emulated
by box64.

Furthermore, this commit enables identifying box64 as the currently
registered emulator for x86_64. This way, applications that know that
their emulation requirements cannot work with box64 can add a check to
find out that it is box64 doing the emulation and are able to print a
helpful error message.

Closes: #1237
2024-01-31 18:29:34 +01:00
ptitSeb 5d8b70cc0d Made PageSize detection / Handling dynamic. nd fixed elfloading for pagesize not 4K. The define are still there but might be removed shortly (for #1231, #1226, #1189, #1175, #999, #384 and probably a few other) 2024-01-31 16:04:49 +01:00
ptitSeb d60ba04cf4 [ANDROID] Fix build 2024-01-31 15:35:33 +01:00
Yang Liu 8b3949497a Added mknod syscall (#1236)
* Added mknod syscall

* Add ifndef

* A comma is needed
2024-01-31 15:29:34 +01:00
ptitSeb 754b69f746 Consider libutil as integral part of glibc 2024-01-31 15:20:45 +01:00
ptitSeb 55c99e9ad7 [LOONGARCH] Fixed potential compilation issue 2024-01-31 12:19:34 +01:00
josch aa2e212480 system/box64.conf.cmake: change rule name to be box64 specific (#1233)
Having an entry named x86_64 in /proc/sys/fs/binfmt_misc/ is not ideal
because:

 - it does not indicate who the binfmt provider is (others start with
   llvm-*, python* or qemu-* to indicate this)
 - it is a namespace grab -- there is no justification for box64 to grab
   the identifier "x86_64" over all other potential binfmt providers
2024-01-31 00:19:29 +01:00
Lily 96c6abc889 [X64LIBS] mbedtls libs (#1232)
* [CMAKE] Prepare for mbedtls libs

* [X64LIBS] mbedtls libs

* [GITIGNORE] Reverting this
2024-01-30 22:06:26 +01:00
ptitSeb 74a73dfc97 Added SOPHGO as hardware donator 2024-01-30 22:03:28 +01:00
ptitSeb d3b5553433 [RV64_DYNAREC] Fixed 0F AF 32bits (for #1210) 2024-01-30 18:59:03 +01:00
ptitSeb b8856af18c [ARM64_DYNAREC] Added UDF printer 2024-01-30 18:57:48 +01:00
ptitSeb 63428d0b2e [ARM64_DYNAREC] Small changes on 32BITS E9 opcode to ensure 32bits jump destination 2024-01-30 14:05:54 +01:00
ptitSeb 22afd245a8 [RCFILE] Added a profile for DaveTheDiver 2024-01-30 14:05:11 +01:00
ptitSeb 26fdf2275a [RV64_DYNAREC] Fixed some isue wiht sse_get_reg helper function tht would incorectly mark a regs as changed single/non-single 2024-01-29 22:50:38 +01:00
ptitSeb 1ad38124df [32BITS] Small improvment to E8/E9 opcode to trucate address to 32bits 2024-01-29 22:46:52 +01:00
ptitSeb aaa4fd1265 [INTERPRETOR] More finetunning to shrd16/shld16 2024-01-29 20:48:04 +01:00
ptitSeb 9793c3b142 [ARM64_DYNAREC] ROL/ROR/RCL/RCR might not update OF if count is not 1 2024-01-29 20:00:25 +01:00
ptitSeb 5a753761dd [ARM64_DYNAREC] Small improvments to SHLD/SHRD helpers 2024-01-29 19:59:46 +01:00
ptitSeb 37be26e539 [INTERPRETER] Small improvements to shr/shl to limit fals-positive on DYNAREC_TEST 2024-01-29 19:58:58 +01:00
ptitSeb 96023f2274 [DYNAREC_TEST] Fixed some potential fals-positive on some CMP opcodes 2024-01-29 16:58:19 +01:00
ptitSeb 30b83f4f9c [ARM64_DYNAREC] Fixed 66 50-5F opcodes (helps Dave the Diver) 2024-01-29 14:46:36 +01:00
ptitSeb 265f969a44 [TRACE] Slightly better trace for some dynarec runtime issues 2024-01-29 14:46:36 +01:00
xctan d5b182cac0 [WRAPPERS] Fixed some typos in rebuild_wrappers.py (#1227) 2024-01-29 13:24:40 +01:00
ptitSeb ce296f0e32 [ARM64_DYNAREC] Added 67 6B opcode 2024-01-29 09:59:18 +01:00
ptitSeb 6d5c3489c9 [ARM64_DYNAREC] Added F0 0F C0 opcode 2024-01-29 09:58:44 +01:00
ptitSeb d48ab49437 Added more slot for X11 Callbacks wrapping 2024-01-29 09:57:46 +01:00
ptitSeb 8ee250e9ac [DYNAREC] Small improvment in dynablock/protectDB handling 2024-01-29 09:57:02 +01:00
ptitSeb e485fe1d18 [ARM64_DYNAREC] Removed old unused code 2024-01-29 09:54:08 +01:00
ptitSeb 35a32481c6 [DYNAREC] Narrow the cases for Strange SIGSEGV to protextion with READ & WIRTE 2024-01-28 13:21:41 +01:00
ptitSeb beaf543012 [RCFIEL] Fixed BOX64_IGNOREINT3 2024-01-28 09:45:20 +01:00
ptitSeb c40e31f374 Fixed SnapDragon builds 2024-01-27 21:16:27 +01:00
ptitSeb f9c09293bf Added BOX64_IGNOREINT3 env. var. to ignore INT3 in the code ([RCFILE] too) 2024-01-27 20:42:32 +01:00
ptitSeb cdffe2388e Rollback vfork changes, it broke SlayTheSpire, and probably other too (for #1221) 2024-01-27 20:13:01 +01:00
ptitSeb 6c0af2dbb9 [ARM64_DYNAREC] Added E4/E5/E6/E7 opcodes 2024-01-27 17:56:48 +01:00
ptitSeb eee428afe5 [ARM64_DYNAREC][32BITS] Added D4/D5 opcodes 2024-01-27 17:49:22 +01:00
ptitSeb 047815c764 [ARM64_DYNAREC][32BITS] Added 37 opcode 2024-01-27 17:45:00 +01:00
ptitSeb 3b8e0d69a3 [ARM64_DYNAREC][32BITS] Added 27 opcode 2024-01-27 17:42:27 +01:00
ptitSeb 56f2749da0 [ARM64_DYNAREC][32BITS] Added 2F opcode 2024-01-27 17:37:39 +01:00
ptitSeb 7d85753350 [RCFILE] Added Celeste.exe profile 2024-01-27 17:37:16 +01:00
ptitSeb 367363a8bd [RCFILE] Fixed Unturned profile 2024-01-27 17:02:41 +01:00
ptitSeb 30d0836329 [RCFILE] Added Unturned profile 2024-01-27 17:00:56 +01:00
ptitSeb 1680dc63d9 [ARM64_DYNAREC] Improved shld16 opcode 2024-01-27 17:00:34 +01:00
ptitSeb 806298843f [ARM64_DYNAREC] Fixed 66 8C opcode and improved many 66 prefix opcode on 32BITS 2024-01-27 17:00:03 +01:00
ptitSeb 7cee4e2453 [TEST_DYNAREC] Improved accuracy of some tests, and avoid a some false-positive 2024-01-27 16:53:57 +01:00
ptitSeb 82f21de83e [ARM64_DYNAREC] Removed unused code 2024-01-27 14:33:32 +01:00
ptitSeb 65c4f9d9c3 [INTERPRETER] Add code for unaligned 32bits F0 87 opcode 2024-01-27 14:31:51 +01:00
ptitSeb 8043f53d7d Track protection even if 0 2024-01-27 13:32:01 +01:00
ptitSeb 124672b811 [ARM64_DYNAREC] Fixed/Improved D9 E5 opcode and add hack for FLD1/FLD1/FPATAN sequence 2024-01-27 13:31:07 +01:00
ptitSeb 28ef6cdefc Improved fxam helper 2024-01-27 13:26:15 +01:00
ptitSeb 5e38ea28b6 [ARM64_DYNAREC] Fixed previous commit 2024-01-26 15:53:18 +01:00
ptitSeb 1d0d7e9e09 Reworked 0F 01 opcode ([ARM64_DYNAREC] too) 2024-01-26 15:39:05 +01:00
ptitSeb aab6bc0869 Added 66 8F opcode ([ARM64_DYNAREC] too) 2024-01-26 14:18:11 +01:00
ptitSeb 77213bee1d [32BITS] Added 16/17 ocodes ([ARM64_DYNAREC] too) 2024-01-26 12:39:53 +01:00
ptitSeb 90fc1d93ad [INTERPRETER] Ignore 36/26 segment prefix for 66 prefixed opcodes 2024-01-26 12:35:53 +01:00
ptitSeb e51f36c651 [32BITS] Added some more opcode to the 32bits part of interpreter, to run more protected binaries 2024-01-26 11:56:50 +01:00
KreitinnSoftware fc63442ded Add 'BOX64_MMAP32' to help info (#1220)
* Add 'BOX64_MMAP32' to help info

* [CI] Update NDK to 25b for Android Builds
2024-01-26 08:20:53 +01:00
leonpano2006 0ee5174e18 add optimize build flag for Jetson orin and xavier (#1219)
* add optmized options for Jetson xavier and orin

* Update CMakeLists.txt

* Update COMPILE.md

add info for build on jetson orin and xavier
2024-01-25 23:04:20 +01:00
ptitSeb 0004f19325 [MMAP32] 31bits address space is in fact 3GB address space (so 31.5 bits?) 2024-01-24 14:58:18 +01:00
ptitSeb da724e3dd5 [MMAP32] Fixed mmap32 behaviour 2024-01-24 14:12:16 +01:00
ptitSeb 96ccf0dab9 [ARM64_DYNAREC] Fixed 67 66 prefixed REX reading 2024-01-24 14:00:47 +01:00
ptitSeb aba3e4a460 Small improvment to MMAP32 managment 2024-01-23 19:41:10 +01:00
ptitSeb bc852aebeb Added a new option BOX64_MMAP32 to use 32bits mapping on external MMAP (help Snapdragon device running Vulkan with Wine/Wow64, active by default on SD845/SD888/SD8G2 profiles) 2024-01-23 15:56:11 +01:00
ptitSeb 89da530898 [DYNAREC] use an rbtree for dynablock size and max_db_size update 2024-01-23 10:01:11 +01:00
Yang Liu 2367e7df50 [DYNAREC_RV64] Enable basic simple wrapper optimization (#1215) 2024-01-23 09:23:49 +01:00
ptitSeb 2ca85a4976 Added 1 syscall 2024-01-22 17:28:37 +01:00
ptitSeb e3860cf09c [TRACE] Slightly improved trace 2024-01-22 17:28:17 +01:00
ptitSeb 07be405f48 Make sure Stack is aligned properly... (should help #1187 and ~1188) 2024-01-22 16:46:45 +01:00
ptitSeb 92d5210e37 [ELFLOADER] Zero'd memory when using mmap and filesize smaller than memsize 2024-01-21 12:22:55 +01:00
ptitSeb 01bf7aa774 Removed a useless test in getProtection utility function 2024-01-21 12:22:47 +01:00
ptitSeb 427ca732fe [TRACE] Improved trace for __libc_start_main init handling 2024-01-21 12:22:08 +01:00
ptitSeb ca92a0b90a Used rb_stree for mapallmem too 2024-01-20 15:28:21 +01:00
ptitSeb db4547115c Added a few wrapped function to libcups 2024-01-20 10:01:09 +01:00
ptitSeb 3ad4a3ae3a Use rbtree for mmapmem tracking 2024-01-19 18:51:31 +01:00
ptitSeb 7bef772488 Fix build on some older compiler 2024-01-19 15:23:00 +01:00
ptitSeb e4c64073c5 Reworked exit, unloading libs and running Fini as it should (plus a workaround for nvidia driver not unloading) 2024-01-19 15:09:20 +01:00
ptitSeb 0ff15e91d9 [RCFILE] Update & Added a few profiles 2024-01-19 15:07:54 +01:00
ptitSeb a584aa7df8 Added 1 more wrapped libc function (for #1208) 2024-01-19 10:18:19 +01:00
ptitSeb 57ca9dfdbc Reworked wrapping of callback in X11 Va args 2024-01-18 22:48:09 +01:00
rajdakin 3a2073f785 Fixes (#1207)
* Fixed signed/unsigned issues and other cosmetics

* [WRAPPERS] Fixed missing `return`s in `my_` functions

* [EMU] More fixes

* [STEAM] Forgot one cleanup

* [WRAPPER] Fixed wrappedpulse callback signatures
2024-01-18 18:57:20 +01:00
ptitSeb e963d99d5e Partial Wrapping of libxkbregistry 2024-01-18 18:53:19 +01:00
ptitSeb bbe188d4f9 Fixed an issue with a failsafe that was not working 2024-01-18 14:23:47 +01:00
ptitSeb 9df1ed0b3b [DYNAREC] Fixed a warning 2024-01-18 14:23:22 +01:00
ptitSeb 742998b477 Added 1 more wrapped function to libc 2024-01-18 12:06:02 +01:00
ptitSeb a577fac1c5 [DYNAREC] Test when changing page on building a dynablock if it's safe 2024-01-18 11:59:39 +01:00
ptitSeb d08abf05ff Added 1 more wrapped function to libgconf2 2024-01-18 11:54:02 +01:00
ptitSeb cd6af18183 [RCFILE] Adjusted steamwebhelper profile for better stability 2024-01-17 17:44:42 +01:00
ptitSeb a425275108 Some more fixes to new memory protection tracking (should help #1202 and #1200) 2024-01-17 15:45:10 +01:00
ptitSeb 92f7b6fd9e Wrapped libpulse-mainloop-glib (for #1203, untested) 2024-01-16 18:22:52 +01:00
ptitSeb 68c7586c4c [INTERPRETER] Fixed D7 opcode 2024-01-16 17:56:43 +01:00
ptitSeb 9549a3599c [ARM64_DYNAREC] Fixed some special case for shrd/shld opcodes 2024-01-16 17:42:39 +01:00
ptitSeb b826049893 Added 1 more syscall 2024-01-16 17:34:22 +01:00
ptitSeb 88d950bafb [RCFILE] Added and Adjusted a few more profile 2024-01-16 10:21:21 +01:00
ptitSeb 50242c6eaa Ficxed an issue with rbtree rb_get_end utility function 2024-01-16 10:20:55 +01:00
ptitSeb e5649d90e7 Round size to pagesize on the tracked memory 2024-01-16 10:20:16 +01:00
ptitSeb d22e6f28a1 Used AddCheckBridge were the check could make sense 2024-01-16 10:19:44 +01:00
ptitSeb 307acee9d3 [INTERPRETER] Fixed VM Detection (TF trick) for interpreter 2024-01-15 17:48:54 +01:00
ptitSeb 184b2cc26b Small fix for a faked wrapped function 2024-01-15 17:20:13 +01:00
ptitSeb 613781e6c0 Fixed xcb_connect wrapping 2024-01-15 17:11:28 +01:00
ptitSeb 92c3c1f829 Added 1 more wrapped function to libgmp 2024-01-15 13:50:29 +01:00
ptitSeb 6268367b22 [ELFLOADER] Fixed some issue with COPY/GLOB_DATA symbol relocations 2024-01-15 12:50:27 +01:00
xctan 4c174a42f8 [RV64_DYNAREC] Fixed 66 87 XCHG opcode (#1198) 2024-01-13 17:25:53 +01:00
rajdakin 71463476f6 [RBTREE] Reverted memory tracking to 32 bits (#1201) 2024-01-13 08:45:52 +01:00
ptitSeb 20b388c1d2 [ARM64_DYNAREC] Re-enable Atomics, seems stable now 2024-01-12 18:43:14 +01:00
ptitSeb 3ab7648384 [TRACE] Better trace for wrapped dladdr1 calls 2024-01-12 18:42:47 +01:00
ptitSeb 9fb84e3ef2 Removed a debug leftover 2024-01-12 18:42:20 +01:00
ptitSeb d6bfce9a5d [VULKAN] Added some more extensions (for #424) 2024-01-12 11:28:10 +01:00
xctan 328d5c6275 [RV64_DYNAREC] Fixed 66 0F B6 MOVZX opcode (#1196) 2024-01-11 17:12:39 +01:00
ptitSeb 19be6b5e17 Added 1 more wrapped function to libcups 2024-01-10 19:54:11 +01:00
ptitSeb 499f9633ba [VULKAN] Wrapped VK_EXT_device_fault extension (for #424) 2024-01-10 16:41:06 +01:00
ptitSeb 774ca6cd80 [VULKAN] Wrapped VK_KHR_map_memory2 extension (for #424) 2024-01-10 15:29:43 +01:00
ptitSeb 22b5cf3536 [VULKAN] Wrapped VK_EXT_host_image_copy extension (for #424) 2024-01-10 14:51:33 +01:00
ptitSeb 18fa8af728 [VULKAN] Completed wrapping of VK_NV_scissor_exclusive extension (for #424) 2024-01-10 13:26:53 +01:00
ptitSeb 0f01bdad13 [VULKAN] Completed wrapping of VK_EXT_discard_rectangles extension (for #424) 2024-01-10 12:18:45 +01:00
Yang Liu d787f67ab8 [DYNAREC_RV64] Added more opcodes and fixed X87_PUSH/POP macros (#1194)
* [DYNAREC_RV64] Added DB F0..F7 FCOMI opcodes

* [DYNAREC_RV64] Added more DA opcodes

* Try to fix X87_PUSH_OR_FAIL

* [DYNAREC_RV64] Added D7 XLAT opcode

* Fix X87_PUSH_OR_FAIL for aarch64 too
2024-01-09 15:26:54 +01:00
Yang Liu 16de80f46a [DYNAREC_RV64] Fixed a wrong Zba optimization (#1193) 2024-01-09 08:20:55 +01:00
ptitSeb 294bc51f83 [ELFLOADER] More elf alignment sections adjustments 2024-01-08 19:20:31 +01:00
ptitSeb 70987fc55f [ELFLOADER] Another attempt at elf allignement fixes 2024-01-08 18:58:52 +01:00
ptitSeb 5b700cb6e6 [ELFLOADER] Try to harden the memory allocation 2024-01-08 17:52:49 +01:00
ptitSeb dcb31fa783 [ARM64_DYNAREC] Fixed 66 0F 3A 17 opcode (should help UE games) 2024-01-08 16:16:24 +01:00
Frank Benkstein 411a52e16f expose minimal libxcb-xinput wrapper (#1192)
Expose minimal libxcb-xinput interface, enough to run the Enpass
password manager. Also expose XkbGetIndicatorState since that is also
required.
2024-01-08 00:05:15 +01:00
ptitSeb 41bfd757ad Added libutil and libresolv to the list of essential libs (not affected by BOX64_PREFER_EMULATED) 2024-01-07 15:25:37 +01:00
ptitSeb d94c6f2132 Added 2 more wrapped function to libgtk3 (for epsxe) 2024-01-07 11:07:32 +01:00
ptitSeb 29052c7a90 Added (much) more slot for genereic GCallback on gobject2 2024-01-07 11:00:47 +01:00
ptitSeb 48de41137d Added ncurses6 as alias to ncurses5 as it's deprecated on modern OS 2024-01-07 11:00:08 +01:00
ptitSeb 203d06831e Added profile for Unigine Heaven Linux version 2024-01-06 17:23:47 +01:00
ptitSeb 3e9c435ed1 Added alias for wrapped libresolv.so 2024-01-06 17:23:13 +01:00
ptitSeb e65fda875a Added 1 more wrapped function to libcups 2024-01-06 17:22:53 +01:00
ptitSeb 70c745dd84 Added 1 syscall 2024-01-06 10:58:28 +01:00
ptitSeb 870b71afec [INTERPRETER] Added 67 66 8D opcode ([ARM64_DYNAREC] too) 2024-01-06 10:58:02 +01:00
ptitSeb 18e0af6b38 [INTERPRETER] Added support for unaligned F0 0F BA /5 opcode 2024-01-06 10:56:59 +01:00
ptitSeb ed87cc1b1e [INTERPRETER] Improved 0F 01 opcode ([ARM64_DYNAREC] too) 2024-01-06 10:56:03 +01:00
ptitSeb 5d6ff69e8d [RCFILE] Added more option to rcfile and added geekbench5 profile 2024-01-06 10:48:18 +01:00
ptitSeb cbea2b5443 Rollback commit 9201559 as it breaks some programs using getopts (should help #1190) 2024-01-06 10:30:31 +01:00
ptitSeb a891e1f85d Added wrapped libicuuc and libicui18n v74 2024-01-05 17:05:21 +01:00
Yang Liu ade0aa770a [DYNAREC_RV64] Added CALL/RET optimization (#1183)
* [DYNAREC_RV64] Added CALL/RET optimization

* More hacks on the call/ret optimization

* Small fixes, but still not working

* More fixes

* More fixes
2024-01-05 16:55:25 +01:00
ptitSeb a5f2f3b3f1 [ARM64_DYNAREC] A few more FRINTTS extension use 2024-01-05 14:58:45 +01:00
ptitSeb 077ba65f7e [ARM64_DYNAREC] More FRINTTS use 2024-01-05 14:22:13 +01:00
ptitSeb 6f6a426424 [ARM64_DYNAREC] Attempt to use FRINTTS extension 2024-01-05 13:55:17 +01:00
ptitSeb 163158cf12 [ARM64_DYNAREC] Simplified a bit CALLRET fallback handling on stack unsync 2024-01-05 12:15:03 +01:00
rajdakin e4821aa9e1 [WRAPPERS] Add a isSimpleWrapper function for RV64 (#1185)
* [WRAPPERS] Added an isSimpleWrapper function for RV64

* [WRAPPERS] Version bump
2024-01-05 08:22:56 +01:00
ptitSeb 9b23c3272b Added 1 more symbol to wrapped libgnutls 2024-01-04 18:58:26 +01:00
ptitSeb 3454afb3e4 [RCFILE] Add profile for Broforce and change 3dSen to limit cmax core to 4, it actualy speedup emulation if many cares are present 2024-01-04 11:04:43 +01:00
ptitSeb ab99ae6951 [ARM64_DYNAREC] Fixed CALLRET optim when unsync occur, should help stability 2024-01-04 11:03:46 +01:00
ptitSeb a609452cfd [DYNAREC] Switched back CALLRET to 0 by Default, many things like GoG Wine Installer needs that 2024-01-02 18:50:48 +01:00
ptitSeb ee1256a676 [RCFILE] Add a function to quickly get current process name 2024-01-02 18:38:38 +01:00
ptitSeb a9837a3aaf [TRACE] Better trace for read wrapped function 2024-01-02 18:38:02 +01:00
Tristan Morgan 499492e10a Remove FASTPAGE/HOTPAGE docs, related to #1180 (#1181) 2024-01-02 08:09:04 +01:00
ptitSeb 6e77ce999a [ARM64] Improved fast path for unaligned access to device memory (for NVidia cards) 2024-01-01 00:00:08 +01:00
ptitSeb dd05eeb821 Fixed issue on rbtree on rb_get_end when end is another block 2023-12-31 19:19:29 +01:00
ptitSeb 919f8faeee More xcb_connection_t wrapping for vulkan 2023-12-31 18:46:27 +01:00
ptitSeb b0db8e1ae0 [ARM64_DYNAREC] Some more warning fixes 2023-12-31 16:02:26 +01:00
ptitSeb 3e0f2bfc4a Fixed some (nasty sometimes) warning 2023-12-31 15:54:45 +01:00
rajdakin 5e9e1faedc [MEMORY] Switched from a sparse array to a red-black tree (#1180)
* [MEMORY] Switched from a sparse array to an RB tree

* [RBTREE] Fixed the Android build
2023-12-31 15:49:57 +01:00
Yang Liu dba6a88341 [DYNAREC_RV64] Fixed a nasty bug in GETEX, but left optim opportunity for later (#1178) 2023-12-28 13:31:15 +01:00
Yang Liu ee0b86c0c2 [WRAPPER] Added 4 more wrapped glib2 functions (for #1175) (#1176) 2023-12-28 13:26:17 +01:00
Creeper-xie 7ea2e1bf51 [CMakelist] Remove a "#" (#1173)
It seems be added by mistake.
2023-12-27 20:47:04 +01:00
Yang Liu c801f2d4a5 [RCFILE] Disable CALL/RET optimization for zoom (#1170) (#1174)
* [WRAPPER] Added 1 more wrapped libc functions

* [RCFILE] Disable CALL/RET optimization for zoom (#1170)

* Do not delete BOX64_DYNAREC_CALLRET=1 in case we make it not default again
2023-12-27 20:07:42 +01:00
ptitSeb ae84f02bd0 Added 2 more wrapped gtk3 functions 2023-12-26 16:23:11 +01:00
ptitSeb a6c73e2840 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-26 15:18:50 +01:00
ptitSeb e6bc1d7c22 More work on xcb wrapping, as xcb_connection_t needs alignment 2023-12-26 15:18:41 +01:00
xctan e2abb6b6db [DYNAREC_RV64] Added more opcodes for VMP-protected GI (#1168)
* [DYNAREC_RV64] Added 66 0F B3 BTR opcode

* [DYNAREC_RV64] Added 66 0F BA /7 BTC opcode

* [DYNAREC_RV64] Added 66 {D1,D3} /{2,3} RCL/RCR opcodes

* [DYNAREC_RV64] Added 66 0F BA /{5,6} BTS/BTR opcodes

* [DYNAREC_RV64] Added 0F C1 XADD opcode

* [DYNAREC_RV64] Added 0F C0 XADD opcode

* [DYNAREC_RV64] Added D3 /2 RCL opcode

* [DYNAREC_RV64] Removed redundant declaration of wb2 in 0F

* [DYNAREC_RV64] Enable 66 0F BD BSR again

* [DYNAREC_RV64] Added 66 1D SBB opcode
2023-12-26 12:55:25 +01:00
xctan cb63cdcd42 [DYNAREC_RV64] Added more opcodes for VMP-protected GI (#1164)
* [DYNAREC_RV64] Added 66 0F C8-CF BSWAP opcode

* [DYNAREC_RV64] Added 66 0F BB BTC opcode

* [DYNAREC_RV64] Added D2 /3 RCR opcode

* [DYNAREC_RV64] Added 66 0F BA /4 BT opcode

* [DYNAREC_RV64] Added 66 D3 /1 ROR opcode

* [DYNAREC_RV64] Added D2 /2 RCL opcode

* [DYNAREC_RV64] Added 66 D3 /0 ROL opcode

* [DYNAREC_RV64] Added 66 0F BC BSF opcode

* [DYNAREC_RV64] Added 66 0F A4 SHLD opcode

* [DYNAREC_RV64] Added 66 0F AB BTS opcode

* [DYNAREC_RV64] Added 36 SS prefix

* [DYNAREC_RV64] Added D3 /3 RCR opcode

* [DYNAREC_RV64] Added C1 /3 RCR opcode

* [DYNAREC_RV64] Added 66 0F AC SHRD opcode

* [DYNAREC_RV64] Fixed emit_shrd16c, emit_shld16c declaration

* [DYNAREC_RV64] Added C1 /2 RCL opcode

* [DYNAREC_RV64] Added 66 0F BD BSR opcode

* [DYNAREC_RV64] Added 66 0F A3 BT opcode

* [DYNAREC_RV64] Added 66 0F C1 XADD opcode

* [DYNAREC_RV64] Added 0F A5 SHLD opcode

* [DYNAREC_RV64] Added C0 /2 RCL opcode

* [DYNAREC_RV64] Added C0 /3 RCR opcode

* [DYNAREC_RV64] Added 66 99 CWD opcode

* [DYNAREC_RV64] Fixed 66 99 CWD opcode

* [DYNAREC_RV64] Revert 66 0F BD BSR opcode

VMP anti-debugger message will break with this opcode
2023-12-25 21:54:42 +01:00
Yang Liu 1f28b9f98d [INTERP] Added 64 66 39 CMP opcode (#1166) 2023-12-25 16:32:03 +01:00
ptitSeb 7fcc0ba8a4 New attempts at mmap fixing 2023-12-25 10:01:04 +01:00
ptitSeb 6773ac88af Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-25 09:09:34 +01:00
ptitSeb 46bee1d532 Small change with not 48bits memory space for mmap64 (might help #1163) 2023-12-25 09:09:28 +01:00
Yang Liu 10062373d1 [DYNAREC_RV64] Added more opcodes for ets2 (#1162)
* [DYNAREC_RV64] Added F2 0F 7C HADDPS opcode

* [DYNAREC_RV64] Added 0F 38 C8..CD opcodes

* [DYNAREC_RV64] Added DF C0..C7 FFREEP opcodes
2023-12-24 18:03:41 +01:00
ptitSeb 68e3c2be9b Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-24 17:16:37 +01:00
ptitSeb 099df7a0ee Reviewed signatures of libxcb and libdbus libs 2023-12-24 17:16:27 +01:00
xctan 21b6537215 [DYNAREC_RV64] Ported INT 3/29 from arm (#1161) 2023-12-24 15:50:29 +01:00
ptitSeb eb70f6d18e Added more wrapped signature to libnuma and libxcb (should help #531) 2023-12-24 14:00:13 +01:00
xctan 4ee6ae5da1 [DYNAREC_RV64] Fixed shift masks for GI (#1160)
* [DYNAREC_RV64] Fixed SHLD for GI

* [DYNAREC_RV64] Fixed SHRD for GI

* [DYNAREC_RV64] Fixed shamt mask of 16-bit shifts
2023-12-24 13:50:51 +01:00
ptitSeb 2c8d2d8643 Merge branch 'main' of https://github.com/ptitSeb/box64 2023-12-23 18:36:59 +01:00
ptitSeb 0582b45389 Apply parameters when binary is behind a symlink 2023-12-23 18:36:52 +01:00
ptitSeb f7cbe71bd9 [RCFILE] Refiled GridAutosport profile again 2023-12-23 12:53:43 +01:00
ptitSeb 1b87600658 [INTERPRETER] Added 64/65 86 opcode (for #1156) 2023-12-23 12:18:08 +01:00
Yang Liu 446fb9c99f [DYNAREC_RV64] Added more opcodes for ets2 (#1158)
* [DYNAREC_RV64] Added F3 0F 52 RSQRTSS opcode

* [DYNAREC_RV64] Added F0 81 /6 LOCK XOR opcode (aligned only)

* [DYNAREC_RV64] Added F3 0F 16 MOVSHDUP opcode

* Format
2023-12-23 10:26:34 +01:00
ptitSeb c774cb0c27 [RCFILE] Made so that BOX64_MAXCPU is the minimum value if set both on command line and a/many profile 2023-12-23 09:34:11 +01:00
ptitSeb 8ff9427a04 Small imrpovment to wrapped libc and mmap 2023-12-23 09:33:03 +01:00
ptitSeb b427e67619 Addedempty wrapped libidn2 (for quake 2 rtx) 2023-12-23 09:32:26 +01:00
xctan 6163f98020 Cleanup some code (#1157)
* Fix the size of random bytes in the auxiliary vector (AT_RANDOM) to 16 bytes

* [ELFLOADER] Remove an unused statement
2023-12-23 09:02:38 +01:00
Yang Liu 316b2fc98a [DYNAREC_RV64] Fixed some bugs in the dynarec for ETS2 (#1155)
* [DYNAREC_RV64] Fixed BSWAP

* [DYNAREC_RV64] Fixed 0F C2 CMPPS opcode
2023-12-22 20:27:10 +01:00
Yang Liu 9c73204224 [DYNAREC_RV64] Added more opcodes and fixes (#1154)
* [DYNAREC_RV64] Added 66 0F 38 28 PMULDQ opcode

* [DYNAREC_RV64] Added DD /6 FSAVE opcode

* [DYNAREC_RV64] Added 66 8C MOV opcode

* [DYNAREC_RV64] Fixed DF /1 /2 opcodes

* [DYNAREC_RV64] Added DB /1 FISTTP opcode
2023-12-22 16:51:33 +01:00
ptitSeb 7da59d5a39 [ARM64_DYNAREC] Added 64/65 23 opcode 2023-12-22 14:13:14 +01:00
ptitSeb a34b63b80d [ARM64_DYNAREC] Partial rollback of previous commit, it was not good 2023-12-22 12:38:01 +01:00
ptitSeb 5b335f0f26 [ARM64_DYNAREC] Small optim on CF flag computation for 8/16bits add/sub operations 2023-12-22 10:50:08 +01:00
ptitSeb 28af18f36e [RCFILE] Limit number of cores to 16 for Hue 2023-12-22 09:59:43 +01:00
liuli 10bb9f7079 [WRAPPER] add dbus_message_iter_get_element_count auto wrapper (#1153) 2023-12-22 09:10:23 +01:00
ptitSeb ed7006bbf4 [RCFILE] Refixed GridAutosport profile 2023-12-21 17:55:53 +01:00
ptitSeb b272f6bf15 Added/Fix some 16bits PUSH POP opcode ([ARM64_DYNAREC] too) (for DaveTheDiver, but not enough for it to run yet) 2023-12-21 16:05:54 +01:00
ptitSeb 715ce5dbe9 Introduce new BOX64_MAXCPU to cap the number of cpu core exposed, and created profile for wine, wine64 and GridAutosport using it 2023-12-21 15:51:55 +01:00
ptitSeb 7d0f807880 Allocated more cleanup when needed to avoid frequent resize 2023-12-21 15:48:42 +01:00
ptitSeb b66eccedc0 Added more wrapped function to libnss3, libnssutils3 and libnspr4 (for GridAutosport) 2023-12-21 14:38:56 +01:00
ptitSeb f79e725aa3 Removed a bridge field from librarian, it's not used anymore 2023-12-21 10:19:08 +01:00
Lily 66c4b6815f [RCFILE] Added FL64 Profile (#1149) 2023-12-20 20:16:07 +01:00
ptitSeb f073da1d27 This should fix x86_64 build 2023-12-20 18:21:07 +01:00
ptitSeb dad0d648a1 Expose max of 64 cpus core when Wine is launched (avoid buch of warning, and help Crysis Remastered) 2023-12-20 17:52:03 +01:00
ptitSeb f20262c5c8 [CMAKE] Asked minimum cmake version to be 3.13 2023-12-20 17:50:40 +01:00
ptitSeb 23b6617a3f Added 1 more syscall 2023-12-20 17:50:04 +01:00
ptitSeb ab5c02c2ae Removed old commented code 2023-12-20 17:49:47 +01:00
ptitSeb 1005cee4bc Small improvment on memory tracking 2023-12-20 17:49:29 +01:00
ptitSeb 95a1b12c07 Added syscall 316 2023-12-20 15:07:57 +01:00
ptitSeb 23542bbfee [INTERPRETER] Added 64/65 0F BA opcode (for #1146) 2023-12-18 15:56:38 +01:00
ptitSeb ec65c26b3c Merge remote-tracking branch 'refs/remotes/origin/main' 2023-12-18 14:16:04 +01:00
ptitSeb 837cc9dd93 [DYNAREC] This should avoid useless segfault on bridge creation 2023-12-18 14:15:10 +01:00
ptitSeb 88a8d1c209 [ARM64] Improved handling of unaligned access to device memory (for NVidia drivers, fixes No Man Sky) 2023-12-18 14:14:17 +01:00
Yang Liu f4b780b806 [DYNAREC_RV64] Added FILD/FISTP i64 optimization (#1145) 2023-12-18 11:38:42 +01:00
ptitSeb 3a296d237f [TRACE] Improve function name retreival in LOG=2 traces 2023-12-18 09:20:51 +01:00
ptitSeb db64c02bee [RCFILE] Fixed file leak 2023-12-18 09:20:01 +01:00
ptitSeb 97023ce1dd [VUKAN] Added 1 more extension 2023-12-18 09:19:41 +01:00
ptitSeb 3a87a2665d [RCFILE] Added Crysis Remastered profile 2023-12-18 09:18:17 +01:00
ptitSeb 6a2f4fb30d [STEAM] Improved pressure-vessel emulation 2023-12-18 09:17:41 +01:00
Yang Liu 49b9b70c29 [DYNAREC_RV64] Fixed some bugs in x87 infra (#1143) 2023-12-18 09:15:04 +01:00
ptitSeb 356340ad09 [ARM64] Added a new case of device memory unaligned write 2023-12-18 09:12:32 +01:00
ptitSeb 986bff1c22 Start of a new dev. cycle 2023-12-18 09:10:18 +01:00
1287 changed files with 101904 additions and 14587 deletions

No files matched your search

+3
View File
@@ -11,4 +11,7 @@ SortIncludes: false
MaxEmptyLinesToKeep: 2
IndentCaseLabels: true
AlignConsecutiveMacros: true
WhitespaceSensitiveMacros: ['QUOTE']
IfMacros: ['IFX', 'IFX2', 'IFXA', 'IFX_PENDOR0', 'IFXX', 'IFX2X', 'IFXN', 'UFLAG_IF', 'PASS2IF']
UseTab: Never
---
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: "Checkout Box64 Repository"
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: "Environment preparation"
run: |
@@ -90,7 +90,7 @@ jobs:
make -j$(nproc) VERBOSE=1
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: box64-${{ github.event.inputs.platform }}-${{ github.event.inputs.build_type }}
path: build/box64
+66 -23
View File
@@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [X64, OTHER_ARM, RISCV, RPI4ARM64, RPI5ARM64, RK3326, RK3399, RK3588, PHYTIUM, SD845, SD888, ADLINK, ARM64, ANDROID]
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:
@@ -41,23 +41,41 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box64 Repository"
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'OTHER_ARM' && ${{ matrix.platform }} != 'RISCV' ]]; then
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 }} == 'ANDROID' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX64_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV
echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DNOLOADADDR=1" >> $GITHUB_ENV
if [[ ${{ matrix.platform }} == 'ANDROID' || ${{ matrix.platform }} == 'TERMUX' ]]; then
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
echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV
git clone https://github.com/termux/termux-docker.git
sudo cp -rf termux-docker/system/arm /system
sudo chown -R $(whoami):$(whoami) /system
sudo chmod 755 -R /system
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
sudo cp -rf data /
sudo chmod 755 -R /data
sudo chown -R $(whoami):$(whoami) /data
echo "CFLAGS=-L/data/data/com.termux/files/usr/lib" >> $GITHUB_ENV
echo "IS_TERMUX=1" >> $GITHUB_ENV
echo "QEMU_SET_ENV=LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib" >> $GITHUB_ENV
else
echo "IS_TERMUX=0" >> $GITHUB_ENV
fi
else
if [[ ${{ matrix.platform }} == 'X64' ]]; then
echo "BOX64_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
@@ -67,6 +85,21 @@ jobs:
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
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 -
sudo ln -sf /usr/local/larch/target /usr/loongarch64-linux-gnu
sudo cp -r /usr/local/larch/loongarch64-unknown-linux-gnu/lib/* /usr/loongarch64-linux-gnu/lib64/
for i in objdump objcopy strip; do
sudo ln -sf /usr/local/larch/bin/loongarch64-unknown-linux-gnu-$i /usr/bin/loongarch64-linux-gnu-$i
done
echo '/usr/local/larch/bin/loongarch64-unknown-linux-gnu-gcc -L/usr/local/larch/loongarch64-unknown-linux-gnu "$@"' | sudo tee /usr/bin/loongarch64-linux-gnu-gcc
echo '/usr/local/larch/bin/loongarch64-unknown-linux-gnu-g++ -L/usr/local/larch/loongarch64-unknown-linux-gnu "$@"' | sudo tee /usr/bin/loongarch64-linux-gnu-g++
sudo chmod 755 /usr/bin/loongarch64-linux-gnu-{gcc,g++}
echo BOX64_PLATFORM_MARCRO="-DLARCH64=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=loongarch64-linux-gnu-gcc" >> $GITHUB_ENV
sudo apt-get -y install git cmake make python3
else
echo BOX64_PLATFORM_MARCRO="-DARM_DYNAREC=ON" >> $GITHUB_ENV
echo "BOX64_COMPILER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
@@ -93,6 +126,7 @@ jobs:
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX64_COMPILER }}\
-DTERMUX=${{ env.IS_TERMUX }}\
${{ env.BOX64_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX64_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX64_HAVE_TRACE }}\
@@ -103,30 +137,39 @@ jobs:
- name: "Test Box64"
if: ${{ matrix.platform != 'TEGRAX1' }}
run: |
if [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then
mkdir qemu8.1.0
wget -O- -q https://archive.archlinux.org/packages/q/qemu-user-static/qemu-user-static-8.1.0-2-x86_64.pkg.tar.zst | tar -I zstd -C qemu8.1.0 -xf -
sudo cp qemu8.1.0/usr/bin/* /usr/bin/
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/
fi
cd build
if [[ ${{ matrix.platform }} == 'RISCV' ]]; then
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,zba=true,zbb=true,zbc=true,zbs=true ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-riscv64-static QEMU_LD_PREFIX=/usr/riscv64-linux-gnu/ QEMU_CPU=rv64,xtheadba=true,xtheadba=true,xtheadbb=true,xtheadbs=true,xtheadcondmov=true,xtheadmemidx=true,xtheadmempair=true,xtheadfmemidx=true,xtheadmac=true,xtheadfmv=true ctest -j$(nproc) --rerun-failed --output-on-failure
elif [[ ${{ matrix.platform }} != 'X64' && ${{ matrix.platform }} != 'ANDROID' ]]; then # AArch64
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
INTERPRETER=qemu-aarch64-static QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/ ctest -j$(nproc) --rerun-failed --output-on-failure
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
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
elif [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
true
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
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
else
BOX64_DYNAREC=0 ctest -j$(nproc) --rerun-failed --output-on-failure
ctest -j$(nproc) --rerun-failed --output-on-failure
ctest -j$(nproc) --output-on-failure
fi
- name: "Upload Artifact"
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: box64-${{ matrix.platform }}-${{ matrix.type }}
path: build/box64
+347 -58
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.4)
cmake_minimum_required(VERSION 3.13)
cmake_policy(SET CMP0065 NEW)
@@ -8,12 +8,13 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RPI5ARM64 "Set to ON if targeting an RaspberryPi5 device with multiarch arm64 and armhf" ${RPI5ARM64})
option(RPI5ARM64PS16K "Set to ON if targeting an RaspberryPi5 device with multiarch arm64, armhf, and 16k pages" ${RPI5ARM64PS16K})
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(RK3588 "Set to ON if targeting an Rockchip RK3588(S) based device" ${RK3588})
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 based device" ${TEGRAX1})
option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_T194})
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
@@ -46,32 +47,28 @@ if(LARCH64)
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
set(LARCH64_DYNAREC ON CACHE BOOL "")
endif()
if(RV64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC ON CACHE BOOL "")
set(PAGE16K OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(PPC64LE)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC OFF CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
set(PAGE16K OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(RPI5ARM64PS16K)
set(RPI5ARM64 ON CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR M1 OR ARM64 OR ADLINK)
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)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
set(RV64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR RK3588 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RK3326 OR TEGRAX1 OR PHYTIUM OR SD845 OR SD888 OR SD8G2 OR LX2160A OR ADLINK)
set(PAGE16K OFF CACHE BOOL "")
set(LARCH64_DYNAREC OFF CACHE BOOL "")
endif()
if(RK3399 OR ODROIDN2 OR RPI3ARM64 OR RPI4ARM64 OR RPI5ARM64)
set(SAVE_MEM ON CACHE BOOL "")
@@ -79,13 +76,9 @@ endif()
if(RK3588)
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
if(M1 OR LARCH64 OR RPI5ARM64PS16K)
set(PAGE16K ON CACHE BOOL "")
endif()
if(SW64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(PAGE8K ON CACHE BOOL "")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
@@ -96,9 +89,7 @@ option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" $
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation" ${ARM_DYNAREC})
option(RV64_DYNAREC "Set to ON to use RISC-V Dynamic Recompilation" ${RV64_DYNAREC})
option(PAGE8K "Set to ON if host device have PageSize of 8K (instead of 4K)" ${PAGE8K})
option(PAGE16K "Set to ON if host device have PageSize of 16K (instead of 4K)" ${PAGE16K})
option(PAGE64K "Set to ON if host device have PageSize of 64K (instead of 4K)" ${PAGE64K})
option(LARCH64_DYNAREC "Set to ON to use LOONGARCH64 Dynamic Recompilation" ${LARCH64_DYNAREC})
option(STATICBUILD "Set to ON to have a static build (Warning, not working)" ${STATICBUILD})
option(NO_LIB_INSTALL "Set ON to not install a few x86_64 libs that are used by many program" ${NO_LIB_INSTALL})
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
@@ -166,6 +157,14 @@ elseif(TEGRAX1)
add_definitions(-DTEGRAX1)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a57+crypto")
elseif(TEGRA_T194)
add_definitions(-DTEGRA_T194)
add_definitions(-pipe -march=armv8.2-a+fp16+simd+crypto+predres -mcpu=cortex-a76+crypto -mtune=cortex-a76)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+fp16+simd+crypto+predres -mcpu=cortex-a76+crypto -mtune=cortex-a76")
elseif(TEGRA_T234)
add_definitions(-DTEGRA_T234)
add_definitions(-pipe -march=armv8.2-a+fp16+simd+crypto+predres -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.2-a+fp16+simd+crypto+predres -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae")
elseif(PHYTIUM)
add_definitions(-DPHYTIUM)
add_definitions(-pipe -march=armv8.1-a+crc+simd+crypto)
@@ -191,7 +190,7 @@ elseif(M1)
add_definitions(-pipe -march=armv8.5-a+simd+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.5-a+simd+crypto")
elseif(LARCH64)
add_definitions(-DLA464)
add_definitions(-DLA64)
add_definitions(-pipe -march=loongarch64)
set(CMAKE_ASM_FLAGS "-pipe -march=loongarch64")
elseif(RV64)
@@ -210,9 +209,7 @@ elseif(ARM64)
#add_definitions(-pipe -march=native)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+simd")
elseif(ARM_DYNAREC)
if(NOT ANDROID)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto")
endif()
if(ANDROID)
add_definitions(-DANDROID)
@@ -226,16 +223,13 @@ endif()
if(SAVE_MEM)
add_definitions(-DSAVE_MEM)
endif()
if(PAGE8K)
add_definitions(-DPAGE8K)
endif()
if(PAGE16K)
add_definitions(-DPAGE16K)
endif()
if(PAGE64K)
add_definitions(-DPAGE64K)
if(STATICBUILD)
#-fno-pic -mcmodel=large
add_definitions(-DSTATICBUILD)
add_definitions(-Wno-deprecated-declarations) #by-design, deprecated function can be used
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(HAVE_TRACE OFF)
endif()
if(NOGIT)
@@ -275,6 +269,12 @@ elseif(RV64_DYNAREC)
enable_language(ASM)
include_directories("${BOX64_ROOT}/src/dynarec/rv64")
set(DYNAREC ON)
elseif(LARCH64_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DLA64)
enable_language(ASM)
include_directories("${BOX64_ROOT}/src/dynarec/la64")
set(DYNAREC ON)
else()
set(DYNAREC OFF)
endif()
@@ -307,15 +307,17 @@ set_source_files_properties(
set(ELFLOADER_SRC
"${BOX64_ROOT}/src/main.c"
"${BOX64_ROOT}/src/core.c"
"${BOX64_ROOT}/src/box64context.c"
"${BOX64_ROOT}/src/build_info.c"
"${BOX64_ROOT}/src/custommem.c"
"${BOX64_ROOT}/src/mallochook.c"
"${BOX64_ROOT}/src/steam.c"
"${BOX64_ROOT}/src/custommmap.c"
"${BOX64_ROOT}/src/dynarec/dynarec.c"
"${BOX64_ROOT}/src/elfs/elfloader.c"
"${BOX64_ROOT}/src/elfs/elfparser.c"
"${BOX64_ROOT}/src/elfs/elfhash.c"
"${BOX64_ROOT}/src/elfs/elfload_dump.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
"${BOX64_ROOT}/src/emu/x64compstrings.c"
"${BOX64_ROOT}/src/emu/x64emu.c"
"${BOX64_ROOT}/src/emu/x64int3.c"
@@ -330,12 +332,9 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/librarian/librarian.c"
"${BOX64_ROOT}/src/librarian/library.c"
"${BOX64_ROOT}/src/librarian/dictionnary.c"
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
"${BOX64_ROOT}/src/librarian/symbols.c"
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
"${BOX64_ROOT}/src/libtools/signals.c"
"${BOX64_ROOT}/src/libtools/threads.c"
"${BOX64_ROOT}/src/tools/bitutils.c"
@@ -343,17 +342,26 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/tools/bridge.c"
"${BOX64_ROOT}/src/tools/callback.c"
"${BOX64_ROOT}/src/tools/my_cpuid.c"
"${BOX64_ROOT}/src/tools/gtkclass.c"
"${BOX64_ROOT}/src/tools/pathcoll.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/wine_tools.c"
"${BOX64_ROOT}/src/wrapped/generated/wrapper.c"
)
if(NOT STATICBUILD)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/mallochook.c"
"${BOX64_ROOT}/src/steam.c"
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
"${BOX64_ROOT}/src/libtools/sdl2rwops.c"
"${BOX64_ROOT}/src/tools/gtkclass.c"
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
)
endif()
if(NOT ANDROID)
list(APPEND ELFLOADER_SRC
"${BOX64_ROOT}/src/libtools/obstack.c"
"${BOX64_ROOT}/src/elfs/elfdwarf_private.c"
)
endif()
@@ -370,6 +378,7 @@ set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run66f0.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64run67avx.c"
"${BOX64_ROOT}/src/emu/x64run67_32.c"
"${BOX64_ROOT}/src/emu/x64run6764_32.c"
"${BOX64_ROOT}/src/emu/x64run670f.c"
@@ -386,8 +395,34 @@ set(INTERPRETER
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
"${BOX64_ROOT}/src/emu/x64runf30f.c"
"${BOX64_ROOT}/src/emu/x64runavx.c"
"${BOX64_ROOT}/src/emu/x64runavx0f.c"
"${BOX64_ROOT}/src/emu/x64runavx0f38.c"
"${BOX64_ROOT}/src/emu/x64runavx660f.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f.c"
"${BOX64_ROOT}/src/emu/x64runavx660f38.c"
"${BOX64_ROOT}/src/emu/x64runavx660f3a.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f38.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f38.c"
"${BOX64_ROOT}/src/emu/x64runavxf20f3a.c"
"${BOX64_ROOT}/src/emu/x64runavxf30f3a.c"
)
if(STATICBUILD)
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.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"
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
)
else()
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
@@ -407,6 +442,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX64_ROOT}/src/wrapped/wrappeddecor0.c"
"${BOX64_ROOT}/src/wrapped/wrappedevent21.c"
"${BOX64_ROOT}/src/wrapped/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped/wrappedfaudio.c"
@@ -421,6 +457,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX64_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX64_ROOT}/src/wrapped/wrappedglesv2.c"
"${BOX64_ROOT}/src/wrapped/wrappedglib2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgmodule2.c"
"${BOX64_ROOT}/src/wrapped/wrappedgmp.c"
@@ -502,6 +539,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbdri3.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbglx.c"
@@ -517,6 +555,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbsync.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxinerama.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxinput.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxkb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
@@ -550,10 +589,12 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX64_ROOT}/src/wrapped/wrappedpam.c"
"${BOX64_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX64_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX64_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsemainloopglib.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1image.c"
@@ -588,6 +629,7 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommon.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbcommonx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedxkbregistry.c"
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
"${BOX64_ROOT}/src/wrapped/wrappedxslt.c"
"${BOX64_ROOT}/src/wrapped/wrappedldapr.c"
@@ -595,13 +637,30 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX64_ROOT}/src/wrapped/wrappedxshmfence.c"
"${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc64.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n64.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc66.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n66.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc67.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n67.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc72.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n72.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc73.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n73.c"
"${BOX64_ROOT}/src/wrapped/wrappedicuuc74.c"
"${BOX64_ROOT}/src/wrapped/wrappedicui18n74.c"
"${BOX64_ROOT}/src/wrapped/wrappedidn2.c"
"${BOX64_ROOT}/src/wrapped/wrappedanl.c"
"${BOX64_ROOT}/src/wrapped/wrappedpsl5.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssh2.c"
"${BOX64_ROOT}/src/wrapped/wrappedp11kit.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtasn1.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibnettle8.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibunistring2.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibhogweed6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsqlite3.c"
)
endif()
if(ANDROID)
list(APPEND WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedandroidshmem.c"
@@ -633,7 +692,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" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "ANDROID" "TERMUX" "STATICBUILD" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
@@ -666,6 +725,7 @@ if(ARM_DYNAREC)
${DYNAREC_SRC}
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_functions.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"
@@ -688,6 +748,7 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_67_avx.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_6764_32.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d8.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_d9.c"
@@ -705,6 +766,16 @@ if(ARM_DYNAREC)
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_66f0.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f20f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_f30f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_0f38.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f2_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_f3_0f.c"
"${BOX64_ROOT}/src/dynarec/arm64/dynarec_arm64_avx_66_0f38.c"
"${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"
)
endif()
@@ -750,6 +821,7 @@ 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_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"
@@ -759,6 +831,39 @@ if(RV64_DYNAREC)
)
endif()
if(LARCH64_DYNAREC)
set(DYNAREC_SRC
${DYNAREC_SRC}
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_functions.c"
"${BOX64_ROOT}/src/dynarec/la64/la64_printer.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_jmpnext.c"
"${BOX64_ROOT}/src/dynarec/la64/la64_prolog.S"
"${BOX64_ROOT}/src/dynarec/la64/la64_epilog.S"
"${BOX64_ROOT}/src/dynarec/la64/la64_next.S"
"${BOX64_ROOT}/src/dynarec/la64/la64_lock.S"
)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_helper.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_emit_tests.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_emit_math.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_emit_shift.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_emit_logic.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_00.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_0f.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_64.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_66.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_6664.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_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_f0.c"
"${BOX64_ROOT}/src/dynarec/la64/dynarec_la64_f20f.c"
)
endif()
if(DYNAREC)
set(DYNAREC_PASS
"${BOX64_ROOT}/src/wrapped/generated/wrapper.h"
@@ -816,7 +921,8 @@ add_dependencies(${BOX64} WRAPPERS)
#add_dependencies(${BOX64} PRINTER)
#target_link_libraries(${BOX64} c m dl rt pthread resolv)
if(STATICBUILD)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-static -Wl,--no-as-needed -Wl,--whole-archive -Wl,--allow-multiple-definition -lm -ldl -lrt -lpthread -lresolv -lc -Wl,-defsym,_DYNAMIC=0 -pthread")
#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)
else()
if(ANDROID)
if(TERMUX)
@@ -825,7 +931,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 -Wl,--as-needed -pthread")
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -lutil -Wl,--as-needed -pthread")
endif()
endif()
if(DYNAREC)
@@ -875,28 +981,45 @@ if(NOT _x86 AND NOT _x86_64)
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_BINARY_DIR}/system/box64.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box64.box64rc DESTINATION ${TERMUX_PATH}/usr/etc/)
endif()
endif()
set(INSTALL_PATH "/usr/lib/x86_64-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION /usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION /usr/lib/x86_64-linux-gnu/)
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()
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/x86_64-linux-gnu/)
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})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libcrypto.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libssl.so.1.0.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedx509.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x64lib/libmbedtls.so.14 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
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})
endif()
endif()
endif()
@@ -960,6 +1083,7 @@ set(CPACK_DEBIAN_FILE_NAME "${BOX64}-${BOX64_MAJOR}.${BOX64_MINOR}.${BOX64_REVIS
endif()
INCLUDE(CPack)
if(NOT ANDROID)
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
@@ -1112,7 +1236,161 @@ add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(avx_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test30 -D TEST_OUTPUT=tmpfile30.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref30.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(avx_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0;BOX64_AVX=2")
else()
add_test(bootSyscall ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01_android -D TEST_OUTPUT=tmpfile01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(bootSyscallC ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02_android -D TEST_OUTPUT=tmpfile02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(printf ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03_android -D TEST_OUTPUT=tmpfile03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(args ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04_android -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(maths1 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05_android -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(threadsStart ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06_android -D TEST_OUTPUT=tmpfile06.txt
-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(pi ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08_android -D TEST_OUTPUT=tmpfile08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(fork ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09_android -D TEST_OUTPUT=tmpfile09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(fpu ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12_android -D TEST_OUTPUT=tmpfile12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref12_android.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(linkingIndirectNoversion ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15_android -D TEST_OUTPUT=tmpfile15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# Box64 for Android now have problems with test16, then disable it for now
#add_test(sse_asm ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16_android -D TEST_OUTPUT=tmpfile16.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# Box64 for Android now have problems with test17, then disable it for now
#set_tests_properties(sse_asm PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
#add_test(sse_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_android -D TEST_OUTPUT=tmpfile17.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_android.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#set_tests_properties(sse_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0")
add_test(aes ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18_android -D TEST_OUTPUT=tmpfile18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
# Android don't have backtrace symbols
add_test(irelative_reloc ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test20_android -D TEST_OUTPUT=tmpfile20.txt
-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(x87 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22_android -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22_android.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(x87 PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTROUND=0")
add_test(pshufb ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23_android -D TEST_OUTPUT=tmpfile23.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24_android -D TEST_OUTPUT=tmpfile24.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(x87cache ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25_android -D TEST_OUTPUT=tmpfile25.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26_android -D TEST_OUTPUT=tmpfile26.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(feround PROPERTIES ENVIRONMENT "BOX64_SYNC_ROUNDING=1")
# TODO: need to regen test with latest test27.c sources
#add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test27_android -D TEST_OUTPUT=tmpfile27.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref27.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(shaext ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test28_android -D TEST_OUTPUT=tmpfile28.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref28.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29_android -D TEST_OUTPUT=tmpfile29.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(avx_intrinsics ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test30_android -D TEST_OUTPUT=tmpfile30.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref30.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#
#set_tests_properties(avx_intrinsics PROPERTIES ENVIRONMENT "BOX64_DYNAREC_FASTNAN=0;BOX64_DYNAREC_FASTROUND=0 BOX64_AVX=2")
endif()
if(NOT ANDROID)
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
@@ -1121,3 +1399,14 @@ foreach(file ${extension_tests})
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
else()
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}_android -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endif()
+8 -7
View File
@@ -57,12 +57,14 @@ Because Box64 works by directly translating function calls from x86_64 to host s
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/box4.box64rc` and `~/.box64rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box64 comes with a default file that should be installed for better stability. The file in in `system/box64.box64rc` and should be installed to `/etc/box64.box64rc` If, for some reason, you don't want to install that file here, at least copy it to `~/.box64rc` or some game may not function correctly.
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...
@@ -72,7 +74,7 @@ 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, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
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.
----
@@ -94,7 +96,7 @@ 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, but the support is quite young so there might be some residual issues.
Note that the new 32-bit PE in 64-bit processes that the Wine team is currently implementing in Wine 7.+ is now supported. It's called "new WoW64" and it's working fine on box64, allowing the use of 32bits windows program on 64bits only system.
----
@@ -111,11 +113,10 @@ Final word
I want to thank everyone who has contributed to box64 development.
There are many ways to contribute: code contribution, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, mogery
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* 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 hardware contribution and LoongArch migration: [xiaoji](https://www.linuxgame.cn/), Deepin Beijing Develop Team
* For their major code contribution on the RV64 Dynarec: ksco, xctan
* For their hardware contribution: [ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) with [Ampere](https://amperecomputing.com/home/edge), [Radxa](https://rockpi.org/), [StarFive](https://rvspace.org/), [Pine64](https://www.pine64.org/), [AYN](https://www.ayntec.com/)
* For their 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/))
And I also thank the many other people who participated even once in this project.
+3 -3
View File
@@ -102,10 +102,10 @@ Box64 封装了 Vulkan 库,但请注意,它仅在 RX550 显卡上进行过
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, mogery
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 代码贡献:rajdakin, mogery, ksco, xctan
* 财务帮助:[Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠和 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), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* 硬件捐赠:[ADLINK](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en) 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
@@ -107,11 +107,10 @@ Box64 використовує бібліотеки Vulkan, але зауваж
Я хочу подякувати всім, хто зробив внесок у розвиток box64.
Є багато способів зробити внесок: внесок коду, фінансовий внесок, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, mogery
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За основний внесок у код: rajdakin, mogery, ksco, xctan
* За великий фінансовий внесок: [Playtron](https://playtron.one), FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За апаратне забезпечення та міграцію LoongArch: [xiaoji](https://www.linuxgame.cn/), команда розробників Deepin Beijing
* За основний внесок у код RV64 Dynarec: ksco, xctan
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [StarFive](https://rvspace.org/)
* За внесок у апаратне забезпечення: [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/))
І я також дякую багатьом іншим людям, які хоч раз брали участь у цьому проекті.
+50
View File
@@ -1,3 +1,53 @@
box64 (0.3.0) unstable; urgency=low
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
* Introduced BOX64_AVX env. var. to enable/disable AVX extension:
* => BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension
* => BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND
* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU)
* => ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before)
* Dynarec: Small optim in the emit_pf helper, on all 3 backends
* Dynarec: ARM64 some fixes to a few opcodes
* Dynarec: LA64 many new opcodes added, and fixes.
* Dynarec: RV64 some new opcodes added, many fixes.
* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation.
* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump.
* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions)
* WRAPPING: Wayland is now supported. Wine-wayland at least works now
* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games)
* Dynarec: RV64 improved LOCK CMPXCHG handling
* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable
* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work
* ElfLoader: Added a new type of relocation
-- Sebastien Chevalier <[email protected]> Thu, 9 Jul 2024 10:30:33 -0100
box64 (0.2.8) unstable; urgency=low
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
* Reworked X11 Callback handling, for better stability
* Reworked exit and the load/unload of libs and symbol resolution
* Some more profiles in box64rc
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
* Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa)
* => Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits.
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
* => should improve games stability
* Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones
* Dynarec: RV64 lots of opcoded added.
* => Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues
* Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default.
* => Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation
* Dynarec: Better handling of large block in the dynarec
* Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation.
* => It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts.
-- Sebastien Chevalier <[email protected]> Thu, 31 May 2024 17:30:33 -0100
box64 (0.2.6) unstable; urgency=low
* X64Libs: Updated libstdc++ & libgcc_s
+12 -1
View File
@@ -10,4 +10,15 @@ override_dh_auto_configure:
-DNOGIT=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
dh_shlibdeps --exclude=libgcc_s.so.1 \
--exclude=libpng12.so.0 \
--exclude=libstdc++.so.5 \
--exclude=libstdc++.so.6 \
--exclude=libmbedcrypto.so.7 \
--exclude=libssl.so.1.1 \
--exclude=libunwind.so.8 \
--exclude=libmbedtls.so.14 \
--exclude=libcrypto.so.1.1 \
--exclude=libmbedx509.so.1 \
--exclude=libcrypto.so.1.0.0 \
--exclude=libssl.1.0.0
+46
View File
@@ -1,3 +1,49 @@
v0.3.0
======
* AVX and AVX2 implemented, along with BMI1, BMI2, ADX, FMA, F16C and RDANDR extension!
* Introduced BOX64_AVX env. var. to enable/disable AVX extension:
=> BOX64_AVX=1 enable AVX, BMI1, F16C and VAES extension
=> BOX64_AVX=2 also enable AVX2, BMI2, FMA, ADX,VPCLMULQDQ and RDRAND
* Dynarec: Implemented most AVX/AVX2 and friends in ARM64 Dynarec (using only NEON, so available on all ARM64 CPU)
=> ARM64 Dynarec build have all AVX/AVX2 extensions enabled by default
* Improved CPUID opcodes, adding a few leaf, fixing same. Returnning an Haswell type of CPU now (was Pentium IV before)
* Dynarec: Small optim in the emit_pf helper, on all 3 backends
* Dynarec: ARM64 some fixes to a few opcodes
* Dynarec: LA64 many new opcodes added, and fixes.
* Dynarec: RV64 some new opcodes added, many fixes.
* Dynarec: RV64 Adding some infrastructure to use RVV (if available) for SIMD emulation.
* Dynarec: Many small changes and fixes around handling of x87, registers and internal jump.
* WRAPPING: Added a workaround on SDL_GetThreadID to fix a race condition that was happening mostly on LA64 and broke many SDL games
* WRAPPING: More libs and functions wrapped. Some wrapping fixes too (including a nasty error on some rare libGL functions)
* WRAPPING: Wayland is now supported. Wine-wayland at least works now
* Dynarec: LA64 improved LOCK CMPXCHG handling, and better 16Byte LOCK handling too (fixes many Unity3D games)
* Dynarec: RV64 improved LOCK CMPXCHG handling
* COSIM: Many fixes and improvment, to make BOX64_DYNAREC_TEST more usable
* Detect when a Wine program use UnityPlayer.dll to atumaticaly use BOX64_DYNAREC_STRONGMEM=1 (unless it's already set), so more games just work
* ElfLoader: Added a new type of relocation
v0.2.8
======
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
* Reworked X11 Callback handling, for better stability
* Reworked exit and the load/unload of libs and symbol resolution
* Some more profiles in box64rc
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
* Improved memory tracking and managment. Also introduce BOX64_MMAP32 to force 32bits compatible mmap for external libs (like mesa)
=> Allow Vulkan drvier on Wine/WOW64 games to allocate 32bits compatible memory, allowing dxvk on 32bits.
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
=> should improve games stability
* Dynarec: ARM64 some opcodes optimisation, especialy shift and rotation ones
* Dynarec: RV64 lots of opcoded added.
=> Some games on linux now have a good speed. Game on Wine are still a bit slow, and dxvk still have issues
* Dynarec: Added Loogarch backend! Note that Loongarch are 16K pagesize platform by default.
=> Linux games are running, and with good speed, especialy on 3A6000 platforms. Games on Wine are not working yet due to 16k pagesize limitation
* Dynarec: Better handling of large block in the dynarec
* Dynarec: Lots of improvments and fixes to BOX86_DYNAREC_CALLRET optimisation.
=> It can be used on more software now, and combine with BOX64_DYNAREC_BOGBLOCKS 2 or 3 can gives some good speed boosts.
v0.2.6
======
* X64Libs: Updated libstdc++ & libgcc_s
+61 -14
View File
@@ -1,17 +1,11 @@
Compiling/Installing
----
### Debian-based Linux
You can use [@ryanfortner](https://github.com/ryanfortner)'s apt repository to install precompiled box64 debs, updated every 24 hours.
If you don't want to compile box64 yourself and prefer to use third-party pre-build version, go to the [end of the document](#pre-build-packages) for alternatives.
```
sudo wget https://ryanfortner.github.io/box64-debs/box64.list -O /etc/apt/sources.list.d/box64.list
wget -qO- https://ryanfortner.github.io/box64-debs/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box64-debs-archive-keyring.gpg
sudo apt update && sudo apt install box64-arm64 -y
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
You can also generate your own package using the [instructions below](https://github.com/ptitSeb/box64/blob/main/docs/COMPILE.md#debian-packaging).
## Per-platform compiling instructions
----
### The general approach is:
@@ -80,7 +74,6 @@ Warning, you need a 64bit OS:
#### for Raspberry Pi 5
If your Raspberry Pi OS use 16K pages use `RPI5ARM64PS16K` instead of `RPI5ARM64`:
```
-D RPI5ARM64=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
@@ -93,6 +86,22 @@ Using a 64bit OS:
-D TEGRAX1=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Jetson Xavier/T194
Using a 64bit OS:
```
-D TEGRA_T194=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for Jetson Orin/T234
Using a 64bit OS:
Caution: please use gcc-11 or higher, older gcc dosen't know cortex-a78ae
```
-D TEGRA_T234=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for ODROID N2/N2+
@@ -134,7 +143,7 @@ Using a 64bit OS:
#### for M1
Only test on Asahi for now, using the default "16K page" kernel
Only test on Asahi with Fedora, using the default "16K page" kernel
```
-D M1=1 -D CMAKE_BUILD_TYPE=RelWithDebInfo
@@ -189,7 +198,7 @@ NOTE: BUILDING BOX64 IN TERMUX NATIVE IS EXPERIMENTAL AND DOESN'T GONNA RUN LINU
You also needed have `libandroid-sysv-semaphore` and `libandroid-spawn` libraries:
```
-D TERMUX=1 -D -DCMAKE_C_COMPILER=clang CMAKE_BUILD_TYPE=RelWithDebInfo
-D TERMUX=1 -DCMAKE_C_COMPILER=clang -D CMAKE_BUILD_TYPE=RelWithDebInfo
```
#### for x86_64 Linux
@@ -234,9 +243,14 @@ If you are not building from a git clone (for example, downloading a release sou
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).
#### 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.
----
Testing
## Testing
----
A few tests are included with box64.
@@ -246,6 +260,39 @@ The tests are very basic and only tests some functionality for now.
----
Debian Packaging
## 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
----
### 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.
```
# check if .list file already exists
if [ -f /etc/apt/sources.list.d/box64.list ]; then
sudo rm -f /etc/apt/sources.list.d/box64.list || exit 1
fi
# check if .sources file already exists
if [ -f /etc/apt/sources.list.d/box64.sources ]; then
sudo rm -f /etc/apt/sources.list.d/box64.sources || exit 1
fi
# download gpg key from specified url
if [ -f /usr/share/keyrings/box64-archive-keyring.gpg ]; then
sudo rm -f /usr/share/keyrings/box64-archive-keyring.gpg
fi
sudo mkdir -p /usr/share/keyrings
wget -qO- "https://pi-apps-coders.github.io/box64-debs/KEY.gpg" | sudo gpg --dearmor -o /usr/share/keyrings/box64-archive-keyring.gpg
# create .sources file
echo "Types: deb
URIs: https://Pi-Apps-Coders.github.io/box64-debs/debian
Suites: ./
Signed-By: /usr/share/keyrings/box64-archive-keyring.gpg" | sudo tee /etc/apt/sources.list.d/box64.sources >/dev/null
sudo apt update
sudo apt install box64-generic-arm -y
```
+51 -18
View File
@@ -104,6 +104,16 @@ Call XInitThreads when loading X11. (This is mostly for old Loki games with the
* 0 : Don't force call XInitThreads. (Default.)
* 1 : Call XInitThreads as soon as libX11 is loaded.
#### BOX64_MMAP32 *
Will use 32bits address in priority for external MMAP (when 32bits process are detected)
* 0 : Use regular mmap (default, except for Snapdragron build)
* 1 : Use 32bits address space mmap in priority for external mmap as soon a 32bits process are detected (default for SnapDragon and TegraX1 build)
#### BOX64_IGNOREINT3 *
What to do when a CC INT3 opcode is encounter in the code being run
* 0 : Trigger a TRAP signal if a handler is present
* 1 : Just skip silently the opcode
#### BOX64_X11GLX *
Force libX11's GLX extension to be present.
* 0 : Do not force libX11's GLX extension to be present.
@@ -138,8 +148,10 @@ Forbid dynablock creation in the interval specified (helpfull for debugging beha
#### BOX64_DYNAREC_TEST *
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
* 0 : No comparison
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different
* 0 : No comparison. (Default.)
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different.
* 2 : Thread-safe tests, extremely slow.
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynarec is tested (inclusive-exclusive)
#### BOX64_DYNAREC_BIGBLOCK *
Enables/Disables Box64's Dynarec building BigBlock.
@@ -183,18 +195,8 @@ Handling of flags on CALL/RET opcodes
#### BOX64_DYNAREC_CALLRET *
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
* 0 : Don't optimize CALL/RET, use Jump Table for boths
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (Default)
#### BOX64_DYNAREC_HOTPAGE *
Handling of HotPage (Page being both executed and written)
* 0 : Don't track hotpage (Default)
* 1-255 : Track HotPage, and disable execution of a page being written for N attempts
#### BOX64_DYNAREC_FASTPAGE *
Will use a faster handling of HotPage (Page being both executed and written)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible
#### BOX64_DYNAREC_ALIGNED_ATOMICS *
Generated code for aligned atomics only
@@ -207,9 +209,9 @@ Detect MonoBleedingEdge and apply conservative settings
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX64_DYNAREC_JVM *
Detect libjvm and apply conservative settings
Detect libjvm and apply conservative settings. Obsolete, use BOX64_JVM instead.
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 SSE42=0 if detected (Default)
#### BOX64_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
@@ -231,6 +233,11 @@ Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX64_MAXCPU
Maximum CPU Core exposed
* 0 : Don't cap the number of cpu core exposed (Default)
* XXX : Cap the maximum CPU Core exposed to XXX (usefull with wine64 or GridAutosport for example)
#### BOX64_SYNC_ROUNDING *
Box64 will sync rounding mode with fesetround/fegetround.
* 0 : Disable rounding mode syncing. (Default.)
@@ -241,6 +248,16 @@ Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
#### BOX64_JVM *
Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 SSE42=0 if detected (Default)
#### BOX64_UNITYPLAYER *
Detect UnityPlayer.dll and apply strongmem settings
* 0 : Don't detect UnityPlayer.dll
* 1 : Detect UnityPlayer.dll, and apply BOX64_DYNAREC_STRONGMEM=1 if detected (Default)
#### BOX64_SDL2_JGUID *
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
* 0 : Don't use any workaround
@@ -301,6 +318,11 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX64_SSE42 *
Expose or not SSE 4.2 capabilites
* 0 : Do not expose SSE 4.2 capabilites (default when libjvm is detected)
* 1 : Expose SSE 4.2 capabilites (Default.)
#### BOX64_FUTEX_WAITV *
Use of the new fuext_waitc syscall
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
@@ -315,11 +337,11 @@ Define x86_64 bash to launch script
* XXX=yyyy
will add XXX=yyyy env. var.
#### BOX64_ENV1
#### BOX64_ENV1 *
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX64_RESERVE_HIGH
#### BOX64_RESERVE_HIGH *
* 0 : Don't try to pe-reserve high memory (beyond 47bits) (Default)
* 1 : Try to reserve (without allocating it) memory beyond 47bits (seems unstable)
@@ -338,6 +360,9 @@ Define x86_64 bash to launch script
#### BOX64_NORCFILES
If the env var exist, no rc files (like /etc/box64.box64rc and ~/.box64rc) will be loaded
#### BOX64_RCFILE
If the env var is set and file exists, this variable will be used as path to the box64rc file instead of default paths (BOX64_RCFILE is loaded first, default paths are not loaded)
----
Those variables are only valid inside a rcfile:
@@ -351,6 +376,14 @@ Those variables are only valid inside a rcfile:
* 0 : Nothing special
* 1 : Added "--in-process-gpu" to command line arguments (usefull for chrome based programs)
#### BOX64_CEFDISABLEGPU
* 0 : Nothing special
* 1 : Added "-cef-disable-gpu" to command line arguments (usefull for steamwebhelper/cef based programs)
#### BOX64_CEFDISABLEGPUCOMPOSITOR
* 0 : Nothing special
* 1 : Added "-cef-disable-gpu-compositor" to command line arguments (usefull for steamwebhelper/cef based programs)
#### BOX64_EXIT
* 0 : Nothing special
* 1 : Just exit, don't try to run the program
+21 -20
View File
@@ -33,7 +33,7 @@ Print box64 version and quit.
=head1 CONFIGURATION FILE
B<Box64> now have configurations files. There are 2 files loaded.
F</etc/box4.box64rc> and F<~/.box64rc>. Both files have the same syntax, and is
F</etc/box64.box64rc> and F<~/.box64rc>. Both files have the same syntax, and is
basically an ini files. Section in square brackets define the process name, and
the rest is the environment variable. B<Box64> comes with a default file that
should be installed for better stability. Note that the priority is:
@@ -264,15 +264,15 @@ down the program a lot and generate huge logs.
=item B<BOX64_NODYNAREC>=I<0xXXXXXXXX-0xYYYYYYYY>
Forbid dynablock creation in the interval specified (helpfull for debugging
behaviour difference between Dynarec and Interpretor)
behaviour difference between Dynarec and Interpreter)
=item B<BOX64_DYNAREC_TEST>=I<0|1>
Enables/Disables test for generated code. This will run interpreter along the Dynacrec, so this will slow
down the program a lot.
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
* 0 : No test for generated code. (Default.)
* 1 : Enable Tests for generated code
* 0 : No comparison. (Default.)
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different.
* 2 : Thread-safe tests, extremely slow.
=item B<BOX64_DYNAREC_BIGBLOCK>=I<0|1|2|3>
@@ -334,20 +334,6 @@ Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible (will crash if blacks are invalidate, so probably incompatible with JIT/Dynarec)
=item B<BOX64_DYNAREC_HOTPAGE>=I<0|1-255>
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Track HotPage, and disable execution of a page beeing writen for N attempts (default is 4)
=item B<BOX64_DYNAREC_FASTPAGE>=I<0|1>
Will use a faster handling of HotPage (Page beeing both executed and writen)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
=item B<BOX64_DYNAREC_BLEEDING_EDGE>=I<0|1>
Detect MonoBleedingEdge and apply conservative settings
@@ -481,4 +467,19 @@ script. yyyy needs to be a full path to a valid x86_64 version of bash
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting. When in gdb, you need to find the correct thread yourself (the one with `my_box64signalhandler` in is stack) then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box64signalhandler`, just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting. Use `gdb /PATH/TO/box64` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX64_JITGDB=1`. This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
=back
=head1 VARIABLES FOR ENVIRONMENT ONLY
=over 8
=item B<BOX64_VERSION>
When set, B<box64> will only print its version and then exit. This option is
analogous to B<QEMU_VERSION> used by C<binfmt_misc> emulation of qemu-user. Its
purpose is the same: provide a way to soft-disable C<binfmt_misc> emulation as
well as for identifying B<box64> as the registered C<binfmt_misc> emulator.
=back
=cut
+206 -122
View File
@@ -150,12 +150,12 @@ class FunctionConvention(object):
self.ident = ident
self.name = convname
self.values = valid_chars
# Free letters: B FG J QR T XYZab e gh jk mno qrst xyz
# Free letters: B FG J QR T YZa e gh jk mno qrst z
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']),
'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'])
}
sortedvalues = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P', 'A', 'x', 'X', '0', '1']
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']
assert(all(all(c not in conv.values[:i] and c in sortedvalues for i, c in enumerate(conv.values)) for conv in conventions.values()))
class FunctionType(str):
@@ -197,7 +197,7 @@ class FunctionType(str):
except ValueError as e:
raise ValueError("Value is " + self) from e
def __getitem__(self, i: Union[int, slice]) -> 'FunctionType':
def __getitem__(self, i: Union[int, slice]) -> 'FunctionType': # type: ignore [override]
return FunctionType(super().__getitem__(i))
RedirectType = NewType('RedirectType', FunctionType)
@@ -399,7 +399,9 @@ def readFiles(files: Iterable[Filename]) -> Tuple[JumbledGlobals, JumbledRedirec
or match("sdl1mixer", "sdl2mixer") \
or match("sdl1net", "sdl2net") \
or match("sdl1ttf", "sdl2ttf") \
or match("libGL", "libEGL") \
or match("libgl", "libegl") \
or match("libgl", "glesv2") \
or match("libegl", "glesv2") \
or match("libc", "tcmallocminimal") \
or match("libc", "tbbmallocproxy") \
or match("libc", "androidshmem") \
@@ -816,62 +818,75 @@ def main(root: str, files: Iterable[Filename], ver: str):
return 0
# Detect simple wrappings
simple_wraps: Dict[ClausesStr, List[Tuple[FunctionType, int]]] = {}
allowed_conv_ident = "F"
allowed_conv = conventions[allowed_conv_ident]
# H could be allowed maybe?
allowed_simply: str = "v"
allowed_regs : str = "cCwWiuIUlLp"
allowed_fpr : str = "fd"
allowed_simply: Dict[str, str] = {"ARM64": "v", "RV64": "v"}
allowed_regs : Dict[str, str] = {"ARM64": "cCwWiuIUlLp", "RV64": "CWuIUlLp"}
allowed_fpr : Dict[str, str] = {"ARM64": "fd", "RV64": "fd"}
# Detect functions which return in an x87 register
retx87_wraps: Dict[ClausesStr, List[FunctionType]] = {}
return_x87: str = "DK"
# Sanity checks
forbidden_simple: str = "EDKVOSNMHPAxX"
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(allowed_conv.values))
assert(all(c not in allowed_regs for c in allowed_simply))
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
assert(all(c not in allowed_simply + allowed_regs + allowed_fpr for c in forbidden_simple))
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in allowed_conv.values))
forbidden_simple: Dict[str, str] = {"ARM64": "EDKVOSNMHPAxXYyb", "RV64": "EcwiDKVOSNMHPAxXYyb"}
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(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_conv.values for c in return_x87))
def check_simple(v: FunctionType) -> Optional[int]:
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
if v.get_convention() is not allowed_conv:
return None
if v[0] in forbidden_simple:
return None
for c in v[2:]:
if c in allowed_regs:
regs_count = regs_count + 1
elif c in allowed_fpr:
fpr_count = fpr_count + 1
elif c in allowed_simply:
ret = {}
for k in forbidden_simple:
if v.get_convention() is not allowed_conv:
continue
if v[0] in forbidden_simple[k]:
continue
for c in v[2:]:
if c in allowed_regs[k]:
regs_count = regs_count + 1
elif c in allowed_fpr[k]:
fpr_count = fpr_count + 1
elif c in allowed_simply[k]:
continue
else:
break
else:
return None
# No character in forbidden_simply
if (regs_count <= 6) and (fpr_count <= 8):
# All checks passed!
ret_val = 1 + fpr_count
if v[0] in allowed_fpr:
ret_val = -ret_val
return ret_val
else:
# Too many arguments...
return None
# No character in forbidden_simply
if (regs_count <= 6) and (fpr_count <= 8):
# All checks passed!
ret_val = 1 + fpr_count
if v[0] in allowed_fpr[k]:
ret_val = -ret_val
ret[k] = ret_val
# Else, too many arguments
return ret
# Only search in real wrappers (mapped ones are nearly always not simple)
for k in gbls:
tmp = [ (v, ret_val) for v, ret_val in map(lambda v: (v, check_simple(v)), gbls[k]) if ret_val is not None ]
if tmp:
simple_wraps[k] = tmp
simple_idxs = sorted(simple_wraps.keys(), key=lambda x: Clauses(x).splitdef())
for v in gbls[k]:
simples = check_simple(v)
for k1, i in simples.items():
if k in simple_wraps[k1]:
simple_wraps[k1][k].append((v, i))
else:
simple_wraps[k1][k] = [(v, i)]
simple_idxs = { k1: sorted(v1.keys(), key=lambda x: Clauses(x).splitdef()) for k1, v1 in simple_wraps.items() }
def check_return_x87(v: FunctionType) -> bool:
return v[0] in return_x87
@@ -918,6 +933,8 @@ def main(root: str, files: Iterable[Filename], ver: str):
#define ST0val ST0.d
int of_convert(int);
void* align_xcb_connection(void* src);
void unalign_xcb_connection(void* src, void* dst);
""",
"wrapper.h": """
@@ -954,6 +971,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
// 0 = constant 0, 1 = constant 1
// x = float complex
// X = double complex
// b = xcb_connection_t*
""",
"fntypes.h": """
@@ -1015,8 +1033,8 @@ 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
'F': ["x64emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*", "void*", "complexf_t", "complex_t"],
# E v c w i I C W u U f d 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*"]
}
@@ -1074,8 +1092,11 @@ def main(root: str, files: Iterable[Filename], ver: str):
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
"\n#error Invalid return type: pointer in the stack\n", # P
"\n#error Invalid return type: va_list\n", # A
'from_complexf(emu, fn({0})));', # x
'from_complex(emu, fn({0})));' # X
'from_complexf(emu, fn({0}));', # x
'from_complex(emu, fn({0}));', # X
'from_complexl(emu, fn({0}));', # Y
'from_complexk(emu, fn({0}));', # y
"\n#error Invalid return type: xcb_connection_t*\n", # b
],
conventions['W']: [
"\n#error Invalid return type: emulator\n", # E
@@ -1105,17 +1126,17 @@ def main(root: str, files: Iterable[Filename], ver: str):
}
# vreg: value is in a general register
# E v c w i I C W u U f d D K l L p V O S N M H P A x X
vreg = [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0, 1, 0, 0]
# 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]
# 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
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]
# 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]
# 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
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]
# 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]
# 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
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]
# 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]
arg_r = [
"", # E
"", # v
@@ -1144,64 +1165,73 @@ def main(root: str, files: Iterable[Filename], ver: str):
"(void*){p}, ", # A
"", # x
"", # X
"", # Y
"", # y
"aligned_xcb, ", # b
]
arg_x = [
"", # E
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"to_complexf(emu, {p}),",# x
"to_complex(emu, {p})," # X
"", # E
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"to_complexf(emu, {p}), ", # x
"to_complex(emu, {p}), ", # X
"", # Y
"", # y
"", # b
]
arg_o = [
"emu, ", # E
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"(void*)(R_RSP + {p}), ", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"", # x
"", # X
"emu, ", # E
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"(void*)(R_RSP + {p}), ", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
"", # A
"", # x
"", # X
"", # Y
"", # y
"", # b
]
arg_s = [
"", # E
@@ -1226,11 +1256,14 @@ def main(root: str, files: Iterable[Filename], ver: str):
"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
"*(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
"aligned_xcb, ", # b
]
# Asserts
@@ -1258,7 +1291,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
for k in conventions:
c = conventions[k]
if c not in vals:
raise NotImplementedError("[{k}]values not in vals".format(k=k, lenval=len(c.values), lenvals=len(vals[c])))
raise NotImplementedError("convention {k} not in vals".format(k=k))
if len(c.values) != len(vals[c]):
raise NotImplementedError("len([{k}]values) = {lenval} != len(vals[...]) = {lenvals}".format(k=k, lenval=len(c.values), lenvals=len(vals[c])))
# When arg_* is not empty, v* should not be 0
@@ -1282,6 +1315,50 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Helper functions to write the function definitions
systemVconv = conventions['F']
def function_pre_systemV(args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> Tuple[Optional[str], str]:
# args: string of argument types
# d: delta (in the stack)
# r: general register no
# x: XMM register no
if len(args) == 0:
return None, ""
# Redirections
if args[0] == "0":
return function_pre_systemV(args[1:], d, r, x)
elif args[0] == "1":
return function_pre_systemV(args[1:], d, r, x)
idx = systemVconv.values.index(args[0])
# Name of the registers
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
if args[0] == "b":
if 'b' in args[1:]:
raise NotImplementedError("Multiple XCB connections unsupported")
content = ""
if r < len(reg_arg):
content = reg_arg[r]
else:
content = "(R_RSP + " + str(d) + ")"
return "(void*)" + content, f"void *aligned_xcb = align_xcb_connection((void*){content}); "
elif (r < len(reg_arg)) and (vreg[idx] > 0):
for _ in range(vreg[idx]):
if r < len(reg_arg):
r = r + 1
else:
d = d + 8
return function_pre_systemV(args[1:], d, r, x)
elif (x < 8) and (vxmm[idx] > 0):
return function_pre_systemV(args[1:], d, r, x+1)
elif vstack[idx] > 0:
return function_pre_systemV(args[1:], d+8*vstack[idx], r, x)
else:
return function_pre_systemV(args[1:], d, r, x)
def function_post_systemV(content: Optional[str]) -> str:
if content is not None:
return f" unalign_xcb_connection(aligned_xcb, {content});"
else:
return ""
def function_args_systemV(args: FunctionType, d: int = 8, r: int = 0, x: int = 0) -> str:
# args: string of argument types
# d: delta (in the stack)
@@ -1314,7 +1391,7 @@ def main(root: str, files: Iterable[Filename], ver: str):
return ret + function_args_systemV(args[1:], d, r, x)
elif (x < 8) and (vxmm[idx] > 0):
# Value is in an XMM register
return arg_x[idx].format(p=x) + function_args_systemV(args[1:], d, r, x+1)
return arg_x[idx].format(p=x) + function_args_systemV(args[1:], d, r, x+vxmm[idx])
elif vstack[idx] > 0:
# Value is in the stack
return arg_s[idx].format(p=d) + function_args_systemV(args[1:], d+8*vstack[idx], r, x)
@@ -1361,9 +1438,11 @@ def main(root: str, files: Iterable[Filename], ver: str):
# Generic function
conv = N.get_convention()
if conv is systemVconv:
f.write(vals[conv][conv.values.index(N[0])].format(function_args_systemV(N[2:])[:-2]) + " }\n")
prepost, pre = function_pre_systemV(N[2:])
f.write(pre + vals[conv][conv.values.index(N[0])].format(function_args_systemV(N[2:])[:-2]) + function_post_systemV(prepost))
else:
f.write(vals[conv][conv.values.index(N[0])].format(function_args_windows(N[2:])[:-2]) + " }\n")
f.write(vals[conv][conv.values.index(N[0])].format(function_args_windows(N[2:])[:-2]))
f.write(" }\n")
for k in gbls:
if k != str(Clauses()):
@@ -1386,15 +1465,20 @@ def main(root: str, files: Iterable[Filename], ver: str):
file.write("#endif\n")
# Write the isSimpleWrapper function
file.write("\nint isSimpleWrapper(wrapper_t fun) {\n")
for k in simple_idxs:
if k != str(Clauses()):
file.write("#if " + k + "\n")
for vf, val in simple_wraps[k]:
file.write("\tif (fun == &" + vf + ") return " + str(val) + ";\n")
if k != str(Clauses()):
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
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))
inttext = "el"
for k in simple_idxs[k1]:
if k != str(Clauses()):
file.write("#if " + k + "\n")
for vf, val in simple_wraps[k1][k]:
file.write("\tif (fun == &" + vf + ") return " + str(val) + ";\n")
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")
# Write the isRetX87Wrapper function
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
@@ -1480,6 +1564,6 @@ if __name__ == '__main__':
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.2.0.18") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.4.0.21") != 0:
exit(2)
exit(0)
+23 -2
View File
@@ -21,6 +21,8 @@
#include "signals.h"
#include "rcfile.h"
#include "gltools.h"
#include "rbtree.h"
#include "dynarec.h"
EXPORTDYN
void initAllHelpers(box64context_t* context)
@@ -211,8 +213,12 @@ box64context_t *NewBox64Context(int argc)
init_custommem_helper(context);
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
#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
@@ -229,7 +235,9 @@ box64context_t *NewBox64Context(int argc)
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
// get handle to box64 itself
#ifndef STATICBUILD
context->box64lib = dlopen(NULL, RTLD_NOW|RTLD_GLOBAL);
#endif
context->dlprivate = NewDLPrivate();
context->argc = argc;
@@ -262,8 +270,13 @@ box64context_t *NewBox64Context(int argc)
context->segtls[4].is32bits = 1;
context->globdata = NewMapSymbols();
context->uniques = NewMapSymbols();
initAllHelpers(context);
#ifdef DYNAREC
context->db_sizes = init_rbtree();
#endif
return context;
}
@@ -335,8 +348,10 @@ void FreeBox64Context(box64context_t** context)
FreeBridge(&ctx->system);
#ifndef STATICBUILD
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
#endif
if(ctx->stack_clone)
box_free(ctx->stack_clone);
@@ -358,6 +373,12 @@ void FreeBox64Context(box64context_t** context)
FreeX64Emu(&ctx->emu_sig);
FreeMapSymbols(&ctx->globdata);
FreeMapSymbols(&ctx->uniques);
#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);
#endif
finiAllHelpers(ctx);
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX64_VERSION_H_
#define BOX64_MAJOR 0
#define BOX64_MINOR 2
#define BOX64_REVISION 6
#define BOX64_MINOR 3
#define BOX64_REVISION 0
#endif //__BOX64_VERSION_H_
+1 -1
View File
@@ -9,7 +9,7 @@
void PrintBox64Version()
{
printf("Box64%s%s v%d.%d.%d %s built on %s %s\n",
printf_log(LOG_NONE, "Box64%s%s v%d.%d.%d %s built on %s %s\n",
#ifdef HAVE_TRACE
" with trace",
#else
+2301
View File
File diff suppressed because it is too large. Load diff
+400 -591
View File
File diff suppressed because it is too large. Load diff
+48
View File
@@ -0,0 +1,48 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <unistd.h>
#include <stdint.h>
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
#define EXPORTDYN __attribute__((visibility("default")))
#else
#define EXPORTDYN
#endif
typedef void x64emu_t;
extern void* mapallmem;
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* 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;
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);
else
ret = internal_mmap(addr, length, prot, flags, fd, offset);
if(ret!=MAP_FAILED && mapallmem)
setProtection((uintptr_t)ret, length, prot);
return ret;
}
EXPORT void* mmap(void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset) __attribute__((alias("mmap64")));
EXPORT int munmap(void* addr, unsigned long length)
{
int ret = internal_munmap(addr, length);
if(!ret && mapallmem) {
freeProtection((uintptr_t)addr, length);
}
return ret;
}
+200 -26
View File
@@ -5,6 +5,41 @@
*/
/*
ARM64 Linux Call Convention
SP The Stack Pointer.
r30 LR The Link Register.
r29 FP The Frame Pointer
r19…r28 Callee-saved registers
r18 The Platform Register, if needed; otherwise a temporary register. See notes.
r17 IP1 The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
r16 IP0 The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as a temporary register.
r9…r15 Temporary registers
r8 Indirect result location register
r0…r7 Parameter/result registers
For SIMD:
The first eight registers, v0-v7, are used to pass argument values into a subroutine and to return result values from a function.
They may also be used to hold intermediate values within a routine (but, in general, only between subroutine calls).
Registers v8-v15 must be preserved by a callee across subroutine calls;
the remaining registers (v0-v7, v16-v31) do not need to be preserved (or should be preserved by the caller).
Additionally, only the bottom 64 bits of each value stored in v8-v15 need to be preserved [8];
it is the responsibility of the caller to preserve larger values.
For SVE:
z0-z7 are used to pass scalable vector arguments to a subroutine, and to return scalable vector results from a function.
If a subroutine takes at least one argument in scalable vector registers or scalable predicate registers,
or returns results in such regisers, the subroutine must ensure that the entire contents of z8-z23 are preserved across the call.
In other cases it need only preserve the low 64 bits of z8-z15, as described in SIMD and Floating-Point registers.
p0-p3 are used to pass scalable predicate arguments to a subroutine and to return scalable predicate results from a function.
If a subroutine takes at least one argument in scalable vector registers or scalable predicate registers,
or returns results in such registers, the subroutine must ensure that p4-p15 are preserved across the call.
In other cases it need not preserve any scalable predicate register contents.
*/
// x86 Register mapping
#define xRAX 10
#define xRCX 11
@@ -70,24 +105,46 @@
#define wZR xZR
// conditions
// Z == 1
#define cEQ 0b0000
// Z != 1
#define cNE 0b0001
// C == 1
#define cCS 0b0010
// C == 1
#define cHS cCS
// C != 1
#define cCC 0b0011
// C != 1
#define cLO cCC
// N == 1
#define cMI 0b0100
// N != 1
#define cPL 0b0101
// V == 1
#define cVS 0b0110
// V != 1
#define cVC 0b0111
// C == 1 && Z == 0
#define cHI 0b1000
// C !=1 || Z == 1
#define cLS 0b1001
// N == V
#define cGE 0b1010
// N != V
#define cLT 0b1011
// N == V && Z == 0
#define cGT 0b1100
// N != V || Z == 1
#define cLE 0b1101
// always
#define c__ 0b1110
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)
#define convert_bitmask_xw(A) convert_bitmask(rex.w?((uint64_t)(A)):(((uint64_t)(A) << 32) + (uint32_t)(A)))
#define invCond(cond) ((cond)^0b0001)
// MOVZ
@@ -111,23 +168,8 @@
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd))
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd))
// This macro will give a -Wsign-compare warning, probably bug #38341
#define MOV32w(Rd, imm32) \
if(~((uint32_t)(imm32))<0xffffu) { \
MOVNw(Rd, (~(uint32_t)(imm32))&0xffff); \
} else { \
MOVZw(Rd, (imm32)&0xffff); \
if((imm32)&0xffff0000) {MOVKw_LSL(Rd, ((imm32)>>16)&0xffff, 16);} \
}
#define MOV64x(Rd, imm64) \
if(~((uint64_t)(imm64))<0xffff) { \
MOVNx(Rd, (~(uint64_t)(imm64))&0xffff); \
} else { \
MOVZx(Rd, ((uint64_t)(imm64))&0xffff); \
if(((uint64_t)(imm64))&0xffff0000) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>16)&0xffff, 16);} \
if(((uint64_t)(imm64))&0xffff00000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>32)&0xffff, 32);} \
if(((uint64_t)(imm64))&0xffff000000000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>48)&0xffff, 48);} \
}
#define MOV32w(Rd, imm32) arm64_move32(dyn, ninst, Rd, imm32)
#define MOV64x(Rd, imm64) arm64_move64(dyn, ninst, Rd, imm64)
#define MOV64xw(Rd, imm64) if(rex.w) {MOV64x(Rd, imm64);} else {MOV32w(Rd, imm64);}
#define MOV64z(Rd, imm64) if(rex.is32bits) {MOV32w(Rd, imm64);} else {MOV64x(Rd, imm64);}
@@ -513,18 +555,24 @@
// logic to get the mask is ... convoluted... list of possible value there: https://gist.github.com/dinfuehr/51a01ac58c0b23e4de9aac313ed6a06a
#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 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))
#define EORx_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(1, 0b10, N, immr, imms, Rn, Rd))
#define EORw_mask(Rd, Rn, immr, imms) EMIT(LOGIC_gen(0, 0b10, 0, immr, imms, Rn, Rd))
#define EORxw_mask(Rd, Rn, N, immr, imms) EMIT(LOGIC_gen(rex.w, 0b10, rex.w?(N):0, immr, imms, Rn, Rd))
#define TSTx_mask(Rn, N, immr, imms) ANDSx_mask(xZR, Rn, N, immr, imms)
#define TSTw_mask(Rn, immr, imms) ANDSw_mask(wZR, Rn, immr, imms)
#define TSTxw_mask(Rn, N, immr, imms) ANDSxw_mask(xZR, Rn, N, immr, imms)
#define LOGIC_REG_gen(sf, opc, shift, N, Rm, imm6, Rn, Rd) ((sf)<<31 | (opc)<<29 | 0b01010<<24 | (shift)<<22 | (N)<<21 | (Rm)<<16 | (imm6)<<10 | (Rn)<<5 | (Rd))
#define ANDx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b00, 0b00, 0, Rm, 0, Rn, Rd))
#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))
@@ -610,6 +658,7 @@
#define BFIx(Rd, Rn, lsb, width) BFMx(Rd, Rn, ((-(lsb))%64)&0x3f, (width)-1)
#define BFIw(Rd, Rn, lsb, width) BFMw(Rd, Rn, ((-(lsb))%32)&0x1f, (width)-1)
#define BFIxw(Rd, Rn, lsb, width) if(rex.w) {BFIx(Rd, Rn, lsb, width);} else {BFIw(Rd, Rn, lsb, width);}
#define BFIz(Rd, Rn, lsb, width) if(rex.is32bits) {BFIw(Rd, Rn, lsb, width);} else {BFIx(Rd, Rn, lsb, width);}
#define BFCx(Rd, lsb, width) BFMx(Rd, xZR, ((-(lsb))%64)&0x3f, (width)-1)
#define BFCw(Rd, lsb, width) BFMw(Rd, xZR, ((-(lsb))%32)&0x1f, (width)-1)
#define BFCxw(Rd, lsb, width) BFMxw(Rd, xZR, rex.w?(((-(lsb))%64)&0x3f):(((-(lsb))%32)&0x1f), (width)-1)
@@ -766,6 +815,12 @@
// mrs x0, fpsr : 1101010100 1 1 1 011 0100 0100 001 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=1
#define MRS_fpsr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 1, Rt))
#define MSR_fpsr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 1, Rt))
// mrs x0, cntvct_el0 op0=0b11 op1=0b011 CRn=0b1110 CRm=0b0000 op2=0b010
#define MRS_cntvct_el0(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b1110, 0b0000, 0b010, Rt))
// mrs x0, cntpctss_el0 op0=0b11 op1=0b011 CRn=0b1110 CRm=0b0000 op2=0b101
#define MRS_cntpctss_el0(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b1110, 0b0000, 0b101, Rt))
// mrs rt, rndr op0=0b11 op1=0b011 CRn=0b0010 CRm=0b0100 op2=0b000
#define MRS_rndr(Rt) EMIT(MRS_gen(1, 1, 0b011, 0b0010, 0b0100, 0b000, Rt))
// NEON Saturation Bit
#define FPSR_QC 27
// NEON Input Denormal Cumulative
@@ -1062,6 +1117,12 @@
#define VMOVHto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<2) | 2, Vn, Wd))
#define VMOVSto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<3) | 4, Vn, Wd))
#define SMOV_gen(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 0b01<<13 | 0<<12 | 1<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SMOVQDto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<4) | 8, Vn, Xd))
#define SMOVQBto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<1) | 1, Vn, Xd))
#define SMOVQHto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<2) | 2, Vn, Xd))
#define SMOVQSto(Xd, Vn, index) EMIT(SMOV_gen(1, ((index)<<3) | 4, Vn, Xd))
#define MVN_vector(Q, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VMVNQ(Rd, Rn) EMIT(MVN_vector(1, Rn, Rd))
@@ -1132,6 +1193,13 @@
#define FABSS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b01, Sn, Sd))
#define FABSD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b01, Dn, Dd))
#define FNEGABS_vector(Q, U, sz, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b01111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFNEGS(Vd, Vn) EMIT(FNEGABS_vector(0, 1, 0, Vn, Vd))
#define VFNEGQS(Vd, Vn) EMIT(FNEGABS_vector(1, 1, 0, Vn, Vd))
#define VFNEGQD(Vd, Vn) EMIT(FNEGABS_vector(1, 1, 1, Vn, Vd))
#define VFABSS(Vd, Vn) EMIT(FNEGABS_vector(0, 0, 0, Vn, Vd))
#define VFABSQS(Vd, Vn) EMIT(FNEGABS_vector(1, 0, 0, Vn, Vd))
#define VFABSQD(Vd, Vn) EMIT(FNEGABS_vector(1, 0, 1, Vn, Vd))
// MUL
#define FMUL_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11011<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1143,11 +1211,6 @@
#define FMULS(Sd, Sn, Sm) EMIT(FMUL_scalar(0b00, Sm, Sn, Sd))
#define FMULD(Dd, Dn, Dm) EMIT(FMUL_scalar(0b01, Dm, Dn, Dd))
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMLAS(Sd, Sn, Sm) EMIT(FMLA_vector(0, 0, 0, Sm, Sn, Sd))
#define VFMLAQS(Sd, Sn, Sm) EMIT(FMLA_vector(1, 0, 0, Sm, Sn, Sd))
#define VFMLAQD(Dd, Dn, Dm) EMIT(FMLA_vector(1, 0, 1, Dm, Dn, Dd))
// DIV
#define FDIV_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFDIVS(Sd, Sn, Sm) EMIT(FDIV_vector(0, 0, Sm, Sn, Sd))
@@ -1192,8 +1255,8 @@
#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, 0, Sn, 0b01))
#define FCMPD_0(Dn) EMIT(FCMP_scalar(0b01, 0, Dn, 0b01))
#define FCMPS_0(Sn) EMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) EMIT(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))
@@ -1349,18 +1412,30 @@
#define FCVTN(Vd, Vn) EMIT(FCVTN_vector(0, 1, Vn, Vd))
// Convert Vn from 2*Double to higher Vd as 2*float, use FPCR rounding
#define FCVTN2(Vd, Vn) EMIT(FCVTN_vector(1, 1, Vn, Vd))
// Convert Vn from 2*Float to lower Vd as 2*float16 and clears the upper half, use FPCR rounding
#define FCVTN16(Vd, Vn) EMIT(FCVTN_vector(0, 0, Vn, Vd))
// Convert Vn from 2*Float to higher Vd as 2*float16, use FPCR rounding
#define FCVTN162(Vd, Vn) EMIT(FCVTN_vector(1, 0, Vn, Vd))
#define FCVTXN_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10110<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert Vn from 2*Double to lower Vd as 2*float and clears the upper half
#define FCVTXN(Vd, Vn) EMIT(FCVTXN_vector(0, 1, Vn, Vd))
// Convert Vn from 2*Double to higher Vd as 2*float
#define FCVTXN2(Vd, Vn) EMIT(FCVTXN_vector(1, 1, Vn, Vd))
// Convert Vn from 2*Float to lower Vd as 2*float16 and clears the upper half
#define FCVTXN16(Vd, Vn) EMIT(FCVTXN_vector(0, 0, Vn, Vd))
// Convert Vn from 2*Float to higher Vd as 2*float16
#define FCVTXN162(Vd, Vn) EMIT(FCVTXN_vector(1, 0, Vn, Vd))
#define FCVTL_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b10111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Convert lower Vn from 2*float to Vd as 2*double
#define FCVTL(Vd, Vn) EMIT(FCVTL_vector(0, 1, Vn, Vd))
// Convert higher Vn from 2*float to Vd as 2*double
#define FCVTL2(Vd, Vn) EMIT(FCVTL_vector(1, 1, Vn, Vd))
// Convert lower Vn from 2*float16 to Vd as 2*float
#define FCVTL16(Vd, Vn) EMIT(FCVTL_vector(0, 0, Vn, Vd))
// Convert higher Vn from 2*float16 to Vd as 2*float
#define FCVTL162(Vd, Vn) EMIT(FCVTL_vector(1, 0, Vn, Vd))
#define SCVTF_scalar(sf, type, rmode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
#define SCVTFSw(Sd, Wn) EMIT(SCVTF_scalar(0, 0b00, 0b00, 0b010, Wn, Sd))
@@ -1432,6 +1507,37 @@
// FMAXNM NaN vs Number: number is picked
#define FMAXNMD(Dd, Dn, Dm) EMIT(FMINMAX_scalar(0b01, Dm, 0b10, Dn, Dd))
// Fused Add Multiply
#define FMADD_gen(type, o1, Rm, o0, Ra, Rn, Rd) (0b11111<<24 | (type)<<22 | (o1)<<21 | (Rm)<<16 | (o0)<<15 | (Ra)<<10 | (Rn)<<5 | (Rd))
// scalar Rd = Ra + Rn*Rm
#define FMADD_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 0, Sm, 0, Sa, Sn, Sd))
// scalar Rd = Ra + Rn*Rm
#define FMADD_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 0, Dm, 0, Da, Dn, Dd))
// scalar Rd = -Ra - Rn*Rm
#define FNMADD_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 1, Sm, 0, Sa, Sn, Sd))
// scalar Rd = -Ra - Rn*Rm
#define FNMADD_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 1, Dm, 0, Da, Dn, Dd))
// scalar Rd = Ra - Rn*Rm
#define FMSUB_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 0, Sm, 1, Sa, Sn, Sd))
// scalar Rd = Ra - Rn*Rm
#define FMSUB_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 0, Dm, 1, Da, Dn, Dd))
// scalar Rd = -Ra + Rn*Rm
#define FNMSUB_32(Sd, Sa, Sn, Sm) EMIT(FMADD_gen(0b00, 1, Sm, 1, Sa, Sn, Sd))
// scalar Rd = -Ra + Rn*Rm
#define FNMSUB_64(Dd, Da, Dn, Dm) EMIT(FMADD_gen(0b01, 1, Dm, 1, Da, Dn, Dd))
#define FMLA_vector(Q, op, sz, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (op)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11001<<11 | 1<<10 | (Rn)<<5 | (Rd))
// Vd += Vn*Vm
#define VFMLAS(Vd, Vn, Vm) EMIT(FMLA_vector(0, 0, 0, Vm, Vn, Vd))
// Vd += Vn*Vm
#define VFMLAQS(Vd, Vn, Vm) EMIT(FMLA_vector(1, 0, 0, Vm, Vn, Vd))
// Vd += Vn*Vm
#define VFMLAQD(Vd, Vn, Vm) EMIT(FMLA_vector(1, 0, 1, Vm, Vn, Vd))
// Vd -= Vn*Vm
#define VFMLSQS(Vd, Vn, Vm) EMIT(FMLA_vector(1, 1, 0, Vm, Vn, Vd))
// Vd -= Vn*Vm
#define VFMLSQD(Vd, Vn, Vm) EMIT(FMLA_vector(1, 1, 1, Vm, Vn, Vd))
// ZIP / UZP
#define ZIP_gen(Q, size, Rm, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (size)<<22 | (Rm)<<16 | (op)<<14 | 0b11<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VZIP1Q_8(Rt, Rn, Rm) EMIT(ZIP_gen(1, 0b00, Rm, 0, Rn, Rt))
@@ -1465,6 +1571,16 @@
#define VUZP1Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 0, Rn, Rt))
#define VUZP2Q_64(Rt, Rn, Rm) EMIT(UZP_gen(1, 0b11, Rm, 1, Rn, Rt))
#define BITBIF_gen(Q, opc2, Rm, Rn, Rd) ((Q)<<30 | 0b101110<<24 | (opc2)<<22 | 1<<21 | (Rm)<<16 | 0b000111<<10 | (Rn)<<5 | (Rd))
// Bitwise insert Vn in Vd if Vm is "0"
#define VBIF(Vd, Vn,Vm) EMIT(BITBIF_gen(0, 0b11, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "0"
#define VBIFQ(Vd, Vn,Vm) EMIT(BITBIF_gen(1, 0b11, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "1"
#define VBIT(Vd, Vn,Vm) EMIT(BITBIF_gen(0, 0b10, Vm, Vn, Vd))
// Bitwise insert Vn in Vd if Vm is "1"
#define VBITQ(Vd, Vn,Vm) EMIT(BITBIF_gen(1, 0b10, Vm, Vn, Vd))
#define DUP_element(Q, imm5, Rn, Rd) ((Q)<<30 | 0b01110000<<21 | (imm5)<<16 | 1<<10 | (Rn)<<5 | (Rd))
#define VDUP_8(Vd, Vn, idx) EMIT(DUP_element(0, ((idx)<<1|1), Vn, Vd))
#define VDUPQ_8(Vd, Vn, idx) EMIT(DUP_element(1, ((idx)<<1|1), Vn, Vd))
@@ -1563,6 +1679,15 @@
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit higher part of Rd
#define SQXTUN2_8(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b00, Rn, Rd))
#define XTN_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b10010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Xtract narrow to X bits
#define XTN_8(Vd, Vn) EMIT(XTN_vector(0, 0b00, Vn, Vd))
#define XTN_16(Vd, Vn) EMIT(XTN_vector(0, 0b01, Vn, Vd))
#define XTN_32(Vd, Vn) EMIT(XTN_vector(0, 0b10, Vn, Vd))
#define XTN2_8(Vd, Vn) EMIT(XTN_vector(1, 0b00, Vn, Vd))
#define XTN2_16(Vd, Vn) EMIT(XTN_vector(1, 0b01, Vn, Vd))
#define XTN2_32(Vd, Vn) EMIT(XTN_vector(1, 0b10, Vn, Vd))
// Integer CMP
// EQual
#define CMEQ_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10001<<11 | 1<<10 | (Rn)<<5 | (Rd))
@@ -1600,8 +1725,8 @@
#define VCHIQQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b11, 0, Rm, Rn, Rd))
// Less Than 0
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
#define CMLT_0_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define CMLT_0_8(Rd, Rn) EMIT(CMLT_0_vector(0, 0b00, Rn, Rd))
#define CMLT_0_16(Rd, Rn) EMIT(CMLT_0_vector(0, 0b01, Rn, Rd))
#define CMLT_0_32(Rd, Rn) EMIT(CMLT_0_vector(0, 0b10, Rn, Rd))
#define CMLTQ_0_8(Rd, Rn) EMIT(CMLT_0_vector(1, 0b00, Rn, Rd))
@@ -1785,8 +1910,12 @@
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVIQ_16(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
#define MOVIQ_32(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
#define MOVIQ_32_lsl(Rd, imm8, lsl8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), (lsl8<<1), ((imm8)&0b11111), Rd))
#define MOVIQ_64(Rd, imm8) EMIT(MOVI_vector(1, 1, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_16(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1000|((lsl8)?0b10:0), ((imm8)&0b11111), Rd))
#define MOVI_32_lsl(Rd, imm8, lsl8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), (lsl8<<1), ((imm8)&0b11111), Rd))
#define MOVI_32(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b0000, ((imm8)&0b11111), Rd))
#define MOVI_64(Rd, imm8) EMIT(MOVI_vector(0, 1, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
@@ -1888,6 +2017,33 @@
#define UMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 1, Vn, Vd))
//#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
// MIN or MAX accros vector
#define MAXMINV_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b11000<<17 | (op)<<16 | 0b1010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SMAXV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b00, 0, Vn, Vd))
#define SMINV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b00, 1, Vn, Vd))
#define UMAXV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b00, 0, Vn, Vd))
#define UMINV_8(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b00, 1, Vn, Vd))
#define SMAXV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b01, 0, Vn, Vd))
#define SMINV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b01, 1, Vn, Vd))
#define UMAXV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b01, 0, Vn, Vd))
#define UMINV_16(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b01, 1, Vn, Vd))
#define SMAXV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b10, 0, Vn, Vd))
#define SMINV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 0, 0b10, 1, Vn, Vd))
#define UMAXV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b10, 0, Vn, Vd))
#define UMINV_32(Vd, Vn) EMIT(MAXMINV_vector(0, 1, 0b10, 1, Vn, Vd))
#define SMAXVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b00, 0, Vn, Vd))
#define SMINVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b00, 1, Vn, Vd))
#define UMAXVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b00, 0, Vn, Vd))
#define UMINVQ_8(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b00, 1, Vn, Vd))
#define SMAXVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b01, 0, Vn, Vd))
#define SMINVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b01, 1, Vn, Vd))
#define UMAXVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b01, 0, Vn, Vd))
#define UMINVQ_16(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b01, 1, Vn, Vd))
#define SMAXVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b10, 0, Vn, Vd))
#define SMINVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 0, 0b10, 1, Vn, Vd))
#define UMAXVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b10, 0, Vn, Vd))
#define UMINVQ_32(Vd, Vn) EMIT(MAXMINV_vector(1, 1, 0b10, 1, Vn, Vd))
// HADD vector
#define HADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 1<<10 | (Rn)<<5 | (Rd))
#define SHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b00, Vm, Vn, Vd))
@@ -2171,6 +2327,24 @@
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
#define FRINTxx_vector(Q, U, sz, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b1111<<13 | (op)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFRINT32ZS(Vd, Vn) EMIT(FRINTxx_vector(0, 0, 0, 0, Vn, Vd))
#define VFRINT32ZSQ(Vd, Vn) EMIT(FRINTxx_vector(1, 0, 0, 0, Vn, Vd))
#define VFRINT32XS(Vd, Vn) EMIT(FRINTxx_vector(0, 1, 0, 0, Vn, Vd))
#define VFRINT32XSQ(Vd, Vn) EMIT(FRINTxx_vector(1, 1, 0, 0, Vn, Vd))
#define VFRINT32ZD(Vd, Vn) EMIT(FRINTxx_vector(0, 0, 1, 0, Vn, Vd))
#define VFRINT32ZDQ(Vd, Vn) EMIT(FRINTxx_vector(1, 0, 1, 0, Vn, Vd))
#define VFRINT32XD(Vd, Vn) EMIT(FRINTxx_vector(0, 1, 1, 0, Vn, Vd))
#define VFRINT32XDQ(Vd, Vn) EMIT(FRINTxx_vector(1, 1, 1, 0, Vn, Vd))
#define VFRINT64ZS(Vd, Vn) EMIT(FRINTxx_vector(0, 0, 0, 1, Vn, Vd))
#define VFRINT64ZSQ(Vd, Vn) EMIT(FRINTxx_vector(1, 0, 0, 1, Vn, Vd))
#define VFRINT64XS(Vd, Vn) EMIT(FRINTxx_vector(0, 1, 0, 1, Vn, Vd))
#define VFRINT64XSQ(Vd, Vn) EMIT(FRINTxx_vector(1, 1, 0, 1, Vn, Vd))
#define VFRINT64ZD(Vd, Vn) EMIT(FRINTxx_vector(0, 0, 1, 1, Vn, Vd))
#define VFRINT64ZDQ(Vd, Vn) EMIT(FRINTxx_vector(1, 0, 1, 1, Vn, Vd))
#define VFRINT64XD(Vd, Vn) EMIT(FRINTxx_vector(0, 1, 1, 1, Vn, Vd))
#define VFRINT64XDQ(Vd, Vn) EMIT(FRINTxx_vector(1, 1, 1, 1, Vn, Vd))
// CRC32 extension
#define CRC32C_gen(sf, Rm, sz, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b010<<13 | 1<<12 | (sz)<<10 | (Rn)<<5 | (Rd))
#define CRC32CB(Wd, Wn, Wm) EMIT(CRC32C_gen(0, Wm, 0b00, Wn, Wd))
-20
View File
@@ -34,23 +34,3 @@ arm64_epilog:
ldp x30, x29, [sp], 16 // saved lr
//end, return...
ret
.global arm64_epilog_fast
arm64_epilog_fast:
//restore all used register
add sp, x28, 0
//vpop {d8-d15}
ldp x19, x20, [sp, (8 * 0)]
ldp x21, x22, [sp, (8 * 2)]
ldp x23, x24, [sp, (8 * 4)]
ldp x25, x26, [sp, (8 * 6)]
ldp x27, x28, [sp, (8 * 8)]
ldp d8, d9, [sp, (8 *10)]
ldp d10, d11, [sp, (8 *12)]
ldp d12, d13, [sp, (8 *14)]
ldp d14, d15, [sp, (8 *16)]
add sp, sp, (8 * 18)
ldp x30, x29, [sp], 16 // saved lr
//end, return...
ret
+88
View File
@@ -0,0 +1,88 @@
#include <stdint.h>
#include "arm64_immenc.h"
#define one (uint64_t)1
// Returns the packed valid-N-imms-immr (1-1-6-6 bits); returns 0 if bitmask is not encodable
int convert_bitmask(uint64_t bitmask) {
if (bitmask == 0 || bitmask == ~0ULL) return 0;
uint64_t size, mask, pat;
for (size = 6; size > 1; --size) {
mask = (one << (1 << (size - 1))) - 1;
pat = bitmask & mask;
if (pat != ((bitmask >> (1 << (size - 1))) & mask)) {
break;
}
}
mask = (size >= 6) ? ~0ULL : ((one << (1 << size)) - 1);
pat = bitmask & mask;
for (uint64_t i = 1; i < 7 - size; ++i) {
uint64_t boff = i * (1 << size);
if (((bitmask >> boff) & mask) != pat) {
return 0;
}
}
int immr = 0;
uint64_t last_bit = one << ((1 << size) - 1);
if (pat & 1) {
while (pat & last_bit) {
pat = ((pat - last_bit) << 1) | 1;
++immr;
}
} else {
immr = 1 << size;
while (!(pat & 1)) {
pat >>= 1;
--immr;
}
}
if (pat & (pat + 1)) return 0;
int to = 1;
while (pat & (one << to)) ++to;
return 0x2000 + ((size == 6) << 12) + ((((0x1E << size) & 0x3F) + (to - 1)) << 6) + immr;
}
#if 0
#include <unordered_set>
int main() {
std::unordered_set<uint64_t> okvals;
uint64_t val;
for (int n = 1; n < 7; ++n) {
int imms0 = ((n == 6) ? 0xC0 : 0x80) + ((0x1E << n) & 0x3F);
for (int nones = 0; nones < (1 << n) - 1; ++nones) {
val = (one << (nones + 1)) - 1;
for (int j = 0; j < 6 - n; ++j) {
val += val << (1 << (n + j));
}
for (int immr = 0; immr < (1 << n); ++immr) {
int exp = ((imms0 + nones) << 6) + immr;
int got = convert_bitmask(val);
if (exp != got) {
printf("0x%016lX: expected %04X, got %04X\n", val, exp, got);
}
okvals.emplace(val);
val = (val >> 1) | ((val & 1) << 63);
}
}
}
#pragma omp parallel for
for (uint64_t i = 1; i < 0xFFFFFFFFFFFFFFFFu; ++i) {
int got = convert_bitmask(i);
if (!!got != (okvals.find(i) != okvals.cend())) {
printf("0x%016lX: expected %s, got %04X\n", i, (!!got ? "non0" : "0000"), got);
}
}
}
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef __ARM64_IMMENC_H__
#define __ARM64_IMMENC_H__
#include <stdint.h>
int convert_bitmask(uint64_t bitmask);
#endif // __ARM64_IMMENC_H__
+82 -9
View File
@@ -34,10 +34,12 @@ uint64_t DecodeBitMasks(int N, int imms, int immr)
if(s==levels) return 0;
uint64_t mask = (1LL<<(s+1))-1;
if(r) { // rotate
mask=(mask>>r)|(mask<<(e-r));
mask&=((1LL<<e)-1);
mask=(mask>>r)|(mask<<(e-r));
if(e<64) {
mask&=((1LL<<e)-1);
}
}
while (e<64) { // replicate
while(e<64) { // replicate
mask|=(mask<<e);
e<<=1;
}
@@ -387,13 +389,13 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
if(isMask(opcode, "f00100101wwiiiiiiiiiiiiiiiiddddd", &a)) {
if(sf) {
uint64_t noti=~(uint64_t)imm;
uint64_t noti=~(((uint64_t)imm)<<(hw*16));
if(!hw)
snprintf(buff, sizeof(buff), "MOVN %s, 0x%x\t; 0x%lx", Xt[Rd], imm, noti);
else
snprintf(buff, sizeof(buff), "MOVN %s, 0x%x LSL %d\t; 0x%lx", Xt[Rd], imm, 16*hw, noti);
} else {
uint32_t noti=~(uint32_t)imm;
uint32_t noti=~(((uint32_t)imm)<<(hw*16));
if(!hw)
snprintf(buff, sizeof(buff), "MOVN %s, 0x%x\t; 0x%x", Wt[Rd], imm, noti);
else
@@ -914,7 +916,6 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
// UMOV
if(isMask(opcode, "0Q001110000rrrrr001111nnnnnddddd", &a)) {
char q = a.Q?'Q':'D';
char s = '?';
int sz=0;
if(a.Q==0 && immr&1) {s='B'; sz=0; }
@@ -923,9 +924,24 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
else if(a.Q==1 && (immr&15)==8) {s='D'; sz=3; }
int index = (immr)>>(sz+1);
if(sz>2)
snprintf(buff, sizeof(buff), "MOV %s, %c%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], q, Rn, s, index);
snprintf(buff, sizeof(buff), "MOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
else
snprintf(buff, sizeof(buff), "UMOV %s, %c%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], q, Rn, s, index);
snprintf(buff, sizeof(buff), "UMOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
return buff;
}
// SMOV
if(isMask(opcode, "0Q001110000rrrrr001011nnnnnddddd", &a)) {
char s = '?';
int sz=0;
if(a.Q==0 && immr&1) {s='B'; sz=0; }
else if(/*a.Q==0 &&*/ (immr&3)==2) {s='H'; sz=1; }
else if(/*a.Q==0 &&*/ (immr&7)==4) {s='S'; sz=2; }
else if(a.Q==1 && (immr&15)==8) {s='D'; sz=3; }
int index = (immr)>>(sz+1);
if(sz>2)
snprintf(buff, sizeof(buff), "MOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
else
snprintf(buff, sizeof(buff), "SMOV %s, V%d.%c[%d]", a.Q?Xt[Rd]:Wt[Rd], Rn, s, index);
return buff;
}
// VEOR
@@ -950,6 +966,12 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "VMUL V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// VBIT / VBIF
if(isMask(opcode, "0Q1011101o1mmmmm000111nnnnnddddd", &a)) {
char q = a.Q?'Q':'D';
snprintf(buff, sizeof(buff), "VBI%c %c%d, %c%d, %c%d", a.o?'F':'T', q, Rd, q, Rn, q, Rm);
return buff;
}
// CMP
if(isMask(opcode, "0Q101110ff1mmmmm100011nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -1005,6 +1027,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm<<8);
return buff;
}
// MOV immediate 64bits
if(isMask(opcode, "0Q10111100000iii111001iiiiiddddd", &a)) {
uint64_t tmp64u = 0;
for(int i=0; i<8; ++i)
if((imm)&(1<<i))
tmp64u |= 0xffLL<<(i*8);
if(a.Q)
snprintf(buff, sizeof(buff), "MOVI V%d.2D, #0x%016lx", Rd, tmp64u);
else
snprintf(buff, sizeof(buff), "MOVI D%d, #0x%016lx", Rd, tmp64u);
return buff;
}
// Shift
if(isMask(opcode, "0QU011110hhhhrrr000001nnnnnddddd", &a)) {
@@ -1295,6 +1330,28 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "F%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FMADD
if(isMask(opcode, "00011111tt0mmmmmoaaaaannnnnddddd", &a)) {
char s = (a.t==0b00)?'S':((a.t==0b01)?'D':'?');
int n = (a.t==0)?1:2;
snprintf(buff, sizeof(buff), "FM%s V%d.%d%c, V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"SUB":"ADD", Rd, n, s, Ra, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FNMADD
if(isMask(opcode, "00011111tt1mmmmmoaaaaannnnnddddd", &a)) {
char s = (a.t==0b00)?'S':((a.t==0b01)?'D':'?');
int n = (a.t==0)?1:2;
snprintf(buff, sizeof(buff), "FNM%s V%d.%d%c, V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"SUB":"ADD", Rd, n, s, Ra, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FMLA
if(isMask(opcode, "0Q001110of1mmmmm110011nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
int n = (sf==0)?2:1;
n *= a.Q?2:1;
snprintf(buff, sizeof(buff), "FML%s%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"S":"A", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// NEG
if(isMask(opcode, "0Q101110ff100000101110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
@@ -1574,6 +1631,17 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "%cSHLL%s V%d.%s, V%d.%s, #%d", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd, sh);
return buff;
}
if(isMask(opcode, "0Q0011110hhhhiii010101nnnnnddddd", &a) && (a.h != 0b1000)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
int sz = 3;
if((a.h&0b1111)==0b0001) sz=0;
else if((a.h&0b1110)==0b0010) sz=1;
else if((a.h&0b1100)==0b0100) sz=2;
int sh=(((a.h)<<3)|(imm)) - (8<<sz);
const char* Vd = Y[(sz<<1)|a.Q];
snprintf(buff, sizeof(buff), "SHL%s V%d.%s, V%d.%s, #%d", a.Q?"Q":"", Rd, Vd, Rn, Vd, sh);
return buff;
}
// DUP
if(isMask(opcode, "0Q001110000iiiii000001nnnnnddddd", &a)) {
@@ -1583,7 +1651,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
if((imm&0b0001)==0b0001) sz=0;
else if((imm&0b0011)==0b0010) sz=1;
else if((imm&0b0111)==0b0100) sz=2;
int sh=imm - (1<<sz);
int sh=(imm>>sz) - 1;
const char* Vd = Y[(sz<<1)|a.Q];
const char* Vn = Z[sz];
snprintf(buff, sizeof(buff), "DUP V%d.%s, V%d.%s[%d]", Rd, Vd, Rn, Vn, sh);
@@ -1759,6 +1827,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "SHA256H2 Q%d, Q%d, V%d.4S", Rd, Rn, Rm);
return buff;
}
// UDF
if(isMask(opcode, "0000000000000000iiiiiiiiiiiiiiii", &a)) {
snprintf(buff, sizeof(buff), "UDF 0x%x", a.i);
return buff;
}
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
return buff;
+1 -4
View File
@@ -6,8 +6,6 @@
.text
.align 4
.extern arm64_next
.global arm64_prolog
arm64_prolog:
//save all 18 used register
@@ -34,8 +32,7 @@ arm64_prolog:
ldp x24, x25, [x0, (8 * 14)]
ldp x26, x27, [x0, (8 * 16)]
// Push a jump next on the stack
adr x28, arm64_next
stp x28, xzr, [sp, -16]!
stp xzr, xzr, [sp, -16]!
// Save old xSP in x28
add x28, sp, 16
//jump to function
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+126 -25
View File
@@ -78,6 +78,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0B:
INST_NAME("OR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_or32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0F:
opcode = F8;
switch(opcode) {
@@ -278,6 +288,17 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x13:
INST_NAME("ADC Gd, Seg:Ed");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_adc32(dyn, ninst, rex, gd, ed, x3, x5);
break;
case 0x21:
INST_NAME("AND Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -289,6 +310,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
WBACKO(x4);
break;
case 0x23:
INST_NAME("AND Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_and32(dyn, ninst, rex, gd, ed, x3, x5);
break;
case 0x29:
INST_NAME("SUB Seg:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -397,6 +428,24 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
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 0x80:
nextop = F8;
switch((nextop>>3)&7) {
@@ -762,27 +811,19 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(ed!=x1) {MOVxw_REG(x1, ed);}
CALL_(rcl32, ed, x6);
WBACK;
emit_rcl32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 3:
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(ed!=x1) {MOVxw_REG(x1, ed);}
CALL_(rcr32, ed, x6);
WBACK;
emit_rcr32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 4:
case 6:
@@ -867,7 +908,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
if(rex.w) {
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
@@ -884,7 +925,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
if(rex.w) {
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
@@ -946,6 +987,10 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xEB:
// just use regular inconditional jump
return dynarec64_00(dyn, addr-1, ip, ninst, rex, rep, ok, need_epilog);
case 0xF7:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
@@ -1011,9 +1056,19 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
SET_DFNONE(x2);
GETEDO(x6, 0);
if(box64_dynarec_div0) {
CBNZx_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
if(MODREG) {
@@ -1029,8 +1084,17 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETEDO(x6, 0);
if(box64_dynarec_div0) {
CBNZx_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
@@ -1041,10 +1105,19 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CALL(div64, -1);
B_NEXT_nocond;
MARK;
if(box64_dynarec_div0) {
CBNZx_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2);
}
}
break;
@@ -1052,11 +1125,21 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2)
if(!rex.w) {
SET_DFNONE(x2)
GETSEDOw(x6, 0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
if(box64_dynarec_div0) {
CBNZx_MARK3(wb);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
SDIVx(x2, x3, wb);
MSUBx(x4, x2, wb, x3);
MOVw_REG(xRAX, x2);
@@ -1066,13 +1149,32 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
GETEDO(x6, 0);
if(box64_dynarec_div0) {
CBNZx_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
} else {
GETEDO(x6, 0);
if(box64_dynarec_div0) {
CBNZx_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
CBZxw_MARK(xRDX);
MVNx_REG(x2, xRDX);
CBZxw_MARK(x2);
@@ -1083,7 +1185,6 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2)
}
}
break;
@@ -1116,7 +1217,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
}
GETEDOz(x6, 0);
if(box64_dynarec_callret && box64_dynarec_bigblock>1) {
@@ -1145,14 +1246,14 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STPx_S7_preindex(x4, xRIP, xSP, -16);
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
GETEDOz(x6, 0);
jump_to_next(dyn, 0, ed, ninst);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
*need_epilog = 0;
*ok = 0;
break;
+262 -148
View File
@@ -13,6 +13,7 @@
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "emu/x87emu_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
@@ -81,26 +82,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_add16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x06:
if(rex.is32bits) {
INST_NAME("PUSH ES");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
PUSH1_32(x1);
} else {
DEFAULT;
}
INST_NAME("PUSH ES");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
PUSH1_16(x1);
break;
case 0x07:
if(rex.is32bits) {
INST_NAME("POP ES");
POP1_32(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_ES]));
} else {
DEFAULT;
}
INST_NAME("POP ES");
POP1_16(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_ES]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_ES]));
break;
case 0x09:
@@ -128,7 +121,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x0F:
@@ -166,7 +159,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_adc16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x19:
@@ -197,26 +190,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOVZw(x2, i16);
emit_sbb16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x1E:
if(rex.is32bits) {
INST_NAME("PUSH DS");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
PUSH1_32(x1);
} else {
DEFAULT;
}
INST_NAME("PUSH DS");
LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
PUSH1_16(x1);
break;
case 0x1F:
if(rex.is32bits) {
INST_NAME("POP DS");
POP1_32(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
} else {
DEFAULT;
}
INST_NAME("POP DS");
POP1_16(x1);
STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
break;
case 0x21:
@@ -244,7 +229,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x29:
@@ -272,7 +257,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_sub16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x31:
@@ -300,7 +285,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x1, xRAX);
MOV32w(x2, i32);
emit_xor16(dyn, ninst, x1, x2, x3, x4);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x39:
@@ -370,17 +355,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x55:
case 0x56:
case 0x57:
if(rex.is32bits) {
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07);
if (gd==xRSP) {
MOVw_REG(x1, xRSP);
PUSH1_16(x1);
} else {
PUSH1_16(gd);
}
INST_NAME("PUSH reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if (gd==xRSP) {
MOVw_REG(x1, xRSP);
PUSH1_16(x1);
} else {
DEFAULT;
PUSH1_16(gd);
}
break;
case 0x58:
@@ -391,14 +372,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x5D:
case 0x5E:
case 0x5F:
if(rex.is32bits) {
INST_NAME("POP reg");
gd = xRAX+(opcode&0x07);
POP1_16(x1);
BFIw(gd, x1, 0, 16);
} else {
DEFAULT;
}
INST_NAME("POP reg");
gd = xRAX+(opcode&0x07)+(rex.b<<3);
POP1_16(x1);
BFIw(gd, x1, 0, 16);
break;
case 0x60:
if(rex.is32bits) {
@@ -449,6 +426,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x68:
INST_NAME("PUSH Iw");
u16 = F16;
MOV32w(x2, u16);
PUSH1_16(x2);
break;
case 0x69:
case 0x6B:
if(opcode==0x69) {
@@ -586,8 +569,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGD;
GETED(0);
MOVxw_REG(x1, gd);
BFIx(gd, ed, 0, 16);
BFIx(ed, x1, 0, 16);
BFIz(gd, ed, 0, 16);
BFIz(ed, x1, 0, 16);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
@@ -621,7 +604,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SMDMB();
MARK2;
}
BFIx(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
}
break;
@@ -632,7 +615,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
BFIx(ed, gd, 0, 16);
BFIz(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
@@ -647,13 +630,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
if(ed!=gd) {
BFIx(gd, ed, 0, 16);
BFIz(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
SMREADLOCK(lock);
LDH(x1, ed, fixedaddress);
BFIx(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
}
break;
case 0x8C:
@@ -662,7 +645,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = (nextop&0x38)>>3;
LDRH_U12(x3, xEmu, offsetof(x64emu_t, segs[u8]));
if((nextop&0xC0)==0xC0) { // reg <= seg
UXTHw(xRAX+(nextop&7)+(rex.b<<3), x3);
BFIz(xRAX+(nextop&7)+(rex.b<<3), x3, 0, 16);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x3, wback, fixedaddress);
@@ -685,30 +668,41 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRH_U12(ed, xEmu, offsetof(x64emu_t, segs[u8]));
STRw_U12(wZR, xEmu, offsetof(x64emu_t, segs_serial[u8]));
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
MOVw_REG(x2, xRAX);
BFIx(xRAX, gd, 0, 16);
BFIx(gd, x2, 0, 16);
}
case 0x8F:
INST_NAME("POP Ew");
nextop = F8;
POP1_16(x1);
if((nextop&0xC0)==0xC0) {
wback = xRAX+(nextop&7)+(rex.b<<3);
BFIz(wback, x1, 0, 16);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
STH(x1, wback, fixedaddress);
}
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = xRAX+(opcode&0x07)+(rex.b<<3);
if(gd==xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
MOVw_REG(x2, xRAX);
BFIz(xRAX, gd, 0, 16);
BFIz(gd, x2, 0, 16);
}
break;
case 0x98:
INST_NAME("CBW");
SXTBw(x1, xRAX);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
break;
case 0x99:
INST_NAME("CWD");
@@ -718,11 +712,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x9C:
INST_NAME("PUSHF");
READFLAGS(X_ALL);
WILLWRITE();
PUSH1_16(xFlags);
SMWRITE();
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET);
SMREAD();
POP1_16(x1); // probably not usefull...
BFIw(xFlags, x1, 0, 16);
MOV32w(x1, 0x3F7FD7);
@@ -731,10 +728,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SET_DFNONE(x1);
if(box64_wine) { // should this be done all the time?
TBZ_NEXT(xFlags, F_TF);
MOV64x(x1, addr);
STORE_XEMU_CALL(x1);
CALL(native_singlestep, -1);
BFCw(xFlags, F_TF, 1);
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
@@ -748,7 +743,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(isLockAddress(u64)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDRH_U12(x2, x1, 0);
BFIx(xRAX, x2, 0, 16);
BFIz(xRAX, x2, 0, 16);
break;
case 0xA3:
@@ -759,11 +754,40 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u64 = F64;
MOV64z(x1, u64);
if(isLockAddress(u64)) lock=1; else lock = 0;
WILLWRITELOCK(lock);
STRH_U12(xRAX, x1, 0);
SMWRITELOCK(lock);
break;
case 0xA4:
SMREAD();
if(rep) {
INST_NAME("REP MOVSB");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
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;
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);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, 1);
LDRB_U12(x1, xRSI, 0);
STRB_U12(x1, xRDI, 0);
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xA5:
SMREAD();
if(rep) {
INST_NAME("REP MOVSW");
CBZx_NEXT(xRCX);
@@ -788,9 +812,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ADDx_REG(xRSI, xRSI, x3);
ADDx_REG(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xA7:
SMREAD();
switch(rep) {
case 1:
case 2:
@@ -840,6 +866,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xAB:
WILLWRITE();
if(rep) {
INST_NAME("REP STOSW");
CBZx_NEXT(xRCX);
@@ -848,11 +875,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRH_S9_postindex(xRAX, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
B_MARK3_nocond;
MARK2; // Part with DF==1
STRH_S9_postindex(xRAX, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
MARK3;
// done
} else {
INST_NAME("STOSW");
@@ -860,6 +888,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRH_U12(xRAX, xRDI, 0);
ADDx_REG(xRDI, xRDI, x3);
}
SMWRITE();
break;
case 0xAD:
@@ -877,14 +906,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
MARK3;
BFIx(xRAX, x2, 0, 16);
BFIz(xRAX, x2, 0, 16);
// done
} else {
INST_NAME("LODSW");
GETDIR(x3, 2);
LDRH_U12(x2, xRSI, 0);
ADDx_REG(xRSI, xRSI, x3);
BFIx(xRAX, x2, 0, 16);
BFIz(xRAX, x2, 0, 16);
}
break;
@@ -938,7 +967,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u16 = F16;
MOV32w(x1, u16);
gd = xRAX+(opcode&7)+(rex.b<<3);
BFIx(gd, x1, 0, 16);
BFIz(gd, x1, 0, 16);
break;
case 0xC1:
@@ -946,11 +975,12 @@ 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");
if(geted_ib(dyn, addr, ninst, nextop)&15) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
u8 = geted_ib(dyn, addr, ninst, nextop) & 15;
if (u8) {
SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);
GETEW(x1, 1);
u8 = F8;
emit_rol16c(dyn, ninst, x1, u8&15, x4, x5);
u8 = (F8)&0x1f;
emit_rol16c(dyn, ninst, x1, u8, x4, x5);
EWBACK;
} else {
FAKEED;
@@ -959,11 +989,11 @@ 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_OF|X_CF, SF_SUBSET_PENDING);
if (geted_ib(dyn, addr, ninst, nextop) & 15) {
SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING);
GETEW(x1, 1);
u8 = F8;
emit_ror16c(dyn, ninst, x1, u8&15, x4, x5);
u8 = (F8)&0x1f;
emit_ror16c(dyn, ninst, x1, u8, x4, x5);
EWBACK;
} else {
FAKEED;
@@ -972,31 +1002,37 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcl16, x1, x3);
EWBACK;
if (geted_ib(dyn, addr, ninst, nextop) & 31) {
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
emit_rcl16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 3:
INST_NAME("RCR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rcr16, x1, x3);
EWBACK;
if (geted_ib(dyn, addr, ninst, nextop) & 31) {
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 1);
u8 = F8;
emit_rcr16c(dyn, ninst, ed, u8, x4, x5);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8)&0x1f;
emit_shl16c(dyn, ninst, x1, u8, x5, x4);
@@ -1007,9 +1043,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 5:
INST_NAME("SHR Ed, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
INST_NAME("SHR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1, 0);
u8 = (F8)&0x1f;
emit_shr16c(dyn, ninst, x1, u8, x5, x4);
@@ -1020,9 +1056,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 7:
INST_NAME("SAR Ed, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
INST_NAME("SAR Ew, Ib");
if (geted_ib(dyn, addr, ninst, nextop) & 0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEW(x1, 0);
u8 = (F8)&0x1f;
emit_sar16c(dyn, ninst, x1, u8, x5, x4);
@@ -1042,7 +1078,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
u16 = F16;
MOV32w(x1, u16);
BFIx(ed, x1, 0, 16);
BFIz(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 2);
u16 = F16;
@@ -1071,22 +1107,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ew, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
emit_rcl16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
emit_rcr16c(dyn, ninst, x1, 1, x5, x4);
EWBACK;
break;
case 4:
@@ -1172,7 +1204,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("RCL Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
CALL_(rcl16, x1, x3);
@@ -1182,7 +1216,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("RCR Ew, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(box64_dynarec_safeflags>1)
MAYSETFLAGS();
SETFLAGS(X_OF|X_CF, SF_SET_DF);
ANDw_mask(x2, xRCX, 0, 0b00100);
GETEW(x1, 0);
CALL_(rcr16, x1, x3);
@@ -1236,6 +1272,54 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xD9:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
MOV32w(x2, 1);
CALL(fpu_savenv, -1);
break;
default:
DEFAULT;
}
break;
case 0xDD:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 4:
INST_NAME("FRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\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);}
CALL(native_frstor16, -1);
break;
case 6:
INST_NAME("FNSAVE Ed");
MESSAGE(LOG_DUMP, "Need Optimization\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);}
CALL(native_fsave16, -1);
CALL(reset_fpu, -1);
break;
default:
DEFAULT;
}
break;
case 0xF0:
return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
@@ -1272,7 +1356,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_mul16);
break;
@@ -1283,35 +1367,69 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SXTHw(x2, xRAX);
MULw(x1, x2, x1);
UFLAG_RES(x1);
BFIx(xRAX, x1, 0, 16);
BFIz(xRAX, x1, 0, 16);
BFXILx(xRDX, x1, 16, 16);
UFLAG_DF(x1, d_imul16);
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) {
CBNZw_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
UDIVw(x3, x2, ed);
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIx(xRAX, x3, 0, 16);
BFIx(xRDX, x4, 0, 16);
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
break;
case 7:
INST_NAME("IDIV Ew");
SKIPTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
GETSEW(x1, 0);
if(box64_dynarec_div0) {
CBNZw_MARK3(ed);
GETIP_(ip);
STORE_XEMU_CALL(xRIP);
CALL(native_div0, -1);
CLEARIP();
LOAD_XEMU_CALL(xRIP);
jump_to_epilog(dyn, 0, xRIP, ninst);
MARK3;
}
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
SDIVw(x3, x2, ed);
MSUBw(x4, x3, ed, x2); // x4 = x2 mod ed (i.e. x2 - x3*ed)
BFIx(xRAX, x3, 0, 16);
BFIx(xRDX, x4, 0, 16);
BFIz(xRAX, x3, 0, 16);
BFIz(xRDX, x4, 0, 16);
break;
}
break;
case 0xF8:
INST_NAME("CLC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
BFCx(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
ORRx_mask(xFlags, xFlags, 1, 0, 0); // xFlags | 1
break;
case 0xFF:
nextop = F8;
@@ -1331,13 +1449,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
EWBACK;
break;
case 6: // Push Ew
if(rex.is32bits) {
INST_NAME("PUSH Ew");
GETEW(x1, 0);
PUSH1_16(ed);
} else {
DEFAULT;
}
INST_NAME("PUSH Ew");
GETEW(x1, 0);
PUSH1_16(ed);
break;
default:
File diff suppressed because it is too large. Load diff
+140 -17
View File
@@ -27,8 +27,9 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t gd, ed, wb1, wback;
int64_t j64;
int16_t i16;
int v0, v1;
int64_t fixedaddress;
int unscaled;
@@ -60,33 +61,155 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
VLDR64_REG(v1, ed, x4);
}
FCMPD(v0, v1);
FCOMI(x1, x2);
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR64_REG(v0, ed, x4);
SMWRITE();
}
break;
case 0x6F:
INST_NAME("MOVDQA Gx,Ex");
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
} else {
GETGX_empty(v0);
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
SMREAD();
VLDR128_REG(v0, ed, x4);
}
break;
case 0x7F:
INST_NAME("MOVDQA Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVQ(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR128_REG(v0, ed, x4);
SMWRITE2();
}
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
FMOVD(v1, v0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VSTR64_REG(v0, ed, x4);
SMWRITE();
}
break;
default:
DEFAULT;
}
break;
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
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);
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);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
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);
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);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x1, seg);
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);
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);
GETEWO(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV FS:Ew, Gw");
nextop = F8;
+88 -6
View File
@@ -48,6 +48,37 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETREX();
switch(opcode) {
case 0x01:
INST_NAME("LOCK ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
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, 0);
if(arm64_atomics) {
UFLAG_IF {
LDADDALH(x5, x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
} else {
STADDLH(x5, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
break;
case 0x09:
INST_NAME("LOCK OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -98,8 +129,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK3(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 0xF);
B_MARK3(cGE);
} else {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK3(cNE);
}
}
// Aligned version
if(arm64_atomics) {
@@ -171,6 +208,7 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
DEFAULT;
}
break;
case 0x11:
INST_NAME("LOCK ADC Ew, Gw");
READFLAGS(X_CF);
@@ -192,6 +230,38 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SMDMB();
}
break;
case 0x21:
INST_NAME("LOCK AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x5);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, gd, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(arm64_atomics) {
MVNw_REG(x3, gd);
UFLAG_IF {
LDCLRALH(x3, x1, wback);
emit_and16(dyn, ninst, x1, gd, x3, x4);
} else {
STCLRLH(x3, wback);
}
} else {
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, gd, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
SMDMB();
}
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -215,8 +285,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 0xF);
B_MARK(cGE);
} else {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
}
}
if(arm64_atomics) {
LDADDALH(x5, x1, wback);
@@ -370,8 +446,14 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
if(!ALIGNED_ATOMICH) {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 0xF);
B_MARK(cGE);
} else {
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
}
}
if(arm64_atomics) {
NEGw_REG(x4, x5);
+318 -24
View File
@@ -15,6 +15,7 @@
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
@@ -36,6 +37,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int16_t i16;
int cacheupd = 0;
int lock;
int v0, v1, s0;
@@ -55,9 +57,14 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETREX();
while(opcode==0x67) opcode = F8;
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
while((opcode==0xF2) || (opcode==0xF3) || (opcode>=0x40 && opcode<=0x4F)) {
if((opcode==0xF2) || (opcode==0xF3))
rep = opcode-0xF1;
if(opcode>=0x40 && opcode<=0x4F)
rex.rex = opcode;
opcode = F8;
}
@@ -200,7 +207,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(MODREG) {
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
} else {
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
SMREAD();
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
@@ -652,8 +659,114 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x66:
opcode=F8;
GETREX();
switch(opcode) {
case 0x0F:
nextop = F8;
switch(nextop) {
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
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;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ew, Iw");} else {INST_NAME("ADD Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
EWBACK;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
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);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
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);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOVZw(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
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);
GETEW32(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOVZw(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
@@ -665,16 +778,66 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);
WILLWRITELOCK(lock);
STH(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8D:
INST_NAME("LEA Gw, Ed");
nextop=F8;
//GETGW(x1);
gd = x1; // no need to read
if(MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=gd)
gd = ed;
}
GWBACK;
break;
default:
DEFAULT;
}
break;
case 0x6B:
INST_NAME("IMUL Gd, Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETGD;
GETED32(1);
i64 = F8S;
MOV64xw(x4, i64);
if(rex.w) {
// 64bits imul
UFLAG_IF {
SMULH(x3, ed, x4);
MULx(gd, ed, x4);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
MULxw(gd, ed, x4);
}
} else {
// 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);
} else {
MULxw(gd, ed, x4);
}
}
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -782,6 +945,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
}
@@ -794,6 +958,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVxw_REG(xRAX+(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);
STxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
@@ -880,25 +1045,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x4);
WBACK;
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rcl32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 3:
INST_NAME("RCR Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETED32W(x4, x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x4);
WBACK;
SETFLAGS(X_OF|X_CF, SF_SUBSET); // removed PENDING on purpose
GETED32(1);
u8 = (F8)&(rex.w?0x3f:0x1f);
emit_rcr32c(dyn, ninst, rex, ed, u8, x3, x4);
if(u8) { WBACK; }
break;
case 4:
case 6:
@@ -932,6 +1093,81 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC4:
nextop = F8;
if(rex.is32bits && !(MODREG)) {
DEFAULT;
} else {
if(rex.is32bits) {
DEFAULT;
return addr;
}
vex_t vex = {0};
vex.rex = rex;
u8 = nextop;
vex.m = u8&0b00011111;
vex.rex.b = (u8&0b00100000)?0:1;
vex.rex.x = (u8&0b01000000)?0:1;
vex.rex.r = (u8&0b10000000)?0:1;
u8 = F8;
vex.p = u8&0b00000011;
vex.l = (u8>>2)&1;
vex.v = ((~u8)>>3)&0b1111;
vex.rex.w = (u8>>7)&1;
addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);
}
break;
case 0xC5:
nextop = F8;
if(rex.is32bits && !(MODREG)) {
DEFAULT;
} else {
if(rex.is32bits) {
DEFAULT;
return addr;
}
vex_t vex = {0};
vex.rex = rex;
u8 = nextop;
vex.p = u8&0b00000011;
vex.l = (u8>>2)&1;
vex.v = ((~u8)>>3)&0b1111;
vex.rex.r = (u8&0b10000000)?0:1;
vex.rex.b = 0;
vex.rex.x = 0;
vex.rex.w = 0;
vex.m = VEX_M_0F;
addr = dynarec64_67_AVX(dyn, addr, ip, ninst, vex, ok, need_epilog);
}
break;
case 0xC6:
INST_NAME("MOV Eb, Ib");
nextop=F8;
if(MODREG) { // reg <= u8
u8 = F8;
if(!rex.rex) {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0;
}
MOV32w(x3, u8);
BFIx(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted32(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 1);
u8 = F8;
if(u8) {
MOV32w(x3, u8);
ed = x3;
} else
ed = xZR;
WILLWRITELOCK(lock);
STB(ed, wback, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0xC7:
INST_NAME("MOV Ed, Id");
nextop=F8;
@@ -943,6 +1179,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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);
}
@@ -960,7 +1197,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
jump_to_next(dyn, addr+i8, 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);\
@@ -1077,8 +1314,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
SET_DFNONE(x2);
GETED32(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
@@ -1095,7 +1332,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x31
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0xD2) {
SET_DFNONE(x2);
GETED32(0);
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
@@ -1110,7 +1346,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2);
}
}
break;
@@ -1118,8 +1353,8 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("IDIV Ed");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x2);
if(!rex.w) {
SET_DFNONE(x2)
GETSED32w(0);
MOVw_REG(x3, xRAX);
ORRx_REG_LSL(x3, x3, xRDX, 32);
@@ -1132,7 +1367,6 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
&& dyn->insts[ninst-1].x64.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr)==0x48
&& *(uint8_t*)(dyn->insts[ninst-1].x64.addr+1)==0x99) {
SET_DFNONE(x2)
GETED32(0);
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
@@ -1149,12 +1383,72 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SDIVx(x2, xRAX, ed);
MSUBx(xRDX, x2, ed, xRAX);
MOVx_REG(xRAX, x2);
SET_DFNONE(x2)
}
}
break;
}
break;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
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);
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) ||
((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
} else {
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) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
GETIP_(addr);
if(box64_dynarec_callret) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j64 = getJumpTableAddress64(addr);
TABLE64(x4, j64);
LDRx_U12(x4, x4, 0);
}
STPx_S7_preindex(x4, xRIP, xSP, -16);
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
break;
default:
DEFAULT;
return addr;
}
break;
default:
DEFAULT;
+54
View File
@@ -61,6 +61,60 @@ uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, in
switch(opcode) {
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
MOVxw_REG(xRAX+(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);
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
nextop=F8;
GETGD;
if(MODREG) { // reg => reg
MOVxw_REG(gd, xRAX+(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);
}
break;
case 0x8F:
INST_NAME("POP Seg:Ed");
nextop=F8;
if(MODREG) { // reg <= reg
POP1_32(x1);
MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), x1);
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
POP1_32(x1);
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, 0);
STRw_REG(x1, ed, x4);
}
break;
case 0xA1:
INST_NAME("MOV EAX, Seg:[Od]");
i32 = F16;
grab_segdata(dyn, addr, ninst, x4, seg);
if(i32<4096 && !(i32&3)) {
LDRw_U12(xRAX, x4, i32);
} else if(i32<256) {
LDURw_I9(xRAX, x4, i32);
} else {
MOV32w(x1, i32);
LDRw_REG(xRAX, x4, x1);
}
break;
case 0xA3:
INST_NAME("MOV Seg:[Od], EAX");
i32 = F16;
+60
View File
@@ -65,6 +65,66 @@ uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
addr = dynarec64_6764_32(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x64.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->native_size); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x64.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst, rex.is32bits); \
} else { \
CacheTransform(dyn, ninst, cacheupd, 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); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cNE, cEQ);
break;
case 0xE1:
INST_NAME("LOOPZ (16bits)");
READFLAGS(X_ZF);
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
B_NEXT(cEQ); // ECX is 0, no LOOP
TSTw_mask(xFlags, 0b011010, 0); //mask=0x40
GO(cEQ, cNE);
break;
case 0xE2:
INST_NAME("LOOP (16bits)");
i8 = F8S;
UXTHw(x1, xRCX);
SUBSw_U12(x1, x1, 1);
BFIx(xRCX, x1, 0, 16);
GO(cEQ, cNE);
break;
case 0xE3:
INST_NAME("JCXZ");
i8 = F8S;
TSTw_mask(xRCX, 0, 15); //mask=0xffff
GO(cNE, cEQ);
break;
#undef GO
default:
DEFAULT;
}
+112
View File
@@ -0,0 +1,112 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
switch(p) {
case VEX_P_NONE: return "0";
case VEX_P_66: return "66";
case VEX_P_F2: return "F2";
case VEX_P_F3: return "F3";
default: return "??";
}
}
static const char* avx_map_string(uint16_t m)
{
switch(m) {
case VEX_M_NONE: return "0";
case VEX_M_0F: return "0F";
case VEX_M_0F38: return "0F38";
case VEX_M_0F3A: return "0F3A";
default: return "??";
}
}
uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2)) {
switch(opcode) {
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED32(0);
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
LSRx(gd, x3, 32);
}
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);
}
return addr;
}
+76
View File
@@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "arm64_printer.h"
#include "dynarec_arm64_private.h"
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
static const char* avx_prefix_string(uint16_t p)
{
switch(p) {
case VEX_P_NONE: return "0";
case VEX_P_66: return "66";
case VEX_P_F2: return "F2";
case VEX_P_F3: return "F3";
default: return "??";
}
}
static const char* avx_map_string(uint16_t m)
{
switch(m) {
case VEX_M_NONE: return "0";
case VEX_M_0F: return "0F";
case VEX_M_0F38: return "0F38";
case VEX_M_0F3A: return "0F3A";
default: return "??";
}
}
uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = PK(0);
rex_t rex = vex.rex;
if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_NONE))
addr = dynarec64_AVX_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_NONE))
addr = dynarec64_AVX_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F2))
addr = dynarec64_AVX_F2_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F) && (vex.p==VEX_P_F3))
addr = dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F3A) && (vex.p==VEX_P_66))
addr = dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if( (vex.m==VEX_M_0F38) && (vex.p==VEX_P_F2))
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 {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);
}
return addr;
}
+712
View File
@@ -0,0 +1,712 @@
#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_arm64_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)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
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);
#if STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
rex_t rex = vex.rex;
switch(opcode) {
case 0x10:
INST_NAME("VMOVUPS Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(v0!=v1) VMOVQ(v0, v1);
if(vex.l) {
v1 = ymm_get_reg(dyn, ninst, x1, ed, 0, gd, -1, -1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, ed, -1, -1);
if(v0!=v1) VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress); // no alignment issue with ARMv8 NEON :)
if(vex.l) {
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVUPS Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, ed, -1, -1);
v1 = ymm_get_reg_empty(dyn, ninst, x1, ed, gd, -1, -1);
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);
if(vex.l) {
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, ed, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
break;
case 0x12:
nextop = F8;
GETVX(v2, 0);
if(MODREG) {
INST_NAME("VMOVHLPS Gx, Vx, Ex");
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
if((v0!=v2) && (v0!=v1))
VMOVQ(v0, v2);
VMOVeD(v0, 0, v1, 1);
if((v0!=v2) && (v0==v1))
VMOVeD(v0, 1, v2, 1);
} else {
INST_NAME("VMOVLPS Gx, Vx, Ex");
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(v0!=v2)
VMOVQ(v0, v2);
VLD1_64(v0, 0, ed);
}
YMM0(gd);
break;
case 0x13:
nextop = F8;
INST_NAME("VMOVLPS Ex, Vx, Gx");
GETGX(v0, 0);
GETVX(v2, 0);
if(v1!=v2)
VMOVQ(v0, v2);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
if(v0!=v1) VMOVeD(v1, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
SMWRITE2();
}
break;
case 0x14:
INST_NAME("VUNPCKLPS Gx, Vx, Ex");
nextop = F8;
SMREAD();
GETGX_empty_VXEX(v0, v2, v1, 0);
VZIP1Q_32(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VZIP1Q_32(v0, v2, v1);
} else YMM0(gd);
break;
case 0x15:
INST_NAME("VUNPCKHPS Gx, Vx, Ex");
nextop = F8;
SMREAD();
GETGX_empty_VXEX(v0, v2, v1, 0);
VZIP2Q_32(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VZIP2Q_32(v0, v2, v1);
} else YMM0(gd);
break;
case 0x16:
nextop = F8;
if(MODREG) {
INST_NAME("VMOVLHPS Gx, Vx, Ex");
GETGX(v0, 1);
GETVX(v2, 0);
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
if(v0!=v2 && v0!=v1) VMOVQ(v0, v2);
VMOVeD(v0, 1, v1, 0);
if(v0!=v2 && v0==v1) VMOVeD(v0, 0, v2, 0);
} else {
INST_NAME("VMOVHPS Gx, Vx, Ex");
SMREAD();
GETGX(v0, 1);
GETVX(v2, 0);
if(v0!=v2) VMOVQ(v0, v2);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLD1_64(v0, 1, ed);
}
YMM0(gd);
break;
case 0x17:
INST_NAME("VMOVHPS Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1);
VMOVeD(v1, 0, v0, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VST1_64(v0, 1, ed);
}
break;
case 0x28:
INST_NAME("VMOVAPS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x29:
INST_NAME("VMOVAPS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
GETGYEY_empty(v0, v1);
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);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
SMWRITE2();
}
break;
case 0x2B:
INST_NAME("VMOVNTPS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg_empty(dyn, ninst, x1, ed);
VMOVQ(v1, v0);
if(vex.l) {
GETGYEY_empty(v0, v1);
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);
if(vex.l) {
GETGY(v0, 0, -1, -1, -1);
VSTR128_U12(v0, ed, fixedaddress+16);
}
}
break;
case 0x2E:
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("VCOMISS Gx, Ex");} else {INST_NAME("VUCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET_NODF);
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
FCMPS(v0, s0);
FCOMI(x1, x2);
break;
case 0x50:
INST_NAME("VMOVMSPKPS Gd, Ex");
nextop = F8;
GETGD;
MOV32w(gd, 0);
if(MODREG) {
// 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); }
SQXTN_16(q0, v0); // reduces the 4 32bits to 4 16bits
VMOVQDto(x1, q0, 0);
LSRx(x1, x1, 15);
BFIx(gd, x1, 0+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 1+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 2+(l*4), 1);
LSRx(x1, x1, 16);
BFIx(gd, x1, 3+(l*4), 1);
}
} else {
// EX is memory
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, (0xfff<<3)-24, 7, rex, NULL, 0, 0);
for(int l=0; l<1+vex.l; ++l) {
LDRx_U12(x1, ed, fixedaddress+16*l);
LSRx(x1, x1, 31);
BFIx(gd, x1, 0+(l*4), 1);
LSRx(x1, x1, 32);
BFIx(gd, x1, 1+(l*4), 1);
LDRx_U12(x1, ed, fixedaddress+8+16*l);
LSRx(x1, x1, 31);
BFIx(gd, x1, 2+(l*4), 1);
LSRx(x1, x1, 32);
BFIx(gd, x1, 3+(l*4), 1);
}
}
break;
case 0x51:
INST_NAME("VSQRTPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(q0, q1, 0); } else { GETGY_empty_EY(q0, q1); }
VFSQRTQS(q0, q1);
}
if(!vex.l) YMM0(gd);
break;
case 0x52:
INST_NAME("VRSQRTPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
v0 = fpu_get_scratch(dyn, ninst);
VFMOVSQ_8(v0, 0b01110000); //1.0f
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(q0, q1, 0); } else { GETGY_empty_EY(q0, q1); }
#if 0
// the aproximation doesn't not work on Death Stranding. code around 0x1419c9100 fail...
if(!l) {
if(q1==q0)
v1 = fpu_get_scratch(dyn, ninst);
else
v1 = q1;
}
// more precise
VFRSQRTEQS(v0, q1);
VFMULQS(v1, v0, q1);
VFRSQRTSQS(v1, v1, v0);
VFMULQS(q0, v1, v0);
#else
VFSQRTQS(q0, q1);
VFDIVQS(q0, v0, q0);
#endif
}
if(!vex.l) YMM0(gd);
break;
case 0x53:
INST_NAME("VRCPPS Gx, Ex");
nextop = F8;
SKIPTEST(x1);
q0 = fpu_get_scratch(dyn, ninst);
VFMOVSQ_8(q0, 0b01110000); //1.0f
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETGX_empty_EX(v0, v1, 0);
#if 0
if(v0==v1)
q1 = fpu_get_scratch(dyn, ninst);
#endif
} else {
GETGY_empty_EY(v0, v1);
}
#if 0
if(v0!=v1) q1 = v0;
VFRECPEQS(q0, v1);
VFRECPSQS(q1, q0, v1);
VFMULQS(v0, q0, q1);
#else
VFDIVQS(v0, q0, v1);
#endif
}
if(!vex.l) YMM0(gd);
break;
case 0x54:
INST_NAME("VANDPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VANDQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VANDQ(v0, v2, v1);
} else YMM0(gd)
break;
case 0x55:
INST_NAME("VANDNPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VBICQ(v0, v1, v2);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VBICQ(v0, v1, v2);
} else YMM0(gd)
break;
case 0x56:
INST_NAME("VORPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VORRQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VORRQ(v0, v2, v1);
} else YMM0(gd)
break;
case 0x57:
INST_NAME("VXORPS Gx, Vx, Ex");
nextop = F8;
GETGX_empty_VXEX(v0, v2, v1, 0);
VEORQ(v0, v2, v1);
if(vex.l) {
GETGY_empty_VYEY(v0, v2, v1);
VEORQ(v0, v2, v1);
} else YMM0(gd)
break;
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);
VFADDQS(v0, v2, v1);
} else 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);
VFMULQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTPS2PD Gx, Ex");
nextop = F8;
GETGX_empty_EX(v0, v1, 0);
if(vex.l) {
GETGY_empty(q0, -1, -1, -1);
FCVTL2(q0, v1);
} else YMM0(gd)
FCVTL(v0, v1);
break;
case 0x5B:
INST_NAME("VCVTDQ2PS Gx, Ex");
nextop = F8;
GETGX_empty_EX(v0, v1, 0);
SCVTQFS(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
SCVTQFS(v0, v1);
} else YMM0(gd)
break;
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);
VFSUBQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINPS Gx, Vx, Ex");
nextop = F8;
if(!box64_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
VFMINQS(v0, v2, v1);
if(!box64_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
}
}
if(!vex.l) YMM0(gd);
break;
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);
VFDIVQS(v0, v2, v1);
} else YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXPS Gx, Vx, Ex");
nextop = F8;
if(!box64_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
VFMAXQS(v0, v2, v1);
if(!box64_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
}
}
if(!vex.l) YMM0(gd);
break;
case 0x77:
if(!vex.l) {
INST_NAME("VZEROUPPER");
if(vex.v!=0) {
UDF(0);
} else {
for(int i=0; i<(rex.is32bits?8:16); ++i) {
YMM0(i);
}
}
} else {
INST_NAME("VZEROALL");
if(vex.v!=0) {
UDF(0);
} else {
for(int i=0; i<(rex.is32bits?8:16); ++i) {
v0 = sse_get_reg_empty(dyn, ninst, x1, i);
VEORQ(v0, v0, v0);
YMM0(i);
}
}
}
break;
case 0xAE:
nextop = F8;
if(MODREG) {
DEFAULT;
} else
switch((nextop>>3)&7) {
case 2:
INST_NAME("VLDMXCSR Md");
GETED(0);
STRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr));
if(box64_sse_flushto0) {
MRS_fpcr(x1); // get fpscr
LSRw_IMM(x3, ed, 15); // get FZ bit
BFIw(x1, 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
}
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));
STW(x4, ed, fixedaddress);
break;
default:
DEFAULT;
}
break;
case 0xC2:
INST_NAME("VCMPPS Gx, Vx, Ex, Ib");
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, 1); u8 = F8; } else { GETGY_empty_VYEY(v0, v2, v1); }
if(((u8&15)==3) || ((u8&15)==7) || ((u8&15)==8) || ((u8&15)==9) || ((u8&15)==10) || ((u8&15)==12) || ((u8&15)==13) || ((u8&15)==14)) {
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(((u8&15)==7)?v0:q0, q0, q0); // 0 if NAN, 1 if not NAN
}
switch(u8&0xf) {
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
case 0x00: VFCMEQQS(v0, v2, v1); break; // Equal, not unordered
case 0x01: VFCMGTQS(v0, v1, v2); break; // Less than
case 0x02: VFCMGEQS(v0, v1, v2); break; // Less or equal
case 0x03: VMVNQ(v0, q0); break; // unordered
case 0x04: VFCMEQQS(v0, v2, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 0x05: VFCMGTQS(v0, v1, v2); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 0x06: VFCMGEQS(v0, v1, v2); VMVNQ(v0, v0); break; // Greater or unordered
case 0x07: break; // ordered
case 0x08: VFCMEQQS(v0, v2, v1); VORNQ(v0, v0, q0); break; // Equal, or unordered
case 0x09: VFCMGTQS(v0, v1, v2); VORNQ(v0, v0, q0); break; // Less than or unordered
case 0x0a: VFCMGEQS(v0, v1, v2); VORNQ(v0, v0, q0); break; // Less or equal or unordered
case 0x0b: VEORQ(v0, v0, v0); break; // false
case 0x0c: VFCMEQQS(v0, v2, v1); VBICQ(v0, q0, v0); break;
case 0x0d: VFCMGEQS(v0, v2, v1); break;
case 0x0e: VFCMGTQS(v0, v2, v1); break;
case 0x0f: MOVIQ_64(v0, 0xff); break; //true
}
}
if(!vex.l) YMM0(gd);
break;
case 0xC6:
INST_NAME("VSHUFPS Gx, Vx, Ex, Ib");
nextop = F8;
GETVX(v2, 0);
if(!MODREG) {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
v1 = -1; // to avoid a warning
} else
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
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
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) { // easy special case
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
VUZP2Q_32(v0, v2, v1);
} else {
if((v0==v1) || (v0==v2)) {
d0 = fpu_get_scratch(dyn, ninst); s0 = 0;
} else {
d0 = v0; s0 = 1;
}
// first two elements from Vx
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v2, (u8>>(i*2))&3);
}
// second two from Ex
if(MODREG) {
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2))&3);
}
} else {
SMREAD();
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, ((u8>>(i*2))&3)*4);
VLD1_32(d0, i, x2);
}
}
if(v0!=d0) VMOVQ(v0, d0);
}
if(vex.l) {
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1);
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)) {
VMOVQ(v0, v2);
VMOVeS(v0, 1, v0, 0);
} else if(v2==v1 && (u8==0xe5)) {
VMOVQ(v0, v2);
VMOVeS(v0, 0, v0, 1);
} else if(MODREG && u8==0x88) {
VUZP1Q_32(v0, v2, v1);
} else if(MODREG && u8==0xdd) {
VUZP2Q_32(v0, v2, v1);
} else {
if(s0) d0 = v0;
for(int i=0; i<2; ++i) {
VMOVeS(d0, i, v2, (u8>>(i*2))&3);
}
if(MODREG) {
for(int i=2; i<4; ++i) {
VMOVeS(d0, i, v1, (u8>>(i*2))&3);
}
} else {
SMREAD();
for(int i=2; i<4; ++i) {
ADDx_U12(x2, ed, 16+((u8>>(i*2))&3)*4);
VLD1_32(d0, i, x2);
}
}
VMOVQ(v0, d0);
}
} else YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
+146
View File
@@ -0,0 +1,146 @@
#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_arm64_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)
{
(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 0xF2:
INST_NAME("ANDN Gd, Vd, Ed");
nextop = F8;
SETFLAGS(X_ALL, SF_SET);
GETGD;
GETED(0);
GETVD;
BICxw(gd, ed, vd);
break;
case 0xF3:
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("BLSR 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);
IFX(X_ZF)
ANDSxw_REG(vd, ed, x3);
else
ANDxw_REG(vd, ed, x3);
IFX(X_ZF) {
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);
}
IFX(X_OF) BFCw(xFlags, F_OF, 1);
if(box64_dynarec_test) {
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
}
break;
default:
DEFAULT;
}
break;
case 0xF5:
INST_NAME("BZHI Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET);
GETGD;
GETED(0);
GETVD;
UXTBw(x1, vd);
CMPSw_U12(x1, rex.w?64:32);
CSETxw(x2, cPL);
IFX(F_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) {
BICSxw(gd, ed, x2);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1);
} else
BICxw(gd, ed, x2);
IFX(X_SF) {
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);
break;
default:
DEFAULT;
}
return addr;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,778 @@
#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_arm64_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)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
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);
#if STEP > 1
static const int8_t round_round[] = { 0, 2, 1, 3};
#endif
rex_t rex = vex.rex;
switch(opcode) {
case 0x00:
case 0x01:
if(opcode) {INST_NAME("VPERMPD Gx, Ex, Imm8");} else {INST_NAME("VPERMQ Gx, Ex, Imm8");}
nextop = F8;
GETGX_empty_EX(v0, q0, 1);
u8 = F8;
if(v0==q0) d0 = fpu_get_scratch(dyn, ninst);
if(v0==q0 || !MODREG) d1 = fpu_get_scratch(dyn, ninst);
q1 = d1;
GETGY_empty_EY(v1, q1);
if(v0==q0) { VMOVQ(d0, q0); VMOVQ(d1, q1); } else {d1 = q1; d0 = q0;}
VMOVeD(v0, 0, ((u8>>1)&1)?d1:d0, (u8>>0)&1);
VMOVeD(v0, 1, ((u8>>3)&1)?d1:d0, (u8>>2)&1);
VMOVeD(v1, 0, ((u8>>5)&1)?d1:d0, (u8>>4)&1);
VMOVeD(v1, 1, ((u8>>7)&1)?d1:d0, (u8>>6)&1);
break;
case 0x02:
INST_NAME("VPBLENDD Gx, Vx, Ex, u8");
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, 1); u8 = F8;} else { GETGY_empty_VYEY(v0, v2, v1); u8 >>=4;}
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(v0==v1) {
VBIFQ(v0, v2, q0);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x04:
INST_NAME("VPERMILPS Gx, Ex, Imm8");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
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==0x00 || u8==0x55 || u8==0xAA || u8==0xFF)
VDUPQ_32(v0, (v0==v1)?q1:v1, u8&3);
else if(u8==0x50)
VZIP1Q_32(v0, v1, v1);
else if(u8==0xFA)
VZIP2Q_32(v0, v1, v1);
else if(u8==0xA0)
VTRNQ1_32(v0, v1, v1);
else if(u8==0xF5)
VTRNQ2_32(v0, v1, v1);
else for(int i=0; i<4; ++i)
VMOVeS(v0, i, (v0==v1)?q1:v1, (u8>>(i*2))&3);
}
if(!vex.l) YMM0(gd);
break;
case 0x05:
INST_NAME("VPERMILD Gx, Ex, Imm8");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
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);
}
if(!vex.l) YMM0(gd);
break;
case 0x06:
case 0x46:
if(opcode==0x06) { INST_NAME("VPERM2F128 Gx, Vx, Ex, Imm8"); } else { INST_NAME("VPERM2I128 Gx, Vx, Ex, Imm8"); }
nextop = F8;
if(!vex.l) UDF(0);
if(MODREG) {
s0 = (nextop&7)+(rex.b<<3);
v1 = sse_get_reg(dyn, ninst, x1, s0, 0);
} else {
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);
}
u8 = F8;
GETVX(v2, 0);
GETGX_empty(v0);
if((v0==v2) && ((u8&0xf0)==0)) {
q0 = fpu_get_scratch(dyn, ninst);
VMOVQ(q0, v2);
v2 = q0;
}
if((v0==v1) && ((u8&0xf0)==0x20)) {
q1 = fpu_get_scratch(dyn, ninst);
VMOVQ(q1, v1);
v1 = q1;
}
switch(u8&0x0f) {
case 0: if(v0!=v2) VMOVQ(v0, v2); break;
case 1: d2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1); VMOVQ(v0, d2); break;
case 2: if(MODREG) { if(v0!=v1) VMOVQ(v0, v1); } else { VLDR128_U12(v0, ed, fixedaddress); } break;
case 3: if(MODREG) { d1 = ymm_get_reg(dyn, ninst, x1, s0, 0, gd, vex.v, -1); VMOVQ(v0, d1); } else { VLDR128_U12(v0, ed, fixedaddress+16); } break;
default: VEORQ(v0, v0, v0);
}
if((u8&0xf0)==0x10) { if((u8&0x0f)!=1) d2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, s0, -1); }
if(MODREG && ((u8&0xf0)==0x30)) { if((u8&0x0f)!=3) d1 = ymm_get_reg(dyn, ninst, x1, s0, 0, gd, vex.v, -1); }
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, s0, -1);
switch((u8>>4)&0x0f) {
case 0: VMOVQ(v0, v2); break;
case 1: if(v0!=d2) VMOVQ(v0, d2); break;
case 2: if(MODREG) { if(v0!=v1) VMOVQ(v0, v1); } else { VLDR128_U12(v0, ed, fixedaddress); } break;
case 3: if(MODREG) { if(v0!=d1) VMOVQ(v0, d1); } else { VLDR128_U12(v0, ed, fixedaddress+16); } break;
default: VEORQ(v0, v0, v0);
}
break;
case 0x08:
INST_NAME("VROUNDPS Gx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 1); u8 = F8; } else { GETGY_empty_EY(v0, v1); }
if(u8&4) {
if(!l) wb1 = sse_setround(dyn, ninst, x1, x2, x4);
VFRINTISQ(v0, v1);
if(l || !vex.l) x87_restoreround(dyn, ninst, wb1);
} else {
VFRINTRSQ(v0, v1, round_round[u8&3]);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x09:
INST_NAME("VROUNDPD Gx, Ex, Ib");
nextop = F8;
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_EX(v0, v1, 1); u8 = F8; } else { GETGY_empty_EY(v0, v1); }
if(u8&4) {
if(!l) wb1 = sse_setround(dyn, ninst, x1, x2, x4);
VFRINTIDQ(v0, v1);
if(l || !vex.l) x87_restoreround(dyn, ninst, wb1);
} else {
VFRINTRDQ(v0, v1, round_round[u8&3]);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0A:
INST_NAME("VROUNDSS Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSS(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
d1 = fpu_get_scratch(dyn, ninst);
if(u8&4) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXS(d1, v1);
x87_restoreround(dyn, ninst, u8);
} else {
FRINTRRS(d1, v1, round_round[u8&3]);
}
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x0B:
INST_NAME("VROUNDSD Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSD(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
d1 = fpu_get_scratch(dyn, ninst);
if(u8&4) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXD(d1, v1);
x87_restoreround(dyn, ninst, u8);
} else {
FRINTRRD(d1, v1, round_round[u8&3]);
}
if(v0!=v2) VMOVQ(v0, v2);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x0C:
INST_NAME("VBLENDPS Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VXEX(q0, q2, q1, 1);
u8 = F8;
if((u8&0xf)==0xf) {
if(q0!=q1) VMOVQ(q0, q1);
} else if(q0==q1) {
for(int i=0; i<4; ++i)
if(u8&(1<<i)) {
VMOVeS(q0, i, q1, i);
} else if(q0!=q2)
VMOVeS(q0, i, q2, i);
} else {
if(q0!=q2)
VMOVQ(q0, q2);
if((u8&15)==0b0011) {
VMOVeD(q0, 0, q1, 0);
} else if((u8&15)==0b1100) {
VMOVeD(q0, 1, q1, 1);
} else for(int i=0; i<4; ++i)
if(u8&(1<<i)) {
VMOVeS(q0, i, q1, i);
}
}
if(vex.l) {
GETGY_empty_VYEY(q0, q2, q1);
if((u8&0xf0)==0xf0) {
if(q0!=q1) VMOVQ(q0, q1);
} else if(q0==q1) {
for(int i=0; i<4; ++i)
if(u8&(1<<(i+4))) {
VMOVeS(q0, i, q1, i);
} else if(q0!=q2)
VMOVeS(q0, i, q2, i);
} else {
if(q0!=q2)
VMOVQ(q0, q2);
if((u8>>4)==0b0011) {
VMOVeD(q0, 0, q1, 0);
} else if((u8>>4)==0b1100) {
VMOVeD(q0, 1, q1, 1);
} else for(int i=0; i<4; ++i)
if(u8&(1<<(i+4))) {
VMOVeS(q0, i, q1, i);
}
}
} else YMM0(gd);
break;
case 0x0D:
INST_NAME("VPBLENDPD 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); }
switch(u8>>(l*2)&3) {
case 0b00: if(q0!=q2) VMOVQ(q0, q2); break; // VxVx
case 0b01: if(q0!=q1) VMOVeD(q0, 0, q1, 0); if(q0!=q2) VMOVeD(q0, 1, q2, 1); break; // Ex[0]Vx[1]
case 0b10: if(q0!=q2) VMOVeD(q0, 0, q2, 0); if(q0!=q1) VMOVeD(q0, 1, q1, 1); break; // Vx[0]Ex[1]
case 0b11: if(q0!=q1) VMOVQ(q0, q1); break; // ExEx
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0E:
INST_NAME("VPBLENDW Gx, Vx, Ex, u8");
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, 1); u8 = F8;} else { GETGY_empty_VYEY(v0, v2, v1); }
if(!l) {
MOVI_64(q0, u8);
SXTL_8(q0, q0); // expand 8bits to 16bits...
}
if(v0==v1) {
VBIFQ(v0, v2, q0);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x0F:
INST_NAME("VPALIGNR Gx, Vx, Ex, Ib");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
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);
}
if(u8>31) {
VEORQ(v0, v0, v0);
} else if(u8>15) {
if(!l) VEORQ(d0, d0, d0);
VEXTQ_8(v0, v2, d0, u8-16);
} else {
VEXTQ_8(v0, v1, v2, u8);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x14:
INST_NAME("VPEXTRB Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVBto(ed, v0, u8&0x0f);
if(!MODREG) {
STB(ed, wback, fixedaddress);
}
break;
case 0x15:
INST_NAME("VPEXTRW Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVHto(ed, v0, u8&7);
if(!MODREG) {
STH(ed, wback, fixedaddress);
}
break;
case 0x16:
INST_NAME("VPEXTRD/Q Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(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);
ed = x1;
}
u8 = F8;
if(rex.w) {
VMOVQDto(ed, v0, u8&1);
} else {
VMOVSto(ed, v0, u8&3);
}
if(!MODREG) {
STxw(ed, wback, fixedaddress);
}
break;
case 0x17:
INST_NAME("VEXTRACTPS Ed, Gx, imm8");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
ed = x1;
}
u8 = F8;
VMOVSto(ed, v0, u8&3);
if(!MODREG) {
STW(ed, wback, fixedaddress);
}
break;
case 0x18:
case 0x38:
if(opcode==0x18) {INST_NAME("VINSERTF128 Gx, Vx, Ex, imm8");} else {INST_NAME("VINSERTI128 Gx, Vx, Ex, imm8");}
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<<4, 15, rex, NULL, 0, 1);
v1 = -1; // to avoid a warning
}
u8 = F8;
GETVX(v2, 0);
GETGX_empty(v0);
if(v0==v2 && u8==1) {
GETGY_empty(q0, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
q2 = q0;
} else {
GETGY_empty_VY(q0, q2, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
}
if(MODREG)
VMOVQ((u8&1)?q0:v0, v1);
else
VLD128((u8&1)?q0:v0, ed, fixedaddress);
if(v0!=v2)
VMOVQ((u8&1)?v0:q0, (u8&1)?v2:q2);
break;
case 0x19:
case 0x39:
if(opcode==0x19) {INST_NAME("VEXTRACTF128 Ex, Gx, imm8");} else {INST_NAME("VEXTRACTI128 Ex, Gx, imm8");}
nextop = F8;
u8 = geted_ib(dyn, addr, ninst, nextop);
GETGX(v0, 0);
if(u8&1) {GETGY(v0, ((nextop&7)+(rex.b<<3)==gd && MODREG)?1:0, -1, -1, -1);}
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
if((nextop&7)+(rex.b<<3)==gd && (u8&1))
VEORQ(v0, v0, v0); // special case like vextractf128 xmm3, ymm3, 0x01
else
YMM0((nextop&7)+(rex.b<<3));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 1);
VST128(v0, ed, fixedaddress);
}
F8; // read u8, but it's been already handled
break;
case 0x1D:
INST_NAME("VCVTPS2PH Ex, Gx");
nextop = F8;
GETGX(v0, 0);
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);
}
if(vex.l && v0==v1) {
q0 = fpu_get_scratch(dyn, ninst);
VMOVQ(q0, v0);
v0 = q0;
}
u8 = F8;
if(u8&4) {
s0 = sse_setround(dyn, ninst, x1, x2, x6);
} else {
u8&=3;
if(u8==1) u8=2;
else if(u8==2) u8=1;
MRS_fpcr(x1); // get fpscr
MOV32w(x2, u8);
MOVx_REG(x6, x1);
BFIx(x1, x2, 22, 2); // inject new round
MSR_fpcr(x1); // put new fpscr
s0 = x6;
}
FCVTN16(v1, v0);
if(vex.l) {
GETGY(v0, 0, MODREG?((nextop&7)+(rex.b<<3)):-1, -1,-1);
FCVTN162(v1, v0);
}
x87_restoreround(dyn, ninst, s0);
if(MODREG) {
YMM0((nextop&7)+(rex.b<<3));
} else {
if(vex.l) {
VST128(v1, ed, fixedaddress);
} else {
VST64(v1, ed, fixedaddress);
}
SMWRITE2();
}
break;
case 0x20:
INST_NAME("VINSERTD Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VX(v0, v2);
GETED(1);
u8 = F8;
if(v0!=v2) VMOVQ(v0, v2);
VMOVQBfrom(v0, u8&0xf, ed);
YMM0(gd);
break;
case 0x21:
INST_NAME("VINSERTPS Gx, Vx, Ex, Ib");
nextop = F8;
if (MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 1);
u8 = F8;
if(v0==v1) {
d0 = fpu_get_scratch(dyn, ninst);
VMOVQ(d0, v1);
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, (u8>>4)&3, d0, (u8>>6)&3);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, (u8>>4)&3, v1, (u8>>6)&3);
}
} else {
GETGX_empty_VX(v0, v2);
if(v0!=v2) VMOVQ(v0, v2);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 1);
u8 = F8;
LDW(x2, wback, fixedaddress);
VMOVQSfrom(v0, (u8>>4)&3, x2);
}
uint8_t zmask = u8 & 0xf;
for (uint8_t i=0; i<4; i++) {
if (zmask & (1<<i)) {
VMOVQSfrom(v0, i, wZR);
}
}
YMM0(gd);
break;
case 0x22:
INST_NAME("VINSERTD Gx, Vx, Ex, Ib");
nextop = F8;
GETGX_empty_VX(v0, v2);
GETED(1);
u8 = F8;
if(v0!=v2) VMOVQ(v0, v2);
if(rex.w)
VMOVQDfrom(v0, u8&1, ed);
else
VMOVQSfrom(v0, u8&3, ed);
YMM0(gd);
break;
case 0x40:
INST_NAME("VDPPS Gx, Vx, Ex, Ib");
nextop = F8;
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...
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
VFADDPQS(v0, v0, v0);
FADDPS(v0, v0);
VDUPQ_32(v0, v0, 0);
VANDQ(v0, v0, q0); // first mask
}
if(!vex.l) YMM0(gd);
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Vx, Ex, Ib");
nextop = F8;
if(arm64_pmull) {
d0 = fpu_get_scratch(dyn, ninst);
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);
}
switch (u8&0b00010001) {
case 0b00000000:
PMULL_128(v0, v2, v1);
break;
case 0b00010001:
PMULL2_128(v0, v2, v1);
break;
case 0b00000001:
VEXTQ_8(d0, v2, v2, 8); // Swap Up/Lower 64bits parts
PMULL_128(v0, d0, v1);
break;
case 0b00010000:
VEXTQ_8(d0, v2, v2, 8); // Swap Up/Lower 64bits parts
PMULL2_128(v0, d0, v1);
break;
}
}
} else {
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETG;
sse_forget_reg(dyn, ninst, gd);
sse_reflect_reg(dyn, ninst, vex.v);
}
MOV32w(x1, gd); // gx
MOV32w(x2, vex.v); // vx
if(MODREG) {
if(!l) {
ed = (nextop&7)+(rex.b<<3);
sse_forget_reg(dyn, ninst, ed);
}
MOV32w(x3, ed);
} else {
if(!l) {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
if(ed!=x3) {
MOVx_REG(x3, ed);
}
} else {
ADDx_U12(x3, ed, 16);
}
}
if(!l) u8 = F8;
MOV32w(x4, u8);
CALL_(l?native_pclmul_y:native_pclmul_x, -1, x3);
}
}
if(!vex.l) YMM0(gd);
break;
//case 0x46: // see 0x06
case 0x4A:
INST_NAME("VBLENDVPS Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_32(q0, q1, 31); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x4B:
INST_NAME("VBLENDVPD Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_64(q0, q1, 63); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x4C:
INST_NAME("VBLENDPVB Gx, Vx, Ex, XMMImm8");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
u8 = geted_ib(dyn, addr, ninst, nextop)>>4;
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
q1 = sse_get_reg(dyn, ninst, x1, u8, 0);
GETGX_empty_VXEX(v0, v2, v1, 1);
F8;
} else {
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
if(MODREG)
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, u8);
else
VLDR128_U12(v1, ed, fixedaddress+16);
q1 = ymm_get_reg(dyn, ninst, x1, u8, 0, vex.v, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, u8, (MODREG)?((nextop&7)+(rex.b<<3)):-1);
}
VSSHRQ_8(q0, q1, 7); // create mask
if(v0==v1)
VBIFQ(v0, v2, q0);
else {
if(v0!=v2) VMOVQ(v0, v2);
VBITQ(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
+484
View File
@@ -0,0 +1,484 @@
#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_arm64_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)
{
(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, u64;
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 0x10:
INST_NAME("VMOVSD Gx, [Vx,] Ex");
nextop = F8;
GETG;
if(MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 0);
if(v0!=v1) VMOVeD(v0, 0, v1, 0);
if(v0!=v2) VMOVeD(v0, 1, v2, 1);
} else {
SMREAD();
GETGX_empty(v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress); // upper part reseted
}
YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVSD Ex, Vx, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
GETVXEX(v2, 0, v1, 1, 0);
if(v0!=v1) VMOVeD(v1, 0, v0, 0);
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();
}
break;
case 0x12:
INST_NAME("VMOVDDUP Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VDUPQ_64(v0, v1, 0);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VDUPQ_64(v0, v1, 0);
}
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLDQ1R_64(v0, ed);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
ADDx_U12(x3, ed, 16);
VLDQ1R_64(v0, ed);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x2A:
INST_NAME("VCVTSI2SD Gx, Vx, Ed");
nextop = F8;
GETGX_empty_VX(v0, v1);
GETED(0);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFDx(d1, ed);
} else {
SCVTFDw(d1, ed);
}
if(v0!=v1) VMOVQ(v0, v1);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x2C:
INST_NAME("VCVTTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwD(gd, q0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x2D:
INST_NAME("VCVTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn, ninst);
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x51:
INST_NAME("VSQRTSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_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) {
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
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x58:
INST_NAME("VADDSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FADDD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FMULD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTSD2SS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCVT_S_D(d1, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5C:
INST_NAME("VSUBSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBD(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
// VMINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
FCMPD(v2, v1);
FCSELD(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x5E:
INST_NAME("VDIVSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(!box64_dynarec_fastnan) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = 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
}
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXSD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPD(v1, v2);
FCSELD(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeD(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x70:
INST_NAME("VPSHUFLW Gx, Ex, Ib");
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(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
if(v0==v1) {
VMOVQ(d0, v1);
}
VDUP_16(v0, v1, u8&3);
if(v0==v1)
v1 = d0;
} else {
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
if(!l) {
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
}
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
}
if(v0!=v1) {
VMOVeD(v0, 1, v1, 1);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x7C:
INST_NAME("VHADDPS Gx, Vx, Ex");
nextop = F8;
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); }
VFADDPQS(v0, v2, v1);
}
if(!vex.l) YMM0(gd);
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
GETEXSD(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
FCMPD(v2, v1);
if(v0!=v2) VMOVQ(v0, v2);
switch(u8&7) {
case 0: CSETMx(x2, cEQ); break; // Equal
case 1: CSETMx(x2, cCC); break; // Less than
case 2: CSETMx(x2, cLS); break; // Less or equal
case 3: CSETMx(x2, cVS); break; // NaN
case 4: CSETMx(x2, cNE); break; // Not Equal or unordered
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMx(x2, cHI); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: CSETMx(x2, cVC); break; // not NaN
}
VMOVQDfrom(v0, 0, x2);
YMM0(gd);
break;
case 0xD0:
INST_NAME("VADDSUBPS Gx, Vx, Ex");
nextop = F8;
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);
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(v0==v1) {
VFMULQS(q1, v1, q0);
VFADDQS(v0, v2, q1);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VFMLAQS(v0, v1, q0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0xE6:
INST_NAME("VCVTPD2DQ Gx, Ex");
nextop = F8;
u8 = sse_setround(dyn, ninst, x1, x2, x6);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
if(!box64_dynarec_fastround || vex.l)
d0 = fpu_get_scratch(dyn, ninst);
} else {
GETEY(v1);
}
if(box64_dynarec_fastround) {
VFRINTIDQ(l?d0:v0, v1);
VFCVTNSQD(l?d0:v0, l?d0:v0); // convert double -> int64
if(!l)
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
else
SQXTN2_32(v0, d0); // convert int64 -> int32 with saturation in higher part
} else {
if(!l) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
}
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if(i) {
VMOVeD(d0, 0, v1, i);
FRINTID(d0, d0);
} else {
FRINTID(d0, v1);
}
FCVTZSwD(x1, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TSTw_mask(x5, 0, 0); // mask = 1 = FPSR_IOC
CSELx(x1, x1, x4, cEQ);
VMOVQSfrom(v0, i+l*2, x1);
}
if(!vex.l && !l) VMOVQDfrom(v0, 1, xZR);
}
}
x87_restoreround(dyn, ninst, u8);
YMM0(gd);
break;
case 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
if(vex.l) {
GETGY_empty_EY(v0, v1);
VMOVQ(v0, v1);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 7, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
v0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
if(!vex.l) YMM0(gd);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,96 @@
#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_arm64_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)
{
(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 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED(0);
GETVD;
if(rex.w) {
// 64bits mul
UMULH(x3, xRDX, ed);
MULx(vd, xRDX, ed);
MOVx_REG(gd, x3);
} else {
// 32bits mul
UMULL(x3, xRDX, ed);
MOVw_REG(vd, x3);
LSRx(gd, x3, 32);
}
break;
case 0xF7:
INST_NAME("SHRX Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
ANDx_mask(x3, vd, 1, 0, rex.w?5:4); // mask 0x3f/0x1f
LSRxw_REG(gd, ed, x3);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,78 @@
#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_arm64_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)
{
(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 0xF0:
INST_NAME("RORX Gd, Ed, Ib");
nextop = F8;
GETGD;
GETED(1);
u8 = F8;
u8&=rex.w?0x3f:0x1f;
RORxw(gd, ed, u8);
break;
default:
DEFAULT;
}
return addr;
}
+504
View File
@@ -0,0 +1,504 @@
#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_arm64_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)
{
(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, u64;
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 0x10:
INST_NAME("VMOVSS Gx, Ex [,Vx]");
nextop = F8;
GETG;
if(MODREG) {
GETGX_empty_VXEX(v0, v2, v1, 0);
if((v0!=v2) && (v0!=v1)) VMOVQ(v0, v2);
if(v0!=v1) VMOVeS(v0, 0, v1, 0);
if((v0!=v2) && (v0==v1)) { VMOVeS(v0, 1, v2, 1); VMOVeD(v0, 1, v2, 1);}
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v0, ed, fixedaddress);
}
YMM0(gd);
break;
case 0x11:
INST_NAME("VMOVSS Ex, Gx [,Vx]");
nextop = F8;
GETG;
if(MODREG) {
GETGXVXEX_empty(v0, v2, v1, 0);
if((v2!=v1) && (v2!=v0)) VMOVQ(v2, v1);
if(v2!=v0) VMOVeS(v2, 0, v0, 0);
if((v2!=v1) && (v2==v0)) { VMOVeS(v2, 1, v0, 1); VMOVeD(v2, 1, v0, 1);}
YMM0((nextop&7)+(rex.b<<3));
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x12:
INST_NAME("VMOVSLDUP Gx, Ex");
nextop = F8;
GETEX_Y(q1, 0, 0);
GETGX_empty(q0);
VTRNQ1_32(q0, q1, q1);
if(vex.l) {
GETGY_empty_EY(q0, q1);
VTRNQ1_32(q0, q1, q1);
} else YMM0(gd);
break;
case 0x16:
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
GETEX_Y(q1, 0, 0);
GETGX_empty(q0);
VTRNQ2_32(q0, q1, q1);
if(vex.l) {
GETGY_empty_EY(q0, q1);
VTRNQ2_32(q0, q1, q1);
} else YMM0(gd);
break;
case 0x2A:
INST_NAME("VCVTSI2SS Gx, Vx, Ed");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETGX_empty_VX(v0, v1);
GETED(0);
if(rex.w) {
SCVTFSx(d1, ed);
} else {
SCVTFSw(d1, ed);
}
if(v0!=v1) VMOVQ(v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x2C:
INST_NAME("VCVTTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSS(d0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
FCVTZSxwS(gd, d0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
case 0x2D:
INST_NAME("VCVTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSS(q0, 0, 0);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn, ninst);
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
if(!box64_dynarec_fastround) {
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
if(rex.w) {
ORRx_mask(gd, xZR, 1, 1, 0); //0x8000000000000000
} else {
ORRw_mask(gd, xZR, 1, 0); //0x80000000
}
}
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETEXSS(d0, 0, 0);
GETGX_empty_VX(v0, v2);
d1 = fpu_get_scratch(dyn, ninst);
FSQRTS(d1, d0);
if(v0!=v2) VMOVQ(v0, v2);
VMOVeS(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x52:
INST_NAME("VRSQRTSS Gx, Vx Ex");
nextop = F8;
GETGX(v0, 1);
GETVX(v2, 0);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
FMOVS_8(d0, 0b01110000);
FSQRTS(d1, v1);
FDIVS(d0, d0, d1);
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);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FADDS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x59:
INST_NAME("VMULSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FMULS(d1, v0, v1);
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5A:
INST_NAME("VCVTSS2SD Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
if(v0!=v2) {
if(v0==v1) {
VMOV(d1, v1);
v1 = d1;
}
VMOVQ(v0, v2);
}
FCVT_D_S(d1, v1);
VMOVeD(v0, 0, d1, 0);
YMM0(gd);
break;
case 0x5B:
INST_NAME("VCVTTPS2DQ Gx, Ex");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
if(!box64_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) {
VFCVTZSQS(v0, v1);
} else {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
for(int i=0; i<4; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
VMOVeS(d0, 0, v1, i);
VFCVTZSs(d0, d0);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ(x5, FPSR_IOC, 4+4);
VMOVQSfrom(d0, 0, x4);
VMOVeS(v0, i, d0, 0);
}
}
}
if(!vex.l) YMM0(gd);
break;
case 0x5C:
INST_NAME("VSUBSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FSUBS(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5D:
INST_NAME("VMINSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPS(v2, v1);
FCSELS(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x5E:
INST_NAME("VDIVSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FDIVS(d1, v2, v1);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0);
YMM0(gd)
break;
case 0x5F:
INST_NAME("VMAXSS Gx, Vx, Ex");
nextop = F8;
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(v1, 0, 0);
GETGX_empty_VX(v0, v2);
FCMPS(v1, v2);
FCSELS(d1, v1, v2, cCS);
if(v0!=v2) {
VMOVQ(v0, v2);
}
VMOVeS(v0, 0, d1, 0); // to not erase uper part
YMM0(gd)
break;
case 0x6F:
INST_NAME("VMOVDQU Gx, Ex");// no alignment constraint on NEON here, so same as MOVDQA
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
GETGX_empty(v0);
VMOVQ(v0, v1);
if(vex.l) {
v1 = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, -12, -1);
GETGY_empty(v0, (nextop&7)+(rex.b<<3), -1, -1);
VMOVQ(v0, v1);
}
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
if(vex.l) {
GETGY_empty(v0, -1, -1, -1);
VLDR128_U12(v0, ed, fixedaddress+16);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x70:
INST_NAME("VPSHUFHW Gx, Ex, Ib");
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(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
VDUP_16(d0, v1, 4+(u8&3));
} else {
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
if(!l) {
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+8)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+9)<<(i*16+8);
}
MOV64x(x2, u64);
}
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
}
VMOVeD(v0, 1, d0, 0);
if(v0!=v1) {
VMOVeD(v0, 0, v1, 0);
}
}
if(!vex.l) YMM0(gd);
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3), 0);
GETGX_empty(v0);
FMOVD(v0, v1);
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
}
YMM0(gd);
break;
case 0x7F:
INST_NAME("VMOVDQU Ex, Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVQ(v1, v0);
if(vex.l) {
GETGY(v0, 0, (nextop&7) + (rex.b<<3), -1, -1);
v1 = ymm_get_reg_empty(dyn, ninst, x1, (nextop&7) + (rex.b<<3), gd, -1, -1);
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);
}
SMWRITE2();
}
break;
case 0xC2:
INST_NAME("VCMPSS Gx, Vx, Ex, Ib");
nextop = F8;
GETEXSS(v1, 0, 1);
GETGX_empty_VX(v0, v2);
u8 = F8;
if(((u8&15)!=11) && ((u8&15)!=15)) {
if((u8&15)>7)
FCMPS(v1, v2);
else
FCMPS(v2, v1);
}
// TODO: create a test for this one, there might be an issue with cases 9, 10 and 13
if(v0!=v2) VMOVQ(v0, v2);
switch(u8&15) {
case 0x00: CSETMw(x2, cEQ); break; // Equal
case 0x01: CSETMw(x2, cCC); break; // Less than
case 0x02: CSETMw(x2, cLS); break; // Less or equal
case 0x03: CSETMw(x2, cVS); break; // NaN
case 0x04: CSETMw(x2, cNE); break; // Not Equal or unordered
case 0x05: CSETMw(x2, cCS); break; // Greater or equal or unordered
case 0x06: CSETMw(x2, cHI); break; // Greater or unordered
case 0x07: CSETMw(x2, cVC); break; // not NaN
case 0x08: CSETMw(x2, cEQ); CSETMw(x3, cVS); ORRw_REG(x2, x2, x3); break; // Equal or unordered
case 0x09: CSETMw(x2, cHI); break; // Less than or unordered
case 0x0a: CSETMw(x2, cCS); break; // Less or equal or unordered
case 0x0b: MOV32w(x2, 0); break; // false
case 0x0c: CSETMw(x2, cNE); CSETMw(x3, cVS); BICw(x2, x2, x3); break; // Not Equal not unordered
case 0x0d: CSETMw(x2, cLS); break; // Greater or equal not unordered
case 0x0e: CSETMw(x2, cCC); break; // Greater not unordered
case 0x0f: MOV32w(x2, 0xffffffff); break; // true
}
VMOVQSfrom(v0, 0, x2);
YMM0(gd);
break;
case 0xE6:
INST_NAME("VCVTDQ2PD Gx, Ex");
nextop = F8;
if(vex.l) {
GETEX_Y(v1, 0, 0);
} else {
GETEXSD(v1, 0, 0);
}
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn, ninst);
if(vex.l) {
q0 = ymm_get_reg_empty(dyn, ninst, x1, gd, -1, -1, -1);
SXTL2_32(q0, v1);
SCVTQFD(q0, q0);
} else YMM0(gd);
SXTL_32(v0, v1);
SCVTQFD(v0, v0);
break;
default:
DEFAULT;
}
return addr;
}
+115 -113
View File
@@ -38,6 +38,7 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v2);
MAYUSE(v1);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -178,119 +179,120 @@ uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FDIVD(v1, v2, v1);
}
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FADDD(v1, v1, s0);
}
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FMULD(v1, v1, s0);
}
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, v1, s0);
}
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, s0, v1);
}
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, v1, s0);
}
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, s0, v1);
}
break;
default:
DEFAULT;
}
}
DEFAULT;
break;
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FADDS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FADDD(v1, v1, s0);
}
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FMULS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FMULD(v1, v1, s0);
}
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FCMPS(v1, s0);
} else {
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
}
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, v1, s0);
}
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FSUBS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FSUBD(v1, s0, v1);
}
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
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(ST_IS_F(0)) {
FDIVS(v1, v1, s0);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, v1, s0);
}
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
s0 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(s0, ed, fixedaddress);
if(ST_IS_F(0)) {
FDIVS(v1, s0, v1);
} else {
FCVT_D_S(s0, s0);
FDIVD(v1, s0, v1);
}
break;
default:
DEFAULT;
}
return addr;
}
+172 -93
View File
@@ -31,7 +31,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int64_t fixedaddress;
int64_t fixedaddress, j64;
int unscaled;
int v1, v2;
int s0;
@@ -41,6 +41,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v2);
MAYUSE(v1);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -131,18 +132,109 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xE5:
INST_NAME("FXAM");
#if 1
i1 = x87_get_current_cache(dyn, ninst, 0, NEON_CACHE_ST_D);
// value put in x14
if(i1==-1) {
if(fpu_is_st_freed(dyn, ninst, 0)) {
MOV32w(x4, 0b100000100000000);
B_MARK3_nocond;
} else {
// not in cache, so check Empty status and load it
i2 = -dyn->n.x87stack;
LDRw_U12(x3, xEmu, offsetof(x64emu_t, fpu_stack));
if(i2) {
if(i2<0) {
ADDw_U12(x3, x3, -i2);
} else {
SUBw_U12(x3, x3, i2);
}
}
CMPSw_U12(x3, 0);
MOV32w(x4, 0b100000100000000); // empty: C3,C2,C0 = 101
B_MARK3(cLE);
// x5 will be the actual top
LDRw_U12(x5, xEmu, offsetof(x64emu_t, top));
if(i2) {
if(i2<0) {
SUBw_U12(x5, x5, -i2);
} else {
ADDw_U12(x5, x5, i2);
}
ANDw_mask(x5, x5, 0, 3); // (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));
}
} else {
// simply move from cache reg to x2
v1 = dyn->n.x87reg[i1];
VMOVQDto(x2, v1, 0);
}
// get exponant in x1
LSRx_IMM(x1, x2, 20+32);
ANDSx_mask(x1, x1, 1, 0b00000, 0b001010); // 0x7ff
B_MARK(cNE); // not zero or denormal
ANDSx_mask(x1, x2, 1, 0, 0b111110); // 0x7fffffffffffffff
MOV32w(x4, 0b100000000000000); // Zero: C3,C2,C0 = 100
MOV32w(x5, 0b100010000000000); // Denormal: C3,C2,C0 = 110
CSELx(x4, x4, x5, cEQ);
B_MARK3(c__);
MARK;
CMPSx_U12(x1, 0x7ff); // infinite/NaN?
MOV32w(x5, 0b000010000000000); // normal: C3,C2,C0 = 010
CSELx(x4, x5, x4, cNE);
B_MARK3(cNE);
TSTx_mask(x2, 1, 0b000000, 0b110011); // 0x000fffffffffffff
MOV32w(x4, 0b000010100000000); // infinity: C3,C2,C0 = 011
MOV32w(x3, 0b000000100000000); // NaN: C3,C2,C0 = 001
CSELx(x4, x4, x3, cEQ);
MARK3;
// Extract signa & Update SW
LSRx_IMM(x1, x2, 63);
BFIx(x4, x1, 9, 1); //C1
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
MOV32w(x2, 0b01000111);
BICw_REG_LSL(x1, x1, x2, 8);
ORRw_REG(x4, x4, x1);
STRH_U12(x4, xEmu, offsetof(x64emu_t, sw));
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_refresh(dyn, ninst, x1, x2, 0);
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
x87_unstackcount(dyn, ninst, x1, i1);
#endif
break;
case 0xE8:
INST_NAME("FLD1");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
if(ninst<dyn->size+2 && (dyn->insts[ninst+1].pred_sz==1) && (dyn->insts[ninst+2].pred_sz==1)
&& PK(0)==0xD9 && PK(1)==0xE8
&& PK(2)==0xD9 && PK(3)==0xF3
) {
MESSAGE(LOG_DUMP, "Hack for FLD1 FLD1 FPATAN");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
FTABLE64(v1, PI/4.0);
addr+=4;
} else {
FMOVD_8(v1, 0b01110000);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
FMOVS_8(v1, 0b01110000);
} else {
FMOVD_8(v1, 0b01110000);
}
}
break;
case 0xE9:
@@ -245,7 +337,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
FDIVD(s0, v1, v2);
FRINTRRD(s0, s0, 0b00); // Nearest == TieToEven?
FCVTZSxD(x4, s0);
@@ -293,7 +385,7 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch(dyn);
s0 = fpu_get_scratch(dyn, ninst);
FDIVD(s0, v1, v2);
FRINTZD(s0, s0);
FCVTZSxD(x4, s0);
@@ -384,92 +476,79 @@ uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CALL(native_fcos, -1);
x87_unstackcount(dyn, ninst, x1, i1);
break;
case 0xD1:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
default:
DEFAULT;
break;
default:
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
if(!ST_IS_F(0)) {
FCVT_D_S(v1, v1);
}
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
if(!ST_IS_F(0)) {
FCVT_S_D(v1, v1);
}
VST32(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_loadenv, -1);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
STRH_U12(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_savenv, -1);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
wb1 = 1;
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
}
} else
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);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
if(!ST_IS_F(0)) {
FCVT_D_S(v1, v1);
}
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else {
s0 = fpu_get_scratch(dyn, ninst);
FCVT_S_D(s0, v1);
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VST32(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
if(!ST_IS_F(0)) {
FCVT_S_D(v1, v1);
}
VST32(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_loadenv, -1);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
STRH_U12(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_savenv, -1);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
wb1 = 1;
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
return addr;
}
+88 -98
View File
@@ -42,6 +42,7 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(ed);
MAYUSE(j64);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -134,106 +135,95 @@ uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFD:
default:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v2, v1);
break;
}
}
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v2, ed, fixedaddress);
SXTL_32(v2, v2); // i32 -> i64
SCVTFDD(v2, v2); // i64 -> double
FDIVD(v1, v2, v1);
break;
}
return addr;
}
+151 -154
View File
@@ -42,6 +42,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v1);
MAYUSE(j64);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -176,35 +177,29 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCOMI(x1, x2);
break;
case 0xE0:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
default:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
SXTL_32(v1, v1); // i32 -> i64
SCVTFDD(v1, v1); // i64 -> double
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
VLD32(v1, ed, fixedaddress);
SXTL_32(v1, v1); // i32 -> i64
SCVTFDD(v1, v1); // i64 -> double
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32ZD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
FCVTZSwD(x5, s0);
STW(x5, wback, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -217,21 +212,20 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
#endif
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32XD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
FCVTZSwD(x5, s0);
STW(x5, wback, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -244,21 +238,20 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn);
#if 0
ed = x1;
}
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, 0);
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT32XD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
FCVTZSwD(x5, s0);
STW(x5, wback, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -271,112 +264,116 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOV32w(x5, 0x80000000);
STW(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FLD tbyte");
}
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if((PK(0)==0xDB && ((PK(1)>>3)&7)==7) || (!rex.is32bits && PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
NOTEST(x5);
// the FLD is immediatly followed by an FSTP
LDRx_U12(x5, ed, 0);
LDRH_U12(x6, ed, 8);
// no persistant scratch register, so unrool both instruction here...
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; // 0xDB or rex
if(!rex.is32bits && nextop>=0x40 && nextop<=0x4f) {
rex.rex = nextop;
nextop = F8; //0xDB
} else
rex.rex = 0;
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if((PK(0)==0xDB && ((PK(1)>>3)&7)==7) || (PK(0)>=0x40 && PK(0)<=0x4f && PK(1)==0xDB && ((PK(2)>>3)&7)==7)) {
// the FLD is immediatly followed by an FSTP
LDRx_U12(x5, ed, 0);
LDRH_U12(x6, ed, 8);
// no persistant scratch register, so unrool both instruction here...
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; // 0xDB or rex
if(nextop>=0x40 && nextop<=0x4f) {
rex.rex = nextop;
nextop = F8; //0xDB
} else
rex.rex = 0;
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
if(box64_x87_no80bits) {
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
VLDR64_U12(v1, ed, fixedaddress);
} else {
if(ed!=x1) {
MOVx_REG(x1, ed);
}
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x3);
CALL(native_fld, -1);
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
if(box64_x87_no80bits) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, wback, fixedaddress);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
VLDR64_U12(v1, ed, 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);
}
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_PUSH_EMPTY_OR_FAIL(dyn, ninst, 0);
// sync top
s0 = x87_stackcount(dyn, ninst, x3);
CALL(native_fld, -1);
// go back with the top & stack counter
x87_unstackcount(dyn, ninst, x3, s0);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
}
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if(box64_x87_no80bits) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &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);
}
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;
default:
DEFAULT;
}
return addr;
}
+73 -70
View File
@@ -36,6 +36,7 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v2);
MAYUSE(v1);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -177,75 +178,77 @@ uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
break;
}
}
DEFAULT;
break;
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
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);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
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);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
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);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v2, wback, fixedaddress);
FDIVD(v1, v2, v1);
break;
}
return addr;
}
+87 -102
View File
@@ -40,6 +40,7 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v1);
MAYUSE(j64);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -50,10 +51,20 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
#if 1
if((nextop&7)==0 && PK(0)==0xD9 && PK(1)==0xF7) {
MESSAGE(LOG_DUMP, "Hack for FFREE ST0 / FINCSTP\n");
x87_do_pop(dyn, ninst, x1);
addr+=2;
SKIPTEST(x1);
} else
x87_free(dyn, ninst, x1, x2, x3, nextop&7);
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
MOV32w(x1, nextop&7);
CALL(fpu_do_free, -1);
#endif
break;
case 0xD0:
case 0xD1:
@@ -129,121 +140,95 @@ uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
default:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x3, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, ed, fixedaddress);
break;
case 1:
INST_NAME("FISTTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
if(ST_IS_I64(0)) {
VST64(v1, ed, fixedaddress);
} else {
s0 = fpu_get_scratch(dyn);
#if 0
// those are ARM 8.5 opcode!
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x3, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, ed, fixedaddress);
break;
case 1:
INST_NAME("FISTTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
if(ST_IS_I64(0)) {
VST64(v1, ed, fixedaddress);
} else {
s0 = fpu_get_scratch(dyn, ninst);
if(arm64_frintts) {
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
#else
STx(x2, ed, fixedaddress);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTRRD(s0, v1, 3);
FCVTZSxD(x2, s0);
STx(x2, ed, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, ed, fixedaddress);
ORRx_mask(x2, xZR, 1, 1, 0); //0x8000000000000000
MARK3;
#endif
STx(x2, ed, fixedaddress);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_frstor, -1);
break;
case 6:
INST_NAME("FSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_fsave, -1);
break;
case 7:
INST_NAME("FNSTSW m2byte");
//fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
if(dyn->n.x87stack) {
// update top
if(dyn->n.x87stack>0) {
SUBw_U12(x2, x2, dyn->n.x87stack);
} else {
ADDw_U12(x2, x2, -dyn->n.x87stack);
}
ANDw_mask(x2, x2, 0, 2);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VST64(v1, ed, fixedaddress);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FRSTOR m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(native_frstor, -1);
break;
case 6:
INST_NAME("FNSAVE m108byte");
MESSAGE(LOG_DUMP, "Need Optimization\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);}
CALL(native_fsave, -1);
CALL(reset_fpu, -1);
break;
case 7:
INST_NAME("FNSTSW m2byte");
//fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
if(dyn->n.x87stack) {
// update top
if(dyn->n.x87stack>0) {
SUBw_U12(x2, x2, dyn->n.x87stack);
} else {
ADDw_U12(x2, x2, -dyn->n.x87stack);
}
BFIw(x3, x2, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
STH(x3, ed, fixedaddress); // store whole sw flags
break;
default:
DEFAULT;
}
}
ANDw_mask(x2, x2, 0, 2);
}
BFIw(x3, x2, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
STH(x3, ed, fixedaddress); // store whole sw flags
break;
default:
DEFAULT;
}
return addr;
}
+96 -102
View File
@@ -36,6 +36,7 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v2);
MAYUSE(v1);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -177,109 +178,102 @@ uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
default:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v2, v1);
break;
}
}
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FIADD ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FADDD(v1, v1, v2);
break;
case 1:
INST_NAME("FIMUL ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FMULD(v1, v1, v2);
break;
case 2:
INST_NAME("FICOM ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FICOMP ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v1, v2);
break;
case 5:
INST_NAME("FISUBR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FSUBD(v1, v2, v1);
break;
case 6:
INST_NAME("FIDIV ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v1, v2);
break;
case 7:
INST_NAME("FIDIVR ST0, word[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
VLD16(v2, wback, fixedaddress);
SXTL_16(v2, v2);
SXTL_32(v2, v2);
SCVTFDD(v2, v2);
FDIVD(v1, v2, v1);
break;
}
return addr;
}
+246 -264
View File
@@ -41,6 +41,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v1);
MAYUSE(j64);
if(MODREG)
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -55,6 +56,25 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FSTP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
FMOVS(v2, v1);
} else {
FMOVD(v2, v1);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
@@ -114,283 +134,245 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
default:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDSHw(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
SCVTFSw(v1, x1);
} else {
SCVTFDw(v1, x1);
}
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
// this version needs ARM v8.5, //TODO: add detection of this extension to use it
FRINT32ZD(s0, v1);
// no saturation instruction on Arm, so using NEON
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
LDSHw(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
SCVTFSw(v1, x1);
} else {
SCVTFDw(v1, x1);
}
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn, ninst);
#if 0
// this version needs ARM v8.5, and doesn't handle saturation for 32bits integer not fitting 16bits
FRINT32ZD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
VFCVTZSs(s0, v1);
} else {
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn, ninst);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
VFCVTZSs(s0, s0);
} else {
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
VFCVTZSs(s0, v1);
} else {
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn, ninst);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
VFCVTZSs(s0, s0);
} else {
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
BFCw(x5, FPSR_QC, 1); // reset QC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
VFCVTZSs(s0, s0);
} else {
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VST16(s0, wback, fixedaddress);
#else
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if(ST_IS_F(0)) {
FRINTXS(s0, v1);
VFCVTZSs(s0, s0);
} else {
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
X87_POP_OR_FAIL(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbld, -1);
break;
case 5:
INST_NAME("FILD ST0, i64");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_I64);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, wback, fixedaddress);
if(!ST_IS_I64(0)) {
if(rex.is32bits) {
// need to also feed the STll stuff...
ADDx_U12(x4, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ANDw_mask(x1, x1, 0, 2); //mask=7
}
VMOVSto(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);
MARK2;
MOV32w(x3, 0x8000);
MARK3;
STH(x3, wback, fixedaddress);
#endif
X87_POP_OR_FAIL(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
s0 = x87_stackcount(dyn, ninst, x3);
CALL(fpu_fbld, -1);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 5:
INST_NAME("FILD ST0, i64");
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_I64);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v1, wback, fixedaddress);
if(!ST_IS_I64(0)) {
if(rex.is32bits) {
// need to also feed the STll stuff...
ADDx_U12(x4, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ADDx_REG_LSL(x1, x4, x1, 4); // fpu_ll is 2 i64
VSTR64_U12(v1, x1, 8); // ll
}
SCVTFDD(v1, v1);
if(rex.is32bits) {
VSTR64_U12(v1, x1, 0); // ref
ANDw_mask(x1, x1, 0, 2); //mask=7
}
ADDx_REG_LSL(x1, x4, x1, 4); // fpu_ll is 2 i64
VSTR64_U12(v1, x1, 8); // ll
}
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbst, -1);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
if(!ST_IS_I64(0)) {
u8 = x87_setround(dyn, ninst, x1, x2, x4);
SCVTFDD(v1, v1);
if(rex.is32bits) {
VSTR64_U12(v1, x1, 0); // ref
}
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
if(ST_IS_I64(0)) {
VST64(v1, wback, fixedaddress);
} else {
#if 0
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
#else
if(rex.is32bits) {
// need to check STll first...
ADDx_U12(x5, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
VMOVQDto(x3, v1, 0);
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ANDw_mask(x1, x1, 0, 2); //mask=7
}
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
i1 = x87_stackcount(dyn, ninst, x1);
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbst, -1);
x87_unstackcount(dyn, ninst, x1, i1);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_I64);
if(!ST_IS_I64(0)) {
u8 = x87_setround(dyn, ninst, x1, x2, x4);
}
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn, ninst);
if(ST_IS_I64(0)) {
VST64(v1, wback, fixedaddress);
} else {
#if 0
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
#else
if(rex.is32bits) {
// need to check STll first...
ADDx_U12(x5, xEmu, offsetof(x64emu_t, fpu_ll));
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
VMOVQDto(x3, v1, 0);
int a = 0 - dyn->n.x87stack;
if(a) {
if(a<0) {
SUBw_U12(x1, x1, -a);
} else {
ADDw_U12(x1, x1, a);
}
ADDx_REG_LSL(x1, x5, x1, 4); // fpu_ll is 2 i64
LDRx_U12(x5, x1, 0); // ref
SUBx_REG(x5, x5, x3);
CBNZx_MARK2(x5);
LDRx_U12(x5, x1, 8); // ll
STx(x5, wback, fixedaddress);
B_MARK3(c__);
MARK2;
ANDw_mask(x1, x1, 0, 2); //mask=7
}
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
ADDx_REG_LSL(x1, x5, x1, 4); // fpu_ll is 2 i64
LDRx_U12(x5, x1, 0); // ref
SUBx_REG(x5, x5, x3);
CBNZx_MARK2(x5);
LDRx_U12(x5, x1, 8); // ll
STx(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
B_MARK3(c__);
MARK2;
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
}
}
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VST64(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
ORRx_mask(x5, xZR, 1, 1, 0); //0x8000000000000000
STx(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
}
return addr;
}
+72 -34
View File
@@ -48,7 +48,7 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3,
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -60,8 +60,13 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
MOV64xw(s3, c);
ORRxw_REG(s1, s1, s3);
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);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -79,7 +84,7 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -110,7 +115,7 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -122,8 +127,13 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
MOV64xw(s3, c);
EORxw_REG(s1, s1, s3);
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);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -141,7 +151,7 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -175,7 +185,7 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -187,11 +197,20 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
MOV64xw(s3, c);
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
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 {
ANDxw_REG(s1, s1, s3);
MOV64xw(s3, c);
IFX(X_ALL) {
ANDSxw_REG(s1, s1, s3);
} else {
ANDxw_REG(s1, s1, s3);
}
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -209,7 +228,7 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -232,20 +251,25 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRw_REG(s1, s1, s3);
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);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -255,7 +279,7 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -278,20 +302,25 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
EORw_REG(s1, s1, s3);
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);
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -301,7 +330,7 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -335,23 +364,32 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, 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)
{
MOV32w(s3, c&0xff);
IFX(X_PEND) {
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ZF) {
ANDSw_REG(s1, s1, s3);
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 {
ANDw_REG(s1, s1, s3);
MOV32w(s3, c&0xff);
IFX(X_ZF) {
ANDSw_REG(s1, s1, s3);
} else {
ANDw_REG(s1, s1, s3);
}
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
@@ -369,7 +407,7 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -393,7 +431,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -439,7 +477,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -462,7 +500,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -508,7 +546,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -542,7 +580,7 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -588,6 +626,6 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
+34 -37
View File
@@ -67,7 +67,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -139,7 +139,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -190,7 +190,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -263,7 +263,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
BFIx(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -297,15 +297,14 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
IFX(X_CF) {
LSRw(s3, s1, 8);
BFIw(xFlags, s3, F_CF, 1);
BFXILw(xFlags, s1, 8, 1);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -341,15 +340,14 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
IFX(X_CF) {
LSRw(s3, s1, 8);
BFIw(xFlags, s3, F_CF, 1);
BFXILw(xFlags, s1, 8, 1);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -393,7 +391,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -443,7 +441,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -478,15 +476,14 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
IFX(X_CF) {
LSRw(s3, s1, 16);
BFIw(xFlags, s3, F_CF, 1);
BFXILw(xFlags, s1, 16, 1);
}
IFX(X_PEND) {
STRw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -553,7 +550,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -596,7 +593,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -661,7 +658,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -710,7 +707,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
BFIxw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -746,7 +743,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -783,7 +780,7 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -833,7 +830,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
BFIxw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -881,7 +878,7 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -929,7 +926,7 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -983,7 +980,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1053,7 +1050,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -1099,7 +1096,7 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1153,7 +1150,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1220,7 +1217,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -1276,7 +1273,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1348,7 +1345,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -1395,7 +1392,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1450,7 +1447,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1517,7 +1514,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// emit_pf(dyn, ninst, s1, s4);
// }
//}
@@ -1564,7 +1561,7 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1614,7 +1611,7 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1663,6 +1660,6 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+308 -107
View File
@@ -75,13 +75,15 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -131,7 +133,12 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
if(c>7) {
// the 0xff area will be 0, so PF is known
MOV32w(s3, 1);
BFIw(xFlags, s3, F_PF, 1);
} else
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -178,13 +185,15 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -193,12 +202,6 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF) {
if(c==1) {
BFIw(xFlags, s1, 0, 1);
@@ -223,21 +226,23 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
// no sign if c>0
BFCw(xFlags, F_SF, 1);
}
if(box64_dynarec_test)
IFX(X_AF) {
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -246,12 +251,6 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF) {
ASRxw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
@@ -278,7 +277,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -309,7 +308,7 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
COMP_ZFSF(s1, 8)
IFX(X_OF) {
CMPSw_U12(s2, 1); // if s2==1
IFX(X_SF && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
@@ -319,7 +318,7 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -348,7 +347,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
COMP_ZFSF(s1, 8)
IFX(X_OF) {
if(c==1) {
IFX(X_SF && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);}
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
@@ -359,7 +358,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
@@ -423,15 +422,14 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
if(!c)
return;
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -464,7 +462,7 @@ void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -498,15 +496,14 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
if(!c)
return;
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -530,7 +527,7 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
BFCw(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
LSRw(s3, s1, 7);
@@ -570,7 +567,7 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s2, 1); // if s2==1
IFX(X_SF && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
@@ -580,15 +577,14 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
if(!c)
return;
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -610,7 +606,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
COMP_ZFSF(s1, 16)
IFX(X_OF) {
if(c==1) {
IFX(X_SF && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);}
EORw_REG(s4, s3, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
@@ -621,7 +617,12 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
if(c>7) {
// the 0xff area will be 0, so PF is known
MOV32w(s3, 1);
BFIw(xFlags, s3, F_PF, 1);
} else
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
@@ -678,7 +679,7 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -719,7 +720,7 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -753,15 +754,14 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
if(!c)
return;
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -788,13 +788,16 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
BFCw(xFlags, F_AF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -827,6 +830,9 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -860,6 +866,9 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -867,15 +876,11 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
if(c&7) {
int rc = 8-(c&7);
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, rc);
}
int rc = 8-(c&7);
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, rc);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -894,6 +899,9 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRB_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -901,14 +909,10 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
if(c&7) {
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, c&7);
}
ORRw_REG_LSL(s1, s1, s1, 8);
LSRw(s1, s1, c&7);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -928,6 +932,9 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -935,9 +942,11 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
int rc = 16-(c&15);
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, rc);
if(c&15) {
int rc = 16-(c&15);
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, rc);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -956,6 +965,9 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!c) return;
IFX(X_PEND) {
MOV32w(s3, c);
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -963,8 +975,10 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, c&15);
if(c&15) {
ORRw_REG_LSL(s1, s1, s1, 16);
LSRw(s1, s1, c&15);
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
@@ -980,6 +994,203 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int
}
}
// emit RCL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!(c%9)) return;
SET_DFNONE(s4);
c%=9;
BFIw(s1, xFlags, 8, 1); // insert cf
IFX(X_OF|X_CF) {
if(c!=8) {
LSRw_IMM(s3, s1, 8-c);
} else {
MOVw_REG(s3, s1);
}
}
ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again
LSRw_IMM(s1, s1, 9-c); // do the rcl
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_OF|X_CF) {
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
EORw_REG_LSR(s3, s3, s1, 7);
BFIw(xFlags, s3, F_OF, 1);
}
}
}
}
// emit RCR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!(c%9)) return;
SET_DFNONE(s4);
c%=9;
IFX(X_OF) {
MOVw_REG(s3, wFlags);
}
BFIw(s1, xFlags, 8, 1); // insert cf
IFX(X_CF) {
BFXILw(xFlags, s1, c-1, 1);
}
if(c>1) {
ORRw_REG_LSL(s1, s1, s1, 9); // insert s1 again
}
LSRw_IMM(s1, s1, c); // do the rcr
IFX(X_OF) {
if(c==1) {
EORw_REG_LSR(s3, s3, s1, 7);
BFIw(xFlags, s3, F_OF, 1);
}
}
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit RCL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!(c%17)) return;
SET_DFNONE(s4);
c%=17;
BFIw(s1, xFlags, 16, 1); // insert cf
IFX(X_OF|X_CF) {
if(c!=16) {
LSRw_IMM(s3, s1, 16-c);
} else {
MOVw_REG(s3, s1);
}
}
ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again
LSRx_IMM(s1, s1, 17-c); // do the rcl
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
EORw_REG_LSR(s3, s3, s1, 15);
BFIw(xFlags, s3, F_OF, 1);
}
}
}
// emit RCR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
if (!(c%17)) return;
SET_DFNONE(s4);
c%=17;
BFIw(s1, xFlags, 16, 1); // insert cf
IFX(X_OF) {
MOVw_REG(s3, wFlags);
}
IFX(X_CF) {
BFXILx(xFlags, s1, c-1, 1);
}
if(c>1) {
ORRx_REG_LSL(s1, s1, s1, 17); // insert s1 again
}
LSRx_IMM(s1, s1, c); // do the rcr
IFX(X_OF) {
if(c==1) {
EORw_REG_LSR(s3, s3, s1, 15);
BFIw(xFlags, s3, F_OF, 1);
}
}
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit RCL32/RCL64 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
SET_DFNONE(s4);
IFX(X_OF|X_CF) {
LSRxw_IMM(s3, s1, (rex.w?64:32)-c);
}
if(c==1) {
LSLxw(s1, s1, 1);
BFIxw(s1, xFlags, 0, 1);
} else {
LSLxw(s4, s1, c);
BFIxw(s4, xFlags, c-1, 1);
ORRxw_REG_LSR(s1, s4, s1, (rex.w?65:33)-c);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_CF) {
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
EORxw_REG_LSR(s3, s3, s1, rex.w?63:31);
BFIw(xFlags, s3, F_OF, 1);
}
}
}
// emit RCR32/RCR64 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
SET_DFNONE(s4);
IFX(X_OF) {
if(c==1) {
EORxw_REG_LSR(s3, xFlags, s1, rex.w?63:31);
BFIw(xFlags, s3, F_OF, 1);
}
}
IFX(X_CF) {
BFXILxw(s3, s1, c-1, 1);
}
if(c==1) {
LSRxw(s1, s1, 1);
BFIxw(s1, xFlags, rex.w?63:31, 1);
} else {
LSRxw(s4, s1, c);
BFIxw(s4, xFlags, (rex.w?64:32)-c, 1);
ORRxw_REG_LSL(s1, s4, s1, (rex.w?65:33)-c);
}
IFX(X_CF) {
BFIw(wFlags, s3, 0, 1);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
@@ -1022,13 +1233,12 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
}
IFX(X_OF) {
if(c==1) {
LSRxw(s4, s1, rex.w?63:31);
EORw_REG_LSR(s4, s4, xFlags, F_OF); // set if sign changed
BFIw(xFlags, s4, F_OF, 1);
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1076,15 +1286,14 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint
}
IFX(X_OF) {
if(c==1) {
LSRxw(s3, s1, rex.w?63:31);
EORxw_REG_LSR(s3, s3, xFlags, F_OF); // OF is set if sign changed
BFIw(xFlags, s3, F_OF, 1);
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1127,13 +1336,12 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+3*4);
LSRxw(s4, s1, rex.w?63:31);
EORw_REG_LSR(s4, s4, xFlags, F_OF); // Set if sign changed
BFIw(xFlags, s4, F_OF, 1);
Bcond(cNE, 4+2*4);
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1174,13 +1382,12 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+3*4);
LSRxw(s3, s1, rex.w?63:31);
EORxw_REG_LSR(s3, s3, xFlags, F_OF); // OF is set if sign changed
BFIw(xFlags, s3, F_OF, 1);
Bcond(cNE, 4+2*4);
UBFXx(s3, s1, rex.w?63:31, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1219,13 +1426,12 @@ void emit_shrd16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
COMP_ZFSF(s1, 16)
IFX(X_OF) {
if(c==1) {
LSRw(s4, s1, 15);
EORw_REG_LSR(s4, s4, xFlags, F_OF); // set if sign changed
BFIw(xFlags, s4, F_OF, 1);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1257,13 +1463,12 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+3*4);
LSRw(s4, s1, 15);
EORw_REG_LSR(s4, s4, xFlags, F_OF); // Set if sign changed
BFIw(xFlags, s4, F_OF, 1);
Bcond(cNE, 4+2*4);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1292,7 +1497,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
if(c<16)
LSRw(s3, s1, 16-c);
else
MOVx_REG(s3, s1);
LSRw(s3, s2, 32-c);
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
@@ -1307,15 +1512,14 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
COMP_ZFSF(s1, 16)
IFX(X_OF) {
if(c==1) {
LSRw(s3, s1, 15);
EORw_REG_LSR(s3, s3, xFlags, F_OF); // OF is set if sign changed
BFIw(xFlags, s3, F_OF, 1);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1328,20 +1532,18 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
ORRw_REG_LSL(s1, s1, s2, 16); // create concat first
IFX(X_CF) {
MOVw_REG(s3, s1);
CMPSw_U12(s5, 16);
Bcond(cGE, 4+3*4);
MOV32w(s3, 16);
SUBw_REG(s3, s3, s5);
LSRw_REG(s3, s1, s3);
ORRw_REG_LSL(s4, s2, s1, 16);
MOV32w(s3, 32);
SUBw_REG(s3, s3, s5);
LSRw_REG(s3, s4, s3);
BFIw(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
LSRw(s3, s1, 15);
BFIw(xFlags, s3, F_OF, 1); // store current sign for later use
}
ORRw_REG_LSL(s1, s1, s2, 16); // create concat first
MOV32w(s3, 32);
SUBw_REG(s3, s3, s5);
RORw_REG(s1, s1, s3);
@@ -1352,12 +1554,11 @@ void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
COMP_ZFSF(s1, 16)
IFX(X_OF) {
CMPSw_U12(s5, 1);
Bcond(cNE, 4+3*4);
LSRw(s3, s1, 15);
EORw_REG_LSR(s3, s3, xFlags, F_OF); // OF is set if sign changed
BFIw(xFlags, s3, F_OF, 1);
Bcond(cNE, 4+2*4);
UBFXw(s3, s1, 15, 1);
EORw_REG_LSL(xFlags, xFlags, s3, F_OF); // OF is set if sign changed
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+9 -12
View File
@@ -64,7 +64,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -96,7 +96,7 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
BFIw(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -138,7 +138,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -161,7 +161,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 16)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit CMP8 instruction, from cmp s1, s2, using s3 and s4 as scratch
@@ -201,7 +201,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
@@ -223,7 +223,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
COMP_ZFSF(s1, 8)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -252,9 +252,8 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
LSRxw(s4, s3, rex.w?63:31);
BFIw(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
emit_pf(dyn, ninst, s3, s5);
}
}
@@ -283,9 +282,8 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
LSRw(s4, s5, 15);
BFIw(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
@@ -314,8 +312,7 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
LSRw(s4, s5, 7);
BFIw(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
emit_pf(dyn, ninst, s5, s3, s4);
emit_pf(dyn, ninst, s5, s4);
}
}
+294 -58
View File
@@ -24,7 +24,7 @@
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
@@ -46,8 +46,13 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
rep = opcode-0xF1;
opcode = F8;
}
while((opcode==0x36) || (opcode==0x2e) || (opcode==0x3E) || (opcode==0x26)) {
opcode = F8;
}
GETREX();
SKIPTEST(x1); // DYNAREC_TEST doesn't work, by nature, on atomic opration
switch(opcode) {
case 0x00:
@@ -96,6 +101,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_add32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
UFLAG_IF {
LDADDALxw(gd, x1, wback);
@@ -103,14 +118,27 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
STADDLxw(gd, wback);
}
SMDMB();
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_add32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
SMDMB();
}
SMDMB();
}
break;
@@ -214,7 +242,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARKLOCK;
LDAXRB(ed, wback);
LSRw_REG(x4, ed, x2);
BFIw(xFlags, x5, F_CF, 1);
BFIw(xFlags, x4, F_CF, 1);
LSLw_REG(x4, x5, x2);
ORRw_REG(ed, ed, x4);
STLXRB(x4, ed, wback);
@@ -302,8 +330,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK3(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK3(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK3(cNE);
}
}
// Aligned version
if(arm64_atomics) {
@@ -528,6 +562,52 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC0:
switch(rep) {
case 0:
INST_NAME("LOCK XADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x1);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
GETEB(x2, 0);
gd = x2; ed = x1; // swap gd/ed
emit_add8(dyn, ninst, x1, x2, x4, x5);
GBBACK; // gb gets x2 (old ed)
EBBACK; // eb gets x1 (sum)
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(arm64_atomics) {
UFLAG_IF {
MOVxw_REG(x3, gd);
LDADDALB(x3, gd, wback);
SMDMB();
emit_add8(dyn, ninst, x3, gd, x4, x5);
} else {
LDADDALB(gd, gd, wback);
SMDMB();
}
GBBACK;
} else {
MARKLOCK;
LDAXRB(x1, wback);
ADDw_REG(x4, x1, gd);
STLXRB(x3, x4, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
IFX(X_ALL|X_PEND) {
MOVxw_REG(x2, x1);
emit_add8(dyn, ninst, x2, gd, x3, x4);
}
BFIz(gb1, x1, gb2, 8);
}
}
break;
default:
DEFAULT;
}
break;
case 0xC1:
switch(rep) {
case 0:
@@ -544,8 +624,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
}
}
if(arm64_atomics) {
UFLAG_IF {
@@ -598,52 +684,99 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0xC7:
switch(rep) {
case 0:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(arm64_atomics) {
MOVx_REG(x2, xRAX);
MOVx_REG(x3, xRDX);
MOVx_REG(x4, xRBX);
MOVx_REG(x5, xRCX);
CASPALxw(x2, x4, wback);
UFLAG_IF {
CMPSxw_REG(x2, xRAX);
CCMPxw(x3, xRDX, 0, cEQ);
CSETw(x1, cEQ);
// rep has no impact here
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
if(rex.w) {
TSTx_mask(wback, 1, 0, 3);
B_MARK2(cNE);
} else {
ANDx_mask(x2, wback, 1, 0, 3); // mask = F
CMPSw_U12(x2, 8);
B_MARK2(cGT);
}
MOVx_REG(xRAX, x2);
MOVx_REG(xRDX, x3);
} else {
MARKLOCK;
LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
STLXPxw(x4, xRBX, xRCX, wback);
CBNZx_MARKLOCK(x4);
UFLAG_IF {
MOV32w(x1, 1);
}
B_MARK3_nocond;
MARK;
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
MOV32w(x1, 0);
}
TSTx_mask(wback, 1, 0, 2+rex.w); // mask=7 or F
B_MARK2(cNE); // unaligned
}
MARK3;
SMDMB();
}
if(arm64_atomics) {
MOVx_REG(x2, xRAX);
MOVx_REG(x3, xRDX);
MOVx_REG(x4, xRBX);
MOVx_REG(x5, xRCX);
CASPALxw(x2, x4, wback);
UFLAG_IF {
BFIw(xFlags, x1, F_ZF, 1);
CMPSxw_REG(x2, xRAX);
CCMPxw(x3, xRDX, 0, cEQ);
CSETw(x1, cEQ);
}
break;
default:
DEFAULT;
MOVx_REG(xRAX, x2);
MOVx_REG(xRDX, x3);
if(!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
}
} else {
MARKLOCK;
LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
STLXPxw(x4, xRBX, xRCX, wback);
CBNZx_MARKLOCK(x4);
UFLAG_IF {
MOV32w(x1, 1);
}
B_MARK3_nocond;
MARK;
STLXPxw(x4, x2, x3, wback); // write back, to be sure it was "atomic"
CBNZx_MARKLOCK(x4);
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
MOV32w(x1, 0);
}
if(!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
}
}
if(!ALIGNED_ATOMICxw) {
MARK2;
LDPxw_S7_offset(x2, x3, wback, 0);
LDAXRB(x5, wback);
CMPSxw_REG(xRAX, x2);
CCMPxw(xRDX, x3, 0, cEQ);
B_MARKSEG(cNE); // EAX!=ED[0] || EDX!=Ed[1]
STLXRB(x4, xRBX, wback);
CBNZx_MARK2(x4);
STPxw_S7_offset(xRBX, xRCX, wback, 0);
UFLAG_IF {
MOV32w(x1, 1);
}
B_MARK3_nocond;
MARKSEG;
STLXRB(x4, x5, wback); //write back
CBNZx_MARK2(x4);
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
UFLAG_IF {
MOV32w(x1, 0);
}
}
MARK3;
SMDMB();
UFLAG_IF {
BFIw(xFlags, x1, F_ZF, 1);
}
break;
default:
DEFAULT;
}
break;
@@ -737,6 +870,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
NEGxw_REG(x1, gd);
UFLAG_IF {
@@ -753,6 +896,69 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
SMDMB();
}
}
break;
case 0x31:
INST_NAME("LOCK XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_xor32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
UFLAG_IF {
LDEORALxw(gd, x1, wback);
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
} else {
STEORLxw(gd, wback);
}
SMDMB();
} else {
MARKLOCK;
LDAXRxw(x1, wback);
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
SMDMB();
}
if(!ALIGNED_ATOMICxw) {
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_xor32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRxw_U12(x1, wback, 0); // put the whole value
SMDMB();
}
}
break;
@@ -998,8 +1204,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
MOV64xw(x3, i64);
@@ -1147,8 +1359,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
MOV64xw(x5, -i64);
@@ -1277,8 +1495,14 @@ uintptr_t dynarec64_F0(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_ATOMICxw) {
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
if(arm64_uscat) {
ANDx_mask(x1, ed, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
}
}
if(arm64_atomics) {
SWPALxw(gd, gd, ed);
@@ -1419,8 +1643,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
}
}
if(arm64_atomics) {
MOV32w(x3, 1);
@@ -1461,8 +1691,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
if(!ALIGNED_ATOMICxw) {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
if(arm64_uscat) {
ANDx_mask(x1, wback, 1, 0, 3); // mask = F
CMPSw_U12(x1, 16-(1<<(2+rex.w)));
B_MARK(cGT);
} else {
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
}
}
if(arm64_atomics) {
MOV64xw(x3, -1);
+63 -39
View File
@@ -71,6 +71,7 @@ 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();
@@ -83,14 +84,13 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, d0, 0);
VDUPQ_64(v0, d0, 0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0);
VLD64(v0, ed, fixedaddress);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
VLDQ1R_64(v0, ed);
}
VMOVeD(v0, 1, v0, 0);
break;
case 0x2A:
@@ -98,7 +98,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFDx(d1, ed);
} else {
@@ -139,7 +139,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FRINTID(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwD(gd, d1);
@@ -206,10 +206,10 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
FCMLTD_0(v1, d0);
SHL_64(v1, v1, 63);
FSQRTD(d1, d0);
@@ -224,11 +224,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -246,11 +246,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("MULSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -269,7 +269,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSD(d0, 0, 0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FCVT_S_D(d1, d0);
VMOVeS(v0, 0, d1, 0);
break;
@@ -278,11 +278,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
GETGX(d1, 1);
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETEXSD(d0, 0, 0);
if(!box64_dynarec_fastnan) {
v0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -303,7 +303,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSD(v1, 0, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMINNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
@@ -316,11 +316,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSD(v1, 0, 0);
if(!box64_dynarec_fastnan) {
d0 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(d0, v0, v1); // propagate NAN
FCMEQD(d0, d0, d0); // 0 if NAN, 1 if not NAN
@@ -341,7 +341,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSD(v1, 0, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMAXNMD(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeD(v0, 0, d0, 0); // to not erase uper part
#else
@@ -358,17 +358,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
u8 = F8;
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
if(u8==0b00000000 || u8==0b01010101 || u8==0b10101010 || u8==0b11111111) {
if(v0==v1) {
d0 = fpu_get_scratch(dyn, ninst);
VMOVQ(d0, v1);
}
VDUP_16(v0, v1, u8&3);
if(v0==v1)
v1 = d0;
} else {
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn, ninst);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
}
if(v0!=v1) {
VMOVeD(v0, 1, v1, 1);
}
@@ -382,7 +392,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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);
v1 = fpu_get_scratch(dyn, ninst);
VLD128(v1, ed, fixedaddress);
}
VFADDPQS(v0, v0, v1);
@@ -395,14 +405,28 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
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);
v1 = fpu_get_scratch(dyn, ninst);
VLD128(v1, ed, fixedaddress);
}
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
VUZP1Q_32(d0, v0, v1);
VUZP2Q_32(v0, v0, v1);
VFSUBQS(v0, d0, v0);
break;
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
case 6:
INST_NAME("(unsupported) UWAIT Ed");
FAKEED;
UDF(0);
break;
default:
DEFAULT;
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
@@ -428,7 +452,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn);
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);
@@ -461,7 +485,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
+110 -41
View File
@@ -84,7 +84,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn, ninst);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
@@ -99,7 +99,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, 0);
q1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn, ninst);
VLD128(q1, ed, fixedaddress);
}
GETGX_empty(q0);
@@ -117,7 +117,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
if(rex.w) {
SCVTFSx(d1, ed);
} else {
@@ -158,7 +158,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MSR_fpsr(x5);
}
u8 = sse_setround(dyn, ninst, x1, x2, x3);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
FRINTIS(d1, q0);
x87_restoreround(dyn, ninst, u8);
FCVTZSxwS(gd, d1);
@@ -172,11 +172,41 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
break;
case 0x38: /* MAP */
opcode = F8;
switch(opcode) {
case 0xF6:
INST_NAME("ADOX Gd, Ed");
nextop = F8;
READFLAGS(X_OF);
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
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;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FSQRTS(d1, d0);
VMOVeS(v0, 0, d1, 0);
@@ -186,8 +216,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
@@ -203,7 +233,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMOVS_8(d0, 0b01110000); //1.0f
FDIVS(d0, d0, v1);
VMOVeS(v0, 0, d0, 0);
@@ -213,7 +243,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = 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);
@@ -222,7 +252,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FMULS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
@@ -232,7 +262,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FCVT_D_S(d0, v1);
VMOVeD(v0, 0, d0, 0);
break;
@@ -248,7 +278,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
for(int i=0; i<4; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
@@ -261,12 +291,11 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
}
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FSUBS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
@@ -278,7 +307,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSS(v1, 0, 0);
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMINNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
@@ -291,7 +320,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn, ninst);
GETEXSS(d0, 0, 0);
FDIVS(d1, v0, d0);
VMOVeS(v0, 0, d1, 0);
@@ -303,7 +332,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEXSS(v1, 0, 0);
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
#if 0
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
FMAXNMS(d0, v0, v1); // NaN handling may be slightly different, is that a problem?
VMOVeS(v0, 0, d0, 0); // to not erase uper part
#else
@@ -312,7 +341,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeS(v0, 0, v1, 0); // to not erase uper part
#endif
break;
case 0x6F:
INST_NAME("MOVDQU Gx,Ex");// no alignment constraint on NEON here, so same as MOVDQA
nextop = F8;
@@ -333,16 +362,20 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(v1, 0, 1) ;
GETGX(v0, 1);
u8 = F8;
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+8)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+9)<<(i*16+8);
d0 = fpu_get_scratch(dyn, ninst);
if (u8 == 0b00000000 || u8 == 0b01010101 || u8 == 0b10101010 || u8 == 0b11111111) {
VDUPQ_16(d0, v1, (u8 & 3) + 4);
} else {
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i = 0; i < 4; ++i) {
u64 |= ((uint64_t)((u8 >> (i * 2)) & 3) * 2 + 8) << (i * 16 + 0);
u64 |= ((uint64_t)((u8 >> (i * 2)) & 3) * 2 + 9) << (i * 16 + 8);
}
MOV64x(x2, u64);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 1, d0, 0);
if(v0!=v1) {
VMOVeD(v0, 0, v1, 0);
@@ -377,12 +410,40 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("(unsupported) WRFSBASE Ed");
FAKEED;
UDF(0);
break;
case 3:
INST_NAME("(unsupported) WRGSBASE Ed");
FAKEED;
UDF(0);
break;
case 5:
INST_NAME("(unsupported) INCSSPD/INCSSPQ Ed");
FAKEED;
UDF(0);
break;
case 6:
INST_NAME("(unsupported) UMONITOR Ed");
FAKEED;
UDF(0);
break;
default:
DEFAULT;
}
break;
case 0xB8:
INST_NAME("POPCNT Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
SET_DFNONE(x1);
nextop = F8;
v1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn, ninst);
GETGD;
if(MODREG) {
GETED(0);
@@ -420,14 +481,18 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
RBITxw(x3, ed); // reverse
CLZxw(gd, x3); // x2 gets leading 0 == TZCNT
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
break;
case 0xBD:
INST_NAME("LZCNT Gd, Ed");
@@ -436,13 +501,17 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETED(0);
GETGD;
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
IFX(X_CF) {
TSTxw_REG(ed, ed);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_CF, 1); // CF = is source 0?
}
CLZxw(gd, ed); // x2 gets leading 0 == LZCNT
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
IFX(X_ZF) {
TSTxw_REG(gd, gd);
CSETw(x3, cEQ);
BFIw(xFlags, x3, F_ZF, 1); // ZF = is dest 0?
}
break;
case 0xC2:
@@ -485,7 +554,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETEXSD(v1, 0, 0);
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn, ninst);
SXTL_32(v0, v1);
SCVTQFD(v0, v0); // there is only I64 -> Double vector conversion, not from i32
break;
+240 -34
View File
@@ -26,26 +26,55 @@
#include "custommem.h"
#include "bridge.h"
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn)
int fpu_get_scratch(dynarec_arm_t* dyn, int ninst)
{
return SCRATCH0 + dyn->n.fpu_scratch++; // return an Sx
int ret = SCRATCH0 + dyn->n.fpu_scratch++;
if(dyn->n.ymm_used) printf_log(LOG_INFO, "Warning, getting a scratch register after getting some YMM at inst=%d\n", ninst);
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
return ret;
}
// Get 2 consicutive FPU scratch reg
int fpu_get_double_scratch(dynarec_arm_t* dyn, int ninst)
{
int ret = SCRATCH0 + dyn->n.fpu_scratch;
if(dyn->n.ymm_used) printf_log(LOG_INFO, "Warning, getting a double scratch register after getting some YMM at inst=%d\n", ninst);
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
if(dyn->n.neoncache[ret+1].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret+1].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret+1].n); // mark as purged
dyn->n.neoncache[ret+1].v = 0; // reset it
}
dyn->n.fpu_scratch+=2;
return ret;
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->n.fpu_scratch = 0;
dyn->n.ymm_used = 0;
dyn->n.ymm_regs = 0;
dyn->n.ymm_write = 0;
dyn->n.ymm_removed = 0;
}
// Get a x87 double reg
int fpu_get_reg_x87(dynarec_arm_t* dyn, int t, int n)
int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n)
{
int i=X870;
while (dyn->n.fpuused[i]) ++i;
if(dyn->n.neoncache[i].t==NEON_CACHE_YMMR || dyn->n.neoncache[i].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[i].n); // mark as purged
dyn->n.neoncache[i].v = 0; // reset it
}
dyn->n.fpuused[i] = 1;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i].t = t;
@@ -57,17 +86,34 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
dyn->n.fpuused[reg] = 0;
if(dyn->n.neoncache[reg].t==NEON_CACHE_YMMR || dyn->n.neoncache[reg].t==NEON_CACHE_YMMW) {
dyn->n.ymm_removed |= 1<<dyn->n.neoncache[reg].n;
if(dyn->n.neoncache[reg].t==NEON_CACHE_YMMW)
dyn->n.ymm_write |= 1<<dyn->n.neoncache[reg].n;
if(reg>SCRATCH0)
dyn->n.ymm_regs |= (8LL+reg-SCRATCH0)<<(dyn->n.neoncache[reg].n*4);
else
dyn->n.ymm_regs |= ((uint64_t)(reg-EMM0))<<(dyn->n.neoncache[reg].n*4);
}
if(dyn->n.neoncache[reg].t!=NEON_CACHE_ST_F && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_D && dyn->n.neoncache[reg].t!=NEON_CACHE_ST_I64)
dyn->n.neoncache[reg].v = 0;
if(dyn->n.fpu_scratch && reg==SCRATCH0+dyn->n.fpu_scratch-1)
--dyn->n.fpu_scratch;
}
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm)
int fpu_get_reg_emm(dynarec_arm_t* dyn, int ninst, int emm)
{
dyn->n.fpuused[EMM0 + emm] = 1;
dyn->n.neoncache[EMM0 + emm].t = NEON_CACHE_MM;
dyn->n.neoncache[EMM0 + emm].n = emm;
dyn->n.news |= (1<<(EMM0 + emm));
return EMM0 + emm;
int ret = EMM0 + emm;
if(dyn->n.neoncache[ret].t==NEON_CACHE_YMMR || dyn->n.neoncache[ret].t==NEON_CACHE_YMMW) {
// should only happens in step 0...
dyn->insts[ninst].purge_ymm |= (1<<dyn->n.neoncache[ret].n); // mark as purged
dyn->n.neoncache[ret].v = 0; // reset it
}
dyn->n.fpuused[ret] = 1;
dyn->n.neoncache[ret].t = NEON_CACHE_MM;
dyn->n.neoncache[ret].n = emm;
dyn->n.news |= (1<<(ret));
return ret;
}
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
@@ -84,15 +130,53 @@ int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm)
dyn->n.news |= (1<<i);
return i;
}
int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg)
{
if((dyn->n.neoncache[reg].t==NEON_CACHE_YMMR) || (dyn->n.neoncache[reg].t==NEON_CACHE_YMMW)) {
if(dyn->n.neoncache[reg].n == ymm) {
// already there!
if(t==NEON_CACHE_YMMW)
dyn->n.neoncache[reg].t=t;
return reg;
}
} else if(!dyn->n.neoncache[reg].v) {
// found a slot!
dyn->n.neoncache[reg].t=t;
dyn->n.neoncache[reg].n=ymm;
return reg;
}
return -1;
}
int is_ymm_to_keep(dynarec_arm_t* dyn, int reg, int k1, int k2, int k3)
{
if((k1!=-1) && (dyn->n.neoncache[reg].n==k1))
return 1;
if((k2!=-1) && (dyn->n.neoncache[reg].n==k2))
return 1;
if((k3!=-1) && (dyn->n.neoncache[reg].n==k3))
return 1;
if((dyn->n.neoncache[reg].t==NEON_CACHE_YMMR || dyn->n.neoncache[reg].t==NEON_CACHE_YMMW) && (dyn->n.ymm_used&(1<<dyn->n.neoncache[reg].n)))
return 1;
return 0;
}
// Reset fpu regs counter
static void fpu_reset_reg_neoncache(neoncache_t* n)
{
n->fpu_reg = 0;
for (int i=0; i<32; ++i) {
n->fpuused[i]=0;
n->neoncache[i].v = 0;
}
n->ymm_regs = 0;
n->ymm_removed = 0;
n->ymm_used = 0;
n->ymm_write = 0;
}
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->n.fpu_reg = 0;
for (int i=0; i<24; ++i) {
dyn->n.fpuused[i]=0;
dyn->n.neoncache[i].v = 0;
}
fpu_reset_reg_neoncache(&dyn->n);
}
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a)
@@ -208,15 +292,13 @@ static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int
neoncache_promote_double_internal(dyn, ninst-1, maxinst, a-dyn->insts[ninst].n.stack_push);
// go forward is combined is not pop'd
if(a-dyn->insts[ninst].n.stack_pop>=0)
if(!dyn->insts[ninst+1].n.barrier)
if(!((ninst+1<dyn->size) && dyn->insts[ninst+1].n.barrier))
neoncache_promote_double_forward(dyn, ninst+1, maxinst, a-dyn->insts[ninst].n.stack_pop);
}
}
}
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
if(dyn->insts[ninst+1].n.barrier)
return;
while(ninst>=0) {
a+=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: add pop'd ST (going backward)
int i = neoncache_get_st_f_i64(dyn, ninst, a);
@@ -341,10 +423,11 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
return ((dyn->insts[ninst].x64.barrier&BARRIER_FLOAT))?0:(isCacheEmpty(dyn, ninst)?0:1);
int ret = 0;
if(!i2) { // just purge
if(dyn->insts[ninst].n.stack_next) {
if(dyn->insts[ninst].n.stack_next)
return 1;
}
for(int i=0; i<24 && !ret; ++i)
if(dyn->insts[ninst].ymm0_out)
return 1;
for(int i=0; i<32 && !ret; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
@@ -359,10 +442,12 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
if(dyn->insts[ninst].n.stack_next != dyn->insts[i2].n.stack-dyn->insts[i2].n.stack_push) {
return 1;
}
if(dyn->insts[ninst].ymm0_out && (dyn->insts[ninst].ymm0_out&~dyn->insts[i2].ymm0_in))
return 1;
neoncache_t cache_i2 = dyn->insts[i2].n;
neoncacheUnwind(&cache_i2);
for(int i=0; i<24; ++i) {
for(int i=0; i<32; ++i) {
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!cache_i2.neoncache[i].v) { // but there is nothing at i2 for i
ret = 1;
@@ -372,6 +457,8 @@ int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
}
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_XMMR && cache_i2.neoncache[i].t == NEON_CACHE_XMMW)
{/* nothing */ }
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_YMMR && cache_i2.neoncache[i].t == NEON_CACHE_YMMW)
{/* nothing */ }
else
ret = 1;
}
@@ -387,6 +474,7 @@ void neoncacheUnwind(neoncache_t* cache)
// unswap
int a = -1;
int b = -1;
// in neoncache
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F || cache->neoncache[j].t == NEON_CACHE_ST_I64)) {
if(cache->neoncache[j].n == cache->combined1)
@@ -399,11 +487,12 @@ void neoncacheUnwind(neoncache_t* cache)
cache->neoncache[a].n = cache->neoncache[b].n;
cache->neoncache[b].n = tmp;
}
// done
cache->swapped = 0;
cache->combined1 = cache->combined2 = 0;
}
if(cache->news) {
// reove the newly created neoncache
// remove the newly created neoncache
for(int i=0; i<24; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
@@ -420,17 +509,28 @@ void neoncacheUnwind(neoncache_t* cache)
}
}
cache->x87stack-=cache->stack_push;
cache->tags>>=(cache->stack_push*2);
cache->stack-=cache->stack_push;
if(cache->pushed>=cache->stack_push)
cache->pushed-=cache->stack_push;
else
cache->pushed = 0;
cache->stack_push = 0;
}
cache->x87stack+=cache->stack_pop;
cache->stack_next = cache->stack;
if(cache->stack_pop) {
if(cache->poped>=cache->stack_pop)
cache->poped-=cache->stack_pop;
else
cache->poped = 0;
cache->tags<<=(cache->stack_pop*2);
}
cache->stack_pop = 0;
cache->barrier = 0;
// And now, rebuild the x87cache info with neoncache
cache->mmxcount = 0;
cache->fpu_scratch = 0;
cache->fpu_extra_qscratch = 0;
cache->fpu_reg = 0;
for(int i=0; i<8; ++i) {
cache->x87cache[i] = -1;
@@ -440,7 +540,7 @@ void neoncacheUnwind(neoncache_t* cache)
cache->ssecache[i*2+1].v = -1;
}
int x87reg = 0;
for(int i=0; i<24; ++i) {
for(int i=0; i<32; ++i) {
if(cache->neoncache[i].v) {
cache->fpuused[i] = 1;
switch (cache->neoncache[i].t) {
@@ -455,6 +555,10 @@ void neoncacheUnwind(neoncache_t* cache)
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
++cache->fpu_reg;
break;
case NEON_CACHE_YMMR:
case NEON_CACHE_YMMW:
cache->fpuused[i] = 0; // YMM does not mark the fpu reg as used
break;
case NEON_CACHE_ST_F:
case NEON_CACHE_ST_D:
case NEON_CACHE_ST_I64:
@@ -472,6 +576,24 @@ void neoncacheUnwind(neoncache_t* cache)
cache->fpuused[i] = 0;
}
}
// add back removed YMM
if(cache->ymm_removed) {
for(int i=0; i<16; ++i)
if(cache->ymm_removed&(1<<i)) {
int reg = cache->ymm_regs>>(i*4)&15;
if(reg>7)
reg = reg - 8 + SCRATCH0;
else
reg = reg + EMM0;
if(cache->neoncache[reg].v)
printf_log(LOG_INFO, "Warning, recreating YMM%d on non empty slot %s", i, getCacheName(cache->neoncache[reg].t, cache->neoncache[reg].n));
cache->neoncache[reg].t = (cache->ymm_write&(1<<i))?NEON_CACHE_YMMW:NEON_CACHE_YMMR;
cache->neoncache[reg].n = i;
}
cache->ymm_regs = 0;
cache->ymm_write = cache->ymm_removed = 0;
}
cache->ymm_used = 0;
}
#define F8 *(uint8_t*)(addr++)
@@ -527,6 +649,8 @@ const char* getCacheName(int t, int n)
case NEON_CACHE_MM: sprintf(buff, "MM%d", n); break;
case NEON_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case NEON_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
case NEON_CACHE_YMMW: sprintf(buff, "YMM%d", n); break;
case NEON_CACHE_YMMR: sprintf(buff, "ymm%d", n); break;
case NEON_CACHE_SCR: sprintf(buff, "Scratch"); break;
case NEON_CACHE_NONE: buff[0]='\0'; break;
}
@@ -537,7 +661,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
{
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",
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,
@@ -552,19 +676,23 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
dyn->insts[ninst].x64.use_flags,
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smread, dyn->smwrite);
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(!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<24; ++ii) {
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;
@@ -572,11 +700,27 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_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))) {
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":"");
}
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)
@@ -589,3 +733,65 @@ 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));
}
static void x87_reset(neoncache_t* n)
{
for (int i=0; i<8; ++i)
n->x87cache[i] = -1;
n->tags = 0;
n->x87stack = 0;
n->stack = 0;
n->stack_next = 0;
n->stack_pop = 0;
n->stack_push = 0;
n->combined1 = n->combined2 = 0;
n->swapped = 0;
n->barrier = 0;
n->pushed = 0;
n->poped = 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].t == NEON_CACHE_ST_F
|| n->neoncache[i].t == NEON_CACHE_ST_D
|| n->neoncache[i].t == NEON_CACHE_ST_I64)
n->neoncache[i].v = 0;
}
static void mmx_reset(neoncache_t* n)
{
n->mmxcount = 0;
for (int i=0; i<8; ++i)
n->mmxcache[i] = -1;
}
static void sse_reset(neoncache_t* n)
{
for (int i=0; i<16; ++i)
n->ssecache[i].v = -1;
for (int i=0; i<32; ++i)
if(n->neoncache[i].t==NEON_CACHE_YMMR || n->neoncache[i].t==NEON_CACHE_YMMW)
n->neoncache[i].v = 0;
}
void fpu_reset(dynarec_native_t* dyn)
{
x87_reset(&dyn->n);
mmx_reset(&dyn->n);
sse_reset(&dyn->n);
fpu_reset_reg(dyn);
dyn->ymm_zero = 0;
}
void fpu_reset_ninst(dynarec_native_t* dyn, int ninst)
{
x87_reset(&dyn->insts[ninst].n);
mmx_reset(&dyn->insts[ninst].n);
sse_reset(&dyn->insts[ninst].n);
fpu_reset_reg_neoncache(&dyn->insts[ninst].n);
}
int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st)
{
return (dyn->n.tags&(0b11<<(st*2)))?1:0;
}
+21 -3
View File
@@ -4,21 +4,32 @@
#include "../dynarec_native_functions.h"
#define SCRATCH0 24
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_arm_t* dyn);
int fpu_get_scratch(dynarec_arm_t* dyn, int ninst);
// Get 2 consecutive FPU scratch reg
int fpu_get_double_scratch(dynarec_arm_t* dyn, int ninst);
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn);
// Get an x87 double reg
int fpu_get_reg_x87(dynarec_arm_t* dyn, int t, int n);
int fpu_get_reg_x87(dynarec_arm_t* dyn, int ninst, int t, int n);
// Get an MMX double reg
int fpu_get_reg_emm(dynarec_arm_t* dyn, int emm);
int fpu_get_reg_emm(dynarec_arm_t* dyn, int ninst, int emm);
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_arm_t* dyn, int t, int xmm);
// Free a FPU/MMX/XMM reg
void fpu_free_reg(dynarec_arm_t* dyn, int reg);
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn);
// internal YMM handling
int internal_mark_ymm(dynarec_arm_t* dyn, int t, int ymm, int reg);
// is ymm neoncache[reg] one of k1, k2, k3?
int is_ymm_to_keep(dynarec_arm_t* dyn, int reg, int k1, int k2, int k3);
// ---- Neon cache functions
// Get type for STx
@@ -54,4 +65,11 @@ const char* getCacheName(int t, int n);
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex);
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode);
// reset the cache
void fpu_reset(dynarec_native_t* dyn);
void fpu_reset_ninst(dynarec_native_t* dyn, int ninst);
// is st freed
int fpu_is_st_freed(dynarec_native_t* dyn, int ninst, int st);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
File diff suppressed because it is too large. Load diff
+353 -62
View File
@@ -33,37 +33,65 @@
#define PKip(a) *(uint8_t*)(ip+a)
// Strong mem emulation helpers
#define SMREAD_MIN 2
#define SMWRITE_MIN 1
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
#define SMREAD_VAL 4
#define SMWRITE2_MIN 1
#define SMFIRST_MIN 1
#define SMSEQ_MIN 2
#define SMSEQ_MAX 3
#if STEP == 1
// pass 1 has the jump point available
#define SMWRITE() dyn->insts[ninst].will_write = 1; dyn->smwrite = 1
#define SMREAD()
#define SMREADLOCK(lock)
#define SMMIGHTREAD()
#define WILLWRITE2() if(box64_dynarec_strongmem>SMWRITE2_MIN) {WILLWRITE();}
#define SMWRITE2() if(box64_dynarec_strongmem>SMWRITE2_MIN) {SMWRITE();}
#define SMWRITELOCK(lock) SMWRITE()
#define WILLWRITELOCK(lock)
#define WILLWRITE()
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
#define SMSTART() dyn->smwrite = 0; dyn->smread = 0;
#define SMEND() if(dyn->smwrite && (box64_dynarec_strongmem>SMFIRST_MIN)) {int i = ninst; while(i>=0 && !dyn->insts[i].will_write) --i; if(i>=0) {dyn->insts[i].last_write = 1;}} dyn->smwrite = 0
#define SMDMB()
#else
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
// Block will trigget at 1st and last if strongmem is >= SMFIRST_MIN
// Read will contribute to trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
// Opcode will read
#define SMREAD() if((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
#define SMREAD() if(dyn->insts[ninst].will_write) {WILLWRITE();} else if(box64_dynarec_strongmem==SMREAD_VAL && !dyn->smread) {DSB_SY(); dyn->smread = 1;}
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
#define SMREADLOCK(lock) if((lock)) {SMWRITELOCK(lock);} else {SMREAD();}
// Opcode might read (depend on nextop)
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
// Opcode has wrote
#define SMWRITE() dyn->smwrite=1
#define SMWRITE() if((box64_dynarec_strongmem>=SMFIRST_MIN) && dyn->smwrite==0 && (box64_dynarec_strongmem!=SMREAD_VAL)) {SMDMB();} if(box64_dynarec_strongmem>SMSEQ_MIN && (box64_dynarec_strongmem!=SMREAD_VAL)) {if(++dyn->smwrite>=SMSEQ_MAX) {SMDMB(); dyn->smwrite=1;}} else dyn->smwrite=1
// Opcode has wrote (strongmem>1 only)
#define SMWRITE2() if(box64_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
#define WILLWRITE2() if(box64_dynarec_strongmem>SMWRITE2_MIN) {WILLWRITE();}
#define SMWRITE2() if(box64_dynarec_strongmem>SMWRITE2_MIN) {SMWRITE();}
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock || (box64_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
#define SMWRITELOCK(lock) if(lock) {SMDMB(); dyn->smwrite=1;} else {SMWRITE();}
// Opcode has wrote with option forced lock
#define WILLWRITELOCK(lock) if(lock) {DMB_ISH();} else {WILLWRITE();}
// Opcode might have wrote (depend on nextop)
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
// Opcode will write (without reading)
#define WILLWRITE() if((box64_dynarec_strongmem>=SMFIRST_MIN) && dyn->smwrite==0 && (box64_dynarec_strongmem!=SMREAD_VAL)) {SMDMB();} else if(box64_dynarec_strongmem>=SMFIRST_MIN && dyn->insts[ninst].last_write && (box64_dynarec_strongmem!=SMREAD_VAL)) {SMDMB();} dyn->smwrite=1
// Start of sequence
#define SMSTART() SMEND()
// End of sequence
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem && (box64_dynarec_strongmem!=SMREAD_VAL)) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
#define SMDMB() if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=0
#endif
//LOCK_* define
#define LOCK_LOCK (int*)1
// GETGD get x64 register in gd
#define GETGD gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3)
// GETVD get x64 register in vd
#define GETVD vd = xRAX+vex.v
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETED(D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
@@ -254,6 +282,34 @@
ed = i; \
wb1 = 1; \
}
//GETEW will use i for ed, and can use r3 for wback.
#define GETEW32(i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
UXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted32(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
LDH(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
}
//GETEWO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEWO(i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
UXTHw(i, wback); \
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, &unscaled, 0xfff<<1, (1<<1)-1, rex, NULL, 0, D); \
ADDx_REG(x3, wback, i); \
if(wback!=x3) wback = x3; \
LDH(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
//GETSEW will use i for ed, and can use r3 for wback. This is the Signed version
#define GETSEW(i, D) if(MODREG) { \
wback = xRAX+(nextop&7)+(rex.b<<3);\
@@ -395,14 +451,180 @@
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
// Get VX as a quad (might use x1)
#define GETVX(a, w) \
a = sse_get_reg(dyn, ninst, x1, vex.v, w)
// Get an empty VX (use x1)
#define GETVX_empty(a) \
a = sse_get_reg_empty(dyn, ninst, x1, vex.v)
// Get empty VX, and non-writen EX
#define GETVX_empty_EX(vx, ex, D) \
GETEX_Y(ex, 0, D); \
GETVX_empty(vx)
// Get VX, and EX
#define GETVXEX(vx, w1, ex, w2, D) \
GETEX_Y(ex, w2, D); \
GETVX(vx, w1)
#define GETGY_VY(a, w1, b, w2, k1, k2) \
if(w2) b = ymm_get_reg(dyn, ninst, x1, vex.v, w2, gd, k1, k2); \
a = ymm_get_reg(dyn, ninst, x1, gd, w1, vex.v, k1, k2); \
if(!w2) b = ymm_get_reg(dyn, ninst, x1, vex.v, w2, gd, k1, k2)
#define GETGY_empty(a, k1, k2, k3) \
a = ymm_get_reg_empty(dyn, ninst, x1, gd, k1, k2, k3)
#define GETGY(a, w, k1, k2, k3) \
a = ymm_get_reg(dyn, ninst, x1, gd, w, k1, k2, k3)
#define GETGY_empty_VY(a, b, w2, k1, k2) \
b = ymm_get_reg(dyn, ninst, x1, vex.v, w2, gd, k1, k2); \
a = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, k1, k2)
// Get empty GX, and non-writen VX and EX
#define GETGX_empty_VXEX(gx, vx, ex, D) \
GETVX(vx, 0); \
GETEX_Y(ex, 0, D); \
GETGX_empty(gx)
// Get empty GX, and non-writen EX
#define GETGX_empty_EX(gx, ex, D) \
GETEX_Y(ex, 0, D); \
GETGX_empty(gx)
// Get empty GX, and non-writen VX
#define GETGX_empty_VX(gx, vx) \
GETVX(vx, 0); \
GETGX_empty(gx)
// Get EX and and non-writen VX and GX
#define GETGXVXEX(gx, vx, ex, D) \
GETVX(vx, 0); \
GETEX_Y(ex, 1, D); \
GETGX(gx, 0)
// Get GX and and non-writen VX and EX
#define GETGX_VXEX(gx, vx, ex, D) \
GETVX(vx, 0); \
GETEX_Y(ex, 0, D); \
GETGX(gx, 1)
#define GETGXVXEX_empty(gx, vx, ex, D) \
GETVX(vx, 0); \
GETGX(gx, 0); \
GETEX_empty_Y(ex, D);
// Get empty GY, and non-writen VY and EY
#define GETGY_empty_VYEY(gy, vy, ey) \
vy = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1); \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
gy = ymm_get_reg_empty(dyn, ninst, x1, gd, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1)
// Get EY and non-writen VY and GY
#define GETGYVYEY(gy, vy, ey) \
vy = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1); \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1, gd, vex.v, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
gy = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1)
// Get GY and non-writen VY and EY
#define GETGY_VYEY(gy, vy, ey) \
vy = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1); \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, vex.v, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
gy = ymm_get_reg(dyn, ninst, x1, gd, 1, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1)
// Get empty EY and non-writen VY and GY
#define GETGYVYEY_empty(gy, vy, ey) \
vy = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1); \
gy = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1); \
if(MODREG) \
ey = ymm_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3), gd, vex.v, -1)
// Get EY and non-writen GY
#define GETGYEY(gy, ey) \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1, gd, -1, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
gy = ymm_get_reg(dyn, ninst, x1, gd, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1, -1)
// Get EY
#define GETEY(ey) \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, -1, -1, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
// Get written EY
#define GETEYw(ey) \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 1, -1, -1, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
// Get empty EY and non-writen GY
#define GETGYEY_empty(gy, ey) \
gy = ymm_get_reg(dyn, ninst, x1, gd, 0, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1, -1); \
if(MODREG) \
ey = ymm_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3), gd, -1, -1)
// Get empty GY, and non-writen EY
#define GETGY_empty_EY(gy, ey) \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, gd, -1, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
gy = ymm_get_reg_empty(dyn, ninst, x1, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1, -1)
// Get empty VY, and non-writen EY
#define GETVY_empty_EY(vy, ey) \
if(MODREG) \
ey = ymm_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), 0, vex.v, -1, -1); \
else \
VLDR128_U12(ey, ed, fixedaddress+16); \
vy = ymm_get_reg_empty(dyn, ninst, x1, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1, -1)
// Get EX as a quad, (x3 is used)
#define GETEX_Y(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x3, (nextop&7)+(rex.b<<3), w); \
} else { \
if(w) {WILLWRITE2();} else {SMREAD();} \
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, D); \
unscaled = 0; \
a = fpu_get_scratch(dyn, ninst); \
VLDR128_U12(a, ed, fixedaddress); \
}
// Get EX as a quad, (x3 is used)
#define GETEX_empty_Y(a, D) \
if(MODREG) { \
a = sse_get_reg_empty(dyn, ninst, x3, (nextop&7)+(rex.b<<3)); \
} else { \
WILLWRITE2(); \
a = fpu_get_scratch(dyn, ninst); \
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, NULL, 0xffe<<4, 15, rex, NULL, 0, D); \
unscaled = 0; \
}
// Get EX as a quad, (x1 is used)
#define GETEX(a, w, D) \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
if(w) {WILLWRITE2();} else {SMREAD();} \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<4, 15, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
a = fpu_get_scratch(dyn, ninst); \
VLD128(a, ed, fixedaddress); \
}
@@ -419,8 +641,8 @@
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
if(w) {WILLWRITE2();} else {SMREAD();} \
a = fpu_get_scratch(dyn, ninst); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
VLD64(a, ed, fixedaddress); \
}
@@ -433,8 +655,8 @@
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
if(w) {WILLWRITE2();} else {SMREAD();} \
a = fpu_get_scratch(dyn, ninst); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<2, 3, rex, NULL, 0, D); \
VLD32(a, ed, fixedaddress); \
}
@@ -447,8 +669,8 @@
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3), w); \
} else { \
SMREAD(); \
a = fpu_get_scratch(dyn); \
if(w) {WILLWRITE2();} else {SMREAD();} \
a = fpu_get_scratch(dyn, ninst); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, NULL, 0, D); \
VLD16(a, ed, fixedaddress); \
}
@@ -465,7 +687,7 @@
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, D); \
a = fpu_get_scratch(dyn); \
a = fpu_get_scratch(dyn, ninst); \
VLD64(a, ed, fixedaddress); \
}
@@ -476,6 +698,7 @@
SMWRITE2(); \
}
#define YMM0(a) ymm_mark_zero(dyn, ninst, a);
// Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
// F_DF is 1<<10, so 1 ROR 11*2 (so F_OF)
@@ -484,7 +707,7 @@
TSTw_mask(xFlags, 0b010110, 0); \
CNEGx(r, r, cNE)
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&((1<<(2+rex.w)-1)))) || box64_dynarec_aligned_atomics)
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress&(((1<<(2+rex.w))-1)))) || box64_dynarec_aligned_atomics)
#define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress&1)) || box64_dynarec_aligned_atomics)
// CALL will use x7 for the call address. Return value can be put in ret (unless ret is -1)
@@ -650,6 +873,7 @@
CBNZx(reg, j64)
#define IFX(A) if((dyn->insts[ninst].x64.gen_flags&(A)))
#define IFX2(A, B) if((dyn->insts[ninst].x64.gen_flags&(A)) B)
#define IFX_PENDOR0 if((dyn->insts[ninst].x64.gen_flags&(X_PEND) || !dyn->insts[ninst].x64.gen_flags))
#define IFXX(A) if((dyn->insts[ninst].x64.gen_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x64.gen_flags==(A) || dyn->insts[ninst].x64.gen_flags==(B) || dyn->insts[ninst].x64.gen_flags==((A)|(B))))
@@ -660,12 +884,12 @@
LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw)); /*offset is 8bits right?*/\
MOV32w(s1, 0b0100011100000000); \
BICw_REG(s3, s3, s1); \
/* greater than leave 0 */ \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
MOV32w(s2, 0b01000000); /* zero */ \
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
ORRw_REG_LSL(s3, s3, s1, 8); \
STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
@@ -765,28 +989,37 @@
LDP_REGS(R12, R13); \
LDP_REGS(R14, R15)
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
if (dyn->n.stack == +8) { \
*ok = 0; \
break; \
} \
var = x87_do_push(dyn, ninst, scratch, t);
#if STEP == 0
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) var = x87_do_push(dyn, ninst, scratch, t)
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) x87_do_push_empty(dyn, ninst, scratch)
#define X87_POP_OR_FAIL(dyn, ninst, scratch) x87_do_pop(dyn, ninst, scratch)
#else
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
var = x87_do_push(dyn, ninst, scratch, t)
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
if (dyn->n.stack == +8) { \
*ok = 0; \
break; \
} \
x87_do_push_empty(dyn, ninst, scratch);
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
x87_do_push_empty(dyn, ninst, scratch)
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
if (dyn->n.stack == -8) { \
*ok = 0; \
break; \
} \
x87_do_pop(dyn, ninst, scratch);
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==-8) || (dyn->n.poped==8)) { \
if(box64_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Pop, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.poped, ninst); \
dyn->abort = 1; \
return addr; \
} \
x87_do_pop(dyn, ninst, scratch)
#endif
#define SET_DFNONE(S) if(!dyn->f.dfnone) {STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}
#define SET_DFNONE(S) do {dyn->f.dfnone_here=1; if(!dyn->f.dfnone) {STRw_U12(wZR, xEmu, offsetof(x64emu_t, df)); dyn->f.dfnone=1;}} while(0);
#define SET_DF(S, N) \
if((N)!=d_none) { \
MOVZw(S, (N)); \
@@ -799,10 +1032,10 @@
dyn->f.dfnone=0; \
} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
#define SET_DFOK() dyn->f.dfnone = 1; dyn->f.dfnone_here=1
#ifndef MAYSETFLAGS
#define MAYSETFLAGS()
#define MAYSETFLAGS() do {} while (0)
#endif
#ifndef READFLAGS
@@ -830,6 +1063,8 @@
if(dyn->insts[ninst].x64.gen_flags) switch(B) { \
case SF_SUBSET: \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_SET_DF: dyn->f.pending = SF_SET; dyn->f.dfnone = 1; break; \
case SF_SET_NODF: dyn->f.pending = SF_SET; dyn->f.dfnone = 0; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SUBSET_PENDING: \
case SF_SET_PENDING: \
@@ -868,13 +1103,14 @@
#define FTABLE64(A, V)
#endif
#define ARCH_INIT() \
dyn->doublepush = 0; \
#define ARCH_INIT() \
dyn->smread = dyn->smwrite = 0; \
dyn->doublepush = 0; \
dyn->doublepop = 0;
#if STEP < 2
#define GETIP(A)
#define GETIP_(A)
#define GETIP(A) TABLE64(0, 0)
#define GETIP_(A) TABLE64(0, 0)
#else
// put value in the Table64 even if not using it for now to avoid difference between Step2 and Step3. Needs to be optimized later...
#define GETIP(A) \
@@ -932,6 +1168,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_66 STEPNAME(dynarec64_66)
#define dynarec64_67 STEPNAME(dynarec64_67)
#define dynarec64_67_32 STEPNAME(dynarec64_67_32)
#define dynarec64_67_AVX STEPNAME(dynarec64_67_AVX)
#define dynarec64_6764_32 STEPNAME(dynarec64_6764_32)
#define dynarec64_D8 STEPNAME(dynarec64_D8)
#define dynarec64_D9 STEPNAME(dynarec64_D9)
@@ -949,6 +1186,16 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_66F0 STEPNAME(dynarec64_66F0)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
#define dynarec64_AVX STEPNAME(dynarec64_AVX)
#define dynarec64_AVX_0F STEPNAME(dynarec64_AVX_0F)
#define dynarec64_AVX_0F38 STEPNAME(dynarec64_AVX_0F38)
#define dynarec64_AVX_66_0F STEPNAME(dynarec64_AVX_66_0F)
#define dynarec64_AVX_F2_0F STEPNAME(dynarec64_AVX_F2_0F)
#define dynarec64_AVX_F3_0F STEPNAME(dynarec64_AVX_F3_0F)
#define dynarec64_AVX_66_0F38 STEPNAME(dynarec64_AVX_66_0F38)
#define dynarec64_AVX_66_0F3A STEPNAME(dynarec64_AVX_66_0F3A)
#define dynarec64_AVX_F2_0F38 STEPNAME(dynarec64_AVX_F2_0F38)
#define dynarec64_AVX_F2_0F3A STEPNAME(dynarec64_AVX_F2_0F3A)
#define geted STEPNAME(geted)
#define geted32 STEPNAME(geted32)
@@ -1044,6 +1291,12 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define emit_ror8c STEPNAME(emit_ror8c)
#define emit_rol16c STEPNAME(emit_rol16c)
#define emit_ror16c STEPNAME(emit_ror16c)
#define emit_rcl8c STEPNAME(emit_rcl8c)
#define emit_rcr8c STEPNAME(emit_rcr8c)
#define emit_rcl16c STEPNAME(emit_rcl16c)
#define emit_rcr16c STEPNAME(emit_rcr16c)
#define emit_rcl32c STEPNAME(emit_rcl32c)
#define emit_rcr32c STEPNAME(emit_rcr32c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
#define emit_shld32c STEPNAME(emit_shld32c)
@@ -1063,7 +1316,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
#define x87_get_st STEPNAME(x87_get_st)
#define x87_get_st_empty STEPNAME(x87_get_st)
#define x87_refresh STEPNAME(x87_refresh)
#define x87_free STEPNAME(x87_free)
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
@@ -1076,13 +1329,16 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_purge07cache STEPNAME(sse_purge07cache)
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_purge07cache STEPNAME(sse_purge07cache)
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
#define ymm_get_reg STEPNAME(ymm_get_reg)
#define ymm_get_reg_empty STEPNAME(ymm_get_reg_empty)
#define ymm_mark_zero STEPNAME(ymm_mark_zero)
#define fpu_get_reg_ymm STEPNAME(fpu_get_reg_ymm)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
#define fpu_purgecache STEPNAME(fpu_purgecache)
@@ -1090,9 +1346,13 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define x87_purgecache STEPNAME(x87_purgecache)
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
#define avx_purge_ymm STEPNAME(avx_purge_ymm)
#define CacheTransform STEPNAME(CacheTransform)
#define arm64_move32 STEPNAME(arm64_move32)
#define arm64_move64 STEPNAME(arm64_move64)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta);
@@ -1105,7 +1365,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
// generic x64 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits);
@@ -1195,6 +1455,12 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcr16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4);
void emit_rcl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_rcr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s5, int s3, int s4);
@@ -1204,7 +1470,7 @@ void emit_shrd16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3,
void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int s3, int s4);
void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4);
// x87 helper
// cache of the local stack counter, to avoid update at every call, return old internal stack counter
@@ -1227,8 +1493,8 @@ int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// get vfpu register for a x87 reg, create the entry if needed. Do not fetch the Stx if not already in cache
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// refresh a value from the cache ->emu (nothing done if value is not cached)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// Free st, using the FFREE opcode (so it's freed but stack is not moved)
void x87_free(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int st);
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh the cache value from emu
@@ -1241,9 +1507,14 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// purge ymm_zero mask according to purge_ymm
void avx_purge_ymm(dynarec_arm_t* dyn, int ninst, uint16_t mask, int s1);
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val);
void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val);
#if STEP < 2
#define CHECK_CACHE() 0
#else
@@ -1252,6 +1523,7 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2,
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
// scratch fpu regs for convertions
#if STEP == 0
#define ST_IS_F(A) 0
@@ -1288,15 +1560,13 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// forget neon register for a SSE reg, create the entry if needed
// forget neon register for a SSE reg, YMM high part too
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a);
// purge the XMM0..XMM7 cache (before function call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
// Push current value to the cache
// Push current value to the cache (ymm too)
void sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn);
// reset the cache with n
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n);
// propagate stack state
@@ -1311,6 +1581,15 @@ void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
// avx helpers
// get neon register for a SSE reg, create the entry if needed
int ymm_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite, int k1, int k2, int k3);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int ymm_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a, int k1, int k2, int k3);
// mark an ymm upper part has zero (forgetting upper part if needed)
void ymm_mark_zero(dynarec_arm_t* dyn, int ninst, int a);
// Get an YMM upper quad reg, while keeping up to 3 other YMM reg (-1 to no keep)
int fpu_get_reg_ymm(dynarec_arm_t* dyn, int ninst, int t, int ymm, int k1, int k2, int k3);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
@@ -1319,6 +1598,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_6764_32(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
@@ -1336,6 +1616,16 @@ uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
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);
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);
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);
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);
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);
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);
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);
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);
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);
#if STEP < 2
#define PASS2(A)
@@ -1493,5 +1783,6 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} \
}
#define PURGE_YMM() avx_purge_ymm(dyn, ninst, dyn->insts[ninst+1].purge_ymm, x1)
#endif //__DYNAREC_ARM64_HELPER_H__
+6 -11
View File
@@ -5,28 +5,23 @@
dyn->insts[ninst].x64.addr = addr; \
if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr
#define MESSAGE(A, ...)
#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;\
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = B; \
dyn->insts[ninst].x64.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#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->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
#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; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_native_t*)dynaRealloc(dyn->insts, sizeof(instruction_native_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_native_t)*dyn->cap); \
dyn->cap *= 2; \
} \
dyn->insts[ninst].x64.addr = ip; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0; \
@@ -43,7 +38,7 @@
*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?"32bits ":"",\
(void*)ip, rex.is32bits?"x86 ":"x64 ",\
PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
+2 -2
View File
@@ -1,7 +1,7 @@
#define INIT
#define FINI
#define MESSAGE(A, ...)
#define EMIT(A)
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do {} while (0)
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
+3 -2
View File
@@ -5,14 +5,15 @@
dyn->insts_size += 1+((dyn->insts[ninst].x64.size>(dyn->insts[ninst].size/4))?dyn->insts[ninst].x64.size:(dyn->insts[ninst].size/4))/15; \
}
#define MESSAGE(A, ...)
#define MESSAGE(A, ...) do {} while (0)
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->native_size+=4;}while(0)
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst-1].x64.size>(dyn->insts[ninst-1].size/4))?dyn->insts[ninst-1].x64.size:(dyn->insts[ninst-1].size/4))/15; \
dyn->insts[ninst].ymm0_pass2 = dyn->ymm_zero; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->native_size;
#define INST_NAME(name)
#define TABLE64(A, V) {Table64(dyn, (V), 2); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0);}
+4 -2
View File
@@ -14,8 +14,10 @@
#define MESSAGE(A, ...) if(box64_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x64.size, dyn->insts[ninst-1].size/4);
if(ninst) { \
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; \
}
#define INST_EPILOG
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name, rex)
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V), 3); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
+29 -9
View File
@@ -16,7 +16,9 @@ typedef struct instsize_s instsize_t;
#define NEON_CACHE_MM 4
#define NEON_CACHE_XMMW 5
#define NEON_CACHE_XMMR 6
#define NEON_CACHE_SCR 7
#define NEON_CACHE_YMMW 7
#define NEON_CACHE_YMMR 8
#define NEON_CACHE_SCR 9
typedef union neon_cache_s {
int8_t v;
struct {
@@ -33,7 +35,7 @@ typedef union sse_cache_s {
} sse_cache_t;
typedef struct neoncache_s {
// Neon cache
neon_cache_t neoncache[24];
neon_cache_t neoncache[32];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
@@ -42,23 +44,30 @@ typedef struct neoncache_s {
uint8_t combined2;
uint8_t swapped; // the combined reg were swapped
uint8_t barrier; // is there a barrier at instruction epilog?
uint8_t pushed; // positive pushed value (to check for overflow)
uint8_t poped; // positive poped value (to check for underflow)
uint32_t news; // bitmask, wich neoncache are new for this opcode
// fpu cache
int8_t x87cache[8]; // cache status for the 8 x87 register behind the fpu stack
int8_t x87reg[8]; // reg used for x87cache entry
int16_t tags; // similar to fpu_tags
int8_t mmxcache[8]; // cache status for the 8 MMX registers
sse_cache_t ssecache[16]; // cache status for the 16 SSE(2) registers
int8_t fpuused[24]; // all 0..24 double reg from fpu, used by x87, sse and mmx
int8_t fpuused[32]; // all neon regs, used by x87, mmx, sse and avx
int8_t x87stack; // cache stack counter
int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
int8_t fpu_scratch; // scratch counter
int8_t fpu_extra_qscratch; // some opcode need an extra quad scratch register
int8_t fpu_reg; // x87/sse/mmx reg counter
uint16_t ymm_used; // mask of the ymm regs used in this opcode
uint64_t ymm_regs; // 4bits (0-15) position of 16 ymmXX regs removed
uint16_t ymm_write; // 1bits of ymmXX removed write
uint16_t ymm_removed; // 1bits if ymmXX was removed
} neoncache_t;
typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
int dfnone; // if deferred flags is already set to df_none
uint8_t dfnone; // if deferred flags is already set to df_none
uint8_t dfnone_here;// defered flags is cleared in this opcode
} flagcache_t;
typedef struct instruction_arm64_s {
@@ -75,8 +84,16 @@ typedef struct instruction_arm64_s {
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
int barrier_maybe;
uint16_t retn;
uint16_t purge_ymm; // need to purge some ymm
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_pass2, ymm0_pass3;
uint8_t barrier_maybe;
uint8_t will_write;
uint8_t last_write;
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
@@ -109,21 +126,24 @@ typedef struct dynarec_arm_s {
dynablock_t* dynablock;
instsize_t* instsize;
size_t insts_size; // size of the instruction size array (calculated)
uint8_t smread; // for strongmem model emulation
uint8_t smwrite; // for strongmem model emulation
uintptr_t forward; // address of the last end of code while testing forward
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
int32_t forward_size; // size at the forward point
int forward_ninst; // ninst at the forward point
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
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int get_first_jump_addr(dynarec_arm_t *dyn, uintptr_t next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
+47 -55
View File
@@ -25,14 +25,15 @@
#include "custommem.h"
#include "khash.h"
#include "rbtree.h"
uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
uint8_t* p = (uint8_t*)addr;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
}
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
@@ -47,6 +48,18 @@ dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
uintptr_t db_size = db->x64_size;
if(db_size && my_context) {
uint32_t n = rb_get(my_context->db_sizes, db_size);
if(n>1)
rb_set(my_context->db_sizes, db_size, db_size+1, n-1);
else
rb_unset(my_context->db_sizes, db_size, db_size+1);
if(db_size == my_context->max_db_size) {
my_context->max_db_size = rb_get_righter(my_context->db_sizes);
dynarec_log(LOG_INFO, "BOX64 Dynarec: lower max_db=%d\n", my_context->max_db_size);
}
}
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
@@ -81,6 +94,18 @@ void FreeDynablock(dynablock_t* db, int need_lock)
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
uintptr_t db_size = db->x64_size;
if(db_size && my_context) {
uint32_t n = rb_get(my_context->db_sizes, db_size);
if(n>1)
rb_set(my_context->db_sizes, db_size, db_size+1, n-1);
else
rb_unset(my_context->db_sizes, db_size, db_size+1);
if(db_size == my_context->max_db_size) {
my_context->max_db_size = rb_get_righter(my_context->db_sizes);
dynarec_log(LOG_INFO, "BOX64 Dynarec: lower max_db=%d\n", my_context->max_db_size);
}
}
if(db->previous)
FreeInvalidDynablock(db->previous, 0);
FreeDynarecMap((uintptr_t)db->actual_block);
@@ -120,15 +145,6 @@ static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2
return 1;
}
static int MarkedDynablock(dynablock_t* db)
{
if(db) {
if(getNeedTest((uintptr_t)db->x64_addr))
return 1; // already done
}
return 0;
}
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
// Mark will try to find *any* blocks that intersect the range to mark
@@ -155,15 +171,6 @@ int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
dynablock_t *AddNewDynablock(uintptr_t addr)
{
dynablock_t* block;
#if 0
// check if memory as the correct flags
int prot = getProtection(addr);
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
return NULL;
}
#endif
// create and add new block
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
@@ -228,17 +235,20 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
}
// check size
if(block) {
int blocksz = block->x64_size;
if(blocksz>my_context->max_db_size)
my_context->max_db_size = blocksz;
// fill-in jumptable
if(!addJumpTableIfDefault64(block->x64_addr, block->dirty?block->jmpnext:block->block)) {
FreeDynablock(block, 0);
block = getDB(addr);
MarkDynablock(block); // just in case...
} else {
if(block->x64_size)
if(block->x64_size) {
if(block->x64_size>my_context->max_db_size) {
my_context->max_db_size = block->x64_size;
dynarec_log(LOG_INFO, "BOX64 Dynarec: higher max_db=%d\n", my_context->max_db_size);
}
block->done = 1; // don't validate the block if the size is null, but keep the block
rb_set(my_context->db_sizes, block->x64_size, block->x64_size+1, rb_get(my_context->db_sizes, block->x64_size)+1);
}
}
}
if(need_lock)
@@ -251,33 +261,17 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
{
if(isInHotPage(addr))
return NULL;
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1, is32bits);
if(db && db->done && db->block && getNeedTest(addr)) {
if(db->always_test)
sched_yield(); // just calm down...
if(AreaInHotPage((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr + db->x64_size - 1)) {
emu->test.test = 0;
if(box64_dynarec_fastpage) {
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
if(hash==db->hash) { // seems ok, run it without reprotecting it
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
return db;
}
db->done = 0; // invalidating the block, it's already not good
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 1);
return NULL; // not building a new one, it's still a hotpage
} else {
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, (void*)addr);
return NULL;
}
}
uint32_t hash = X31_hash_code(db->x64_addr, db->x64_size);
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, (void*)addr);
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X, always_test:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, hash, db->hash, db->always_test,(void*)addr);
// Free db, it's now invalid!
dynablock_t* old = InvalidDynablock(db, need_lock);
// start again... (will create a new block)
@@ -289,12 +283,11 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, int is32bits)
} else
FreeInvalidDynablock(old, need_lock);
} else {
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, (void*)addr);
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
}
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X, always_test:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size-1, db->hash, db->always_test, (void*)addr);
if(db->always_test)
protectDB((uintptr_t)db->x64_addr, db->x64_size);
else
protectDBJumpTable((uintptr_t)db->x64_addr, db->x64_size, db->block, db->jmpnext);
}
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
@@ -328,11 +321,10 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr,
} else
FreeInvalidDynablock(old, need_lock);
} else {
protectDB((uintptr_t)db->x64_addr, db->x64_size);
// fill back jumptable
if(isprotectedDB((uintptr_t)db->x64_addr, db->x64_size) && !db->always_test) {
setJumpTableIfRef64(db->x64_addr, db->block, db->jmpnext);
}
if(db->always_test)
protectDB((uintptr_t)db->x64_addr, db->x64_size);
else
protectDBJumpTable((uintptr_t)db->x64_addr, db->x64_size, db->block, db->jmpnext);
}
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
+31 -5
View File
@@ -19,6 +19,7 @@
#include "dynablock_private.h"
#include "bridge.h"
#include "dynarec_next.h"
#include "custommem.h"
#endif
#ifdef HAVE_TRACE
#include "elfloader.h"
@@ -34,6 +35,9 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
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)");
} 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)");
}
#endif
void * jblock;
@@ -52,9 +56,13 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
if(!block) {
#ifdef HAVE_TRACE
if(LOG_INFO<=box64_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
if(checkInHotPage(addr)) {
dynarec_log(LOG_INFO, "Not trying to run a block from a Hotpage at %p\n", (void*)addr);
} else {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s), RIP=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)", (void*)*x3);
}
}
#endif
//tableupdate(native_epilog, addr, table);
@@ -62,6 +70,12 @@ 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) {
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)");
}
#endif
return native_epilog;
}
if(!(jblock=block->block)) {
@@ -129,16 +143,22 @@ void DynaRun(x64emu_t* emu)
JUMPBUFF jmpbuf[1] = {0};
int skip = 0;
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
#ifdef RV64
uintptr_t old_savesp = emu->xSPSave;
#endif
emu->flags.jmpbuf_ready = 0;
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
#ifdef RV64
emu->old_savedsp = emu->xSPSave;
#endif
emu->flags.jmpbuf_ready = 1;
#ifdef ANDROID
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
#else
if((skip=sigsetjmp(emu->jmpbuf, 1)))
if((skip=sigsetjmp(emu->jmpbuf, 1)))
#endif
{
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", emu->segs[_FS]);
@@ -174,6 +194,9 @@ void DynaRun(x64emu_t* emu)
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x64 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_RIP, block->block, block->isize, block->hash, emu);
// block is here, let's run it!
native_prolog(emu, block->block);
extern int running32bits;
if(emu->segs[_CS]==0x23)
running32bits = 1;
}
if(emu->fork) {
int forktype = emu->fork;
@@ -192,4 +215,7 @@ void DynaRun(x64emu_t* emu)
}
// clear the setjmp
emu->jmpbuf = old_jmpbuf;
#ifdef RV64
emu->xSPSave = old_savesp;
#endif
}
+16 -8
View File
@@ -15,18 +15,24 @@
#include "arm64/arm64_printer.h"
#include "arm64/dynarec_arm64_private.h"
#include "arm64/dynarec_arm64_functions.h"
#elif defined(LA464)
// Limit here is defined by LD litteral, that is 19bits
#define MAXBLOCK_SIZE ((1<<19)-200)
#elif defined(LA64)
#define instruction_native_t instruction_la464_t
#define dynarec_native_t dynarec_la464_t
#define instruction_native_t instruction_la64_t
#define dynarec_native_t dynarec_la64_t
#define ADDITIONNAL_DEFINITION()
#define ADDITIONNAL_DEFINITION() \
int fpuCacheNeedsTransform(dynarec_native_t* dyn, int ninst);
#define OTHER_CACHE()
#define OTHER_CACHE() \
if (fpuCacheNeedsTransform(dyn, ninst)) ret |= 2;
#include "la464/la464_printer.h"
#include "la464/dynarec_la464_private.h"
#include "la464/dynarec_la464_functions.h"
#include "la64/la64_printer.h"
#include "la64/dynarec_la64_private.h"
#include "la64/dynarec_la64_functions.h"
// Limit here is unconditionnal jump, that is signed 28bits
#define MAXBLOCK_SIZE ((1 << 27) - 200)
#elif defined(RV64)
#define instruction_native_t instruction_rv64_t
@@ -41,6 +47,8 @@
#include "rv64/rv64_printer.h"
#include "rv64/dynarec_rv64_private.h"
#include "rv64/dynarec_rv64_functions.h"
// Limit here is unconditionnal jump, that is signed 21bits
#define MAXBLOCK_SIZE ((1<<20)-200)
#else
#error Unsupported platform
#endif
+2 -2
View File
@@ -3,8 +3,8 @@
#ifdef ARM64
#include "arm64/dynarec_arm64_helper.h"
#elif defined(LA464)
#include "la464/dynarec_la464_helper.h"
#elif defined(LA64)
#include "la64/dynarec_la64_helper.h"
#elif defined(RV64)
#include "rv64/dynarec_rv64_helper.h"
#else
+201 -62
View File
@@ -72,8 +72,7 @@ void add_next(dynarec_native_t *dyn, uintptr_t addr) {
}
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 64;
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
printf_log(LOG_NONE, "Warning, overallocating next\n");
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -97,15 +96,19 @@ uintptr_t get_closest_next(dynarec_native_t *dyn, uintptr_t addr) {
void add_jump(dynarec_native_t *dyn, int ninst) {
// add slots
if(dyn->jmp_sz == dyn->jmp_cap) {
dyn->jmp_cap += 64;
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
printf_log(LOG_NONE, "Warning, overallocating jmps\n");
}
dyn->jmps[dyn->jmp_sz++] = ninst;
}
int get_first_jump(dynarec_native_t *dyn, int next) {
if(next<0 || next>dyn->size)
return -2;
return get_first_jump_addr(dyn, dyn->insts[next].x64.addr);
}
int get_first_jump_addr(dynarec_native_t *dyn, uintptr_t next) {
for(int i=0; i<dyn->jmp_sz; ++i)
if(dyn->insts[dyn->jmps[i]].x64.jmp == next)
return i;
return dyn->jmps[i];
return -2;
}
@@ -289,15 +292,10 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
idx = i;
// not found, add it
if(idx==-1) {
if(dyn->table64size == dyn->table64cap) {
dyn->table64cap+=16;
if(pass<3) // do not resize on pass3, it's not the same type of memory anymore
dyn->table64 = (uint64_t*)dynaRealloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
}
idx = dyn->table64size++;
if(idx < dyn->table64cap)
dyn->table64[idx] = val;
else
else if(pass==3)
printf_log(LOG_NONE, "Warning, table64 bigger than expected %d vs %d\n", idx, dyn->table64cap);
}
// calculate offset
@@ -305,23 +303,35 @@ int Table64(dynarec_native_t *dyn, uint64_t val, int pass)
return delta;
}
static void fillPredecessors(dynarec_native_t* dyn)
static void recurse_mark_alive(dynarec_native_t* dyn, int i)
{
if(dyn->insts[i].x64.alive)
return;
dyn->insts[i].x64.alive = 1;
if(dyn->insts[i].x64.jmp && dyn->insts[i].x64.jmp_insts!=-1)
recurse_mark_alive(dyn, dyn->insts[i].x64.jmp_insts);
if(i<dyn->size-1 && dyn->insts[i].x64.has_next)
recurse_mark_alive(dyn, i+1);
}
static int sizePredecessors(dynarec_native_t* dyn)
{
int pred_sz = 1; // to be safe
// compute total size of predecessor to allocate the array
// mark alive...
recurse_mark_alive(dyn, 0);
// first compute the jumps
int jmpto;
for(int i=0; i<dyn->size; ++i) {
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
if(dyn->insts[i].x64.alive && dyn->insts[i].x64.jmp && ((jmpto=dyn->insts[i].x64.jmp_insts)!=-1)) {
pred_sz++;
dyn->insts[dyn->insts[i].x64.jmp_insts].pred_sz++;
dyn->insts[jmpto].pred_sz++;
}
}
// remove "has_next" from orphan branch
for(int i=0; i<dyn->size-1; ++i) {
if(!dyn->insts[i].x64.has_next) {
if(dyn->insts[i+1].x64.has_next && !dyn->insts[i+1].pred_sz)
dyn->insts[i+1].x64.has_next = 0;
}
if(dyn->insts[i].x64.has_next && !dyn->insts[i+1].x64.alive)
dyn->insts[i].x64.has_next = 0;
}
// second the "has_next"
for(int i=0; i<dyn->size-1; ++i) {
@@ -330,8 +340,10 @@ static void fillPredecessors(dynarec_native_t* dyn)
dyn->insts[i+1].pred_sz++;
}
}
int alloc_size = pred_sz;
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
return pred_sz;
}
static void fillPredecessors(dynarec_native_t* dyn)
{
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -340,7 +352,7 @@ static void fillPredecessors(dynarec_native_t* dyn)
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
// fill pred
for(int i=0; i<dyn->size; ++i) {
for(int i=0; i<dyn->size; ++i) if(dyn->insts[i].x64.alive) {
if((i!=dyn->size-1) && dyn->insts[i].x64.has_next)
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x64.jmp && (dyn->insts[i].x64.jmp_insts!=-1)) {
@@ -350,19 +362,15 @@ static void fillPredecessors(dynarec_native_t* dyn)
}
}
// updateNeed goes backward, from last instruction to top
// updateNeed for the current block. recursive function that goes backward
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)) {
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;
}
if((need&X_PEND) && (dyn->insts[ninst].x64.state_flags==SF_SET)) {
need &=~X_PEND;
need |= dyn->insts[ninst].x64.set_flags; // SF_SET will compute all flags, it's not SUBSET!
}
if((need&X_PEND) && dyn->insts[ninst].x64.state_flags==SF_SUBSET_PENDING) {
need |= X_ALL&~(dyn->insts[ninst].x64.set_flags);
}
@@ -397,26 +405,102 @@ static int updateNeed(dynarec_native_t* dyn, int ninst, uint8_t need) {
return ninst;
}
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);
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
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 (pred >= max_ninst_reached) {
//if(box64_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);
ymm0_union |= pred_out;
ymm0_inter &= pred_out;
}
//if(box64_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;
new_ymm0_out = (ymm0_inter | dyn->insts[ninst].ymm0_add) & ~dyn->insts[ninst].ymm0_sub;
if ((dyn->insts[ninst].purge_ymm != new_purge_ymm) || (dyn->insts[ninst].ymm0_in != new_ymm0_in) || (dyn->insts[ninst].ymm0_out != new_ymm0_out)) {
// Need to update self and next(s)
dyn->insts[ninst].purge_ymm = new_purge_ymm;
dyn->insts[ninst].ymm0_in = new_ymm0_in;
dyn->insts[ninst].ymm0_out = new_ymm0_out;
if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++max_ninst_reached;
} else {
// We need to stop here if the opcode has no "real" next or if we reached the ninst of the toplevel
ok = (max_ninst_reached - 1 != ninst) && dyn->insts[ninst].x64.has_next && !dyn->insts[ninst].x64.has_callret;
}
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);
// 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)
updateYmm0s(dyn, jmp, max_ninst_reached);
}
} else {
if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++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);
updateYmm0s(dyn, jmp, max_ninst_reached);
}
} else {
// We didn't update anything, we can leave
ok = 0;
}
}
} else if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
++max_ninst_reached;
} else {
// We didn't update anything, we can leave
ok = 0;
}
++ninst;
}
}
void* current_helper = NULL;
static int static_jmps[MAX_INSTS+2];
static uintptr_t static_next[MAX_INSTS+2];
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 CancelBlock64(int need_lock)
{
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
dynarec_native_t* helper = (dynarec_native_t*)current_helper;
current_helper = NULL;
if(helper) {
dynaFree(helper->next);
dynaFree(helper->jmps);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->table64 && (helper->table64!=(uint64_t*)helper->tablestart))
dynaFree(helper->table64);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = NULL;
}
}
current_helper = NULL;
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
@@ -458,15 +542,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
A .. A+8*n : Table64: n 64bits values
B .. B+7 : dynablock_t* : self (as part of JmpNext, that simulate another block)
B+8 .. B+15 : 2 Native code for jmpnext (or jmp epilog in case of empty block)
B+16 .. B+23 : jmpnext (or jmp_epilog) address
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)
*/
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Canceling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(block, addr);
@@ -483,10 +563,21 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 128;
helper.insts = (instruction_native_t*)dynaCalloc(helper.cap, sizeof(instruction_native_t));
helper.cap = MAX_INSTS;
helper.insts = static_insts;
helper.jmps = static_jmps;
helper.jmp_cap = MAX_INSTS;
helper.next = static_next;
helper.next_cap = MAX_INSTS;
helper.table64 = static_table64;
helper.table64cap = sizeof(static_table64)/sizeof(uint64_t);
// 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");
CancelBlock64(0);
return NULL;
}
// basic checks
if(!helper.size) {
dynarec_log(LOG_INFO, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
@@ -495,12 +586,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
AddHotPage(addr);
CancelBlock64(0);
return NULL;
}
// protect the block of it goes over the 1st page
if((addr&~box64_pagesize)!=(end&~box64_pagesize)) // need to protect some other pages too
if((addr&~(box64_pagesize-1))!=(end&~(box64_pagesize-1))) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
// compute hash signature
uint32_t hash = X31_hash_code((void*)addr, end-addr);
@@ -508,10 +598,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
for(int ii=0; ii<helper.jmp_sz; ++ii) {
int i = helper.jmps[ii];
uintptr_t j = helper.insts[i].x64.jmp;
helper.insts[i].x64.jmp_insts = -1;
if(j<start || j>=end || j==helper.insts[i].x64.addr) {
if(j==helper.insts[i].x64.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x64.jmp_insts = -1;
helper.insts[i].x64.need_after |= X_PEND;
} else {
// find jump address instruction
@@ -544,30 +634,64 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
if(helper.insts[i2].x64.addr==j)
k=i2;
}*/
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
helper.insts[i].x64.jmp_insts = k;
if(k!=-1) {
if(!helper.insts[i].barrier_maybe)
helper.insts[k].x64.barrier |= BARRIER_FULL;
helper.insts[i].x64.jmp_insts = k;
}
}
}
// no need for next and jmps anymore
dynaFree(helper.next);
// no need for next anymore
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
dynaFree(helper.jmps);
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// fill predecessors with the jump address
int alloc_size = sizePredecessors(&helper);
helper.predecessor = (int*)alloca(alloc_size*sizeof(int));
fillPredecessors(&helper);
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// remove fpu stuff on non-executed code
for(int i=1; i<helper.size-1; ++i)
if(!helper.insts[i].pred_sz) {
int ii = i;
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;
++ii;
}
i = ii;
}
// remove trailling dead code
while(helper.size && !helper.insts[helper.size-1].x64.alive) {
helper.isize-=helper.insts[helper.size-1].x64.size;
--helper.size;
}
if(!helper.size) {
// 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);
}
updateYmm0s(&helper, 0, 0);
// 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");
CancelBlock64(0);
return NULL;
}
// 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");
CancelBlock64(0);
return NULL;
}
// keep size of instructions for signal handling
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
@@ -593,7 +717,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
helper.instsize = (instsize_t*)instsize;
*(dynablock_t**)actual_p = block;
helper.table64cap = helper.table64size;
dynaFree(helper.table64);
helper.table64 = (uint64_t*)helper.tablestart;
// pass 3, emit (log emit native opcode)
if(box64_dynarec_dump) {
@@ -604,18 +727,23 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
int oldtable64size = helper.table64size;
size_t oldnativesize = helper.native_size;
size_t oldinstsize = helper.insts_size;
int oldsize= helper.size;
helper.native_size = 0;
helper.table64size = 0; // reset table64 (but not the cap)
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");
CancelBlock64(0);
return NULL;
}
// no need for jmps anymore
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
dynaFree(helper.insts);
helper.insts = NULL;
helper.table64 = NULL;
helper.instsize = NULL;
dynaFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
@@ -634,34 +762,45 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr, int alternate, int is32bit
// Check if something changed, to abort if it is
if((block->hash != hash)) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
AddHotPage(addr);
CancelBlock64(0);
return NULL;
}
if((oldnativesize!=helper.native_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.native_size+helper.table64size*8);
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);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
printf_log(LOG_NONE, "%p:", dump);
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\n", helper.insts[i].size2, helper.insts[i].size);
printf_log(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(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
CancelBlock64(0);
return NULL;
}
// ok, free the helper now
//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));
}
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);
AddHotPage(addr);
block->dirty = 1;
//protectDB(addr, end-addr);
}
if(getProtection(addr)&PROT_NEVERCLEAN) {
block->dirty = 1;
block->always_test = 1;
}
if(block->always_test) {
dynarec_log(LOG_DEBUG, "Note: block marked as always dirty %p:%ld\n", block->x64_addr, block->x64_size);
}
current_helper = NULL;
//block->done = 1;
return (void*)block;
+173 -37
View File
@@ -204,7 +204,18 @@ void native_fsave(x64emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
LD2D(p, &emu->x87[7-i].d);
p+=10;
}
}
void native_fsave16(x64emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 1);
uint8_t* p = ed;
p += 14;
for (int i=0; i<8; ++i) {
LD2D(p, &emu->x87[7-i].d);
p+=10;
}
}
@@ -215,7 +226,19 @@ void native_frstor(x64emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
D2LD(&emu->x87[7-i].d, p);
p+=10;
}
}
void native_frstor16(x64emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 1);
uint8_t* p = ed;
p += 14;
for (int i=0; i<8; ++i) {
D2LD(&emu->x87[7-i].d, p);
p+=10;
}
@@ -245,23 +268,23 @@ void native_fprem1(x64emu_t* emu)
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
b >>= 1;
}
return retval;
return retval;
}
void native_aesimc(x64emu_t* emu, int xmm)
@@ -275,6 +298,17 @@ void native_aesimc(x64emu_t* emu, int xmm)
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void native_aesimc_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1 = emu->ymm[ymm];
for(int j=0; j<4; ++j) {
emu->ymm[ymm].ub[0+j*4] = ff_mult(0x0E, eay1.ub[0+j*4]) ^ ff_mult(0x0B, eay1.ub[1+j*4]) ^ ff_mult(0x0D, eay1.ub[2+j*4]) ^ ff_mult(0x09, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[1+j*4] = ff_mult(0x09, eay1.ub[0+j*4]) ^ ff_mult(0x0E, eay1.ub[1+j*4]) ^ ff_mult(0x0B, eay1.ub[2+j*4]) ^ ff_mult(0x0D, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[2+j*4] = ff_mult(0x0D, eay1.ub[0+j*4]) ^ ff_mult(0x09, eay1.ub[1+j*4]) ^ ff_mult(0x0E, eay1.ub[2+j*4]) ^ ff_mult(0x0B, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[3+j*4] = ff_mult(0x0B, eay1.ub[0+j*4]) ^ ff_mult(0x0D, eay1.ub[1+j*4]) ^ ff_mult(0x09, eay1.ub[2+j*4]) ^ ff_mult(0x0E, eay1.ub[3+j*4]);
}
}
void native_aesmc(x64emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
@@ -286,29 +320,40 @@ void native_aesmc(x64emu_t* emu, int xmm)
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void native_aesmc_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1 = emu->ymm[ymm];
for(int j=0; j<4; ++j) {
emu->ymm[ymm].ub[0+j*4] = ff_mult(0x02, eay1.ub[0+j*4]) ^ ff_mult(0x03, eay1.ub[1+j*4]) ^ eay1.ub[2+j*4] ^ eay1.ub[3+j*4] ;
emu->ymm[ymm].ub[1+j*4] = eay1.ub[0+j*4] ^ ff_mult(0x02, eay1.ub[1+j*4]) ^ ff_mult(0x03, eay1.ub[2+j*4]) ^ eay1.ub[3+j*4] ;
emu->ymm[ymm].ub[2+j*4] = eay1.ub[0+j*4] ^ eay1.ub[1+j*4] ^ ff_mult(0x02, eay1.ub[2+j*4]) ^ ff_mult(0x03, eay1.ub[3+j*4]);
emu->ymm[ymm].ub[3+j*4] = ff_mult(0x03, eay1.ub[0+j*4]) ^ eay1.ub[1+j*4] ^ eay1.ub[2+j*4] ^ ff_mult(0x02, eay1.ub[3+j*4]);
}
}
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
static const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
static const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
void native_aesdlast(x64emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
@@ -317,6 +362,17 @@ void native_aesdlast(x64emu_t* emu, int xmm)
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
void native_aesdlast_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1;
for(int i=0; i<16; ++i)
eay1.ub[i] = emu->ymm[ymm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->ymm[ymm].ub[i] = invsubbytes[eay1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
@@ -348,16 +404,34 @@ void native_aeselast(x64emu_t* emu, int xmm)
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void native_aeselast_y(x64emu_t* emu, int ymm)
{
sse_regs_t eay1;
for(int i=0; i<16; ++i)
eay1.ub[i] = emu->ymm[ymm].ub[shiftrows[i]];
for(int i=0; i<16; ++i)
emu->ymm[ymm].ub[i] = subbytes[eay1.ub[i]];
}
void native_aesd(x64emu_t* emu, int xmm)
{
native_aesdlast(emu, xmm);
native_aesimc(emu, xmm);
}
void native_aesd_y(x64emu_t* emu, int ymm)
{
native_aesdlast_y(emu, ymm);
native_aesimc_y(emu, ymm);
}
void native_aese(x64emu_t* emu, int xmm)
{
native_aeselast(emu, xmm);
native_aesmc(emu, xmm);
}
void native_aese_y(x64emu_t* emu, int ymm)
{
native_aeselast_y(emu, ymm);
native_aesmc_y(emu, ymm);
}
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
@@ -393,6 +467,40 @@ void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8)
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_pclmul_x(x64emu_t* emu, int gx, int vx, void* p, uint32_t u8)
{
sse_regs_t *EX = ((uintptr_t)p<16)?((sse_regs_t*)p):&emu->xmm[(uintptr_t)p];
sse_regs_t *GX = &emu->xmm[gx];
sse_regs_t *VX = &emu->xmm[vx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(VX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8)
{
sse_regs_t *EY = ((uintptr_t)p<16)?((sse_regs_t*)p):&emu->ymm[(uintptr_t)p];
sse_regs_t *GY = &emu->ymm[gy];
sse_regs_t *VY = &emu->ymm[vy];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EY->q[e];
for (int i=0; i<64; ++i)
if(VY->q[g]&(1LL<<i))
result ^= (op2<<i);
GY->q[0] = result&0xffffffffffffffffLL;
GY->q[1] = (result>>64)&0xffffffffffffffffLL;
}
void native_clflush(x64emu_t* emu, void* p)
{
@@ -484,7 +592,7 @@ 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, int* retn)
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, uint16_t* retn)
{
(void)dyn;
@@ -510,3 +618,31 @@ int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress,
#undef PK32
#undef PK
}
// AVX
void avx_mark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero |= (1<<reg);
}
int is_avx_zero(dynarec_native_t* dyn, int ninst, int reg)
{
return (dyn->ymm_zero>>reg)&1;
}
int is_avx_zero_unset(dynarec_native_t* dyn, int ninst, int reg)
{
if((dyn->ymm_zero>>reg)&1) {
dyn->ymm_zero &= ~(1<<reg);
return 1;
}
return 0;
}
void avx_mark_zero_reset(dynarec_native_t* dyn, int ninst)
{
dyn->ymm_zero = 0;
}
void avx_unmark_zero(dynarec_native_t* dyn, int ninst, int reg)
{
dyn->ymm_zero &= ~(1<<reg);
}
+17 -1
View File
@@ -30,16 +30,25 @@ void native_fistp64(x64emu_t* emu, int64_t* ed);
void native_fistt64(x64emu_t* emu, int64_t* ed);
void native_fld(x64emu_t* emu, uint8_t* ed);
void native_fsave(x64emu_t* emu, uint8_t* ed);
void native_fsave16(x64emu_t* emu, uint8_t* ed);
void native_frstor(x64emu_t* emu, uint8_t* ed);
void native_frstor16(x64emu_t* emu, uint8_t* ed);
void native_fprem1(x64emu_t* emu);
void native_aesd(x64emu_t* emu, int xmm);
void native_aesd_y(x64emu_t* emu, int ymm);
void native_aese(x64emu_t* emu, int xmm);
void native_aese_y(x64emu_t* emu, int ymm);
void native_aesdlast(x64emu_t* emu, int xmm);
void native_aesdlast_y(x64emu_t* emu, int ymm);
void native_aeselast(x64emu_t* emu, int xmm);
void native_aeselast_y(x64emu_t* emu, int ymm);
void native_aesimc(x64emu_t* emu, int xmm);
void native_aesimc_y(x64emu_t* emu, int ymm);
void native_aeskeygenassist(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul(x64emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void native_pclmul_x(x64emu_t* emu, int gx, int vx, void* p, uint32_t u8);
void native_pclmul_y(x64emu_t* emu, int gy, int vy, void* p, uint32_t u8);
void native_clflush(x64emu_t* emu, void* p);
@@ -63,7 +72,14 @@ uintptr_t fakeed(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
int isNativeCall(dynarec_native_t* dyn, uintptr_t addr, uintptr_t* calladdress, uint16_t* retn);
// AVX utilities
void avx_mark_zero(dynarec_native_t* dyn, int ninst, int reg);
int is_avx_zero(dynarec_native_t* dyn, int ninst, int reg);
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);
ADDITIONNAL_DEFINITION()
+77 -28
View File
@@ -26,6 +26,12 @@
#error No STEP defined
#endif
#if STEP == 0
#ifndef PROT_READ
#define PROT_READ 0x1
#endif
#endif
uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int is32bits)
{
int ok = 1;
@@ -34,7 +40,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
uintptr_t ip = addr;
uintptr_t init_addr = addr;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int rep = 0; // 0 none, 1=F2 prefix, 2=F3 prefix
int need_epilog = 1;
// Clean up (because there are multiple passes)
dyn->f.pending = 0;
@@ -43,6 +49,10 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
dyn->ymm_zero = 0;
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_native_t));
#endif
fpu_reset(dyn);
ARCH_INIT();
int reset_n = -1;
@@ -50,7 +60,27 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
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
// ok, go now
INIT;
#if STEP == 0
uintptr_t cur_page = (addr)&~box64_pagesize;
#endif
while(ok) {
#if STEP == 0
if(cur_page != ((addr)&~box64_pagesize)) {
cur_page = (addr)&~box64_pagesize;
if(!(getProtection(addr)&PROT_READ)) {
need_epilog = 1;
break;
}
}
// This test is here to prevent things like TABLE64 to be out of range
// native_size is not exact at this point, but it should be larger, not smaller, and not by a huge margin anyway
// so it's good enough to avoid overflow in relative to PC data fectching
if((dyn->native_size >= MAXBLOCK_SIZE) || (ninst >= MAX_INSTS)) {
need_epilog = 1;
break;
}
#endif
fpu_propagate_stack(dyn, ninst);
ip = addr;
if (reset_n!=-1) {
dyn->last_ip = 0;
@@ -73,10 +103,14 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
}
reset_n = -1;
} else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
}
#if STEP > 0
else if(ninst && (dyn->insts[ninst].pred_sz>1 || (dyn->insts[ninst].pred_sz==1 && dyn->insts[ninst].pred[0]!=ninst-1)))
dyn->last_ip = 0; // reset IP if some jump are coming here
fpu_propagate_stack(dyn, ninst);
#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);
@@ -86,14 +120,13 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
GOTEST(x1, x2);
}
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
fpu_reset_scratch(dyn);
if((dyn->insts[ninst].x64.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND);
}
if(box64_dynarec_test) {
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
if(box64_dynarec_test && (!box64_dynarec_test_end || (ip>=box64_dynarec_test_start && ip<box64_dynarec_test_end) )) {
MESSAGE(LOG_DUMP, "TEST STEP ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
GO_TRACE(x64test_init, 1, x5);
GO_TRACE(x64test_step, 1, x5);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
@@ -132,23 +165,23 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
if(dyn->abort)
return ip;
INST_EPILOG;
fpu_reset_scratch(dyn);
int next = ninst+1;
#if STEP > 0
if(!dyn->insts[ninst].x64.has_next && dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts!=-1)
next = dyn->insts[ninst].x64.jmp_insts;
#endif
if(dyn->insts[ninst].x64.has_next && dyn->insts[next].x64.barrier) {
if(dyn->insts[next].x64.barrier&BARRIER_FLOAT)
if(dyn->insts[next].x64.barrier&BARRIER_FLOAT) {
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
}
if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
dyn->f.pending = 0;
dyn->f.dfnone = 0;
dyn->last_ip = 0;
}
}
#endif
#ifndef PROT_READ
#define PROT_READ 1
#endif
@@ -156,34 +189,45 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
if(ii<dyn->size && !dyn->insts[ii].pred_sz) {
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
if((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// reset fpu value...
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
while((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
// may need to skip opcodes to advance
++ninst;
NEW_INST;
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
INST_NAME("Skipped opcode");
addr += dyn->insts[ninst].x64.size;
INST_EPILOG;
addr += dyn->insts[ii].x64.size;
++ii;
}
}
if((dyn->insts[ii].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
if((dyn->insts[ninst+1].x64.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are available
reset_n = getNominalPred(dyn, ninst+1); // may get -1 if no predecessor are available
if(reset_n==-1) {
reset_n = -2;
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
if(!dyn->insts[ninst].x64.has_callret) {
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
}
}
}
}
#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");
ok = 0;
need_epilog = 1;
}
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog) {
if(dyn->forward_to == addr && !need_epilog && ok>=0) {
// we made it!
if(box64_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x64.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to);
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(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;
@@ -219,8 +263,8 @@ 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, dyn->insts[ninst].x64.has_callret?ninst:reset_n);
} else if(next && (next-addr)<box64_dynarec_forward && (getProtection(next)&PROT_READ)/*box64_dynarec_bigblock>=stopblock*/) {
if(box64_dynarec_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(dyn->forward) {
if(next<dyn->forward_to)
@@ -262,12 +306,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
}
#endif
}
if((ok>0) && dyn->insts[ninst].x64.has_callret)
reset_n = -2;
if((ok>0) && reset_n==-1 && dyn->insts[ninst+1].purge_ymm)
PURGE_YMM();
++ninst;
#if STEP == 0
if(ok && (((box64_dynarec_bigblock<stopblock) && !isJumpTableDefault64((void*)addr))
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 && (ninst==dyn->size))
if((ok>0) && (ninst==dyn->size))
#endif
{
#if STEP == 0
@@ -297,7 +346,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
++ninst;
NOTEST(x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
jump_to_next(dyn, addr, 0, ninst, rex.is32bits);
ok=0; need_epilog=0;
}
}
+7 -7
View File
@@ -8,13 +8,13 @@ void arm64_epilog(void) EXPORTDYN;
#define native_next arm64_next
#define native_prolog arm64_prolog
#define native_epilog arm64_epilog
#elif defined(LA464)
void la464_next(void) EXPORTDYN;
void la464_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void la464_epilog(void) EXPORTDYN;
#define native_next la464_next
#define native_prolog la464_prolog
#define native_epilog la464_epilog
#elif defined(LA64)
void la64_next(void) EXPORTDYN;
void la64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
void la64_epilog(void) EXPORTDYN;
#define native_next la64_next
#define native_prolog la64_prolog
#define native_epilog la64_epilog
#elif defined(RV64)
void rv64_next(void) EXPORTDYN;
void rv64_prolog(x64emu_t* emu, void* addr) EXPORTDYN;
+8 -3
View File
@@ -24,17 +24,22 @@
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
#define SF_DF 8
#define SF_SET_DF (SF_SET|SF_DF)
#define SF_NODF 16
#define SF_SET_NODF (SF_SET|SF_NODF)
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint8_t jmp_cond; // 1 of conditionnal jump
uint8_t has_next; // does this opcode can continue to the next?
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 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 has_callret; // this instruction have an optimised call setup
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+393
View File
@@ -0,0 +1,393 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)rep;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t u8;
uint8_t gd, ed, eb1, eb2, gb1, gb2;
uint8_t gback, wback, wb1, wb2, wb;
int64_t i64, j64;
uint64_t u64;
int v0, v1;
int q0;
int d0;
int64_t fixedaddress, gdoffset;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(j64);
MAYUSE(d0);
MAYUSE(q0);
MAYUSE(v0);
MAYUSE(v1);
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
switch (opcode) {
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5);
break;
case 0x33:
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x64:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog);
break;
case 0x80:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0: // ADD
INST_NAME("ADD Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 1: // OR
INST_NAME("OR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK();
break;
case 3: // SBB
INST_NAME("SBB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 4: // AND
INST_NAME("AND Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 5: // SUB
INST_NAME("SUB Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
EBBACK();
break;
case 6: // XOR
INST_NAME("XOR Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK();
break;
case 7: // CMP
INST_NAME("CMP Eb, Ib");
grab_segdata(dyn, addr, ninst, x1, seg);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
if (u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch ((nextop >> 3) & 7) {
case 0:
if (opcode == 0x81) {
INST_NAME("ADD Ed, Id");
} else {
INST_NAME("ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK);
IFXA (X_CF, !la64_lbt)
REGENERATE_MASK(); // use xMASK as a scratch
WBACKO(x6);
break;
case 1:
if (opcode == 0x81) {
INST_NAME("OR Ed, Id");
} else {
INST_NAME("OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 2:
if (opcode == 0x81) {
INST_NAME("ADC Ed, Id");
} else {
INST_NAME("ADC Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
IFXA (X_ALL, !la64_lbt)
ST_D(x6, xEmu, offsetof(x64emu_t, scratch));
emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, xMASK);
IFXA (X_ALL, !la64_lbt) {
LD_D(x6, xEmu, offsetof(x64emu_t, scratch));
REGENERATE_MASK(); // use xMASK as a scratch
}
WBACKO(x6);
break;
case 3:
if (opcode == 0x81) {
INST_NAME("SBB Ed, Id");
} else {
INST_NAME("SBB Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
MOV64xw(x5, i64);
emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, xMASK);
IFXA (X_CF, !la64_lbt)
REGENERATE_MASK(); // use xMASK as a scratch
WBACKO(x6);
break;
case 4:
if (opcode == 0x81) {
INST_NAME("AND Ed, Id");
} else {
INST_NAME("AND Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 5:
if (opcode == 0x81) {
INST_NAME("SUB Ed, Id");
} else {
INST_NAME("SUB Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, xMASK);
IFXA (X_CF, !la64_lbt)
REGENERATE_MASK(); // use xMASK as a scratch
WBACKO(x6);
break;
case 6:
if (opcode == 0x81) {
INST_NAME("XOR Ed, Id");
} else {
INST_NAME("XOR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
WBACKO(x6);
break;
case 7:
if (opcode == 0x81) {
INST_NAME("CMP Ed, Id");
} else {
INST_NAME("CMP Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64) {
MOV64xw(x2, i64);
emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
} else
emit_cmp32_0(dyn, ninst, rex, ed, x3, x4);
break;
}
break;
case 0x89:
INST_NAME("MOV Seg:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_LA64((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD_D(x4, ed, x4);
SDxw(gd, x4, fixedaddress);
SMWRITE2();
}
break;
case 0x8B:
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(gd, TO_LA64((nextop & 7) + (rex.b << 3)));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
ADD_D(x4, ed, x4);
LDxw(gd, x4, fixedaddress);
}
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
if (MODREG) { // reg <= u8
u8 = F8;
if (!rex.rex) {
ed = (nextop & 7);
eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx
eb2 = (ed & 4) >> 2; // L or H
} else {
eb1 = TO_LA64((nextop & 7) + (rex.b << 3));
eb2 = 0;
}
MOV32w(x3, u8);
BSTRINS_D(eb1, x3, eb2 * 8 + 7, eb2 * 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1);
u8 = F8;
if (u8) {
ADDI_D(x3, xZR, u8);
ed = x3;
} else
ed = xZR;
STX_B(x3, wback, x4);
SMWRITE2();
}
break;
case 0xC7:
INST_NAME("MOV Seg:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
if (MODREG) { // reg <= i32
i64 = F32S;
ed = TO_LA64((nextop & 7) + (rex.b << 3));
MOV64xw(ed, i64);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 4);
i64 = F32S;
if (i64) {
MOV64xw(x3, i64);
ed = x3;
} else
ed = xZR;
ADD_D(x4, wback, x4);
SDxw(ed, x4, fixedaddress);
SMWRITE2();
}
break;
default:
DEFAULT;
}
return addr;
}
+719
View File
@@ -0,0 +1,719 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int16_t i16;
uint16_t u16;
uint64_t u64;
int32_t i32;
int64_t j64;
uint8_t gd, ed;
uint8_t wback, wb1;
int64_t fixedaddress;
int unscaled;
int lock;
MAYUSE(u8);
MAYUSE(u16);
MAYUSE(u64);
MAYUSE(j64);
MAYUSE(lock);
while ((opcode == 0x2E) || (opcode == 0x36) || (opcode == 0x66)) // ignoring CS:, SS: or multiple 0x66
opcode = F8;
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
if (rex.w && !(opcode == 0x0f || opcode == 0xf0 || opcode == 0x64 || opcode == 0x65)) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode
switch (opcode) {
case 0x01:
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_add16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
GWBACK;
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_add16(dyn, ninst, x1, x2, x3, x4, x6);
BSTRINS_D(xRAX, x1, 15, 0);
break;
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_or16(dyn, ninst, x1, x2, x4, x2);
EWBACK;
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_or16(dyn, ninst, x1, x2, x4, x5);
GWBACK;
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_or16(dyn, ninst, x1, x2, x3, x4);
BSTRINS_D(xRAX, x1, 15, 0);
break;
case 0x0F:
switch (rep) {
case 0: addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break;
default:
DEFAULT;
}
break;
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_sbb16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_and16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_and16(dyn, ninst, x1, x2, x3, x4);
GWBACK;
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_and16(dyn, ninst, x1, x2, x3, x4);
BSTRINS_D(xRAX, x1, 15, 0);
break;
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sub16(dyn, ninst, x2, x1, x4, x5, x6);
EWBACK;
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
GWBACK;
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
MOV32w(x2, i32);
emit_sub16(dyn, ninst, x1, x2, x3, x4, x5);
BSTRINS_D(xRAX, x1, 15, 0);
break;
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_xor16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
BSTRPICK_D(x1, xRAX, 15, 0);
if (i32) {
MOV32w(x2, i32);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else {
emit_cmp16_0(dyn, ninst, x1, x3, x4);
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog);
break;
case 0x65:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x69:
case 0x6B:
if (opcode == 0x69) {
INST_NAME("IMUL Gw,Ew,Iw");
} else {
INST_NAME("IMUL Gw,Ew,Ib");
}
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
GETSEW(x1, (opcode == 0x69) ? 2 : 1);
if (opcode == 0x69)
i32 = F16S;
else
i32 = F8S;
MOV32w(x2, i32);
MUL_W(x2, x2, x1);
UFLAG_RES(x2);
gd = x2;
GWBACK;
UFLAG_DF(x1, d_imul16);
break;
case 0x81:
case 0x83:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0: // ADD
if (opcode == 0x81) {
INST_NAME("ADD Ew, Iw");
} else {
INST_NAME("ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV64x(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4, x6);
EWBACK;
break;
case 1: // OR
if (opcode == 0x81) {
INST_NAME("OR Ew, Iw");
} else {
INST_NAME("OR Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV64x(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 4: // AND
if (opcode == 0x81) {
INST_NAME("AND Ew, Iw");
} else {
INST_NAME("AND Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV64x(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
EWBACK;
break;
case 5: // SUB
if (opcode == 0x81) {
INST_NAME("SUB Ew, Iw");
} else {
INST_NAME("SUB Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV32w(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 6: // XOR
if (opcode == 0x81) {
INST_NAME("XOR Ew, Iw");
} else {
INST_NAME("XOR Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
MOV32w(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4, x6);
EWBACK;
break;
case 7: // CMP
if (opcode == 0x81) {
INST_NAME("CMP Ew, Iw");
} else {
INST_NAME("CMP Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode == 0x81) ? 2 : 1);
if (opcode == 0x81)
i16 = F16S;
else
i16 = F8S;
if (i16) {
MOV64x(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x4);
break;
default:
DEFAULT;
}
break;
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0x89:
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINS_D(ed, gd, 15, 0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
ST_H(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x8B:
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
if (ed != gd) {
BSTRINS_D(gd, ed, 15, 0);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SMREADLOCK(lock);
LD_HU(x1, ed, fixedaddress);
BSTRINS_D(gd, x1, 15, 0);
}
break;
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
gd = TO_LA64((opcode & 0x07) + (rex.b << 3));
if (gd == xRAX) {
INST_NAME("NOP");
} else {
INST_NAME("XCHG AX, Reg");
MV(x2, xRAX);
BSTRINS_D(xRAX, gd, 15, 0);
BSTRINS_D(gd, x2, 15, 0);
}
break;
case 0xA4:
if (rep) {
INST_NAME("REP MOVSB");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 1);
ADDI_D(xRDI, xRDI, 1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, -1);
ADDI_D(xRDI, xRDI, -1);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSB");
GETDIR(x3, x1, 1);
LD_BU(x1, xRSI, 0);
ST_B(x1, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xA5:
if (rep) {
INST_NAME("REP MOVSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, 2);
ADDI_D(xRDI, xRDI, 2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADDI_D(xRSI, xRSI, -2);
ADDI_D(xRDI, xRDI, -2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("MOVSW");
GETDIR(x3, x1, 2);
LD_H(x1, xRSI, 0);
ST_H(x1, xRDI, 0);
ADD_D(xRSI, xRSI, x3);
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
BSTRPICK_D(x1, xRAX, 15, 0);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xAB:
if (rep) {
INST_NAME("REP STOSW");
CBZ_NEXT(xRCX);
ANDI(x1, xFlags, 1 << F_DF);
BNEZ_MARK2(x1);
MARK; // Part with DF==0
ST_H(xRAX, xRDI, 0);
ADDI_D(xRDI, xRDI, 2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
ST_H(xRAX, xRDI, 0);
ADDI_D(xRDI, xRDI, -2);
ADDI_D(xRCX, xRCX, -1);
BNEZ_MARK2(xRCX);
// done
} else {
INST_NAME("STOSW");
GETDIR(x3, x1, 2);
ST_H(xRAX, xRDI, 0);
ADD_D(xRDI, xRDI, x3);
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
INST_NAME("MOV Reg16, Iw");
u16 = F16;
MOV32w(x1, u16);
gd = TO_LA64((opcode & 7) + (rex.b << 3));
BSTRINS_D(gd, x1, 15, 0);
break;
case 0xC1:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(rol16, x1, x3);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF | X_CF, SF_SET_DF);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, u8);
CALL_(ror16, x1, x3);
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); }
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
UFLAG_IF { MOV32w(x2, (u8 & 15)); }
UFLAG_OP12(ed, x2)
if (MODREG) {
SLLI_D(ed, ed, 48 + (u8 & 15));
SRLI_D(ed, ed, 48);
} else {
SLLI_D(ed, ed, u8 & 15);
}
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
INST_NAME("SHR Ew, Ib");
UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); }
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
UFLAG_IF { MOV32w(x2, (u8 & 15)); }
UFLAG_OP12(ed, x2)
SRLI_D(ed, ed, u8 & 15);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
INST_NAME("SAR Ew, Ib");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF { MESSAGE(LOG_DUMP, "Need Optimization for flags\n"); }
GETSEW(x1, 1);
u8 = F8;
UFLAG_IF { MOV32w(x2, (u8 & 15)); }
UFLAG_OP12(ed, x2)
SRAI_D(ed, ed, u8 & 15);
if (MODREG) BSTRPICK_D(ed, ed, 15, 0);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
default:
DEFAULT;
}
break;
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
u16 = F16;
MOV32w(x1, u16);
BSTRINS_D(ed, x1, 15, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 2);
u16 = F16;
MOV32w(x1, u16);
ST_H(x1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 5:
if (opcode == 0xD1) {
INST_NAME("SHR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SHR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1) MAYSETFLAGS();
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
case 4:
case 6:
if (opcode == 0xD1) {
INST_NAME("SHL Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SHL Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1)
MAYSETFLAGS();
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
case 7:
if (opcode == 0xD1) {
INST_NAME("SAR Ew, 1");
MOV32w(x2, 1);
} else {
INST_NAME("SAR Ew, CL");
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if (box64_dynarec_safeflags > 1)
MAYSETFLAGS();
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
default:
DEFAULT;
}
break;
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
break;
default:
DEFAULT;
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_inc16(dyn, ninst, x1, x2, x4, x5);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4, x5, x6);
EWBACK;
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
File diff suppressed because it is too large. Load diff
+70
View File
@@ -0,0 +1,70 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_6664(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int64_t j64;
int v0, v1;
int64_t fixedaddress;
int unscaled;
MAYUSE(j64);
GETREX();
switch (opcode) {
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
ed = TO_LA64((nextop & 7) + (rex.b << 3));
if (rex.w) {
MV(gd, ed);
} else {
if (ed != gd) BSTRINS_D(gd, ed, 15, 0);
}
} else { // mem <= reg
grab_segdata(dyn, addr, ninst, x4, seg);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
if (rex.w) {
LDX_D(gd, ed, x4);
} else {
LDX_HU(x1, ed, x4);
BSTRINS_D(gd, x1, 15, 0);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+142
View File
@@ -0,0 +1,142 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2;
int64_t fixedaddress;
int unscaled;
int8_t i8;
uint8_t u8;
int32_t i32;
int64_t j64, i64;
int cacheupd = 0;
int lock;
int v0, v1, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(s0);
MAYUSE(lock);
MAYUSE(cacheupd);
if(rex.is32bits) {
// should do a different file
DEFAULT;
return addr;
}
GETREX();
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x88:
INST_NAME("MOV Eb, Gb");
nextop = F8;
gd = ((nextop & 0x38) >> 3) + (rex.r << 3);
if (rex.rex) {
gb2 = 0;
gb1 = TO_LA64(gd);
} else {
gb2 = ((gd & 4) << 1);
gb1 = TO_LA64(gd & 3);
}
if (gb2) {
gd = x4;
BSTRPICK_D(gd, gb1, gb2 + 7, gb2);
} else {
gd = gb1; // no need to extract
}
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
if (rex.rex) {
eb1 = TO_LA64(ed);
eb2 = 0;
} else {
eb1 = TO_LA64(ed & 3); // Ax, Cx, Dx or Bx
eb2 = ((ed & 4) >> 2); // L or H
}
BSTRINS_D(eb1, gd, eb2 * 8 + 7, eb2 * 8);
} else {
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
ST_B(gb1, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0x89:
INST_NAME("MOV Ed, Gd");
nextop = F8;
GETGD;
if (MODREG) { // reg <= reg
MVxw(TO_LA64((nextop & 7) + (rex.b << 3)), gd);
} else { // mem <= reg
addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
SDxw(gd, ed, fixedaddress);
SMWRITELOCK(lock);
}
break;
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
GETED32(0);
if (rex.w) {
if (ed == xRDX)
gd = x3;
else
gd = xRDX;
MULH_DU(gd, xRAX, ed);
MUL_D(xRAX, xRAX, ed);
if (gd != xRDX) MV(xRDX, gd);
} else {
MUL_D(xRDX, xRAX, ed); // 64 <- 32x32
AND(xRAX, xRDX, xMASK);
SRLI_W(xRDX, xRDX, 32);
}
UFLAG_RES(xRAX);
UFLAG_OP1(xRDX);
UFLAG_DF(x2, rex.w ? d_mul64 : d_mul32);
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+635
View File
@@ -0,0 +1,635 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s4, d_xor8);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
X64_XOR_B(s1, s2);
}
XOR(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s4, d_xor8);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
ADDI_D(s3, xZR, c & 0xff);
X64_XOR_B(s1, s3);
}
XORI(s1, s1, c & 0xff);
IFX (X_PEND)
ST_B(s1, xEmu, offsetof(x64emu_t, res));
return;
}
XORI(s1, s1, c & 0xff);
ANDI(s1, s1, 0xff);
CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX (X_PEND) {
SET_DF(s4, d_xor16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
X64_XOR_W(s1, s2);
}
XOR(s1, s1, s2);
BSTRINS_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_ZF | X_SF) {
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s4, rex.w ? d_xor64 : d_xor32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
X64_XOR_D(s1, s2);
else
X64_XOR_W(s1, s2);
}
XOR(s1, s1, s2);
if (!rex.w && s1 != s2) ZEROUP(s1);
IFX(X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
CLEAR_FLAGS(s3);
XOR(s1, s1, s2);
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w && s1 != s2) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit XOR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_xor32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s4, rex.w ? d_xor64 : d_xor32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
MOV64xw(s3, c);
if (rex.w)
X64_XOR_D(s1, s3);
else
X64_XOR_W(s1, s3);
}
if (c >= 0 && c <= 4095) {
XORI(s1, s1, c);
} else {
IFX (X_ALL) {
} else {
MOV64xw(s3, c);
}
XOR(s1, s1, s3);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_PEND)
SDxw(s1, xEmu, offsetof(x64emu_t, res));
return;
}
if (c >= 0 && c <= 4095) {
XORI(s1, s1, c);
} else {
MOV64xw(s3, c);
XOR(s1, s1, s3);
}
CLEAR_FLAGS(s3);
// test sign bit before zeroup.
IFX (X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA(X_ALL, la64_lbt) {
X64_AND_B(s1, s2);
}
AND(s1, s1, s2);
IFX(X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA(X_ALL, la64_lbt) {
MOV32w(s3, c);
X64_AND_B(s1, s3);
}
ANDI(s1, s1, c&0xff);
IFX(X_PEND) {
ST_D(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
void emit_and16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s3, d_tst16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
X64_AND_W(s1, s2);
}
AND(s1, s1, s2); // res = s1 & s2
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA(X_ALL, la64_lbt) {
if (rex.w)
X64_AND_D(s1, s2);
else
X64_AND_W(s1, s2);
}
AND(s1, s1, s2); // res = s1 & s2
if (!rex.w) ZEROUP(s1);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF)
{
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit AND32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA(X_ALL, la64_lbt) {
MOV64xw(s3, c);
if (rex.w)
X64_AND_D(s1, s3);
else
X64_AND_W(s1, s3);
}
if (c >= 0 && c <= 4095) {
ANDI(s1, s1, c);
} else {
IFXA(X_ALL, la64_lbt) { } else MOV64xw(s3, c);
AND(s1, s1, s3); // res = s1 & s2
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s3, d_or16);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
X64_OR_H(s1, s2);
}
OR(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_D(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s4, rex.w?d_or64:d_or32);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
if (rex.w)
X64_OR_D(s1, s2);
else
X64_OR_W(s1, s2);
}
OR(s1, s1, s2);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
if (!rex.w) ZEROUP(s1);
return;
}
CLEAR_FLAGS(s3);
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) ZEROUP(s1);
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
{
IFX(X_PEND) {
SET_DF(s4, rex.w ? d_or64 : d_or32);
} else IFX(X_ALL) {
SET_DFNONE();
}
IFXA(X_ALL, la64_lbt) {
MOV64xw(s3, c);
if (rex.w)
X64_OR_D(s1, s3);
else
X64_OR_W(s1, s3);
}
if (c >= 0 && c <= 4095) {
ORI(s1, s1, c);
} else {
IFXA(X_ALL, la64_lbt) { } else MOV64xw(s3, c);
OR(s1, s1, s3);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) {
if (!rex.w) ZEROUP(s1);
return;
}
CLEAR_FLAGS(s3);
// test sign bit before zeroup.
IFX(X_SF) {
if (!rex.w) SEXT_W(s1, s1);
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX (X_PEND) {
SET_DF(s3, d_or8);
} else IFX (X_ALL) {
SET_DFNONE();
}
IFXA (X_ALL, la64_lbt) {
X64_OR_B(s1, s2);
}
OR(s1, s1, s2);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit OR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4)
{
MOV32w(s2, c & 0xff);
emit_or8(dyn, ninst, s1, s2, s3, s4);
}
File diff suppressed because it is too large. Load diff
+962
View File
@@ -0,0 +1,962 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
// s2 is not 0 here and is 1..1f/3f
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SLL_H(s1, s2);
}
SLL_D(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
SLL_D(s1, s1, s2);
CLEAR_FLAGS(s3);
IFX (X_CF | X_OF) {
SRLI_D(s5, s1, 16);
ANDI(s5, s5, 1); // LSB == F_CF
IFX (X_CF) {
OR(xFlags, xFlags, s5);
}
}
SLLI_D(s1, s1, 48);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRLI_D(s1, s1, 48);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
ADDI_D(s3, s2, -1);
BNEZ(s3, 4 + 4 * 4);
SRLI_D(s3, s1, 15);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3, s4 and s5 as scratch
void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
// s2 is not 0 here and is 1..1f/3f
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
X64_SLL_D(s1, s2);
else
X64_SLL_W(s1, s2);
}
SLL_D(s1, s1, s2);
if (!rex.w) { ZEROUP(s1); }
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF | X_OF) {
ADDI_D(s5, s2, rex.w?-64:-32);
SUB_D(s5, xZR, s5);
SRL_W(s3, s1, s5);
ANDI(s5, s3, 1); // LSB == F_CF
IFX(X_CF) {
OR(xFlags, xFlags, s5);
}
}
SLL_D(s1, s1, s2);
IFX(X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_OF) {
// OF flag is affected only on 1-bit shifts
ADDI_D(s3, s2, -1);
BNEZ(s3, 4 + 4 * 4);
SRLIxw(s3, s1, rex.w?63:31);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch
void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5)
{
if (!c) return;
IFX(X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else {
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
}
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if(la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
if (rex.w)
X64_SLL_D(s1, s3);
else
X64_SLL_W(s1, s3);
}
SLLIxw(s1, s1, c);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF | X_OF) {
if (c > 0) {
SRLI_D(s3, s1, (rex.w ? 64 : 32) - c);
ANDI(s5, s3, 1); // LSB == F_CF
IFX(X_CF) {
OR(xFlags, xFlags, s5);
}
}
}
if (rex.w) {
SLLI_D(s1, s1, c);
} else {
SLLI_W(s1, s1, c);
}
IFX(X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_OF) {
// OF flag is affected only on 1-bit shifts
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s5);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR8 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shr8);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SRL_B(s1, s2);
}
SRL_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
ADDI_D(s3, s2, -1);
SRA_D(s3, s1, s3);
ANDI(s3, s3, 1); // LSB == F_CF
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
ADDI_D(s3, xZR, 1);
BNE(s2, s3, 4 + 3 * 4);
SRLI_D(s3, s1, 7);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
SRL_D(s1, s1, s2);
ANDI(s1, s1, 0xff);
// SF should be unset
IFX (X_PEND) {
ST_B(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR16 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_shr16);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SRL_H(s1, s2);
}
SRL_D(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
ADDI_D(s3, s2, -1);
SRA_D(s3, s1, s3);
ANDI(s3, s3, 1); // LSB == F_CF
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
ADDI_D(s3, xZR, 1);
BNE(s2, s3, 4 + 3 * 4);
SRLI_D(s3, s1, 15);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
SRL_D(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
// SF should be unset
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR32 instruction, from s1 , shift s2 (!0 and and'd already), store result in s1 using s3 and s4 as scratch
void emit_shr32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shr64 : d_shr32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_SRL_D(s1, s2);
else
X64_SRL_W(s1, s2);
}
SRL_D(s1, s1, s2);
if (!rex.w) { ZEROUP(s1); }
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
ADDI_D(s3, s2, -1);
SRA_D(s3, s1, s3);
ANDI(s3, s3, 1); // LSB == F_CF
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
ADDI_D(s3, xZR, 1);
BNE(s2, s3, 4 + 4 * 4);
SRLIxw(s3, s1, rex.w ? 63 : 31);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
SRL_D(s1, s1, s2);
IFX (X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
IFX(X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shr64 : d_shr32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
if (rex.w)
X64_SRL_D(s1, s3);
else
X64_SRL_W(s1, s3);
}
SRLIxw(s1, s1, c);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
// no need to shift
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
IFX(X_OF) {
// OF flag is affected only on 1-bit shifts
// OF flag is set to the most-significant bit of the original operand
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
if (rex.w) {
SRLI_D(s1, s1, c);
} else {
SRLI_W(s1, s1, c);
}
IFX(X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR16 instruction, from s1, shift s2 (!0 and and'd already), store result in s1 using s3, s4 and s5 as scratch
void emit_sar16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
int64_t j64;
IFX (X_PEND) {
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, d_sar8);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_SRA_H(s1, s2);
}
SRL_D(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
ADDI_D(s3, s2, -1);
SRA_D(s3, s1, s3);
ANDI(s3, s3, 1); // LSB == F_CF
OR(xFlags, xFlags, s3);
}
// For the SAR instruction, the OF flag is cleared for all 1-bit shifts.
// OF nop
IFX (X_SF) {
// SF is the same as the original operand
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
SRL_D(s1, s1, s2);
BSTRPICK_D(s1, s1, 15, 0);
IFX (X_PEND) {
ST_H(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
IFX(X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_sar64 : d_sar32);
} else IFX(X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX(X_PEND) {} else { MOV64x(s3, c); }
IFX(X_ALL) {
if (rex.w)
X64_SRA_D(s1, s3);
else
X64_SRA_W(s1, s3);
}
SRAIxw(s1, s1, c);
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
// no need to shift
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
if (rex.w) {
SRAI_D(s1, s1, c);
} else {
SRAI_W(s1, s1, c);
}
// SRAI_W sign-extends, so test sign bit before clearing upper bits
IFX(X_SF) {
BGE(s1, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s1);
}
IFX(X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX (X_PEND) {
MOV32w(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_ror64 : d_ror32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_ROTRI_D(s1, c);
else
X64_ROTRI_W(s1, c);
}
}
ROTRIxw(s1, s1, c);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_CF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the two most-significant bits of the result
if (c == 1) {
SRLI_D(s3, s1, rex.w ? 62 : 30);
SRLI_D(s4, s3, 1);
XOR(s3, s3, s4);
ANDI(s3, s3, 1);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
}
// emit ROL32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_rol32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int64_t j64;
IFX (X_PEND) {
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_rol64 : d_rol32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
if (rex.w)
X64_ROTL_D(s1, s2);
else
X64_ROTL_W(s1, s2);
}
}
if (rex.w) {
ANDI(s4, s2, 0x3f);
} else {
ANDI(s4, s2, 0x1f);
}
if (!rex.w) ZEROUP(s1);
BEQ_NEXT(s4, xZR);
SLLxw(s3, s1, s4);
NEG_D(s4, s4);
ADDI_D(s4, s4, rex.w ? 64 : 32);
SRLxw(s1, s1, s4);
OR(s1, s3, s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
CLEAR_FLAGS(s3);
IFX (X_CF | X_OF) {
ANDI(s4, s1, 1); // LSB == F_CF
IFX (X_CF) OR(xFlags, xFlags, s4);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result.
ADDI_D(s3, xZR, 1);
BNE_NEXT(s2, s3);
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4); // s3: MSB, s4: CF bit
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4)
{
if (!c) return;
IFX (X_PEND) {
MOV32w(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w ? d_rol64 : d_rol32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
if (la64_lbt) {
IFX (X_CF | X_OF) {
if (rex.w)
X64_ROTLI_D(s1, c);
else
X64_ROTLI_W(s1, c);
}
}
ROTRIxw(s1, s1, (rex.w ? 64 : 32) - c);
if (!rex.w) ZEROUP(s1);
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
if (la64_lbt) return;
IFX (X_CF | X_OF) {
MOV64x(s3, (1UL << F_CF | 1UL << F_OF));
ANDN(xFlags, xFlags, s3);
}
IFX (X_CF | X_OF) {
ANDI(s4, s1, 1 << F_CF);
IFX (X_CF) OR(xFlags, xFlags, s4);
}
IFX (X_OF) {
// the OF flag is set to the exclusive OR of the CF bit (after the rotate) and the most-significant bit of the result.
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
}
void emit_shld32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
c &= (rex.w ? 0x3f : 0x1f);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shld64 : d_shld32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 0) {
SRLI_D(s3, s1, (rex.w ? 64 : 32) - c);
ANDI(s4, s3, 1); // F_CF
OR(xFlags, xFlags, s4);
}
}
IFX (X_OF) {
// Store sign for later use.
if (c == 1) SRLIxw(s4, s1, rex.w ? 63 : 31);
}
SLLIxw(s3, s1, c);
SRLIxw(s1, s2, (rex.w ? 64 : 32) - c);
OR(s1, s1, s3);
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_SF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// the OF flag is set if a sign change occurred
if (c == 1) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
ORI(xFlags, xFlags, s3);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFXA (X_ALL, la64_lbt) {
SPILL_EFLAGS();
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shrd32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4)
{
c &= (rex.w ? 0x3f : 0x1f);
IFX (X_PEND) {
if (c) {
MOV64x(s3, c);
SDxw(s3, xEmu, offsetof(x64emu_t, op2));
} else
SDxw(xZR, xEmu, offsetof(x64emu_t, op2));
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SET_DF(s4, rex.w ? d_shrd64 : d_shrd32);
} else IFX (X_ALL) {
SET_DFNONE();
}
if (!c) {
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX (X_CF) {
if (c > 1) {
SRAI_D(s3, s1, c - 1);
ANDI(s3, s3, 1); // LSB == F_CF
} else {
ANDI(s3, s1, 1); // LSB == F_CF
}
OR(xFlags, xFlags, s3);
}
IFX (X_OF) {
// Store sign for later use.
if (c == 1) SRLIxw(s4, s1, rex.w ? 63 : 31);
}
SRLIxw(s3, s1, c);
SLLIxw(s1, s2, (rex.w ? 64 : 32) - c);
OR(s1, s1, s3);
if (!rex.w) {
ZEROUP(s1);
}
IFX (X_SF) {
SRLIxw(s3, s1, rex.w ? 63 : 31);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_PEND) {
SDxw(s1, xEmu, offsetof(x64emu_t, res));
}
IFX (X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_OF) {
// the OF flag is set if a sign change occurred
if (c == 1) {
SRLI_D(s3, s1, rex.w ? 63 : 31);
XOR(s3, s3, s4);
SLLI_D(s3, s3, F_OF);
OR(xFlags, xFlags, s3);
}
}
IFX (X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
IFXA (X_ALL, la64_lbt) {
SPILL_EFLAGS();
}
}
+474
View File
@@ -0,0 +1,474 @@
#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 "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
// emit CMP8 instruction, from cmp s1, s2, using s3, s4, s5 and s6 as scratch
void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6)
{
IFX_PENDOR0 {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp8);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_B(s1, s2);
}
IFX_PENDOR0 {
SUB_D(s6, s1, s2);
ST_B(s6, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
// It's a cmp, we can't store the result back to s1.
SUB_D(s6, s1, s2);
ANDI(s6, s6, 0xff);
IFX_PENDOR0 {
ST_B(s6, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI_D(s3, s6, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 8);
IFX(X_ZF) {
BNEZ(s6, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX_PENDOR0 {
ST_B(s1, xEmu, offsetof(x64emu_t, op1));
ST_B(xZR, xEmu, offsetof(x64emu_t, op2));
ST_B(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_B(s1, xZR);
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, 7);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch
void emit_cmp16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6)
{
IFX_PENDOR0 {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp16);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_H(s1, s2);
}
IFX_PENDOR0 {
SUB_D(s6, s1, s2);
ST_H(s6, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
// It's a cmp, we can't store the result back to s1.
SUB_D(s6, s1, s2);
IFX(X_ALL) {
BSTRPICK_D(s6, s6, 15, 0);
}
IFX_PENDOR0 {
ST_H(s6, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI_D(s3, s6, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 16);
IFX(X_ZF) {
BNEZ(s6, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX_PENDOR0 {
ST_H(s1, xEmu, offsetof(x64emu_t, op1));
ST_H(xZR, xEmu, offsetof(x64emu_t, op2));
ST_H(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
X64_SUB_H(s1, xZR);
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_SF) {
SRLI_D(s3, s1, 15);
BEQZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch
void emit_cmp32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6)
{
IFX_PENDOR0 {
SDxw(s1, xEmu, offsetof(x64emu_t, op1));
SDxw(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
X64_SUB_D(s1, s2);
else
X64_SUB_W(s1, s2);
}
IFX_PENDOR0 {
SUBxw(s6, s1, s2);
SDxw(s6, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_AF | X_CF | X_OF) {
// for later flag calculation
NOR(s5, xZR, s1);
}
// It's a cmp, we can't store the result back to s1.
SUBxw(s6, s1, s2);
IFX_PENDOR0 {
SDxw(s6, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
BGE(s6, xZR, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
if (!rex.w) {
ZEROUP(s6);
}
CALC_SUB_FLAGS(s5, s2, s6, s3, s4, rex.w?64:32);
IFX(X_ZF) {
BNEZ(s6, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s6, s3, s4);
}
}
// emit CMP32 instruction, from cmp s1, 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
{
IFX_PENDOR0 {
ST_D(s1, xEmu, offsetof(x64emu_t, op1));
ST_D(xZR, xEmu, offsetof(x64emu_t, op2));
ST_D(s1, xEmu, offsetof(x64emu_t, res));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
X64_SUB_D(s1, xZR);
else
X64_SUB_W(s1, xZR);
}
return;
}
CLEAR_FLAGS(s3);
IFX(X_SF) {
if (rex.w) {
BGE(s1, xZR, 8);
} else {
SRLI_D(s3, s1, 31);
BEQZ(s3, 8);
}
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s1, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
X64_AND_B(s1, s2);
}
IFX_PENDOR0 {
AND(s3, s1, s2);
ST_D(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
AND(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
ST_D(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI_D(s4, s3, 7);
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
}
// emit TEST16 instruction, from test s1, s2, using s3, s4 and s5 as scratch
void emit_test16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX (X_ALL) {
X64_AND_H(s1, s2);
}
IFX_PENDOR0 {
AND(s3, s1, s2);
ST_H(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
AND(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
ST_H(s3, xEmu, offsetof(x64emu_t, res));
}
IFX (X_SF) {
SRLI_D(s4, s3, 15);
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX (X_ZF) {
BNEZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX (X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
}
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
if (rex.w)
X64_AND_D(s1, s2);
else
X64_AND_W(s1, s2);
}
IFX_PENDOR0 {
AND(s3, s1, s2);
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
AND(s3, s1, s2); // res = s1 & s2
IFX_PENDOR0 {
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF | X_ZF) {
if (!rex.w) ZEROUP(s3);
}
IFX(X_SF) {
SRLI_D(s4, s3, rex.w?63:31);
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
}
// emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
IFX_PENDOR0 {
SET_DF(s3, rex.w ? d_tst64 : d_tst32);
} else {
SET_DFNONE();
}
if (la64_lbt) {
IFX(X_ALL) {
MOV64xw(s3, c);
if (rex.w)
X64_AND_D(s1, s3);
else
X64_AND_W(s1, s3);
}
IFX_PENDOR0 {
if (c >= 0 && c <= 4095) {
ANDI(s3, s1, c);
} else {
IFX(X_ALL) { } else MOV64xw(s3, c);
AND(s3, s1, s3);
}
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
return;
}
CLEAR_FLAGS(s3);
if (c >= 0 && c <= 4095) {
ANDI(s3, s1, c);
} else {
IFXA(X_ALL, la64_lbt) { } else MOV64xw(s3, c);
AND(s3, s1, s3);
}
IFX_PENDOR0 {
SDxw(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_SF) {
SRLI_D(s4, s3, rex.w ? 63 : 31);
BEQZ(s4, 8);
ORI(xFlags, xFlags, 1 << F_SF);
}
IFX(X_ZF) {
BNEZ(s3, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4, s5);
}
}
+488
View File
@@ -0,0 +1,488 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_helper.h"
#include "dynarec_la64_functions.h"
uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
(void)ip;
(void)rep;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed, u8;
uint8_t wback, wb1, wb2, eb1, eb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j64);
while ((opcode == 0xF2) || (opcode == 0xF3)) {
rep = opcode - 0xF1;
opcode = F8;
}
GETREX();
switch (opcode) {
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if ((nextop & 0xC0) == 0xC0) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDxw(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND) {
emit_add32(dyn, ninst, rex, x1, gd, x3, x4, x5);
}
}
SMDMB();
break;
case 0x0F:
nextop = F8;
switch (nextop) {
case 0xB1:
switch (rep) {
case 0:
INST_NAME("LOCK CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
wback = 0;
UFLAG_IF { emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5, x6); }
MV(x1, ed); // save value
SUB_D(x2, x1, xRAX);
BNE_MARK2(x2, xZR);
MV(ed, gd);
MARK2;
MVxw(xRAX, x1);
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
MV(x4, gd);
LLxw(x1, wback, 0);
SUBxw(x3, x1, xRAX);
BNEZ_MARK(x3);
// EAX == Ed
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
B_MARK_nocond;
MARK3;
// Unaligned
ADDI_D(x5, xZR, -(1 << (rex.w + 2)));
AND(x5, x5, wback);
MARK2;
LDxw(x1, wback, 0);
LLxw(x6, x5, 0);
SUBxw(x3, x1, xRAX);
BNEZ_MARK(x3);
// EAX == Ed
SCxw(x6, x5, 0);
BEQZ_MARK2(x6);
SDxw(gd, wback, 0);
MARK;
UFLAG_IF { emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); }
MVxw(xRAX, x1);
SMDMB();
}
break;
default:
DEFAULT;
}
break;
case 0xC1:
switch (rep) {
case 0:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
MVxw(x1, ed);
MVxw(ed, gd);
MVxw(gd, x1);
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDxw(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX(X_ALL | X_PEND) {
MVxw(x2, x1);
emit_add32(dyn, ninst, rex, x2, gd, x3, x4, x5);
}
MVxw(gd, x1);
}
SMDMB();
break;
default:
DEFAULT;
}
break;
case 0xC7:
switch (rep) {
case 0:
if (rex.w) {
INST_NAME("LOCK CMPXCHG16B Gq, Eq");
} else {
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
}
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (la64_lbt) {
X64_SET_EFLAGS(xZR, X_ZF);
} else {
ADDI_D(x2, xZR, ~(1 << F_ZF));
AND(xFlags, xFlags, x2);
}
if (rex.w) {
if (la64_scq) {
MARKLOCK;
LL_D(x2, wback, 0);
LD_D(x3, wback, 8);
// compare RDX:RAX with x3:x2
BNE_MARK(x2, xRAX);
BNE_MARK(x3, xRDX);
MV(x5, xRBX);
SC_Q(x5, xRCX, wback);
BEQZ_MARKLOCK(x5);
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
B_MARK3_nocond;
MARK;
MV(xRAX, x2);
MV(xRDX, x3);
MARK3;
SMDMB();
} else {
// if scq extension is not available, implement it with mutex
LD_D(x6, xEmu, offsetof(x64emu_t, context));
ADDI_D(x6, x6, offsetof(box64context_t, mutex_16b));
ADDI_D(x4, xZR, 1);
MARKLOCK;
AMSWAP_DB_W(x5, x4, x6);
// x4 == 1 if locked
BNEZ_MARKLOCK(x5);
LD_D(x2, wback, 0);
LD_D(x3, wback, 8);
BNE_MARK(x2, xRAX);
BNE_MARK(x3, xRDX);
ST_D(xRBX, wback, 0);
ST_D(xRCX, wback, 8);
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
B_MARK3_nocond;
MARK;
MV(xRAX, x2);
MV(xRDX, x3);
MARK3;
// unlock
AMSWAP_DB_W(xZR, xZR, x6);
}
} else {
SMDMB();
AND(x3, xRAX, xMASK);
SLLI_D(x2, xRDX, 32);
OR(x3, x3, x2);
AND(x4, xRBX, xMASK);
SLLI_D(x2, xRCX, 32);
OR(x4, x4, x2);
MARKLOCK;
LL_D(x2, wback, 0);
BNE_MARK(x2, x3); // EDX_EAX != Ed
MV(x5, x4);
SC_D(x5, wback, 0);
BEQZ_MARKLOCK(x5);
if (la64_lbt) {
ADDI_D(x5, xZR, -1);
X64_SET_EFLAGS(x5, X_ZF);
} else {
ORI(xFlags, xFlags, 1 << F_ZF);
}
B_MARK3_nocond;
MARK;
SLLI_D(xRDX, x2, 32);
AND(xRAX, x2, xMASK);
MARK3;
SMDMB();
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
SUB_D(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4, x5);
}
SMDMB();
break;
case 0x81:
case 0x83:
nextop = F8;
SMDMB();
switch ((nextop >> 3) & 7) {
case 0: // ADD
if (opcode == 0x81) {
INST_NAME("LOCK ADD Ed, Id");
} else {
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if (MODREG) {
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64 < -2048 || i64 >= 2048) {
MOV64xw(x3, i64);
}
MARKLOCK;
LLxw(x1, wback, 0);
if (i64 >= -2048 && i64 < 2048) {
ADDIxw(x4, x1, i64);
} else {
ADDxw(x4, x1, x3);
}
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX(X_ALL | X_PEND) {
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
}
SMDMB();
}
break;
case 1: // OR
if (opcode == 0x81) {
INST_NAME("LOCK OR Ed, Id");
} else {
INST_NAME("LOCK OR Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if (MODREG) {
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81) {
i64 = F32S;
} else {
i64 = F8S;
}
if (i64 <= -2048 || i64 > 2048) {
MOV64xw(x3, i64);
}
MARKLOCK;
LLxw(x1, wback, 0);
if (i64 >= -2048 && i64 < 2048) {
ORI(x4, x1, i64);
} else {
OR(x4, x1, x3);
}
if (!rex.w) ZEROUP(x4);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_or32c(dyn, ninst, rex, x1, i64, x3, x4);
}
break;
case 5: // SUB
if (opcode == 0x81) {
INST_NAME("LOCK SUB Ed, Id");
} else {
INST_NAME("LOCK SUB Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if (MODREG) {
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (opcode == 0x81)
i64 = F32S;
else
i64 = F8S;
if (i64 <= -2048 || i64 > 2048) {
MOV64xw(x3, i64);
}
MARKLOCK;
LLxw(x1, wback, 0);
if (i64 > -2048 && i64 <= 2048) {
ADDIxw(x4, x1, -i64);
} else {
SUBxw(x4, x1, x3);
}
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_sub32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
}
break;
default:
DEFAULT;
}
break;
case 0x87:
INST_NAME("LOCK XCHG Ed, Gd");
nextop = F8;
if (MODREG) {
GETGD;
GETED(0);
MV(x1, gd);
MV(gd, ed);
MV(ed, x1);
} else {
SMDMB();
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
MV(x4, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
MVxw(gd, x1);
SMDMB();
}
break;
case 0xFF:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_inc32(dyn, ninst, rex, ed, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDIxw(x4, x1, 1);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_inc32(dyn, ninst, rex, x1, x3, x4, x5, x6);
}
break;
case 1:
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL & ~X_CF, SF_SUBSET_PENDING);
SMDMB();
if (MODREG) {
ed = TO_LA64((nextop & 7) + (rex.b << 3));
emit_dec32(dyn, ninst, rex, ed, x3, x4, x5, x6);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDIxw(x4, x1, -1);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
IFX (X_ALL | X_PEND)
emit_dec32(dyn, ninst, rex, x1, x3, x4, x5, x6);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+317
View File
@@ -0,0 +1,317 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t u8;
uint64_t u64, j64;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(v0);
MAYUSE(v1);
switch(opcode) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop & 7) + (rex.b << 3);
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
v1 = fpu_get_scratch(dyn);
VXOR_V(v0, v0, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0);
FLD_D(v1, ed, fixedaddress);
}
VEXTRINS_D(v0, v1, 0); // v0[63:0] = v1[63:0]
break;
case 0x11:
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if(MODREG) {
ed = (nextop & 7) + (rex.b << 3);
d0 = sse_get_reg(dyn, ninst, x1, ed, 0);
VEXTRINS_D(d0, v0, 0); // d0[63:0] = v0[63:0]
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
FST_D(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x2A:
INST_NAME("CVTSI2SD Gx, Ed");
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
if (rex.w) {
MOVGR2FR_D(d1, ed);
FFINT_D_L(d1, d1);
} else {
MOVGR2FR_W(d1, ed);
FFINT_D_W(d1, d1);
}
VEXTRINS_D(v0, d1, 0);
break;
case 0x2C:
INST_NAME("CVTTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if (!box64_dynarec_fastround) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
d1 = fpu_get_scratch(dyn);
if (rex.w) {
FTINTRZ_L_D(d1, q0);
MOVFR2GR_D(gd, d1);
} else {
FTINTRZ_W_D(d1, q0);
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
if (!rex.w) ZEROUP(gd);
if (!box64_dynarec_fastround) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
AND(x5, x5, x3);
CBZ_NEXT(x5);
if (rex.w) {
MOV64x(gd, 0x8000000000000000LL);
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSD(q0, 0, 0);
if (!box64_dynarec_fastround) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
d1 = fpu_get_scratch(dyn);
u8 = sse_setround(dyn, ninst, x2, x3);
if (rex.w) {
FTINT_L_D(d1, q0);
MOVFR2GR_D(gd, d1);
} else {
FTINT_W_D(d1, q0);
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!box64_dynarec_fastround) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
AND(x5, x5, x3);
CBZ_NEXT(x5);
if (rex.w) {
MOV64x(gd, 0x8000000000000000LL);
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x51:
INST_NAME("SQRTSD Gx, Ex");
nextop = F8;
GETGX_empty(v0);
d1 = fpu_get_scratch(dyn);
GETEXSD(d0, 0, 0);
FSQRT_D(d1, d0);
if (!box64_dynarec_fastnan) {
v1 = fpu_get_scratch(dyn);
MOVGR2FR_D(v1, xZR);
FCMP_D(fcc0, d0, v1, cLT);
BCEQZ(fcc0, 4 + 4);
FNEG_D(d1, d1);
}
VEXTRINS_D(v0, d1, 0);
break;
case 0x58:
INST_NAME("ADDSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
FADD_D(d0, v0, v1);
if (!box64_dynarec_fastnan) {
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x59:
INST_NAME("MULSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
FMUL_D(d0, v0, v1);
if (!box64_dynarec_fastnan) {
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5A:
INST_NAME("CVTSD2SS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(d0, 0, 0);
d1 = fpu_get_scratch(dyn);
FCVT_S_D(d1, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x5C:
INST_NAME("SUBSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
FSUB_D(d0, v0, v1);
if (!box64_dynarec_fastnan) {
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5D:
INST_NAME("MINSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, v1, v0, cLE);
BCEQZ_MARK2(fcc1);
MARK;
VEXTRINS_D(v0, v1, 0);
MARK2;
break;
case 0x5E:
INST_NAME("DIVSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
d0 = fpu_get_scratch(dyn);
FDIV_D(d0, v0, v1);
if (!box64_dynarec_fastnan) {
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSD(v1, 0, 0);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, v0, v1, cLE);
BCEQZ_MARK2(fcc1);
MARK;
VEXTRINS_D(v0, v1, 0);
MARK2;
break;
case 0x70:
INST_NAME("PSHUFLW Gx, Ex, Ib");
nextop = F8;
GETEX(v1, 0, 1);
GETGX(v0, 1);
u8 = F8;
if (v0 != v1) {
VSHUF4I_H(v0, v1, u8);
VEXTRINS_D(v0, v1, 0x11); // v0[127:64] = v1[127:64]
} else {
q0 = fpu_get_scratch(dyn);
VSHUF4I_H(q0, v1, u8);
VEXTRINS_D(v0, q0, 0x0); // v0[63:0] = q0[63:0]
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 1);
u8 = F8;
switch (u8 & 7) {
case 0: FCMP_D(fcc0, v0, v1, cEQ); break; // Equal
case 1: FCMP_D(fcc0, v0, v1, cLT); break; // Less than
case 2: FCMP_D(fcc0, v0, v1, cLE); break; // Less or equal
case 3: FCMP_D(fcc0, v0, v1, cUN); break; // NaN
case 4: FCMP_D(fcc0, v0, v1, cUNE); break; // Not Equal or unordered
case 5: FCMP_D(fcc0, v1, v0, cULE); break; // Greater or equal or unordered
case 6: FCMP_D(fcc0, v1, v0, cULT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: FCMP_D(fcc0, v0, v1, cOR); break; // not NaN
}
MOVCF2GR(x2, fcc0);
NEG_D(x2, x2);
q1 = fpu_get_scratch(dyn);
MOVGR2FR_D(q1, x2);
VEXTRINS_D(v0, q1, 0);
break;
default:
DEFAULT;
}
return addr;
}
+346
View File
@@ -0,0 +1,346 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "la64_emitter.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "bitutils.h"
#include "la64_printer.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "dynarec_la64_helper.h"
uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed;
uint8_t wback, gback;
uint64_t u64;
int v0, v1;
int q0, q1;
int d0, d1;
int64_t fixedaddress, gdoffset;
int unscaled;
int64_t j64;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(j64);
switch (opcode) {
case 0x10:
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
v1 = fpu_get_scratch(dyn);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
VXOR_V(v0, v0, v0);
FLD_S(v1, ed, fixedaddress);
}
VEXTRINS_W(v0, v1, 0);
break;
case 0x11:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if (MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1);
VEXTRINS_W(q0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
FST_S(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
nextop = F8;
FAKEED;
break;
case 0x2A:
INST_NAME("CVTSI2SS Gx, Ed");
nextop = F8;
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
MOVGR2FR_D(d1, ed);
if(rex.w) {
FFINT_S_L(d1, d1);
} else {
FFINT_S_W(d1, d1);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x2C:
INST_NAME("CVTTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEXSS(d0, 0, 0);
if (!box64_dynarec_fastround) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
d1 = fpu_get_scratch(dyn);
if (rex.w) {
FTINTRZ_L_S(d1, d0);
MOVFR2GR_D(gd, d1);
} else {
FTINTRZ_W_S(d1, d0);
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
if (!rex.w) ZEROUP(gd);
if (!box64_dynarec_fastround) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
AND(x5, x5, x3);
CBZ_NEXT(x5);
if (rex.w) {
MOV64x(gd, 0x8000000000000000LL);
} else {
MOV32w(gd, 0x80000000);
}
}
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FSQRT_S(d1, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FADD_S(d1, v0, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FMUL_S(d1, v0, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 0);
d1 = fpu_get_scratch(dyn);
FCVT_D_S(d1, v1);
VEXTRINS_D(v0, d1, 0);
break;
case 0x5B:
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
VFTINTRZ_W_S(v0, v1);
if (!box64_dynarec_fastround) {
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_S(q0, v1, v1, cEQ);
VLDI(q1, 0b1001110000000); // broadcast 0x80000000
VAND_V(v0, q0, v0);
VANDN_V(d1, q0, q1);
VOR_V(v0, v0, d1);
VSUBI_WU(d1, q1, 1);
VSEQ_W(q0, v0, d1);
VSRLI_W(q0, q0, 31);
VADD_W(v0, v0, q0);
}
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FSUB_S(d1, v0, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x5D:
INST_NAME("MINSS Gx, Ex");
nextop = F8;
GETGX(d0, 1);
GETEXSS(d1, 0, 0);
FCMP_S(fcc0, d0, d1, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d1, d0, cLT);
BCEQZ_MARK2(fcc1);
MARK;
v1 = fpu_get_scratch(dyn);
FMOV_S(v1, d1);
VEXTRINS_W(d0, v1, 0);
MARK2;
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
GETGX(v0, 1);
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FDIV_S(d1, v0, d0);
VEXTRINS_W(v0, d1, 0);
break;
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
nextop = F8;
GETGX(d0, 1);
GETEXSS(d1, 0, 0);
FCMP_S(fcc0, d0, d1, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d0, d1, cLT);
BCEQZ_MARK2(fcc1);
MARK;
v1 = fpu_get_scratch(dyn);
FMOV_S(v1, d1);
VEXTRINS_W(d0, v1, 0);
MARK2;
break;
case 0x6F:
INST_NAME("MOVDQU Gx, Ex");
nextop = F8;
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
GETGX_empty(v0);
VOR_V(v0, v1, v1);
} else {
GETGX_empty(v0);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0);
VLD(v0, ed, fixedaddress);
}
break;
case 0x70:
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
GETEX(v1, 0, 1);
GETGX(v0, 1);
u8 = F8;
VSHUF4I_H(v0, v1, u8);
VEXTRINS_D(v0, v1, 0); // v0[63:0] = v1[63:0]
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
if (MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
v1 = fpu_get_scratch(dyn);
FLD_D(v1, ed, fixedaddress);
}
GETGX_empty(v0);
if (v0 == v1) {
// clear upper bits..
q1 = fpu_get_scratch(dyn);
VXOR_V(q1, q1, q1);
VEXTRINS_D(q1, v1, 0); // q1[63:0] = v1[63:0]
VOR_V(v0, q1, q1);
} else {
VXOR_V(v0, v0, v0);
VEXTRINS_D(v0, v1, 0); // v0[63:0] = v1[63:0]
}
break;
case 0x7F:
INST_NAME("MOVDQU Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop & 7) + (rex.b << 3));
VOR_V(v1, v0, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0);
VST(v0, ed, fixedaddress);
SMWRITE2();
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_ZF, SF_SUBSET);
SET_DFNONE();
nextop = F8;
GETED(0);
GETGD;
if (!rex.w && MODREG) {
AND(x4, ed, xMASK);
ed = x4;
}
RESTORE_EFLAGS(x1);
ANDI(xFlags, xFlags, ~((1 << F_ZF) | (1 << F_CF)));
BNE_MARK(ed, xZR);
ORI(xFlags, xFlags, 1 << F_CF);
MOV32w(gd, rex.w ? 64 : 32);
SPILL_EFLAGS();
B_NEXT_nocond;
MARK;
CTZxw(gd, ed);
BNE(gd, xZR, 4 + 4);
ORI(xFlags, xFlags, 1 << F_ZF);
SPILL_EFLAGS();
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex, Ib");
nextop = F8;
GETGX(v0, 1);
GETEXSS(v1, 0, 1);
u8 = F8;
switch (u8 & 7) {
case 0: FCMP_S(fcc0, v0, v1, cEQ); break; // Equal
case 1: FCMP_S(fcc0, v0, v1, cLT); break; // Less than
case 2: FCMP_S(fcc0, v0, v1, cLE); break; // Less or equal
case 3: FCMP_S(fcc0, v0, v1, cUN); break; // NaN
case 4: FCMP_S(fcc0, v0, v1, cUNE); break; // Not Equal or unordered
case 5: FCMP_S(fcc0, v1, v0, cULE); break; // Greater or equal or unordered
case 6: FCMP_S(fcc0, v1, v0, cULT); break; // Greater or unordered, test inverted, N!=V so unordered or less than (inverted)
case 7: FCMP_S(fcc0, v0, v1, cOR); break; // not NaN
}
MOVCF2GR(x2, fcc0);
NEG_D(x2, x2);
q1 = fpu_get_scratch(dyn);
MOVGR2FR_W(q1, x2);
VEXTRINS_W(v0, q1, 0);
break;
default:
DEFAULT;
}
return addr;
}
+387
View File
@@ -0,0 +1,387 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "emu/x87emu_private.h"
#include "x64trace.h"
#include "signals.h"
#include "dynarec_native.h"
#include "dynarec_la64_private.h"
#include "dynarec_la64_functions.h"
#include "custommem.h"
#include "bridge.h"
#define XMM0 0
#define XMM8 16
#define X870 8
#define EMM0 8
// Get a FPU scratch reg
int fpu_get_scratch(dynarec_la64_t* dyn)
{
return SCRATCH0 + dyn->lsx.fpu_scratch++; // return an Sx
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_la64_t* dyn)
{
dyn->lsx.fpu_scratch = 0;
}
// Free a FPU double reg
void fpu_free_reg(dynarec_la64_t* dyn, int reg)
{
// TODO: check upper limit?
dyn->lsx.fpuused[reg] = 0;
if (dyn->lsx.lsxcache[reg].t != LSX_CACHE_ST_F && dyn->lsx.lsxcache[reg].t != LSX_CACHE_ST_D && dyn->lsx.lsxcache[reg].t != LSX_CACHE_ST_I64)
dyn->lsx.lsxcache[reg].v = 0;
}
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_la64_t* dyn, int t, int xmm)
{
int i;
if (xmm > 7) {
i = XMM8 + xmm - 8;
} else {
i = XMM0 + xmm;
}
dyn->lsx.fpuused[i] = 1;
dyn->lsx.lsxcache[i].t = t;
dyn->lsx.lsxcache[i].n = xmm;
dyn->lsx.news |= (1 << i);
return i;
}
// Reset fpu regs counter
static void fpu_reset_reg_lsxcache(lsxcache_t* lsx)
{
lsx->fpu_reg = 0;
for (int i = 0; i < 24; ++i) {
lsx->fpuused[i] = 0;
lsx->lsxcache[i].v = 0;
}
}
void fpu_reset_reg(dynarec_la64_t* dyn)
{
fpu_reset_reg_lsxcache(&dyn->lsx);
}
static int isCacheEmpty(dynarec_native_t* dyn, int ninst)
{
if (dyn->insts[ninst].lsx.stack_next) {
return 0;
}
for (int i = 0; i < 24; ++i)
if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
if (!(
(dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F
|| dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_D
|| dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_I64)
&& dyn->insts[ninst].lsx.lsxcache[i].n < dyn->insts[ninst].lsx.stack_pop))
return 0;
}
return 1;
}
int fpuCacheNeedsTransform(dynarec_la64_t* dyn, int ninst)
{
int i2 = dyn->insts[ninst].x64.jmp_insts;
if (i2 < 0)
return 1;
if ((dyn->insts[i2].x64.barrier & BARRIER_FLOAT))
// if the barrier as already been apply, no transform needed
return ((dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) ? 0 : (isCacheEmpty(dyn, ninst) ? 0 : 1);
int ret = 0;
if (!i2) { // just purge
if (dyn->insts[ninst].lsx.stack_next) {
return 1;
}
for (int i = 0; i < 24 && !ret; ++i)
if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
if (!(
(dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_F
|| dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_D
|| dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_ST_I64)
&& dyn->insts[ninst].lsx.lsxcache[i].n < dyn->insts[ninst].lsx.stack_pop))
ret = 1;
}
return ret;
}
// Check if ninst can be compatible to i2
if (dyn->insts[ninst].lsx.stack_next != dyn->insts[i2].lsx.stack - dyn->insts[i2].lsx.stack_push) {
return 1;
}
lsxcache_t cache_i2 = dyn->insts[i2].lsx;
lsxcacheUnwind(&cache_i2);
for (int i = 0; i < 24; ++i) {
if (dyn->insts[ninst].lsx.lsxcache[i].v) { // there is something at ninst for i
if (!cache_i2.lsxcache[i].v) { // but there is nothing at i2 for i
ret = 1;
} else if (dyn->insts[ninst].lsx.lsxcache[i].v != cache_i2.lsxcache[i].v) { // there is something different
if (dyn->insts[ninst].lsx.lsxcache[i].n != cache_i2.lsxcache[i].n) { // not the same x64 reg
ret = 1;
} else if (dyn->insts[ninst].lsx.lsxcache[i].t == LSX_CACHE_XMMR && cache_i2.lsxcache[i].t == LSX_CACHE_XMMW) { /* nothing */
} else
ret = 1;
}
} else if (cache_i2.lsxcache[i].v)
ret = 1;
}
return ret;
}
void lsxcacheUnwind(lsxcache_t* cache)
{
if (cache->swapped) {
// unswap
int a = -1;
int b = -1;
for (int j = 0; j < 24 && ((a == -1) || (b == -1)); ++j)
if ((cache->lsxcache[j].t == LSX_CACHE_ST_D || cache->lsxcache[j].t == LSX_CACHE_ST_F || cache->lsxcache[j].t == LSX_CACHE_ST_I64)) {
if (cache->lsxcache[j].n == cache->combined1)
a = j;
else if (cache->lsxcache[j].n == cache->combined2)
b = j;
}
if (a != -1 && b != -1) {
int tmp = cache->lsxcache[a].n;
cache->lsxcache[a].n = cache->lsxcache[b].n;
cache->lsxcache[b].n = tmp;
}
cache->swapped = 0;
cache->combined1 = cache->combined2 = 0;
}
if (cache->news) {
// reove the newly created lsxcache
for (int i = 0; i < 24; ++i)
if (cache->news & (1 << i))
cache->lsxcache[i].v = 0;
cache->news = 0;
}
if (cache->stack_push) {
// unpush
for (int j = 0; j < 24; ++j) {
if ((cache->lsxcache[j].t == LSX_CACHE_ST_D || cache->lsxcache[j].t == LSX_CACHE_ST_F || cache->lsxcache[j].t == LSX_CACHE_ST_I64)) {
if (cache->lsxcache[j].n < cache->stack_push)
cache->lsxcache[j].v = 0;
else
cache->lsxcache[j].n -= cache->stack_push;
}
}
cache->x87stack -= cache->stack_push;
cache->stack -= cache->stack_push;
cache->stack_push = 0;
}
cache->x87stack += cache->stack_pop;
cache->stack_next = cache->stack;
cache->stack_pop = 0;
cache->barrier = 0;
// And now, rebuild the x87cache info with lsxcache
cache->mmxcount = 0;
cache->fpu_scratch = 0;
cache->fpu_extra_qscratch = 0;
cache->fpu_reg = 0;
for (int i = 0; i < 8; ++i) {
cache->x87cache[i] = -1;
cache->mmxcache[i] = -1;
cache->x87reg[i] = 0;
cache->ssecache[i * 2].v = -1;
cache->ssecache[i * 2 + 1].v = -1;
}
int x87reg = 0;
for (int i = 0; i < 24; ++i) {
if (cache->lsxcache[i].v) {
cache->fpuused[i] = 1;
switch (cache->lsxcache[i].t) {
case LSX_CACHE_MM:
cache->mmxcache[cache->lsxcache[i].n] = i;
++cache->mmxcount;
++cache->fpu_reg;
break;
case LSX_CACHE_XMMR:
case LSX_CACHE_XMMW:
cache->ssecache[cache->lsxcache[i].n].reg = i;
cache->ssecache[cache->lsxcache[i].n].write = (cache->lsxcache[i].t == LSX_CACHE_XMMW) ? 1 : 0;
++cache->fpu_reg;
break;
case LSX_CACHE_ST_F:
case LSX_CACHE_ST_D:
case LSX_CACHE_ST_I64:
cache->x87cache[x87reg] = cache->lsxcache[i].n;
cache->x87reg[x87reg] = i;
++x87reg;
++cache->fpu_reg;
break;
case LSX_CACHE_SCR:
cache->fpuused[i] = 0;
cache->lsxcache[i].v = 0;
break;
}
} else {
cache->fpuused[i] = 0;
}
}
}
const char* getCacheName(int t, int n)
{
static char buff[20];
switch (t) {
case LSX_CACHE_ST_D: sprintf(buff, "ST%d", n); break;
case LSX_CACHE_ST_F: sprintf(buff, "st%d", n); break;
case LSX_CACHE_ST_I64: sprintf(buff, "STi%d", n); break;
case LSX_CACHE_MM: sprintf(buff, "MM%d", n); break;
case LSX_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case LSX_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
case LSX_CACHE_SCR: sprintf(buff, "Scratch"); break;
case LSX_CACHE_NONE: buff[0] = '\0'; break;
}
return buff;
}
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",
(box64_dynarec_dump > 1) ? "\e[32m" : "",
(void*)(dyn->native_start + dyn->insts[ninst].address),
dyn->insts[ninst].size / 4,
ninst,
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].x64.may_set ? "may" : "set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
dyn->insts[ninst].x64.need_before,
dyn->insts[ninst].x64.need_after,
dyn->smread, dyn->smwrite);
if (dyn->insts[ninst].pred_sz) {
dynarec_log(LOG_NONE, ", pred=");
for (int ii = 0; ii < dyn->insts[ninst].pred_sz; ++ii)
dynarec_log(LOG_NONE, "%s%d", ii ? "/" : "", dyn->insts[ninst].pred[ii]);
}
if (dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts >= 0)
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x64.jmp_insts);
if (dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts == -1)
dynarec_log(LOG_NONE, ", jmp=out");
if (dyn->last_ip)
dynarec_log(LOG_NONE, ", last_ip=%p", (void*)dyn->last_ip);
for (int ii = 0; ii < 24; ++ii) {
switch (dyn->insts[ninst].lsx.lsxcache[ii].t) {
case LSX_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_ST_I64: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii, getCacheName(dyn->insts[ninst].lsx.lsxcache[ii].t, dyn->insts[ninst].lsx.lsxcache[ii].n)); break;
case LSX_CACHE_NONE:
default: break;
}
}
if (dyn->lsx.stack || dyn->insts[ninst].lsx.stack_next || dyn->insts[ninst].lsx.x87stack)
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->lsx.stack, dyn->insts[ninst].lsx.stack_next, dyn->insts[ninst].lsx.stack_push, dyn->insts[ninst].lsx.stack_pop, dyn->insts[ninst].lsx.x87stack);
if (dyn->insts[ninst].lsx.combined1 || dyn->insts[ninst].lsx.combined2)
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].lsx.swapped ? "SWP" : "CMB", dyn->insts[ninst].lsx.combined1, dyn->insts[ninst].lsx.combined2);
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump > 1) ? "\e[m" : "");
}
}
// will go badly if address is unaligned
static uint8_t extract_byte(uint32_t val, void* address)
{
int idx = (((uintptr_t)address)&3)*8;
return (val>>idx)&0xff;
}
static uint32_t insert_byte(uint32_t val, uint8_t b, void* address)
{
int idx = (((uintptr_t)address)&3)*8;
val&=~(0xff<<idx);
val|=(((uint32_t)b)<<idx);
return val;
}
static uint16_t extract_half(uint32_t val, void* address)
{
int idx = (((uintptr_t)address)&3)*8;
return (val>>idx)&0xffff;
}
static uint32_t insert_half(uint32_t val, uint16_t h, void* address)
{
int idx = (((uintptr_t)address)&3)*8;
val&=~(0xffff<<idx);
val|=(((uint32_t)h)<<idx);
return val;
}
uint8_t la64_lock_xchg_b_slow(void* addr, uint8_t val)
{
uint32_t ret;
uint32_t* aligned = (uint32_t*)(((uintptr_t)addr)&~3);
do {
ret = *aligned;
} while(la64_lock_cas_d(aligned, ret, insert_byte(ret, val, addr)));
return extract_byte(ret, addr);
}
int la64_lock_cas_b_slow(void* addr, uint8_t ref, uint8_t val)
{
uint32_t* aligned = (uint32_t*)(((uintptr_t)addr)&~3);
uint32_t tmp = *aligned;
return la64_lock_cas_d(aligned, ref, insert_byte(tmp, val, addr));
}
int la64_lock_cas_h_slow(void* addr, uint16_t ref, uint16_t val)
{
uint32_t* aligned = (uint32_t*)(((uintptr_t)addr)&~3);
uint32_t tmp = *aligned;
return la64_lock_cas_d(aligned, ref, insert_half(tmp, val, addr));
}
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode)
{
dynarec_log(LOG_NONE, "\t%08x\t%s\n", opcode, la64_print(opcode, (uintptr_t)dyn->block));
}
static void sse_reset(lsxcache_t* lsx)
{
for (int i = 0; i < 16; ++i)
lsx->ssecache[i].v = -1;
}
void fpu_reset(dynarec_la64_t* dyn)
{
// TODO: x87 and mmx
sse_reset(&dyn->lsx);
fpu_reset_reg(dyn);
}
void fpu_reset_ninst(dynarec_la64_t* dyn, int ninst)
{
// TODO: x87 and mmx
sse_reset(&dyn->insts[ninst].lsx);
fpu_reset_reg_lsxcache(&dyn->insts[ninst].lsx);
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef __DYNAREC_LA64_FUNCTIONS_H__
#define __DYNAREC_LA64_FUNCTIONS_H__
#include "../dynarec_native_functions.h"
#define SCRATCH0 24
typedef struct x64emu_s x64emu_t;
typedef struct dynarec_la64_s dynarec_la64_t;
// Get an FPU scratch reg
int fpu_get_scratch(dynarec_la64_t* dyn);
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_la64_t* dyn);
// Get an XMM quad reg
int fpu_get_reg_xmm(dynarec_la64_t* dyn, int t, int xmm);
// Free a FPU/MMX/XMM reg
void fpu_free_reg(dynarec_la64_t* dyn, int reg);
// Reset fpu regs counter
void fpu_reset_reg(dynarec_la64_t* dyn);
// FPU Cache transformation (for loops) // Specific, need to be written by backend
int fpuCacheNeedsTransform(dynarec_la64_t* dyn, int ninst);
// Undo the changes of a lsxcache to get the status before the instruction
void lsxcacheUnwind(lsxcache_t* cache);
const char* getCacheName(int t, int n);
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex);
void print_opcode(dynarec_native_t* dyn, int ninst, uint32_t opcode);
// reset the cache
void fpu_reset(dynarec_native_t* dyn);
void fpu_reset_ninst(dynarec_native_t* dyn, int ninst);
#endif //__DYNAREC_LA64_FUNCTIONS_H__
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+13
View File
@@ -0,0 +1,13 @@
#include <stdint.h>
#include "la64_emitter.h"
#define EMIT(A) *block = (A); ++block;
void CreateJmpNext(void* addr, void* next)
{
uint32_t* block = (uint32_t*)addr;
uintptr_t diff = (intptr_t)next - (intptr_t)addr;
PCADDU12I(x2, SPLIT20(diff));
LD_D(x2, x2, SPLIT12(diff));
BR(x2);
}
Loaded 100 of 1287 files, more files were not shown because too many files have changed in this diff. Show more