Compare commits

...
104 Commits
Author SHA1 Message Date
ptitSeb 7eeb501649 Bumped version to v0.4.2 2026-04-20 18:33:09 +02:00
Yang Liu fe6b9327d1 [DYNAREC] Fixed 69 IMUL opcode load immediate (#3795) 2026-04-20 14:33:45 +02:00
ptitSeb d43e64ee46 [WRAPPER] Added a few more symbols to libhoweed6 2026-04-20 12:06:12 +02:00
ptitSeb e477ccdb19 [WRAPPER] Fixed a potential issue with realpath wrapping 2026-04-20 10:11:35 +02:00
ptitSeb d0c1ec5c8c [TRACE] Fixed a potential issue with mkdirat trace 2026-04-20 10:08:52 +02:00
ptitSeb 274946acf5 [WRAPPER] Fixed an OpenGL extension 2026-04-20 09:53:52 +02:00
Yang Liu 3c976b1ffb [LA64_DYNAREC] Fixed amadd_db.b use in lock opcodes (#3793) 2026-04-18 20:57:22 +02:00
Yang Liu 48c1f8fb11 [LA64_DYNAREC] Fixed dec32 non-lbt path SF computation (#3792) 2026-04-18 20:56:43 +02:00
Yang Liu 599360ce07 [DYNAREC] Fixed callret=2 with always_test out-of-bounds read (#3790)
With callret=2 and always_test=1, CALLRET_RET in pass2 skips writing callret entries, thus callret_size=0. But CALLRET_GETRET in pass3 still reads callrets[0], which is an out-of-bounds read. The garbage offset becomes the native return address, causing RET to jump to a wrong
address. I had this issue on LoongArch with 16KiB page size kernel, but this seems universal so all three backends are changed.
2026-04-18 10:55:59 +02:00
Yang Liu b41c3f22be [TEST] Refactored arg parsing and allow to run single combo by number (#3789) 2026-04-18 10:50:41 +02:00
Yang Liu 13cb80d1b7 [LA64_DYNAREC] Fixed BSF/BSR pf computtation (#3788) 2026-04-18 09:26:24 +02:00
Yang Liu a4479a9ac0 [LA64_DYNAREC] Fixed PCMPESTRI opcode (#3787) 2026-04-17 20:28:27 +02:00
Yang Liu 7edd021c17 [LA64_DYNAREC] Fixed LOCK XADD opcode flags computation (#3786)
gd is a full width register, x5 should be used here.
2026-04-17 20:26:47 +02:00
a9ix f6beb4320e [BOX32] Add library path used by Debian "cross" packages (#3785) 2026-04-17 10:12:42 +02:00
ptitSeb 55e8ebf525 [WOWBOX64] Do not clobber return EAX on NT syscall (for #3782) 2026-04-16 09:15:20 +02:00
ptitSeb f388a8f493 [BOX32][WRAPPER] Added a few more wrapped symbols for SDL1 2026-04-13 13:47:01 +02:00
Yang Liu 3e71087a87 [TEST] Optimized combo with dynarec=0 (#3781)
Following config now has 4 combos instead of 6.
```
{
  "BOX64_DYNAREC": ["0", "1"],
  "BOX64_DYNAREC_CALLRET": ["0", "1", "2"]
}
```
2026-04-13 08:18:21 +02:00
Yang Liu 24e4039d1f [TEST][BOX32] Added proper handling for running 32-bit tests on non-Box32 builds (#3780) 2026-04-13 08:12:13 +02:00
ptitSeb fc8a05e693 [RV64_DYNAREC] Added FAR RET(N) with CALLRET support 2026-04-12 17:07:18 +02:00
ptitSeb ee99b5b167 [RV64_DYNAREC] Refactored IRET so it support CALLRET optimisation 2026-04-12 16:20:56 +02:00
ptitSeb 2f23572e02 [RV64_DYNAREC] Refactored RET/RETN opcodes 2026-04-12 15:57:35 +02:00
ptitSeb 21d66686da [RV64_DYNAREC] Added some workaround for gameoverui crashing 2026-04-12 15:39:03 +02:00
ptitSeb 01af6f3164 [RV64_DYNAREC] Added CALL FAR support 2026-04-12 15:33:03 +02:00
ptitSeb c845ab01c4 [RV64_DYNAREC] Added CALLRET=2 and SEP support 2026-04-12 12:23:55 +02:00
ptitSeb 13c9fdaa40 [WRAPPER][VULKAN] Added some more vulkan extensions 2026-04-11 14:03:37 +02:00
ptitSeb 0bc4d5b532 [CI] Hacking a way around termux-docker debloblification 2026-04-11 09:04:26 +02:00
Yang Liu 18a3f1b039 [ARM64_DYNAREC] Fixed LOCK NOT opcode non atomics path (#3777) 2026-04-11 08:39:12 +02:00
Yang Liu b99dde293d [ARM64_DYNAREC] Fixed uninitilized scratch registers for VCVTTPD2DQ opcode (#3776) 2026-04-10 20:07:39 +02:00
ptitSeb ff634b1e0c [RCFILE] Fine tuned 2 games profile 2026-04-10 14:08:08 +02:00
ptitSeb 657d69aa3b [WRAPPER] Added libgmp.so wrapping too (for #3747) 2026-04-09 17:00:28 +02:00
Yang Liu 913abd14f0 [TEST] Support array values in baked-in variables for combinatorial runs (#3774)
Following example will be ran 8 times (4x2) with all possible combinations.
```
%ifdef CONFIG
{
  "RegData": {
    "RAX": "1"
  },
  "Variables": {
    "BOX64_DYNAREC_BIGBLOCK": ["0", "1", "2", "3"],
    "BOX64_DYNAREC_NATIVEFLAGS": ["0", "1"]
  }
}
%endif

mov rax, 1
hlt
```
2026-04-09 14:02:59 +02:00
Yang Liu 1a7ea1c09a [TEST] Supported baking env variables settings into test (#3773)
Example:
```
%ifdef CONFIG
{
  "Variables": { "BOX64_LOG": "0" }
}
%endif

nop
hlt
```
2026-04-09 08:53:30 +02:00
Yang Liu 08934a3b0c [ARM64_DYNAREC] Better fix for #3762 (#3772)
* [ARM64_DYNAREC] Better fix for #3762

* Fixed more similar patterns
2026-04-08 21:24:10 +02:00
ptitSeb 55c967fe9d [RCFILE] Added some more game profiles 2026-04-08 19:14:12 +02:00
ptitSeb dea4646116 [LA64_DYNAREC] Added AutoCRC support 2026-04-08 19:05:02 +02:00
ptitSeb c90a2ab5a4 [ARM64_DYNAREC] Added some potentials fixes for missing AutoCRC on CALLRET return 2026-04-08 18:47:12 +02:00
ptitSeb 06f5fa3e6c [ARM64_DYNAREC] Fixed autoCRC on Secondary Entry Point 2026-04-08 15:04:13 +02:00
ptitSeb 2260cf8a48 [LA64_DYNAREC] Add CALRET=2 and Secondary Entry Points support 2026-04-08 14:20:10 +02:00
ptitSeb 5571c43de6 [RCFILE] Added some more game profiles 2026-04-08 14:19:01 +02:00
ptitSeb 91b32b01d5 [WRAPPER] Added 1 more dbus symbol 2026-04-08 11:05:40 +02:00
Yang Liu 95b4d665cf [INTERP] Fixed BEXTR opcode (#3770) 2026-04-08 10:24:42 +02:00
ptitSeb ac35b41b9d [WRAPPER] Aded 1 more symbol to gmodule (should be wrapped tho) 2026-04-08 09:40:52 +02:00
Yang Liu 2db72f51be [ARM64_DYNAREC] Removed VMASKMOVPS/D ymm zero gate (#3769)
* [ARM64_DYNAREC] Removed VMASKMOVPS/D ymm zero gate

The gate is an optimization to skip upper 128-bit when the mask is known zero. However, after a merge point, `is_avx_zero()` can return false at step 0 and true at step 3. So step 0 sets wrong `ymm0_sub` -> `updateYmm0s()` sets wrong `ymm_in` for successor, and step 3 never corrects that as it's skipped. Fixed this by making the block unconditional so step 0&3 always agree.

* review
2026-04-08 08:57:38 +02:00
ptitSeb 3c266d33e3 [ARM64_DYNAREC] Some minor modifications on callret and SEP handling 2026-04-07 16:30:46 +02:00
ptitSeb feaf6ffbd0 [DYNAREC] Removed DYNAREC_HOTPAGE_ALT and reworked DIRTY=2 ([ARM64_DYNAREC] only) 2026-04-07 13:47:55 +02:00
Yang Liu 91788694ba [ARM64_DYNAREC] Fixed a regression introduced in #3766 (#3768) 2026-04-07 13:24:47 +02:00
Yang Liu 1f921abaec [INTERP] Fixed cvtf32_16 SNaN -> QNaN conversion (#3767) 2026-04-07 13:23:35 +02:00
Yang Liu 0874bb4d01 [DYNAREC] Fixed XADD where source register overlapping memory base (#3766) 2026-04-07 08:10:51 +02:00
Yang Liu 6b32d6159f [ARM64_DYNAREC] Fixed ADC/SBB opcodes CAS retry corrupting CF (#3765)
Similar situation as the interpreter.
2026-04-07 08:08:51 +02:00
Yang Liu 83336bcb9f [INTERP] Fixed ADC/SBB opcodes CAS retry corrupting CF (#3764) 2026-04-07 08:07:23 +02:00
Yang Liu fe556e957e [ARM64_DYNAREC] Fixed a edge case of df tracking for LOCK CMPXCHG16B opcode (#3762)
call_c() was called in unaligned path, which set status_none, where the aligned path don't. Fix this issue by explicitly calling FORCE_DFNONE at the converge point.
2026-04-06 22:46:32 +02:00
Yang Liu cbcd11894c [ARM64_DYNAREC] Fixed cmpxchg modreg ed=rax case (#3761) 2026-04-06 16:09:19 +02:00
Yang Liu 29bf151ed9 [ARM64_DYNAREC] Fixed CMPXCHG8B CASPALw equal case (#3760)
CASPALw always writes back to dest pairs, zeroing the upper 32 bits, replace blind moves with conditional updates.
2026-04-06 16:06:11 +02:00
ptitSeb 95b68190b3 [ARM64_DYNAREC] Fixed some rare case where native flags might be lost on some speicific opcode with partial flags update 2026-04-06 10:43:21 +02:00
ptitSeb c596f176bf [ARM64_DYNAREC] Changed MESSAGE macro for cleaner Dumps 2026-04-06 10:42:20 +02:00
Yang Liu 74fd2a0a5d Fixed sse42_compare_string_explicit_len for length=INT_MIN (#3759)
...prevents length=0x80000000 being overflow.
2026-04-05 21:55:36 +02:00
Yang Liu f20db6caae [ARM64_DYNAREC] Refined SNaN propagation for various opcodes (#3758)
This is a follow-up of PR #3754.
2026-04-05 19:56:23 +02:00
Yang Liu dd75b58943 [ARM64_DYNAREC] Fixed YMM zero tracking for dynablock entry instructions (#3757) 2026-04-05 19:54:38 +02:00
Yang Liu 17a84fcc51 [ARM64_DYNAREC] Fixed ANDN PF computation (again) (#3756) 2026-04-05 19:53:09 +02:00
Yang Liu eef68182b3 [ARM64_DYNAREC] Fixed IOC bit reset for CVTTPS2PI/CVTPS2PI opcodes (#3755)
This is same as #3733.
2026-04-05 18:46:51 +02:00
ptitSeb 43dcbf3773 [DYNAREC] Added a way to use Dynarec for alt address, for MALLOC_HACK=2 for example 2026-04-05 15:07:26 +02:00
Yang Liu b1a706a650 [ARM64_DYNAREC] Fixed nan propagation for ADDPS and similar opcodes (#3754) 2026-04-05 14:02:25 +02:00
Yang Liu ce14608947 [ARM64_DYNAREC] Fixed nan propagation typo for VADDSS/D and other similar opcodes (#3753) 2026-04-05 13:59:57 +02:00
Yang Liu dc53da7252 [ARM64_DYNAREC] Fixed CF computation for 16-bit LOCK ADC/SBB (#3752)
This is essentially a fix ported from corresponding non-LOCK version opcodes
2026-04-05 13:58:38 +02:00
Yang Liu 9e2779267f [INTERP] Fixed cvtf16_32 SNaN handling (#3751)
Refer to https://github.com/ucb-bar/berkeley-softfloat-3/blob/master/source/8086/s_commonNaNToF32UI.c#L48, bit 22 should be forced for NaN inputs
2026-04-05 13:57:23 +02:00
ptitSeb 0416caa95a [VULKAN] Added VK_ARM_shader_instrumentation extension (for #3749) 2026-04-05 09:59:32 +02:00
ptitSeb 7e2528c538 [ARM64_DYNAREC] Added F2 0F BD opcode (for #3717) 2026-04-04 16:09:50 +02:00
ptitSeb 58fb00b5f7 [INTERP] Added F2 0F BD opcode (for #3717) 2026-04-04 16:08:58 +02:00
Yang Liu 1957721f37 [INTERP] Fixed nan propagation edge-cases for various opcodes (#3734)
* [INTERP] Convert SNaN to QNaN in CHECK_NAN macros

* [INTERP] Fixed nan propagation edge-cases for various opcodes
2026-04-04 09:20:47 +02:00
ptitSeb 132d40108b [ARM64_DYNAREC] Small optim for BSF/BSR opcodes 2026-04-03 15:44:06 +02:00
ptitSeb c843a2df6a [ARM64_DYNAREC] Fixed a regression introduced with a613ff8277 2026-04-03 14:47:36 +02:00
Yang Liu 58542e4a72 [LA64_DYNAREC] Fixed LOCK NEG opcode (#3742) 2026-04-03 12:12:48 +02:00
Yang Liu ba20a27530 [LA64_DYNAREC] Fixed BSF/BSR PF computation (#3741) 2026-04-03 11:14:48 +02:00
Yang Liu 4743babdf2 [LA64_DYNAREC] Reworked fastnan handling (#3739) 2026-04-03 10:54:16 +02:00
ptitSeb c0c2780db4 [ARM64_DYNAREC] Added some F2/F3 faked prefix opcodes (for #3717) 2026-04-03 10:11:58 +02:00
ptitSeb 97edb1092f [INTERP] Added more F2/F3 faked prefix opcodes (for #3717) 2026-04-03 10:06:30 +02:00
Yang Liu 3697d82ad1 [INTERP][DYNAREC] Reworked PF computaion for ANDN opcode (#3740) 2026-04-03 10:00:36 +02:00
Yang Liu df00419f69 [INTERP] Fixed BZHI opcode (#3738) 2026-04-03 08:57:22 +02:00
ptitSeb 11bb70178b [ARM64_DYNAREC] Added native flags support to float/double comparisons opcodes 2026-04-02 19:14:48 +02:00
ptitSeb 5e03e18c68 [ARM64_DYNAREC] Fixed a regression introduced with #3732 2026-04-02 17:09:47 +02:00
Yang Liu a696462cc3 [LA64_DYNAREC] Fixed Gx equals Ex case for VCVTPD2DQ (#3737) 2026-04-02 12:27:04 +02:00
Yang Liu cda0c94b83 [LA64_DYNAREC] Fixed CF tracing for ADC/SBB opcodes (#3736) 2026-04-02 10:40:40 +02:00
Yang Liu 9a1fcc84b0 [INTERP] Fixed a regression introduced in #3719 (#3735) 2026-04-02 09:44:43 +02:00
Yang Liu 9571135b8d [ARM64_DYNAREC] Fixed IOC bit reset for CVTTPD2PI/CVTPD2PI opcodes (#3733) 2026-04-01 18:29:46 +02:00
Yang Liu 95bd956af8 [ARM64_DYNAREC] Fixed BSF/BSR PF computation (#3732) 2026-04-01 17:35:22 +02:00
Yang Liu 6ebd9c3b32 [INTERP] Fixed cvtf32_16 again (#3731) 2026-04-01 10:08:31 +02:00
ptitSeb 0b9df5d5a0 [BOX32] Fixed BOUND exception signal 2026-03-31 14:47:46 +02:00
ptitSeb c52f2fd01a [WRAPPER] Added many symbols to liblcms2 2026-03-30 20:41:15 +02:00
ptitSeb 0a60b449ca [WRAPPER] Added some more symbol to libcrypto3 2026-03-30 20:32:45 +02:00
ptitSeb b3056386f2 [WRAPPER] Added 1 more function to libmpg123 2026-03-30 20:19:28 +02:00
ptitSeb 63feea5fc4 [WRAPPER] Added more symbols to libmpg123 2026-03-30 20:13:51 +02:00
ptitSeb f4f17b7751 [WRAPPER] Added some symbols to libnettle8 2026-03-30 20:08:23 +02:00
ptitSeb 7750e75bcf [WRAPPER] Added 1 more symbol to libvpx 2026-03-30 20:00:48 +02:00
ptitSeb d0d32e763d [WRAPPER] Added 1 more symbol to libpango 2026-03-30 19:50:00 +02:00
ptitSeb e68b1f7584 [WRAPPER] Added 2 more symbols to libcairo 2026-03-30 19:48:19 +02:00
ptitSeb beaa2c8a3a [WRAPPER] Added 1 more symbol to libgio-2 2026-03-30 19:45:06 +02:00
ptitSeb c48c60a814 [WRAPPER] Added 1 symbol to libgobject-2 2026-03-30 19:40:36 +02:00
ptitSeb 7688169969 [WRAPPER] Added some symbol to libpango 2026-03-30 19:35:40 +02:00
ptitSeb aebde89ba3 [WRAPPER] Added more symbols to libgcrypt 2026-03-30 19:20:23 +02:00
ptitSeb 7f96fa4334 [WRAPPER] Added more symbol to libva 2026-03-30 19:16:18 +02:00
ptitSeb 3206d6a76a [RV64_DYNAREC] This should fix the build 2026-03-30 18:43:24 +02:00
ptitSeb a613ff8277 [ARM64_DYNAREC] Reworked how df_unneeded is propagated 2026-03-30 18:13:05 +02:00
ptitSeb 489bd8de29 [ARM64_DYNAREC] Fixed a regression introduced with 537c8f4c53 2026-03-30 13:58:52 +02:00
ptitSeb d5a1864cfa [ARM64_DYNAREC] ymm0 is an ymm operation... 2026-03-29 18:32:55 +02:00
145 changed files with 4378 additions and 1790 deletions

No files matched your search

+3
View File
@@ -183,6 +183,9 @@ jobs:
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
cd termux-docker
git checkout 148b93d989cbc572719e050135b3e13f115f2a8e~1
cd ..
sudo cp -rf termux-docker/system/arm /system
sudo chown -R $(whoami):$(whoami) /system
sudo chmod 755 -R /system
+10
View File
@@ -1,3 +1,13 @@
box64 (0.4.2) unstable; urgency=low
This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning.
=> Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work.
=> Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility.
=> Support for SteamRT3 & new Proton 11
=> New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited.
-- Sebastien Chevalier <[email protected]> Mon, 20 Apr 2026 10:30:33 -0100
box64 (0.4.0) unstable; urgency=low
This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster.
+47
View File
@@ -1,3 +1,50 @@
v0.4.2
======
Highlights:
* This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning!
=> Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work.
=> Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility.
=> Support for SteamRT3 & new Proton 11
=> New PCC64LE in the work. Not finished, but usable already. Note that the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm.
Version summary:
* New RISC-V support for the script to denerate Debian .deb package
* Improved the way system informations (like cpu brand and number of cores) is gathered and cpuid opcode handled
* Improved support for Steam and new SteamRT3 64bit version
* Elf: Improved handling of large pagesize (usefull for PPC64LE with its 64k pagesize)
* Elf: Improved support for AppImage
* Wrapping: Vulkan: Added support wor x64 overlay
* Wrapping; Vulkan: Added BOX64_NOVULKANOVERLAY to disable x64 overlay handling
* Wrapping: more wrapped functions, reworked some existing one with wrapperhelper
* Wrapping: Added more wrapped libs
* Wrapping: BOX32: more wrapped function and some fixes to existing ones
* Wrapping: PPC64: Better handling of ioctl
* Interpreter: Added a few more exotic opcodes
* Dynarec: Added support for STRONGMEM=4
* Dynarec: Improved TF flag handling
* Dynarec: Reworked HotPage detection and handling
* Dynarec: Reworked dynarec generation to batter handle abort mid-block
* Dynarec: Rework how "Alt" addresses are handled
* Dynarec: Removed BOX64_DYNAREC_HOTPAGE_ALT
* Dynarec: Added support for Secondary Entry Point on dynablock when using CALLRET=1
* Dynarec: Improve CALL FAR / RET FAR opcodes handling, adding CALLRET optimisation support
* Dynarec: Improve IRET opcodes handling, adding CALLRET optimisation support
* Dynarec: ARM64: Some new fixes for existing opcodes
* Dynarec: ARM64: Reworked XMM/YMM register handling
* Dynarec: ARM64: Reworked DIRTY=2 with AutoCRC Dynablock
* Dynarec: LA64: Lots of new opcodes added & fixes
* Dynarec: LA64: Added full support for SAFEFLAGS=2
* Dynarec: LA64: Lots of fixes & improvements for FASTNAN=0
* Dynarec: LA64: Refactor opcode printer
* Dynarec: LA64: Reworked DIRTY=2 with AutoCRC Dynablock
* Dynarec: LA64: Added CALLRET=2 support
* Dynarec: RV64: A few fixes to existing opcodes
* Dynarec: RV64: Added CALLRET=2 support
* Dynarec: PPC64: Created a new backend for PPC64LE, with some opcodes already (still WIP)
* WOWBOX64: Some small fixes
v0.4.0
======
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 4
#define BOX64_REVISION 1
#define BOX64_REVISION 2
#endif //__BOX64_VERSION_H_
+10 -1
View File
@@ -497,6 +497,8 @@ void LoadLDPath(box64context_t *context)
AddPath("/usr/lib/i386-linux-gnu", &context->box64_ld_lib, 1);
if(FileExist("/usr/i386-linux-gnu/lib", 0))
AddPath("/usr/i386-linux-gnu/lib", &context->box64_ld_lib, 1);
if(FileExist("/usr/i686-linux-gnu/lib", 0))
AddPath("/usr/i686-linux-gnu/lib", &context->box64_ld_lib, 1);
if(FileExist("/usr/lib/box64-i386-linux-gnu", 0))
AddPath("/usr/lib/box64-i386-linux-gnu", &context->box64_ld_lib, 1);
if(FileExist("/opt/box64/lib32", 0))
@@ -796,7 +798,14 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
exit(0);
}
if (argc >= 3 && (!strcmp(argv[1], "--test") || !strcmp(argv[1], "-t"))) {
int is_test = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--test") || !strcmp(argv[i], "-t")) {
is_test = 1;
break;
}
}
if (is_test) {
box64_unittest_mode = 1;
exit(unittest(argc, argv));
}
+49 -102
View File
@@ -1850,7 +1850,7 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
int cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
{
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?((destroy==2)?"invalidCRC":"destroy"):"mark");
dynablock_t* db = NULL;
uintptr_t end = addr+size;
int ret = 0;
@@ -1858,10 +1858,12 @@ int cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
start_addr = getDBSize(start_addr, end-start_addr, &db);
if(db) {
ret = 1;
if(destroy)
FreeRangeDynablock(db, addr, size);
else
MarkRangeDynablock(db, addr, size);
switch(destroy) {
case 0: MarkRangeDynablock(db, addr, size); break;
case 1: FreeRangeDynablock(db, addr, size); break;
case 2: MarkCRCRangeDynablock(db, addr, size); break;
}
}
}
return ret;
@@ -2390,11 +2392,11 @@ void neverprotectDB(uintptr_t addr, size_t size, int mark)
if(prot&PROT_DYNAREC) {
prot&=~PROT_DYN;
if(mark)
cleanDBFromAddressRange(cur, bend-cur, 0);
cleanDBFromAddressRange(cur, bend-cur, (mark==2)?2:0);
mprotect((void*)cur, bend-cur, prot);
} else if(prot&PROT_DYNAREC_R) {
if(mark)
cleanDBFromAddressRange(cur, bend-cur, 0);
cleanDBFromAddressRange(cur, bend-cur, (mark==2)?2:0);
prot &= ~PROT_DYN;
}
prot |= PROT_NEVERCLEAN;
@@ -2467,18 +2469,22 @@ typedef union hotpage_s {
} hotpage_t;
#define HOTPAGE_MAX ((1<<28)-1)
#define N_HOTPAGE 32
#define N_HOTPAGE_ALT 8
#define HOTPAGE_MARK 64
#define HOTPAGE_DIRTY 128
#define HOTPAGE_DIRTY_ALT 1024
#define HOTPAGE_DIRTY2 16
static hotpage_t hotpage[N_HOTPAGE] = {0};
void SetHotPage(int idx, uintptr_t page)
{
hotpage_t tmp = hotpage[idx];
tmp.addr = page;
tmp.cnt = BOX64ENV(dynarec_dirty)?(BOX64ENV(dynarec_hotpage_alt)?HOTPAGE_DIRTY_ALT:HOTPAGE_DIRTY):HOTPAGE_MARK;
tmp.cnt = 0;
switch(BOX64ENV(dynarec_dirty)) {
case 0: tmp.cnt = HOTPAGE_MARK; break;
case 1: tmp.cnt = HOTPAGE_DIRTY; break;
case 2: tmp.cnt = HOTPAGE_DIRTY2; break;
}
//TODO: use Atomics to update hotpage?
native_lock_store_dd(hotpage+idx, tmp.x);
native_lock_store_dd(&hotpage[idx], tmp.x);
}
int IdxHotPage(uintptr_t page)
{
@@ -2487,36 +2493,14 @@ int IdxHotPage(uintptr_t page)
return i;
return -1;
}
void CancelHotPage(uintptr_t page)
{
unneverprotectDB(page<<12, box64_pagesize);
}
int IdxOldestHotPage(uintptr_t page)
{
int best_idx = -1;
uint32_t best_cnt = HOTPAGE_MAX+1;
if(BOX64ENV(dynarec_hotpage_alt)) {
hotpage_t tmp;
tmp.addr = page;
tmp.cnt = HOTPAGE_MAX;
for(int i=0; i<N_HOTPAGE_ALT; ++i) {
if(!hotpage[i].cnt) {
native_lock_store_dd(hotpage+i, tmp.x);
return i;
}
uint32_t cnt = hotpage[i].cnt;
if(cnt==HOTPAGE_MAX) cnt = 0;
if(cnt < best_cnt) {
best_idx = i;
best_cnt = cnt;
}
}
hotpage_t old = hotpage[best_idx];
native_lock_store_dd(hotpage+best_idx, tmp.x);
if(old.cnt && old.cnt!=HOTPAGE_MAX && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(old.addr);
} else {
for(int i=0; i<N_HOTPAGE && best_cnt; ++i) {
for(int i=0; i<N_HOTPAGE; ++i) {
if(!hotpage[i].x) {
return i;
} else {
uint32_t cnt = hotpage[i].cnt;
if(cnt < best_cnt) {
best_idx = i;
@@ -2524,6 +2508,7 @@ int IdxOldestHotPage(uintptr_t page)
}
}
}
dynarec_log(LOG_INFO, "%04d|No more live Hotpage slot for %p, recycling idx=%d (%p)\n", GetTID(), (void*)(page<<12), best_idx, (void*)(uintptr_t)(hotpage[best_idx].addr<<12));
return best_idx;
}
// this function will create a new HotPage, or re-arm it if it's already registered
@@ -2536,42 +2521,20 @@ void CheckHotPage(uintptr_t addr, uint32_t prot)
if(BOX64ENV(dynarec_nohotpage))
return;
uintptr_t page = addr>>12;
if(!BOX64ENV(dynarec_hotpage_alt)) {
if(!(prot&PROT_EXEC))
return; // needs to be an executable page
/*if(BOX64ENV(dynarec_dirty)>1) {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p, marking page as NEVERCLEAN\n", (void*)(page<<12));
neverprotectDB(page<<12, box64_pagesize, 1);
return;
}*/
}
// look for idx
int idx = IdxHotPage(page);
if(BOX64ENV(dynarec_hotpage_alt)) {
if(idx==-1) { IdxOldestHotPage(page); return; }
hotpage_t hp = hotpage[idx];
/*if(hp.cnt==HOTPAGE_MAX)*/ {
if(BOX64ENV(dynarec_dirty)>1) {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d), marking page as NEVERCLEAN\n", (void*)(page<<12), idx);
neverprotectDB(page<<12, box64_pagesize, 1);
hp.cnt = 0;
native_lock_store_dd(hotpage+idx, hp.x); // free slot
} else {
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
SetHotPage(idx, page);
}
}
} else {
if(idx!=-1 && BOX64ENV(dynarec_dirty)>1 && !hotpage[idx].cnt) {
// Re-arming, so put the page as NEVERCLEAN and stop bothering
neverprotectDB(page<<12, box64_pagesize, 1);
return;
}
if(idx==-1) idx = IdxOldestHotPage(page);
if(idx==-1) return;
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
SetHotPage(idx, page);
if(idx!=-1 && (BOX64ENV(dynarec_dirty)>1)) {
// Re-arming, so put the page as NEVERCLEAN and stop bothering
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d) again, switching the page to NEVERCLEAN\n", (void*)(page<<12), idx);
neverprotectDB(page<<12, box64_pagesize, 2);
hotpage_t hp = {0};
native_lock_store_dd(hotpage+idx, hp.x); // free slot
return;
}
if(idx==-1) idx = IdxOldestHotPage(page);
if(idx==-1) return;
dynarec_log(LOG_INFO, "%04d|Detecting a Hotpage at %p (idx=%d)\n", GetTID(), (void*)(page<<12), idx);
SetHotPage(idx, page);
}
int isInHotPage(uintptr_t addr)
{
@@ -2580,45 +2543,29 @@ int isInHotPage(uintptr_t addr)
return 0;
uintptr_t page = addr>>12;
int idx = IdxHotPage(page);
if(BOX64ENV(dynarec_hotpage_alt)) {
if(idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))
return 0;
//TODO: do Atomic stuffs instead
hotpage_t hp = hotpage[idx];
--hp.cnt;
native_lock_store_dd(hotpage+idx, hp.x);
if(!hp.cnt && BOX64ENV(dynarec_dirty)==1)
CancelHotPage(hp.addr);
return 1;
} else {
int ret = ((idx==-1) || !hotpage[idx].cnt)?0:1;
// decrement all hotpage, it's a hotpage "tick"
for(int i=0; i<N_HOTPAGE; ++i) {
int ok = 0;
do {
hotpage_t hp = hotpage[i];
hotpage_t old = hp;
if(!hp.cnt || (hp.cnt==HOTPAGE_MAX)) {
ok = 1;
} else {
--hp.cnt;
ok = native_lock_storeifref2(hotpage+i, (void*)hp.x, (void*)old.x)==(void*)old.x;
}
} while(!ok);
}
return ret;
int ret = ((idx==-1) || !hotpage[idx].cnt)?0:1;
// decrement all hotpage, it's a hotpage "tick"
for(int i=0; i<N_HOTPAGE; ++i) {
int ok = 0;
do {
hotpage_t hp = hotpage[i];
hotpage_t old = hp;
if(!hp.cnt || (hp.cnt==HOTPAGE_MAX)) {
ok = 1;
} else {
--hp.cnt;
ok = native_lock_storeifref2(hotpage+i, (void*)hp.x, (void*)old.x)==(void*)old.x;
}
} while(!ok);
}
return ret;
}
int checkInHotPage(uintptr_t addr)
{
if(addr>0x1000000000000LL) return 0;
uintptr_t page = addr>>12;
int idx = IdxHotPage(page);
if(BOX64ENV(dynarec_hotpage_alt)) {
return (idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))?0:1;
} else {
return ((idx==-1) || !hotpage[idx].cnt)?0:1;
}
return ((idx==-1) || !hotpage[idx].cnt)?0:1;
}
+5
View File
@@ -1221,6 +1221,11 @@ int convert_bitmask(uint64_t bitmask);
#define FCMPS_0(Sn) FEMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
#define FCMPD_0(Dn) FEMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
// CCMP . CMP if cond is pass, else use nzcv as new flags
#define FCCMP_scalar(type, Rm, cond, Rn, op, nzcv) (0b00011110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | ((cond)<<12 | 0b01<<10 | (Rn)<<5 | (op)<<4 | (nzcv)))
#define FCCMPS(Sn, Sm, nzcv, cond) FEMIT(FCCMP_scalar(0b00, Sm, cond, Sn, 0, nzcv))
#define FCCMPD(Dn, Dm, nzcv, cond) FEMIT(FCCMP_scalar(0b01, Dm, cond, Dn, 0, nzcv))
// 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))
// Floating-point Convert to Signed integer, rounding to nearest with ties to Away
+35
View File
@@ -5,8 +5,10 @@
.align 4
.extern LinkNext
.extern LinkNextInvalid
.global arm64_next
.global arm64_next_invalid
.8byte 0 // NULL pointer before arm64_next, for getDB
arm64_next:
@@ -41,3 +43,36 @@ arm64_next:
// return offset is jump address
br x3
arm64_next_invalid:
// emu is r0
// IP address is r1
sub sp, sp, (8 * 12)
stp x0, x1, [sp, (8 * 0)]
stp x10, x11, [sp, (8 * 2)]
stp x12, x13, [sp, (8 * 4)]
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
#ifdef _WIN32
ldr x18, [x0, 3104]
#endif
mov x1, x27 // xRIP, should not be needed most of the time
mov x2, x30 // "from" is in lr, so put in x2
add x3, sp, 8*11 // x3 is address to change rip
// call the function
bl LinkNextInvalid
// preserve return value
mov x3, x0
// pop regs
ldp x0, x1, [sp, (8 * 0)]
ldp x10, x11, [sp, (8 * 2)]
ldp x12, x13, [sp, (8 * 4)]
ldp x14, x15, [sp, (8 * 6)]
ldp x16, x17, [sp, (8 * 8)]
ldp x18, x27, [sp, (8 * 10)]
add sp, sp, (8 * 12)
// return offset is jump address
br x3
+10 -8
View File
@@ -2936,6 +2936,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
LDRx_REG(x3, x1, x2);
//LDRx_U12(x3, x1, offsetof(box64context_t, signals[X64_SIGTRAP]));
CMPSx_U12(x3, 0);
// commit df before branch, CALL_S in int3 path has FORCE_DFNONE
CHECK_DFNONE(0);
B_MARK(cEQ);
GETIP(addr); // update RIP
STORE_XEMU_CALL(xRIP);
@@ -3823,17 +3825,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1)
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
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 {
if(BOX64DRENV(dynarec_callret)>1)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
@@ -4534,7 +4533,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1)
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
@@ -4589,14 +4588,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// Push actual return address. Note that CS will not be tested, but that should be ok?
if(can_continue) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1)
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
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 {
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
ADR_S20(x4, j64);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
+57 -21
View File
@@ -35,7 +35,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1;
int v0, v1, v2;
int q0, q1;
int d0, d1;
int s0;
@@ -504,12 +504,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSS(q0, q0);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn, ninst);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if (i) {
VMOVeS(d0, 0, v1, i);
FRINTZS(d0, d0);
@@ -542,12 +541,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VFCVTZSS(q0, q0);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn, ninst);
for (int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
if (i) {
VMOVeS(d0, 0, v1, i);
FRINTIS(d0, d0);
@@ -572,10 +570,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
IFX(X_CF|X_PF|X_ZF) {
FCMPS(v0, s0);
}
FCOMI(x1, x2);
FCOMIS(x1, x2, v0, s0);
break;
case 0x30:
INST_NAME("WRMSR");
@@ -1224,6 +1219,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1234,6 +1231,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x59:
@@ -1244,6 +1245,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1254,6 +1257,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5A:
@@ -1278,6 +1285,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1288,6 +1297,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5D:
@@ -1309,6 +1322,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQS(v0, q0, q1); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1319,6 +1334,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5F:
@@ -2152,9 +2171,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CMPSxw_REG(xRAX, ed);
}
MOVxw_REG(x1, ed); // save value
Bcond(cNE, 4 + (rex.w ? 4 : 8));
Bcond(cNE, 4 + 8);
MOVxw_REG(ed, gd);
if (!rex.w) { B_NEXT_nocond; }
B_NEXT_nocond;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
LDxw(x1, wback, fixedaddress);
@@ -2408,10 +2427,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETED(0);
GETGD;
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_PF)
MOV32w(x3, 0); // PF uses 0 when the source is zero
}
TSTxw_REG(ed, ed);
B_MARK(cEQ);
RBITxw(x1, ed); // reverse
CLZxw(gd, x1); // x2 gets leading 0 == BSF
RBITxw(gd, ed); // reverse
CLZxw(gd, gd); // gd gets leading 0 == BSF
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_PF)
MOVxw_REG(x3, gd);
}
MARK;
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
@@ -2424,7 +2451,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
IFX(X_OF) BFCw(xFlags, F_OF, 1);
IFX(X_PF) emit_pf(dyn, ninst, gd, x2);
IFX(X_PF) emit_pf(dyn, ninst, x3, x2);
}
break;
case 0xBD:
@@ -2438,11 +2465,19 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
nextop = F8;
GETED(0);
GETGD;
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_PF)
MOV32w(x3, 0); // PF uses 0 when the source is zero
}
TSTxw_REG(ed, ed);
B_MARK(cEQ);
CLZxw(gd, ed); // x2 gets leading 0
CLZxw(gd, ed); // gd gets leading 0
SUBxw_U12(gd, gd, rex.w?63:31);
NEGxw_REG(gd, gd); // complement
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
IFX(X_PF)
MOVxw_REG(x3, gd);
}
MARK;
IFX(X_ZF) {
IFNATIVE(NF_EQ) {} else {
@@ -2455,7 +2490,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_SF) BFCw(xFlags, F_SF, 1);
IFX(X_OF) BFCw(xFlags, F_OF, 1);
IFX(X_PF) emit_pf(dyn, ninst, gd, x2);
IFX(X_PF) emit_pf(dyn, ninst, x3, x2);
}
break;
case 0xBE:
@@ -2492,7 +2527,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC0:
INST_NAME("XADD Gb, Eb");
INST_NAME("XADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x1);
@@ -2503,16 +2538,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
EBBACK; // eb gets x1 (sum)
break;
case 0xC1:
INST_NAME("XADD Gd, Ed");
INST_NAME("XADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
GETED(0);
MOVxw_REG(x3, ed);
MOVxw_REG(ed, gd);
MOVxw_REG(gd, x3);
if (ed != gd) MOVx_REG(x3, ed);
emit_add32(dyn, ninst, rex, ed, gd, x4, x5);
WBACK;
if (ed != gd) MOVxw_REG(gd, x3);
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
@@ -2679,6 +2713,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
if(rex.w && BOX64DRENV(dynarec_safeflags)>1) {
// unaligned memory cause a GPF
// commit df before branch, CALL_S in GPF path has FORCE_DFNONE
CHECK_DFNONE(0);
TSTx_mask(wback, 1, 0, 3);
B_MARK2(cEQ); // alligned, continue...
STORE_XEMU_CALL(xRIP);
+4
View File
@@ -1612,6 +1612,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
UXTHw(x2, xRAX);
BFIw(x2, xRDX, 16, 16);
if(BOX64ENV(dynarec_div0)) {
// commit df before branch, CALL_S in div0 path has FORCE_DFNONE
CHECK_DFNONE(0);
CBNZw_MARK3(ed);
MARK2;
GETIP_(ip);
@@ -1651,6 +1653,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
GETSEW(x1, 0);
if(BOX64ENV(dynarec_div0)) {
// commit df before branch, CALL_S in div0 path has FORCE_DFNONE
CHECK_DFNONE(0);
CBNZw_MARK3(ed);
MARK2;
GETIP_(ip);
+81 -21
View File
@@ -32,7 +32,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
int64_t j64;
uint64_t tmp64u, tmp64u2;
int mask;
int v0, v1;
int v0, v1, v2;
int q0, q1;
int d0, d1;
int64_t fixedaddress;
@@ -240,12 +240,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SQXTN_32(q0, q0);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn, ninst);
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);
FRINTZD(d0, d0);
@@ -280,12 +279,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SQXTN_32(q0, q0);
} else {
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
ORRw_mask(x2, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn, ninst);
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);
@@ -310,10 +308,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGX(v0, 0);
GETEXSD(q0, 0, 0);
IFX(X_CF|X_PF|X_ZF) {
FCMPD(v0, q0);
}
FCOMI(x1, x2);
FCOMID(x1, x2, v0, q0);
break;
case 0x38: // SSSE3 opcodes
@@ -1728,6 +1723,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQD(v0, q0, q1); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1738,6 +1735,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VDUPQD(v1, x5); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x59:
@@ -1748,6 +1750,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQD(v0, q0, q1); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1758,6 +1762,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VDUPQD(v1, x5); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5A:
@@ -1820,6 +1829,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQD(v0, q0, q1); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1830,6 +1841,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VDUPQD(v1, x5); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5D:
@@ -1851,6 +1867,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q1); // save original src1 (Gx)
// check if any input value was NAN
VFMAXQD(v0, q0, q1); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -1861,6 +1879,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VDUPQD(v1, x5); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
}
break;
case 0x5F:
@@ -2324,13 +2347,23 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXPQD(v0, q1, q0); // propagate NAN
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
VUZP1Q_64(d1, q1, q0); // d1 = {q1[0], q0[0]}
VFCMEQQD(v0, q1, q1); // per-element non-NaN for Gx
VFCMEQQD(d0, q0, q0); // per-element non-NaN for Ex
VUZP1Q_64(v1, v0, d0); // first element of each pair
VUZP2Q_64(v0, v0, d0); // second element of each pair
VANDQ(v0, v1, v0); // both non-NaN per pair
}
VFADDPQD(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(v1, d1, d1); // v1 = src1 non-NaN mask
VDUPQD(d0, x5); // d0 = QNaN bit for double
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
VBIFQ(q1, d0, v1); // where src1 NaN: replace with QNaN(src1)
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
@@ -2342,18 +2375,26 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q1, 0, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch(dyn, ninst);
VUZP1Q_64(v0, q0, q1);
VUZP2Q_64(q0, q0, q1);
VUZP1Q_64(v0, q0, q1); // v0 = src1 (first of each pair)
VUZP2Q_64(q0, q0, q1); // q0 = src2 (second of each pair)
if(!BOX64ENV(dynarec_fastnan)) {
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQD(v1, v0, q0); // propagate NAN
VFCMEQQD(v1, v1, v1); // 0 if NAN, 1 if not NAN
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
VMOVQ(d1, v0); // save src1
VFCMEQQD(v1, v0, v0); // even elements non-NaN
VFCMEQQD(d0, q0, q0); // odd elements non-NaN
VANDQ(v1, v1, d0); // v1 = both non-NaN per pair
}
VFSUBQD(q0, v0, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(v0, q0, q0); // 0 => out is NAN
VBICQ(v1, v1, v0); // forget it in any input was a NAN alreavy
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(d0, d1, d1); // d0 = src1 non-NaN mask
VDUPQD(v0, x5); // v0 = QNaN bit for double
VORRQ(v0, d1, v0); // v0 = QNaN(src1)
VBIFQ(q0, v0, d0); // where src1 NaN: replace with QNaN(src1)
VFCMEQQD(v0, q0, q0); // 0 => out is NAN
VBICQ(v1, v1, v0); // forget it in any input was a NAN already
VSHLQ_64(v1, v1, 63); // only keep the sign bit
VORRQ(q0, q0, v1); // NAN -> -NAN
}
@@ -2877,7 +2918,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xC1:
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
INST_NAME("XADD Gw, Ew");
INST_NAME("XADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
@@ -2989,9 +3030,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(q0, 1);
GETEX(q1, 0, 0);
v0 = fpu_get_scratch(dyn, ninst);
if (!BOX64ENV(dynarec_fastnan)) {
v1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, q0); // save src1
VFCMEQQD(v0, q0, q0);
VFCMEQQD(v1, q1, q1);
VANDQ(v1, v0, v1); // v1 = both non-NaN
}
VFSUBQD(v0, q0, q1);
VFADDQD(q0, q0, q1);
VMOVeD(q0, 0, v0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(v0, q0, q0); // 0 where result is NaN
VBICQ(v0, v1, v0); // both non-NaN but result NaN
VSHLQ_64(v0, v0, 63); // sign bit only
VORRQ(q0, q0, v0); // force -NaN
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
VDUPQD(v1, x5); // QNaN bit
VORRQ(v2, v2, v1); // quiet any SNaN
VBIFQ(q0, v2, v0); // where src1 NaN: use QNaN(src1)
}
break;
case 0xD1:
INST_NAME("PSRLW Gx, Ex");
+17 -2
View File
@@ -210,11 +210,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGW(x5);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
@@ -355,12 +360,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOV32w(x5, (uint16_t)i16);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 3: //SBB
@@ -375,12 +385,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
SETFLAGS(X_ALL, SF_SET_PENDING);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
MOV32w(x5, (uint16_t)i16);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 4: //AND
+5
View File
@@ -30,6 +30,7 @@ typedef struct arch_flags_s
uint8_t vf:1;
uint8_t cf:1;
uint8_t inv_cf:1;
uint8_t pf_v:1;
} arch_flags_t;
#define X87_ST_D 0
@@ -96,6 +97,7 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa
arch->flags_.cf = flags&NF_CF;
if(arch->flags_.cf)
arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry;
arch->flags_.pf_v = flags&NF_PF_V;
}
// opcode can handle unaligned
arch->unaligned = dyn->insts[ninst].unaligned;
@@ -322,6 +324,9 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc)
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_C), F_CF);
}
}
if(flags->pf_v) {
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_V), F_PF);
}
}
struct fpsimd_context *fpsimd = NULL;
// find fpsimd struct
+41 -20
View File
@@ -289,10 +289,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGX(v0, 0);
GETEXSS(s0, 0, 0);
IFX(X_CF|X_PF|X_ZF) {
FCMPS(v0, s0);
}
FCOMI(x1, x2);
FCOMIS(x1, x2, v0, s0);
break;
case 0x50:
@@ -458,20 +455,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFADDQS(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
@@ -482,20 +485,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFMULQS(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
@@ -531,20 +540,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFSUBQS(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
@@ -569,20 +584,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFDIVQS(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
+7 -1
View File
@@ -96,7 +96,13 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
}
// UD flags
IFX(X_AF) BFCw(xFlags, F_AF, 1);
IFX(X_PF) BFCw(xFlags, F_PF, 1);
if (BOX64DRENV(dynarec_safeflags)) {
if (BOX64ENV(cputype)) {
IFX (X_PF) BFCw(xFlags, F_PF, 1);
} else {
IFX (X_PF) emit_pf(dyn, ninst, gd, x3);
}
}
break;
case 0xF3:
nextop = F8;
+100 -38
View File
@@ -268,10 +268,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETGX(v0, 0);
GETEXSD(q0, 0, 0);
IFX(X_CF|X_PF|X_ZF) {
FCMPD(v0, q0);
}
FCOMI(x1, x2);
FCOMID(x1, x2, v0, q0);
break;
case 0x50:
@@ -362,23 +359,30 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFADDQD(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
VDUPQD(q1, x5); // QNaN bit
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
if (!vex.l) YMM0(gd);
break;
case 0x59:
INST_NAME("VMULPD Gx, Vx, Ex");
@@ -386,10 +390,12 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
@@ -400,6 +406,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VDUPQD(q1, x5); // QNaN bit
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd)
@@ -474,20 +485,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQD(q0, v1, v2); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFSUBQD(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
VDUPQD(q1, x5); // QNaN bit
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd);
@@ -512,20 +530,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
// check if any input value was NAN
VFMAXQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
}
VFDIVQD(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
VDUPQD(q1, x5); // QNaN bit
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
}
}
if(!vex.l) YMM0(gd);
@@ -1161,20 +1186,30 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXPQD(q0, v2, v1); // propagate NAN
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
VUZP1Q_64(d1, v2, v1); // d1 = src1 (even elements)
VFCMEQQD(q0, v2, v2); // per-element non-NaN for Vx
VFCMEQQD(d0, v1, v1); // per-element non-NaN for Ex
VUZP1Q_64(q1, q0, d0); // first element of each pair
VUZP2Q_64(q0, q0, d0); // second element of each pair
VANDQ(q0, q1, q0); // both non-NaN per pair
}
VFADDPQD(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(q1, d1, d1); // q1 = src1 non-NaN mask
VDUPQD(d0, x5); // d0 = QNaN bit for double
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
VBIFQ(v0, d0, q1); // where src1 NaN: replace with QNaN(src1)
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd);
@@ -1183,24 +1218,32 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VHSUBPD Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
if(!BOX64ENV(dynarec_fastnan))
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
VUZP1Q_64(q0, v2, v1);
VUZP2Q_64(v0, v2, v1);
VUZP1Q_64(q0, v2, v1); // q0 = src1 (first of each pair)
VUZP2Q_64(v0, v2, v1); // v0 = src2 (second of each pair)
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
// but need to mix low/high part
VFMAXQD(q1, v0, q0); // propagate NAN
VFCMEQQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
VMOVQ(d1, q0); // save src1
VFCMEQQD(q1, q0, q0); // even elements non-NaN
VFCMEQQD(d0, v0, v0); // odd elements non-NaN
VANDQ(q1, q1, d0); // both non-NaN per pair
}
VFSUBQD(v0, q0, v0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQD(q0, v0, v0); // 0 => out is NAN
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(d0, d1, d1); // d0 = src1 non-NaN mask
VDUPQD(q0, x5); // q0 = QNaN bit for double
VORRQ(q0, d1, q0); // q0 = QNaN(src1)
VBIFQ(v0, q0, d0); // where src1 NaN: replace with QNaN(src1)
VFCMEQQD(q0, v0, v0); // 0 => out is NAN
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
VSHLQ_64(q1, q1, 63); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd);
@@ -1349,11 +1392,32 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VADDSUBPD Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if (!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
VFCMEQQD(q0, v2, v2);
VFCMEQQD(q1, v1, v1);
VANDQ(q1, q0, q1); // q1 = both non-NaN
}
FSUBD(q0, v2, v1);
VFADDQD(v0, v2, v1);
VMOVeD(v0, 0, q0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
MOV64x(x5, 0x0008000000000000ULL);
VFCMEQQD(q0, v0, v0); // 0 where result is NaN
VBICQ(q0, q1, q0); // both non-NaN but result NaN
VSHLQ_64(q0, q0, 63); // sign bit only
VORRQ(v0, v0, q0); // force -NaN
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
VDUPQD(q1, x5); // QNaN bit
VORRQ(q2, q2, q1); // quiet any SNaN
VBIFQ(v0, q2, q0); // where src1 NaN: use QNaN(src1)
}
}
if(!vex.l) YMM0(gd);
break;
@@ -1670,13 +1734,12 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xE6:
INST_NAME("VCVTTPD2DQ Gx, Ex");
nextop = F8;
d0 = fpu_get_scratch(dyn, ninst);
for(int l=0; l<1+vex.l; ++l) {
if(!l) {
GETEX_Y(v1, 0, 0);
GETGX_empty(v0);
} else {
if(BOX64ENV(dynarec_fastround))
d0 = fpu_get_scratch(dyn, ninst);
GETEY(v1);
}
if(BOX64ENV(dynarec_fastround)) {
@@ -1697,7 +1760,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!l) {
MRS_fpsr(x5);
ORRw_mask(x4, xZR, 1, 0); //0x80000000
d0 = fpu_get_scratch(dyn, ninst);
}
for(int i=0; i<2; ++i) {
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
@@ -818,6 +818,9 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
ADDx_U12(ed, ed, 4);
TBZ(x4, 3*16, 4+1*4);
VST1_32(v0, 3, ed);
} else if (vex.l) { // keep avx ymm zero tracking consistent
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
}
SMWRITE2();
break;
@@ -860,6 +863,9 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
ADDx_U12(ed, ed, 8);
TBZ(x4, 1*32, 4+1*4);
VST1_64(v0, 1, ed);
} else if (vex.l) { // keep avx ymm zero tracking consistent
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
}
SMWRITE2();
break;
+82 -27
View File
@@ -240,13 +240,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FMAXD(q1, v2, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FADDD(q2, v1, v2); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FADDD(q2, v1, v2); // the high part of the vector is erased...
}
@@ -266,13 +271,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FMAXD(q1, v2, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FMULD(q2, v1, v2); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FMULD(q2, v1, v2); // the high part of the vector is erased...
}
@@ -312,13 +322,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FMAXD(q1, v2, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FSUBD(q2, v2, v1); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FSUBD(q2, v2, v1); // the high part of the vector is erased...
}
@@ -353,13 +368,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXD(q1, v0, v1); // propagate NAN
FMAXD(q1, v2, v1); // propagate NAN
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
FDIVD(q2, v2, v1); // the high part of the vector is erased...
FCMEQD(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FDIVD(q2, v2, v1); // the high part of the vector is erased...
}
@@ -424,20 +444,29 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
if(!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn, ninst);
q1 = fpu_get_scratch(dyn, ninst);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
VFMAXPQS(q0, v2, v1); // propagate NAN
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
VUZP1Q_32(d1, v2, v1); // d1 = src1 (even elements)
VFCMEQQS(q0, v2, v2); // per-element non-NaN for Vx
VFCMEQQS(d0, v1, v1); // per-element non-NaN for Ex
VUZP1Q_32(q1, q0, d0); // even elements of pairs
VUZP2Q_32(q0, q0, d0); // odd elements of pairs
VANDQ(q0, q1, q0); // both non-NaN per pair
}
VFADDPQS(v0, v2, v1);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(q1, d1, d1); // q1 = src1 non-NaN mask
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 (QNaN bit)
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
VBIFQ(v0, d0, q1); // where src1 NaN: replace with QNaN(src1)
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd);
@@ -446,24 +475,31 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VHSUBPS Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
if(!BOX64ENV(dynarec_fastnan))
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
}
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
VUZP1Q_32(q0, v2, v1);
VUZP2Q_32(v0, v2, v1);
VUZP1Q_32(q0, v2, v1); // q0 = src1 (even elements)
VUZP2Q_32(v0, v2, v1); // v0 = src2 (odd elements)
if(!BOX64ENV(dynarec_fastnan)) {
// check if any input value was NAN
// but need to mix low/high part
VFMAXQS(q1, v0, q0); // propagate NAN
VFCMEQQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
VMOVQ(d1, q0); // save src1
VFCMEQQS(q1, q0, q0); // even elements non-NaN
VFCMEQQS(d0, v0, v0); // odd elements non-NaN
VANDQ(q1, q1, d0); // both non-NaN per pair
}
VFSUBQS(v0, q0, v0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q0, v0, v0); // 0 => out is NAN
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
VFCMEQQS(d0, d1, d1); // d0 = src1 non-NaN mask
MOVIQ_32_lsl(q0, 0x40, 2); // q0 = 0x00400000 (QNaN bit)
VORRQ(q0, d1, q0); // q0 = QNaN(src1)
VBIFQ(v0, q0, d0); // where src1 NaN: replace with QNaN(src1)
VFCMEQQS(q0, v0, v0); // 0 => out is NAN
VBICQ(q1, q1, q0); // only when both inputs non-NaN but result is NaN
VSHLQ_32(q1, q1, 31); // only keep the sign bit
VORRQ(v0, v0, q1); // NAN -> -NAN
}
}
if(!vex.l) YMM0(gd);
@@ -509,20 +545,39 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VADDSUBPS Gx, Vx, Ex");
nextop = F8;
q0 = fpu_get_scratch(dyn, ninst);
d0 = fpu_get_scratch(dyn, ninst);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
q2 = fpu_get_scratch(dyn, ninst);
}
TABLE64C(x2, const_4f_m1_1_m1_1);
VLDR128_U12(q0, x2, 0);
for(int l=0; l<1+vex.l; ++l) {
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
if (!BOX64ENV(dynarec_fastnan)) {
VMOVQ(q2, v2); // save src1
VFCMEQQS(q1, v2, v2);
VFCMEQQS(d0, v1, v1);
VANDQ(q1, q1, d0); // q1 = both non-NaN
}
if(v0==v1) {
//TODO: find a better way
if(!l) q1 = fpu_get_scratch(dyn, ninst);
VMOVQ(q1, v2);
VFMLAQS(q1, v1, q0);
VMOVQ(v0, q1);
VMOVQ(d0, v2);
VFMLAQS(d0, v1, q0);
VMOVQ(v0, d0);
} else {
if(v0!=v2) VMOVQ(v0, v2);
VFMLAQS(v0, v1, q0);
}
if (!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(d0, v0, v0); // 0 where result is NaN
VBICQ(d0, q1, d0); // both non-NaN but result NaN
VSHLQ_32(d0, d0, 31); // sign bit only
VORRQ(v0, v0, d0); // force -NaN
VFCMEQQS(q1, q2, q2); // 0 if src1 was NaN
MOVIQ_32_lsl(d0, 0x40, 2); // QNaN bit 0x00400000
VORRQ(q2, q2, d0); // quiet any SNaN
VBIFQ(v0, q2, q1); // where src1 NaN: use QNaN(src1)
}
}
if(!vex.l) YMM0(gd);
break;
+24 -4
View File
@@ -275,13 +275,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FMAXS(q1, v2, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FADDS(q2, v1, v2); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FADDS(q2, v1, v2); // the high part of the vector is erased...
}
@@ -301,13 +306,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FMAXS(q1, v2, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FMULS(q2, v1, v2); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FMULS(q2, v1, v2); // the high part of the vector is erased...
}
@@ -375,13 +385,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FMAXS(q1, v2, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FSUBS(q2, v2, v1); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FSUBS(q2, v2, v1); // the high part of the vector is erased...
}
@@ -415,13 +430,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
q1 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
FMAXS(q1, v0, v1); // propagate NAN
FMAXS(q1, v2, v1); // propagate NAN
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
FDIVS(q2, v2, v1); // the high part of the vector is erased...
FCMEQS(q0, q2, q2); // 0 => out is NAN
VBIC(q0, q1, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(q2, q2, q0); // NAN -> -NAN
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(q0, v2, q0); // QNaN(src1)
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
} else {
FDIVS(q2, v2, v1); // the high part of the vector is erased...
}
+3
View File
@@ -84,6 +84,9 @@ uintptr_t getConst(arm64_consts_t which)
case const_native_fstp: return (uintptr_t)native_fstp;
case const_native_frstor: return (uintptr_t)native_frstor;
case const_native_next: return (uintptr_t)native_next;
case const_native_next_invalidate: return (uintptr_t)arm64_next_invalid;
case const_native_crc32: return (uintptr_t)arm64_crc;
case const_native_x31: return (uintptr_t)arm64_x31_hash;
case const_int3: return (uintptr_t)EmuInt3;
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
+3
View File
@@ -47,6 +47,9 @@ typedef enum arm64_consts_s {
const_native_fstp,
const_native_frstor,
const_native_next,
const_native_next_invalidate,
const_native_crc32,
const_native_x31,
const_int3,
const_x86syscall,
const_x64syscall,
+2 -16
View File
@@ -148,14 +148,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
IFX(X_CF|X_PF|X_ZF) {
if(ST_IS_F(0)) {
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
}
FCOMI(x1, x2);
FCOMI(x1, x2, ST_IS_F(0), v1, v2);
break;
case 0xF0:
case 0xF1:
@@ -169,14 +162,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
IFX(X_CF|X_PF|X_ZF) {
if(ST_IS_F(0)) {
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
}
FCOMI(x1, x2);
FCOMI(x1, x2,ST_IS_F(0), v1, v2);
break;
default:
+2 -18
View File
@@ -101,15 +101,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
IFX(X_CF|X_PF|X_ZF) {
if(ST_IS_F(0))
{
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
}
FCOMI(x1, x2);
FCOMI(x1, x2,ST_IS_F(0), v1, v2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
@@ -124,15 +116,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
IFX(X_CF|X_PF|X_ZF) {
if(ST_IS_F(0))
{
FCMPS(v1, v2);
} else {
FCMPD(v1, v2);
}
}
FCOMI(x1, x2);
FCOMI(x1, x2, ST_IS_F(0), v1, v2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
+39 -5
View File
@@ -704,6 +704,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
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) {
// commit df before branch, CALL_S in GPF path has FORCE_DFNONE
if(rex.w && BOX64DRENV(dynarec_safeflags)>1)
CHECK_DFNONE(0);
if(cpuext.uscat) {
if(rex.w) {
TSTx_mask(wback, 1, 0, 3);
@@ -724,13 +727,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MOVx_REG(x4, xRBX);
MOVx_REG(x5, xRCX);
CASPALxw(x2, x4, wback);
// preserve upper bits of EAX/EDX if equal, per CMPXCHG8B semantics
CMPSxw_REG(x2, xRAX);
CCMPxw(x3, xRDX, 0, cEQ);
CSELx(xRAX, xRAX, x2, cEQ);
CSELx(xRDX, xRDX, x3, cEQ);
UFLAG_IF {
CMPSxw_REG(x2, xRAX);
CCMPxw(x3, xRDX, 0, cEQ);
IFNATIVE(NF_EQ) {} else {CSETw(x1, cEQ);}
}
MOVx_REG(xRAX, x2);
MOVx_REG(xRDX, x3);
if(!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
}
@@ -818,11 +822,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGB(x2);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRB(x1, wback);
emit_adc8(dyn, ninst, x1, x2, x4, x5);
STLXRB(x4, x1, wback);
CBNZx_MARKLOCK(x4);
NATIVE_RESTORE_X87PC();
}
break;
case 0x11:
@@ -838,11 +847,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
SETFLAGS(X_ALL, SF_SET_PENDING);
GETGD;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRxw(x1, wback);
emit_adc32(dyn, ninst, rex, x1, gd, x4, x5);
STLXRxw(x4, x1, wback);
CBNZx_MARKLOCK(x4);
NATIVE_RESTORE_X87PC();
}
break;
case 0x20:
@@ -1093,11 +1107,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRB(x1, wback);
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x3);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 3: //SBB
@@ -1113,11 +1132,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
u8 = F8;
wb1 = 1;
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRB(x1, wback);
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x3);
STLXRB(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 4: //AND
@@ -1345,11 +1369,16 @@ 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;
MOV64xw(x5, i64);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRxw(x1, wback);
emit_adc32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 3: //SBB
@@ -1365,11 +1394,16 @@ 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;
MOV64xw(x5, i64);
MOVx_REG(x6, xFlags);
MRS_nzcv(x87pc);
MARKLOCK;
MOVx_REG(xFlags, x6);
MSR_nzcv(x87pc);
LDAXRxw(x1, wback);
emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
NATIVE_RESTORE_X87PC();
}
break;
case 4: //AND
@@ -1650,7 +1684,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
MARKLOCK;
LDAXRxw(x1, wback);
MVNw_REG(x1, x1);
MVNxw_REG(x1, x1);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
+99 -19
View File
@@ -31,14 +31,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint64_t u64, j64;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1;
int q0, q1;
int d0, d1;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int64_t fixedaddress;
int unscaled;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(d2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(v0);
@@ -261,6 +262,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVD(v2, d1); // save src1
// 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,6 +272,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FADDD(v1, d1, d0); // the high part of the vector is erased...
}
@@ -283,6 +291,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVD(v2, d1); // save src1
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -291,6 +301,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FMULD(v1, d1, d0);
}
@@ -321,6 +336,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVD(v2, d1); // save src1
// check if any input value was NAN
FMAXD(v0, d0, d1); // propagate NAN
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -329,6 +346,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FSUBD(v1, d1, d0);
}
@@ -353,6 +375,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVD(v2, v0); // save src1
// check if any input value was NAN
FMAXD(d0, v0, v1); // propagate NAN
FCMEQD(d0, d0, d0); // 0 if NAN, 1 if not NAN
@@ -361,6 +385,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, d0, q0); // forget it in any input was a NAN already
SHL_64(q0, q0, 63); // only keep the sign bit
VORR(d1, d1, q0); // NAN -> -NAN
FCMEQD(d0, v2, v2); // 0 if src1 was NaN
MOV64x(x5, 0x0008000000000000ULL);
VMOVQDfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(d1, v2, d0); // where src1 was NaN, use QNaN(src1)
} else {
FDIVD(d1, v0, v1);
}
@@ -418,16 +447,25 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXPQS(v0, q1, q0); // propagate NAN
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
d0 = fpu_get_scratch(dyn, ninst);
d1 = fpu_get_scratch(dyn, ninst);
VUZP1Q_32(d1, q1, q0); // d1 = {q1[0], q1[2], q0[0], q0[2]}
VFCMEQQS(v0, q1, q1); // per-element non-NaN mask for Gx
VFCMEQQS(d0, q0, q0); // per-element non-NaN mask for Ex
VUZP1Q_32(v1, v0, d0); // even elements of pairs
VUZP2Q_32(v0, v0, d0); // odd elements of pairs
VANDQ(v0, v1, v0); // v0 = both non-NaN per pair
}
VFADDPQS(q1, q1, q0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
VFCMEQQS(v1, d1, d1); // v1 = 0xFFFFFFFF where src1 non-NaN, 0 where NaN
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 in all lanes (QNaN bit)
VORRQ(d0, d1, d0); // d0 = QNaN(src1) = src1 | 0x00400000
VBIFQ(q1, d0, v1); // where src1 was NaN (v1=0): q1 = d0 (QNaN(src1))
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
VSHLQ_32(v1, v1, 31); // only keep the sign bit
VORRQ(q1, q1, v1); // NAN -> -NAN
}
break;
case 0x7D:
@@ -436,20 +474,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
GETEX(v1, 0, 0);
d0 = fpu_get_scratch(dyn, ninst);
VUZP1Q_32(d0, v0, v1);
VUZP2Q_32(v0, v0, v1);
VUZP1Q_32(d0, v0, v1); // d0 = src1 (even elements: first of each pair)
VUZP2Q_32(v0, v0, v1); // v0 = src2 (odd elements: second of each pair)
if(!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn, ninst);
// check if any input value was NAN
VFMAXQS(d1, d0, v0); // propagate NAN
VFCMEQQS(d1, d1, d1); // 0 if NAN, 1 if not NAN
d2 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
VMOVQ(q0, d0); // save src1 for NaN priority
VFCMEQQS(d1, d0, d0); // even elements non-NaN
VFCMEQQS(d2, v0, v0); // odd elements non-NaN
VANDQ(d1, d1, d2); // d1 = both non-NaN per pair
}
VFSUBQS(v0, d0, v0);
if(!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(d0, v0, v0); // 0 => out is NAN
VBICQ(d1, d1, d0); // forget it in any input was a NAN already
VSHLQ_32(d1, d1, 31); // only keep the sign bit
VORRQ(v0, v0, d1); // NAN -> -NAN
VFCMEQQS(d2, q0, q0); // d2 = src1 non-NaN mask
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 (QNaN bit)
VORRQ(d0, q0, d0); // d0 = QNaN(src1)
VBIFQ(v0, d0, d2); // where src1 NaN: replace with QNaN(src1)
VFCMEQQS(d0, v0, v0); // 0 => out is NAN
VBICQ(d1, d1, d0); // forget it in any input was a NAN already
VSHLQ_32(d1, d1, 31); // only keep the sign bit
VORRQ(v0, v0, d1); // NAN -> -NAN
}
break;
@@ -487,6 +532,23 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GOCOND(0x80, "J", "Id");
#undef GO
case 0xA3: // ignore F2 prefix
case 0xA4:
case 0xA5:
case 0xAB:
case 0xAC:
case 0xAD:
case 0xAF:
case 0xB3:
case 0xB7:
case 0xBA:
case 0xBB:
case 0xBC: // this one is still BSR, not TZCNT
case 0xBD: // and this one is still BSF, not LZCNT
case 0xC1:
case 0xCD:
return dynarec64_0F(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xAE:
nextop = F8;
switch((nextop>>3)&7) {
@@ -526,9 +588,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0, 1);
GETEX(v1, 0, 0);
q0 = fpu_get_scratch(dyn, ninst);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
VMOVQ(v2, v0); // save src1
VFCMEQQS(q0, v0, v0);
VFCMEQQS(q1, v1, v1);
VANDQ(q1, q0, q1); // q1 = both non-NaN
}
TABLE64C(x2, const_4f_m1_1_m1_1);
VLDR128_U12(q0, x2, 0);
VFMLAQS(v0, v1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VFCMEQQS(q0, v0, v0); // 0 where result is NaN
VBICQ(q0, q1, q0); // both non-NaN but result NaN
VSHLQ_32(q0, q0, 31); // sign bit only
VORRQ(v0, v0, q0); // force -NaN
VFCMEQQS(q0, v2, v2); // 0 if src1 was NaN
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
VORRQ(v2, v2, q1); // quiet any SNaN
VBIFQ(v0, v2, q0); // where src1 NaN: use QNaN(src1)
}
break;
case 0xD6:
+48 -1
View File
@@ -28,7 +28,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t gd, ed;
uint8_t wback;
uint64_t u64;
int v0, v1;
int v0, v1, v2;
int q0, q1;
int d0, d1;
int64_t fixedaddress;
@@ -288,6 +288,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVS(v2, d1); // save src1
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -296,6 +298,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
// src1 NaN priority
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FADDS(v1, d1, d0); // the high part of the vector is erased...
}
@@ -310,6 +318,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVS(v2, d1); // save src1
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -318,6 +328,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
// src1 NaN priority
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FMULS(v1, d1, d0); // the high part of the vector is erased...
}
@@ -386,6 +402,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVS(v2, d1); // save src1
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -394,6 +412,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
// src1 NaN priority
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FSUBS(v1, d1, d0); // the high part of the vector is erased...
}
@@ -418,6 +442,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn, ninst);
q0 = fpu_get_scratch(dyn, ninst);
v2 = fpu_get_scratch(dyn, ninst);
FMOVS(v2, d1); // save src1
// check if any input value was NAN
FMAXS(v0, d0, d1); // propagate NAN
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
@@ -426,6 +452,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBIC(q0, v0, q0); // forget it in any input was a NAN already
VSHL_32(q0, q0, 31); // only keep the sign bit
VORR(v1, v1, q0); // NAN -> -NAN
// src1 NaN priority
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
MOV32w(x5, 0x00400000);
VMOVQSfrom(q0, 0, x5);
VORR(v2, v2, q0); // quiet any SNaN in src1
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
} else {
FDIVS(v1, d1, d0); // the high part of the vector is erased...
}
@@ -612,6 +644,21 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xA3: // ignore F3 prefix
case 0xA4:
case 0xA5:
case 0xAC:
case 0xAD:
case 0xAF:
case 0xB3:
case 0xB7:
case 0xBA:
case 0xBB:
case 0xBF:
case 0xC1:
case 0xCD:
return dynarec64_0F(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
if (!BOX64DRENV(dynarec_safeflags)) {
+33 -29
View File
@@ -786,13 +786,13 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
}
static char buf[4096];
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%d, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
df_status[dyn->f],
df_status[dyn->insts[ninst].f_entry],
df_status[dyn->insts[ninst].f_exit],
dyn->insts[ninst].df_notneeded,
dyn->insts[ninst].df_needed?'N':(dyn->insts[ninst].df_notneeded?'U':'-'),
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
@@ -991,27 +991,23 @@ uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before)
return flag;
}
uint8_t flag2native(uint8_t flags)
uint8_t flag2native(uint8_t flags, int vf_is_p)
{
uint8_t ret = 0;
#ifdef ARM64
if(flags&X_ZF) ret|=NF_EQ;
if(flags&X_SF) ret|=NF_SF;
if(flags&X_OF) ret|=NF_VF;
if(!vf_is_p)
if(flags&X_OF) ret|=NF_VF;
if(flags&X_CF) ret|=NF_CF;
if(vf_is_p)
if(flags&X_PF) ret|=NF_PF_V; // but no opcode can generate both NF_VF & NF_PF_V at the same time!
#else
// no native flags on rv64 or la64
#endif
return ret;
}
int flagIsNative(uint8_t flags)
{
if(flags&(X_AF|X_PF)) return 0;
return 1;
}
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags, int vf_is_p)
{
// propagate and check wich flags are actually used
uint8_t used_flags = 0;
@@ -1059,21 +1055,21 @@ static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
}
if(ninst!=start && dyn->insts[ninst].x64.use_flags) {
// some flags not compatible with native, partial use not allowed
if(flag2native(dyn->insts[ninst].x64.use_flags)!=dyn->insts[ninst].use_nat_flags)
if(flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p)!=dyn->insts[ninst].use_nat_flags)
return 0;
// check if flags are used, but not the natives ones
//if(dyn->insts[ninst].use_nat_flags&~used_flags)
// return 0;
}
// check if flags are generated without native option
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags)) {
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after))
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags)) {
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p))
return 0; // partial covert, not supported for now (TODO: this might be fixable)
else
return nat_flags_used?used_flags:0; // full covert... End of propagation
}
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&flags))
if(!(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&flags))
return nat_flags_used?used_flags:0;
// check if flags are destroyed, cancel the use then
if(dyn->insts[ninst].nat_flags_op && (start!=ninst))
@@ -1099,13 +1095,15 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
{
int ninst = start;
// those are the flags generated by the opcode and used later on
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after);
int vf_is_p = (dyn->insts[ninst].set_nat_flags&NF_PF_V)?1:0;
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after, vf_is_p);
//check if they are actualy used before starting
//printf_log(LOG_INFO, "propagateNativeFlags called for start=%d, flags=%x, will need:%x\n", start, flags, flag2native(dyn->insts[ninst].x64.need_after));
if(!flags) return;
// also check if some native flags are used but not genereated here
if(flag2native(dyn->insts[ninst].x64.use_flags)&~flags) return;
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags);
if(flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p)&~flags) return;
if(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&~flags) return;
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags, vf_is_p);
//printf_log(LOG_INFO, " will use:%x, carry:%d, generate inverted carry:%d\n", used_flags, used_flags&NF_CF, dyn->insts[ninst].gen_inverted_carry);
if(!used_flags) return; // the flags wont be used, so just cancel
int nc = dyn->insts[ninst].gen_inverted_carry?0:1;
@@ -1122,17 +1120,17 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
return;
}
// check if flags are generated without native option
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags))
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags))
return;
// mark the opcode
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after);
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags); // should not change anything
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after, vf_is_p);
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p); // should not change anything
//printf_log(LOG_INFO, " marking ninst=%d with %x | %x&%x => %x\n", ninst, dyn->insts[ninst].need_nat_flags, used_flags, use_flags, dyn->insts[ninst].need_nat_flags | (used_flags&use_flags));
dyn->insts[ninst].need_nat_flags |= used_flags&use_flags;
if(carry) dyn->insts[ninst].normal_carry = nc;
if(carry && dyn->insts[ninst].invert_carry) nc = 0;
// check if flags are still needed
if(!(flag2native(dyn->insts[ninst].x64.need_after)&used_flags))
if(!(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags))
return;
// go next
if(!dyn->insts[ninst].x64.has_next) {
@@ -1153,7 +1151,7 @@ void updateNativeFlags(dynarec_native_t* dyn)
return;
// forward check if native flags are used
for(int ninst=0; ninst<dyn->size; ++ninst)
if(flag2native(dyn->insts[ninst].x64.gen_flags) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
if(flag2native(dyn->insts[ninst].x64.gen_flags,(dyn->insts[ninst].set_nat_flags&NF_PF_V)?1:0) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
propagateNativeFlags(dyn, ninst);
}
}
@@ -1183,7 +1181,7 @@ int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst)
flags_after = dyn->insts[jmp].before_nat_flags;
nc_after = dyn->insts[jmp].normal_carry_before;
}
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before, (dyn->insts[jmp].before_nat_flags&NF_PF_V)?1:0);
flags_x86 &= ~flags_after;
if((flags_before&NF_CF) && (flags_after&NF_CF) && (nc_before!=nc_after))
return 1;
@@ -1282,16 +1280,21 @@ static void propagateXYMMUneeded(dynarec_arm_t* dyn, int ninst, uint16_t mask_x,
void updateUneeded(dynarec_arm_t* dyn)
{
propagate_nodf(dyn);
if(!dyn->use_xmm && !dyn->use_ymm)
return;
// first propagate the needed regs: those which are used and are not unneeded
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
uint16_t xmm_needed = dyn->insts[ninst].n.xmm_used&~dyn->insts[ninst].n.xmm_unneeded;
uint16_t ymm_needed = dyn->insts[ninst].n.ymm_used&~dyn->insts[ninst].n.ymm_unneeded;
if((dyn->insts[ninst].x64.barrier&BARRIER_FLOAT) || (dyn->insts[ninst].x64.jmp && (dyn->insts[ninst].x64.jmp_insts==-1)))
{
if(dyn->use_xmm) xmm_needed = 0xffff;
if(dyn->use_ymm) ymm_needed = 0xffff;
}
if(xmm_needed || ymm_needed)
propagateXYMMNeeded(dyn, ninst, xmm_needed, ymm_needed);
if(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)
propagateXYMMNeeded(dyn, ninst, dyn->use_xmm?0xffff:0, dyn->use_ymm?0xffff:0);
}
// then proagate the unneeded one: those which are not needed (not used anymore and will be overwritten)
@@ -1300,8 +1303,6 @@ void updateUneeded(dynarec_arm_t* dyn)
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
propagateXYMMUneeded(dyn, dyn->insts[ninst].pred[i], dyn->insts[ninst].n.xmm_unneeded, dyn->insts[ninst].n.ymm_unneeded);
}
if(dyn->insts[ninst].df_notneeded)
propagate_nodf(dyn, ninst);
}
// try to add some preload of XYMM on jump were it would make sense
for(int ninst=0; ninst<dyn->size; ++ninst)
@@ -1468,6 +1469,7 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached)
}
} else if (can_incr) {
// We always have ninst == max_ninst_reached when can_incr == 1
dyn->insts[ninst].ymm0_out = dyn->insts[ninst].ymm0_add & ~dyn->insts[ninst].ymm0_sub;
++max_ninst_reached;
} else {
// We didn't update anything, we can leave
@@ -1481,6 +1483,7 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached)
// AVX helpers
void avx_mark_zero(dynarec_arm_t* dyn, int ninst, int reg)
{
dyn->use_ymm = 1;
dyn->ymm_zero |= (1<<reg);
}
@@ -1500,6 +1503,7 @@ int is_avx_zero_unset(dynarec_arm_t* dyn, int ninst, int reg)
void avx_mark_zero_reset(dynarec_arm_t* dyn, int ninst)
{
dyn->use_ymm = 1;
dyn->ymm_zero = 0;
}
+1 -1
View File
@@ -52,7 +52,7 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
// transform x86 flags to native flags
uint8_t flag2native(uint8_t flags);
uint8_t flag2native(uint8_t flags, int vf_is_p);
// mark a instruction as using/generating flags. return flag
uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before);
// propage the use of nativeflags or not (done between step 0 and step 1)
+145 -1
View File
@@ -2321,7 +2321,7 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
flags_after = dyn->insts[jmp].before_nat_flags;
nc_after = dyn->insts[jmp].normal_carry_before;
}
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before, (dyn->insts[jmp].before_nat_flags&NF_PF_V)?1:0);
flags_x86 &= ~flags_after;
MESSAGE(LOG_DUMP, "\tNative Flags transform ---- ninst=%d -> %d %hhx -> %hhx/%hhx\n", ninst, jmp, flags_before, flags_after, flags_x86);
// flags present in before and missing in after
@@ -2337,6 +2337,10 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
CSETw(s1, cVS);
BFIw(xFlags, s1, F_OF, 1);
}
if((flags_before&NF_PF_V) && (flags_x86&NF_PF_V)) {
CSETw(s1, cVS);
BFIw(xFlags, s1, F_PF, 1);
}
if((flags_before&NF_CF) && (flags_x86&NF_CF)) {
if(nc_before) // might need to invert carry
CSETw(s1, cCS);
@@ -2362,6 +2366,11 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
UBFXw(s1, xFlags, F_OF, 1);
BFIx(s2, s1, NZCV_V, 1);
}
if(!(flags_before&NF_PF_V) && (flags_after&NF_PF_V)) {
GO_MRS(s2);
UBFXw(s1, xFlags, F_PF, 1);
BFIx(s2, s1, NZCV_V, 1);
}
if(!(flags_before&NF_CF) && (flags_after&NF_CF)) {
GO_MRS(s2);
BFIx(s2, xFlags, NZCV_C, 1); // F_CF is bit 0
@@ -2393,6 +2402,47 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd) {
nativeFlagsTransform(dyn, ninst, x1, x2);
}
void additionnal_checks(dynarec_arm_t* dyn, int ninst)
{
int s1 = x1;
// check if a opcode generate partial flags that may clober existing native flags and see need to be "moved" to xFlags
if(dyn->insts[ninst].nat_flags_op || dyn->insts[ninst].nat_flags_op_before) {
uint8_t nat_flags = dyn->insts[ninst].need_nat_flags; // that's the native flags that will be generated
uint8_t nat_flags_gen = dyn->insts[ninst].set_nat_flags;
//TODO: does it need to fetch previous state with getPred?
uint8_t nat_flags_before = dyn->insts[ninst].before_nat_flags; //flags before the opcode, but it's only there when opcode also consume natflags
uint8_t nat_flags_flush = nat_flags_before&~nat_flags_gen; // flags present before bu not after the operation and so that needs to be spared
if(nat_flags_before && nat_flags_flush) {
// some flags disapear, and need to be saved
MESSAGE(LOG_DUMP, "\tPurging native flags %hhx\n", nat_flags_flush);
uint8_t nc_before = dyn->insts[ninst].normal_carry;
if(nat_flags_flush&NF_EQ) {
CSETw(s1, cEQ);
BFIw(xFlags, s1, F_ZF, 1);
}
if(nat_flags_flush&NF_SF) {
CSETw(s1, cMI);
BFIw(xFlags, s1, F_SF, 1);
}
if(nat_flags_flush&NF_VF) {
CSETw(s1, cVS);
BFIw(xFlags, s1, F_OF, 1);
}
if(nat_flags_flush&NF_PF_V) {
CSETw(s1, cVS);
BFIw(xFlags, s1, F_PF, 1);
}
if(nat_flags_flush&NF_CF) {
if(nc_before) // might need to invert carry
CSETw(s1, cCS);
else
CSETw(s1, cCC);
BFIw(xFlags, s1, F_CF, 1);
}
}
}
}
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_reflectcache(dyn, ninst, s1, s2, s3);
@@ -2787,3 +2837,97 @@ void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
}
MESSAGE(LOG_INFO, "-------- doLeave\n");
}
void emit_fcomi(dynarec_arm_t* dyn, int ninst, int s1, int s2, int isfloat, int d1, int d2)
{
IFX(X_OF|X_AF|X_SF) {
MOV32w(s2, 0b100011010101);
BICw_REG(xFlags, xFlags, s2);
}
IFX(X_CF|X_PF|X_ZF) {
int nonative = 0;
int needCZ = 0;
if(isfloat)
FCMPS(d1, d2);
else
FCMPD(d1, d2);
IFX(X_ZF) {
IFNATIVE(NF_EQ) {
// add ZF if VS is set
needCZ = 1;
} else {
nonative = 1;
}
}
IFX(X_CF) {
IFNATIVE(NF_CF) {
// no need to add CF if VS, because it's a reverse carry (so already "un"set)
GEN_INVERTED_CARRY();
needCZ = 1;
} else {
nonative = 1;
}
}
IFX(X_PF) {
IFNATIVE(NF_PF_V) {
} else {
nonative = 1;
}
}
if(needCZ) {
#if 1
// retest is VF is clear, set NZCV to 0101 if VF is set, to match x86 behaviour (also, inversed Carry)
// probably faster like that then the conditionnal jump + reading / reseting the flags
if(isfloat)
FCCMPS(d1, d2, 0b0101, cVC);
else
FCCMPD(d1, d2, 0b0101, cVC);
#else
if(cpuext.flagm) {
Bcond(cVC, 4+2*4);
MOV32w(s1, 0b0100); //new flags
RMIF(s1, 0, 0b0110); // ZC flags only
} else {
Bcond(cVC, 4+3*4);
MRS_nzcv(s1);
EORx_mask(s1, s1, 1, 0b100011, 0b000001); // mask = (1<<NZCV_Z)|(1<<NZCV_C) == 0x60000000
MSR_nzcv(s1);
}
#endif
}
if(nonative) {
MOV32w(s2, 0b01000101);
IFX(X_OF|X_AF|X_SF) {} else {BICw_REG(xFlags, xFlags, s2);}
CSETw(s1, cMI); /* 1 if less than, 0 else */
/*s2 already set */ /* unordered */
CSELw(s1, s2, s1, cVS);
MOV32w(s2, 0b01000000); /* zero */
CSELw(s1, s2, s1, cEQ);
/* greater than leave 0 */
ORRw_REG(xFlags, xFlags, s1);
}
}
SET_DFNONE();
}
void checkCRC(dynarec_arm_t* dyn, int ninst)
{
// grab the dynablock address in x5, as this on will not be erased by crc functions
int delta = -(dyn->native_size + sizeof(void*));
LDRx_literal(x5, delta);
// move away xEMU to X6, should be safe there
MOVx_REG(x6, xEmu);
// prepare and call the crc function
TABLE64C(x3, cpuext.crc32?const_native_crc32:const_native_x31);
LDRx_U12(xEmu, x5, offsetof(dynablock_t, x64_addr));
LDRw_U12(x1, x5, offsetof(dynablock_t, x64_size));
BLR(x3);
// done, move away result and restore xEmu
MOVw_REG(x1, xEmu);
MOVx_REG(xEmu, x6);
LDRw_U12(x2, x5, offsetof(dynablock_t, hash));
SUBw_REG(x1, x1, x2);
CBZw(x1, 4+2*4);
TABLE64C(x3, const_native_next_invalidate);
BLR(x3);
}
+24 -24
View File
@@ -841,30 +841,10 @@
ORRw_REG_LSL(s3, s3, s1, 8); \
STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
IFX(X_OF|X_AF|X_SF) { \
MOV32w(s2, 0b100011010101); \
BICw_REG(xFlags, xFlags, s2); \
IFX(X_CF|X_PF|X_ZF) { \
MOV32w(s2, 0b01000101); \
} \
} else { \
IFX(X_CF|X_PF|X_ZF) { \
MOV32w(s2, 0b01000101); \
BICw_REG(xFlags, xFlags, s2); \
} \
} \
IFX(X_CF|X_PF|X_ZF) { \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
/*s2 already set */ /* unordered */ \
CSELw(s1, s2, s1, cVS); \
MOV32w(s2, 0b01000000); /* zero */ \
CSELw(s1, s2, s1, cEQ); \
/* greater than leave 0 */ \
ORRw_REG(xFlags, xFlags, s1); \
} \
SET_DFNONE(); \
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is not done)
#define FCOMIS(s1, s2, d1, d2) emit_fcomi(dyn, ninst, s1, s2, 1, d1, d2)
#define FCOMID(s1, s2, d1, d2) emit_fcomi(dyn, ninst, s1, s2, 0, d1, d2)
#define FCOMI(s1, s2, isfloat, d1, d2) emit_fcomi(dyn, ninst, s1, s2, isfloat, d1, d2)
#ifndef IF_UNALIGNED
#define IF_UNALIGNED(A) if(dyn->insts[ninst].unaligned)
@@ -1097,6 +1077,11 @@
dyn->doublepop = 0;
#define ARCH_RESET()
#undef PREFLAGSNEEDED
#define PREFLAGSNEEDED() \
if(dyn->always_test && ninst && (dyn->insts[ninst].sep || (ninst && dyn->insts[ninst-1].x64.has_callret))) \
checkCRC(dyn, ninst);
#if STEP < 2
#define GETIP(A) MOV64x(xRIP, A)
#define GETIP_(A) MOV64x(xRIP, A)
@@ -1307,6 +1292,7 @@
#define emit_shld16 STEPNAME(emit_shld16)
#define emit_pf STEPNAME(emit_pf)
#define emit_fcomi STEPNAME(emit_fcomi)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
@@ -1339,6 +1325,7 @@
#define doPreload STEPNAME(doPreload)
#define doEnterBlock STEPNAME(doEnterBlock)
#define doLeaveBlock STEPNAME(doLeaveBlock)
#define checkCRC STEPNAME(checkCRC)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
@@ -1354,6 +1341,7 @@
#define avx_purge_ymm STEPNAME(avx_purge_ymm)
#define CacheTransform STEPNAME(CacheTransform)
#define additionnal_checks STEPNAME(additionnal_checks)
#define arm64_move32 STEPNAME(arm64_move32)
#define arm64_move64 STEPNAME(arm64_move64)
@@ -1479,6 +1467,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
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 s4);
void emit_fcomi(dynarec_arm_t* dyn, int ninst, int s1, int s2, int isfloat, int d1, int d2);
// x87 helper
// cache of the local stack counter, to avoid update at every call, return old internal stack counter
@@ -1519,6 +1508,7 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
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);
void additionnal_checks(dynarec_arm_t* dyn, int ninst);
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);
@@ -1611,6 +1601,8 @@ void doPreload(dynarec_arm_t* dyn, int ninst);
void doEnterBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Leave a block (atomic decrement of in_used)
void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// in case of allways_test, this insert a check of crc of the dynablock (and exit to ArmNext if wrong)
void checkCRC(dynarec_arm_t* dyn, int ninst);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog);
@@ -1765,13 +1757,21 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
break; \
case B+0xA: \
INST_NAME(T1 "P " T2); \
IFNATIVE(NF_PF_V) { \
GO( , cVC, cVS, X_PF) \
} else { \
GO( TSTw_mask(xFlags, 0b011110, 0) \
, cEQ, cNE, X_PF) \
} \
break; \
case B+0xB: \
INST_NAME(T1 "NP " T2); \
IFNATIVE(NF_PF_V) { \
GO( , cVS, cVC, X_PF) \
} else { \
GO( TSTw_mask(xFlags, 0b011110, 0) \
, cNE, cEQ, X_PF) \
} \
break; \
case B+0xC: \
INST_NAME(T1 "L " T2); \
+7 -3
View File
@@ -31,8 +31,12 @@
Table64(dyn, getConst(V), 2); EMIT(0); \
} while(0)
#define FTABLE64(A, V) do { mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0); } while(0)
#define CALLRET_RET(A) do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); ++dyn->sep_size; } \
if(BOX64DRENV(dynarec_callret)>1) {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP);} \
#define CALLRET_RET(A) do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
} \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
} \
} while(0)
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
+2 -2
View File
@@ -14,7 +14,7 @@
#define MESSAGE(A, ...) \
do { \
if (dyn->need_dump) dynarec_log(LOG_NONE, __VA_ARGS__); \
if (dyn->need_dump) dynarec_log_prefix(0, LOG_NONE, __VA_ARGS__); \
} while (0)
#define ENDPREFIX dyn->insts[ninst].size2 = 0
#define NEW_INST \
@@ -54,7 +54,7 @@
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
++dyn->sep_size; \
} \
if(BOX64DRENV(dynarec_callret)>1) { \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; \
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
EMIT(ARCH_NOP); \
+4 -1
View File
@@ -14,6 +14,7 @@ typedef struct box64env_s box64env_t;
#define NF_SF (1<<1)
#define NF_VF (1<<2)
#define NF_CF (1<<3)
#define NF_PF_V (1<<4)
// Nothing happens to the native flags
#define NAT_FLAG_OP_NONE 0
@@ -125,7 +126,8 @@ typedef struct instruction_arm64_s {
uint8_t will_read:1; // [strongmem] will read from memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t wfe:1; // opcode uses sevl + wfe
uint8_t wfe:1; // opcode uses sevl + wfe
uint8_t sep:1; // opcode is a secondary entry point
uint8_t set_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags; // 0 or combinaison of native flags define
uint8_t use_nat_flags_before; // 0 or combinaison of native flags define
@@ -137,6 +139,7 @@ typedef struct instruction_arm64_s {
unsigned normal_carry:1;
unsigned normal_carry_before:1;
unsigned invert_carry:1; // this opcode force an inverted carry
unsigned df_needed:1;
unsigned df_notneeded:1;
unsigned unaligned:1; // this opcode can be re-generated for unaligned special case
unsigned x87precision:1; // this opcode can handle x87pc
+63 -2
View File
@@ -213,6 +213,18 @@ void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
MarkDynablock(db);
}
void MarkCRCRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
// Mark will try to find *any* blocks that intersect the range to mark
if(!db)
return;
dynarec_log(LOG_DEBUG, "MarkCRCRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x64_addr, (void*)db->x64_size);
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1)) {
MarkDynablock(db); // mark as dirty
db->to_delete = 1; // also invalid hash, so it will be deleted and replace
}
}
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!db)
@@ -233,6 +245,45 @@ void dynablock_leave_runtime(dynablock_t* db)
__atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL);
}
dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits)
{
#ifndef WIN32
static int critical_filled = 0;
static sigset_t critical_prot = {0};
sigset_t old_sig = {0};
if(!critical_filled) {
critical_filled = 1;
sigfillset(&critical_prot);
sigdelset(&critical_prot, SIGSEGV);
sigdelset(&critical_prot, SIGILL);
sigdelset(&critical_prot, SIGBUS);
sigdelset(&critical_prot, SIGINT);
sigdelset(&critical_prot, SIGABRT);
sigdelset(&critical_prot, SIGFPE);
}
#endif
pthread_sigmask(SIG_BLOCK, &critical_prot, &old_sig);
if(BOX64ENV(dynarec_wait)) {
mutex_lock(&my_context->mutex_dyndump);
} else {
if(mutex_trylock(&my_context->mutex_dyndump)) { // FillBlock not available for now
pthread_sigmask(SIG_SETMASK, &old_sig, NULL);
return NULL;
}
}
dynarec_log(LOG_DEBUG, "Will call Fillblock64 for Alt %p\n", (void*)addr);
dynablock_t* block = FillBlock64(addr, is32bits, MAX_INSTS, 0, 1);
mutex_unlock(&my_context->mutex_dyndump);
pthread_sigmask(SIG_SETMASK, &old_sig, NULL);
return block;
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
@@ -243,6 +294,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
if(BOX64ENV(nodynarec_delay) && (addr>=BOX64ENV(nodynarec_start)) && (addr<BOX64ENV(nodynarec_end)))
return NULL;
dynablock_t* block = getDB(addr);
if(block && block->to_delete) {
// just delete the block then, so we can create a new one right away
FreeDynablock(block, 1, 1);
block = NULL;
}
if(block || !create) {
if(block && getNeedTest(addr) && (getProtection(block->x64_readaddr)&req_prot)!=req_prot)
block = NULL;
@@ -276,6 +332,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
}
}
block = getDB(addr); // just in case
if(block && block->to_delete) {
// just delete the block then, so we can create a new one right away
FreeDynablock(block, 0, 1);
block = NULL;
}
if(block) {
if(block && getNeedTest(addr) && (getProtection_fast(block->x64_readaddr)&req_prot)!=req_prot)
block = NULL;
@@ -284,7 +345,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
return block;
}
}
block = FillBlock64(addr, is32bits, MAX_INSTS, is_new);
block = FillBlock64(addr, is32bits, MAX_INSTS, is_new, 0);
if(!block) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
}
@@ -330,7 +391,7 @@ dynablock_t* DBSwapInvalid(x64emu_t* emu, dynablock_t* db, uintptr_t addr, int i
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, (void*)addr);
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr);
// Free db, it's now invalid!
dynablock_t* old = InvalidDynablock(db, 0);
if(old->previous) {
+2
View File
@@ -35,6 +35,8 @@ typedef struct dynablock_s {
uint8_t dirty; // if need to be tested as soon as it's created
uint8_t always_test:2;
uint8_t is32bits:1;
uint8_t autocrc:1;
uint8_t to_delete:1;
int callret_size; // size of the array
int isize;
int arch_size; // size of of arch dependant infos
+54 -1
View File
@@ -104,6 +104,31 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
//dynablock_t *father = block->father?block->father:block;
return jblock;
}
void* LinkNextInvalid(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
{
// like LinkNext, but invalid the db found first
int is32bits = (R_CS == 0x23);
dynablock_t* db = getDB(addr);
if(db) {
if(db->previous && !db->dirty && X31_hash_code(db->previous->x64_addr, db->previous->x64_size)==db->previous->hash)
db = DBSwitchPrevious(emu, db, addr, 1);
else
db = DBSwapInvalid(emu, db, addr, is32bits, 1);
if(db && db->done && db->block) {
void* jblock = db->block;
if(db->sep_size && (uintptr_t)db->x64_addr!=addr) {
jblock = NULL; // not sure how this would happens here, but lets put the case it starts on SEP anyway
for(int i=0; i<db->sep_size && !jblock; ++i) {
if(addr==(uintptr_t)db->x64_addr + db->sep[i].x64_offs)
jblock = db->block + db->sep[i].nat_offs;
}
}
if(jblock)
return jblock;
}
}
return LinkNext(emu, addr, x2, x3);
}
#endif
void DynaCall(x64emu_t* emu, uintptr_t addr, int no_alt)
@@ -162,6 +187,21 @@ static dynablock_t* fastDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, in
ret = DBGetBlock(emu, R_RIP, 1, is32bits);
return ret;
}
#ifdef HAVE_ALTJUMP
static dynablock_t* getDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits)
{
dynablock_t* ret = getAlternateData((void*)addr);
if(ret == (void*)-1LL)
return NULL;
if(!ret) {
ret = CreateDBnoAlt(emu, addr, is32bits);
setAlternateData((void*)addr, ret);
}
dynarec_log(LOG_DEBUG, "Will use No-Alt block %p for Alt %p\n", ret, (void*)addr);
return ret;
}
#endif
#endif
void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
@@ -202,7 +242,14 @@ void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
if(emu->flags.need_jmpbuf)
emu->flags.need_jmpbuf = 0;
if(no_alt)
{ no_alt = 0; skip = 1;} // the Dynarec will shadow the Entry Point, so using Intperter to enter the function
{
// the Dynarec will shadow the Entry Point, so using Intperter to enter the function
#if defined(DYNAREC) && defined(HAVE_ALTJUMP)
if(!BOX64ENV(dynarec))
#endif
no_alt = 0;
skip = 1;
}
else
R_RIP = (uintptr_t)getAlternate((void*)R_RIP);
#ifdef DYNAREC
@@ -228,6 +275,12 @@ void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
}
}
dynablock_t* block = (skip || ACCESS_FLAG(F_TF))?NULL:fastDBGetBlock(emu, R_RIP, 1, is32bits);
#ifdef HAVE_ALTJUMP
if(skip && no_alt) {
block = getDBnoAlt(emu, R_RIP, is32bits);
no_alt = 0;
}
#endif
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
// no block, or block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
+17
View File
@@ -37,6 +37,9 @@ extern uint32_t arm64_x31_hash(void* p, uint32_t len);
#define ARCH_CRC(A, B) if(cpuext.crc32) return arm64_crc(A, B); else return arm64_x31_hash(A, B)
extern void* create_updateflags();
#define ARCH_UPDATEFLAGS() create_updateflags()
#define ADDITIONNAL_CHECKS() additionnal_checks(dyn, ninst);
#define ARCH_CRC_INLINE
extern void arm64_next_invalid();
#define ARCH_NOP 0b11010101000000110010000000011111
#define ARCH_UDF 0xcafe
@@ -70,8 +73,16 @@ extern void* create_updateflags();
#define STOP_NATIVE_FLAGS(A, B) {}
#define ARCH_UNALIGNED(A, B) 0
extern uint32_t la64_crc(void* p, uint32_t len);
extern void la64_crc_autocrc(); // same as la64_crc, but not using regular ABI
#define ARCH_CRC(A, B) return la64_crc(A, B)
#define ARCH_NOP (0b0000001101<<22)
#define ARCH_UDF 0b1010100
#define JMPNEXT_SIZE (4*sizeof(void*))
#define ADDITIONNAL_CHECKS()
#define ARCH_CRC_INLINE
extern void la64_next_invalid();
#elif defined(RV64)
@@ -104,7 +115,12 @@ extern uint32_t la64_crc(void* p, uint32_t len);
#define ARCH_ADJUST(A, B, C, D) {}
#define STOP_NATIVE_FLAGS(A, B) {}
#define ARCH_UNALIGNED(A, B) arch_unaligned(A, B)
#define ARCH_NOP 0b0010011
#define ARCH_UDF 0xc0001073
#define JMPNEXT_SIZE (4*sizeof(void*))
#define ADDITIONNAL_CHECKS()
#elif defined(PPC64LE)
@@ -143,6 +159,7 @@ extern uint32_t ppc64le_fast_hash(void* p, uint32_t len);
// PPC64LE CreateJmpNext needs 5 instructions (20 bytes) for PC-relative load + branch,
// so the jmpnext area needs 5 void* slots (40 bytes) instead of the default 4 (32 bytes).
#define JMPNEXT_SIZE (5*sizeof(void*))
#define ADDITIONNAL_CHECKS()
#else
#error Unsupported platform
+7 -1
View File
@@ -207,10 +207,16 @@
#define SMDMB() DMB_ISH()
#endif
#ifndef PREFLAGSNEEDED
#define PREFLAGSNEEDED()
#endif
#define AREFLAGSNEEDED() \
PREFLAGSNEEDED() \
if((dyn->insts[ninst].x64.need_before&~X_PEND) && (!ninst || dyn->insts[ninst-1].x64.has_callret)) { \
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND); \
}
} \
ADDITIONNAL_CHECKS()
// Insert a Secondary Entry Point if it's asked, but only on block that are from file mapped memory (so some binary file)
// and that are not flagged as always_test (as this could slow down a bit, and the block is unsafe), unless SEP level 2 is asked
+19 -7
View File
@@ -419,7 +419,7 @@ dynablock_t* CreateEmptyBlock(uintptr_t addr, int is32bits, int is_new) {
return block;
}
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new) {
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt) {
/*
A Block must have this layout:
@@ -437,7 +437,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ;
uintptr_t old_addr = addr;
#ifdef HAVE_ALTJUMP
uintptr_t altjump = getAlternateJump((void*)addr, is32bits);
uintptr_t altjump = noalt?0:getAlternateJump((void*)addr, is32bits);
if(altjump) {
dynarec_log(LOG_INFO, "Building a Dynablock for %p with an alternate content at %p\n", (void*)addr, (void*)altjump);
addr = altjump;
@@ -487,6 +487,9 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
helper.next_cap = MAX_INSTS;
helper.table64 = NULL;
helper.env = GetCurEnvByAddr(addr);
if(getProtection(addr)&PROT_NEVERCLEAN) {
helper.always_test = 1;
}
ResetTable64(&helper);
helper.table64cap = 0;
helper.end = addr + SizeFileMapped(addr);
@@ -740,7 +743,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
--imax;
if(dyn->need_dump || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Dynablock oversized, with %zu (max=%zd), recomputing cutting at %d from %d\n", native_size, MAXBLOCK_SIZE, imax, helper.size);
CancelBlock64(0);
return FillBlock64(old_addr, is32bits, imax, is_new);
return FillBlock64(old_addr, is32bits, imax, is_new, noalt);
}
insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
@@ -789,6 +792,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
helper.sep = (sep_t*)seps;
block->prefixsize = helper.prefixsize;
block->table64 = helper.table64;
helper.dynablock = block;
if(callret_size)
memcpy(helper.callrets, static_callrets, helper.callret_size*sizeof(callret_t));
helper.callret_size = 0;
@@ -831,7 +835,13 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
block->isize = helper.size;
block->block = p;
block->jmpnext = next+sizeof(void*);
#ifdef ARCH_CRC_INLINE
block->always_test = 0;
block->autocrc = helper.always_test?1:0;
#else
block->always_test = helper.always_test;
block->autocrc = 0;
#endif
block->dirty = block->always_test;
block->is32bits = is32bits;
block->relocsize = helper.reloc_size*sizeof(uint32_t);
@@ -908,11 +918,13 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
block->dirty = 1;
//protectDB(addr, end-addr);
}
if(getProtection(addr)&PROT_NEVERCLEAN) {
block->always_test = 1;
}
else if(is_inhotpage)
#ifdef ARCH_CRC_INLINE
if(is_inhotpage && !block->autocrc)
block->always_test = 2;
#else
if(is_inhotpage)
block->always_test = 2;
#endif
if(block->always_test) {
dynarec_log(LOG_INFO, "Note: block marked as always dirty %p:%ld\n", block->x64_addr, block->x64_size);
#ifdef ARCH_NOP
+42 -4
View File
@@ -856,22 +856,60 @@ uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
}
#undef F8
void propagate_nodf(dynarec_native_t* dyn, int ninst)
#if defined(ARM64) || defined(LA64) || defined(PPC64LE)
static void propagate_dfneeded_internal(dynarec_native_t* dyn, int ninst)
{
while(ninst>=0) {
if(dyn->insts[ninst].df_needed)
return; // already flagged
dyn->insts[ninst].df_needed = 1;
if(dyn->insts[ninst].x64.gen_flags || (dyn->insts[ninst].x64.use_flags&X_PEND) || (dyn->insts[ninst].x64.need_before))
return; // flags are use, we can stop propagate there
if(!dyn->insts[ninst].pred_sz)
return;
for(int i=1; i<dyn->insts[ninst].pred_sz; ++i)
propagate_dfneeded_internal(dyn, dyn->insts[ninst].pred[i]);
ninst = dyn->insts[ninst].pred[0];
}
}
static void propagate_nodf_internal(dynarec_native_t* dyn, int ninst)
{
while(ninst>=0) {
if(dyn->insts[ninst].df_needed)
return; // flag are needed, stop
if(dyn->insts[ninst].df_notneeded)
return; // already flagged
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
return; // flags are use, so maybe it's needed
if(dyn->insts[ninst].x64.has_callret || (dyn->insts[ninst].x64.barrier&BARRIER_FLAGS))
return; // stop propagate
dyn->insts[ninst].df_notneeded = 1;
if(!dyn->insts[ninst].pred_sz)
return;
for(int i=1; i<dyn->insts[ninst].pred_sz; ++i)
propagate_nodf(dyn, dyn->insts[ninst].pred[i]);
propagate_nodf_internal(dyn, dyn->insts[ninst].pred[i]);
ninst = dyn->insts[ninst].pred[0];
}
}
void propagate_nodf(dynarec_native_t* dyn)
{
// first propagate the df_needed flag
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
if((dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)
|| (dyn->insts[ninst].x64.barrier&BARRIER_FLAGS) || (dyn->insts[ninst].x64.use_flags)
|| dyn->insts[ninst].x64.has_callret
|| ((dyn->insts[ninst].x64.state_flags&SF_SUB) && dyn->insts[ninst].x64.need_before)
)
propagate_dfneeded_internal(dyn, ninst);
}
// and now propagete df_unneeded
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
if(dyn->insts[ninst].f_exit!=status_unk && dyn->insts[ninst].x64.gen_flags)
propagate_nodf_internal(dyn, ninst);
}
}
#endif
void x64disas_add_register_mapping_annotations(char* buf, const char* disas, const register_mapping_t* mappings, size_t mappings_sz)
{
static char tmp[32];
+1 -1
View File
@@ -71,7 +71,7 @@ void native_div0(x64emu_t* emu);
// Caches transformation (for loops) // Specific, need to be written par backend
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
// propagete defererd to unknow, as state is not needed
void propagate_nodf(dynarec_native_t* dyn, int ninst);
void propagate_nodf(dynarec_native_t* dyn);
// predecessor access
int isPred(dynarec_native_t* dyn, int ninst, int pred);
+7
View File
@@ -127,10 +127,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
if(!ninst) {
if(dyn->have_purge)
doEnterBlock(dyn, 0, x1, x2, x3);
if(dyn->always_test)
checkCRC(dyn, 0);
if(dyn->insts[0].preload_xmmymm)
doPreload(dyn, 0);
ENDPREFIX;
}
#elif defined(LA64)
if(!ninst) {
if(dyn->always_test)
checkCRC(dyn, 0);
}
#endif
fpu_propagate_stack(dyn, ninst);
if (reset_n!=-1) {
+27 -6
View File
@@ -16,6 +16,7 @@
#include "callback.h"
#include "bridge.h"
#include "emu/x64run_private.h"
#include "../dynablock_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "custommem.h"
@@ -787,7 +788,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGD;
GETED(4);
i64 = F32S;
MOV64xw(x4, i64);
MOV64x(x4, i64);
CLEAR_FLAGS(x3);
if (rex.w) {
UFLAG_IF {
@@ -3381,7 +3382,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
// 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;
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI_D(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
@@ -3403,6 +3407,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
else
j64 = addr + i32;
jump_to_next(dyn, j64, 0, ninst, rex.is32bits);
int can_continue = (addr < (dyn->start + dyn->isize));
CALLRET_RET(can_continue);
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
@@ -3416,6 +3422,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LD_D(x4, x4, 0);
BR(x4);
}
CLEARIP();
break;
}
break;
@@ -4016,7 +4023,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
// 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;
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI_D(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
@@ -4032,6 +4042,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
int can_continue = (addr < (dyn->start + dyn->isize));
CALLRET_RET(can_continue);
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
@@ -4041,6 +4053,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
LD_D(x4, x4, 0);
BR(x4);
}
CLEARIP();
break;
case 3: // CALL FAR Ed
if (MODREG) {
@@ -4063,17 +4076,24 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
*ok = 0;
}
GETIP_(addr, x7);
int can_continue = (addr < (dyn->start + dyn->isize));
if (BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
// Push actual return address. Note that CS will not be tested, but that should be ok?
if (addr < (dyn->start + dyn->isize)) {
if (can_continue) {
// there is a next...
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI_D(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
} else {
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI_D(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
@@ -4091,6 +4111,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
ST_H(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
CALLRET_RET(can_continue);
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
// jumps out of current dynablock...
MARK;
+52 -16
View File
@@ -928,7 +928,25 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETEX(q0, 0, 0);
GETGX(v0, 1);
if (!BOX64ENV(dynarec_fastnan)) {
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_S(v1, q0, v0, cUN);
VFCMP_S(d0, v0, v0, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(d1, x5);
VOR_V(d1, v0, d1);
}
VFADD_S(v0, v0, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(v0, v0, d1, d0);
VFCMP_S(d0, v0, v0, cUN);
VANDN_V(v1, v1, d0);
VLDI(d0, 0b011111111100);
VSLLI_W(d0, d0, 20);
VBITSEL_V(v0, v0, d0, v1);
}
break;
case 0x59:
INST_NAME("MULPS Gx, Ex");
@@ -938,17 +956,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
VFCMP_S(d0, q1, q1, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(v1, x5);
VOR_V(v1, q1, v1);
}
VFMUL_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, v1, d0);
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VLDI(v1, 0b011111111100);
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5A:
@@ -973,17 +995,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
VFCMP_S(d0, q1, q1, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(v1, x5);
VOR_V(v1, q1, v1);
}
VFSUB_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, v1, d0);
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VLDI(v1, 0b011111111100);
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5D:
@@ -1003,17 +1029,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
d0 = fpu_get_scratch(dyn);
VFCMP_S(v0, q0, q1, cUN);
VFCMP_S(d0, q1, q1, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(v1, x5);
VOR_V(v1, q1, v1);
}
VFDIV_S(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, v1, d0);
VFCMP_S(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
VLDI(v1, 0b011111111100);
VSLLI_W(v1, v1, 20);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5F:
@@ -1966,13 +1996,16 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
}
B_MARK2_nocond;
MARK;
CTZxw(gd, ed);
MARK2;
IFX (BOX64DRENV(dynarec_safeflags)) {
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
MARK2;
SPILL_EFLAGS();
break;
case 0xBD:
@@ -1993,15 +2026,18 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
}
B_MARK2_nocond;
MARK;
CLZxw(gd, ed);
ADDI_D(x1, xZR, rex.w ? 63 : 31);
SUB_D(gd, x1, gd);
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
MARK2;
SPILL_EFLAGS();
break;
case 0xBE:
@@ -2060,8 +2096,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETED(0);
if (ed != gd) MV(x7, ed);
emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
if (ed != gd) MVxw(gd, x7);
WBACK;
if (ed != gd) MVxw(gd, x7);
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
+84 -32
View File
@@ -1367,8 +1367,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 1);
}
MV(x2, xRDX);
MV(x4, xRAX);
SEXT_W(x2, xRDX);
SEXT_W(x4, xRAX);
u8 = F8;
MOV32w(x5, u8);
CALL6(const_sse42_compare_string_explicit_len, x1, ed, x2, x3, x4, x5, 0);
@@ -1541,17 +1541,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q1, q0, cUN);
VFCMP_D(d0, q1, q1, cUN);
VLDI(d1, (0b011 << 10) | 0b0000001000);
VSLLI_D(d1, d1, 48);
VOR_V(d1, q1, d1);
}
VFADD_D(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, d1, d0);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x59:
@@ -1562,17 +1567,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q1, q0, cUN);
VFCMP_D(d0, q1, q1, cUN);
VLDI(d1, (0b011 << 10) | 0b0000001000);
VSLLI_D(d1, d1, 48);
VOR_V(d1, q1, d1);
}
VFMUL_D(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, d1, d0);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5A:
@@ -1621,17 +1631,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q1, q0, cUN);
VFCMP_D(d0, q1, q1, cUN);
VLDI(d1, (0b011 << 10) | 0b0000001000);
VSLLI_D(d1, d1, 48);
VOR_V(d1, q1, d1);
}
VFSUB_D(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, d1, d0);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5D:
@@ -1654,17 +1669,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64ENV(dynarec_fastnan)) {
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q0, q1, cUN);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_D(v0, q1, q0, cUN);
VFCMP_D(d0, q1, q1, cUN);
VLDI(d1, (0b011 << 10) | 0b0000001000);
VSLLI_D(d1, d1, 48);
VOR_V(d1, q1, d1);
}
VFDIV_D(q1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q1, q1, d1, d0);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x5F:
@@ -2044,13 +2064,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
VFADD_D(q1, d0, q1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
VFCMP_D(d1, d0, d0, cUN);
VLDI(v1, (0b011 << 10) | 0b0000001000);
VSLLI_D(v1, v1, 48);
VOR_V(d0, d0, v1);
VBITSEL_V(q1, q1, d0, d1);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x7D:
@@ -2068,13 +2092,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
VFSUB_D(q1, d0, q1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
VFCMP_D(d1, d0, d0, cUN);
VLDI(v1, (0b011 << 10) | 0b0000001000);
VSLLI_D(v1, v1, 48);
VOR_V(d0, d0, v1);
VBITSEL_V(q1, q1, d0, d1);
VFCMP_D(v1, q1, q1, cUN);
VANDN_V(v0, v0, v1);
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
VLDI(v1, (0b011 << 10) | 0b1111111000);
VSLLI_D(v1, v1, 48);
VAND_V(v1, v0, v1);
VANDN_V(v0, v0, q1);
VOR_V(q1, v0, v1);
VBITSEL_V(q1, q1, v1, v0);
}
break;
case 0x7E:
@@ -2503,16 +2531,19 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGWEW(x4, x5, 0);
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
}
B_MARK2_nocond;
MARK;
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
CTZ_D(gd, ed);
GWBACK;
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
}
MARK2;
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBD:
@@ -2527,6 +2558,9 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGWEW(x4, x5, 0);
BNE_MARK(ed, xZR);
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
}
B_MARK2_nocond;
MARK;
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
@@ -2535,10 +2569,10 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
ADDI_D(x1, xZR, 63);
SUB_D(gd, x1, gd);
GWBACK;
MARK2;
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
}
MARK2;
IFX (X_ALL) SPILL_EFLAGS();
break;
case 0xBE:
@@ -2671,10 +2705,28 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
d2 = fpu_get_scratch(dyn);
VFCMP_D(d0, q0, q1, cUN);
VFCMP_D(d1, q0, q0, cUN);
VLDI(d2, (0b011 << 10) | 0b0000001000);
VSLLI_D(d2, d2, 48);
VOR_V(d2, q0, d2);
}
v0 = fpu_get_scratch(dyn);
VFSUB_D(v0, q0, q1);
VFADD_D(q0, q0, q1);
VEXTRINS_D(q0, v0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q0, q0, d2, d1);
VFCMP_D(d2, q0, q0, cUN);
VANDN_V(d0, d0, d2);
VLDI(d2, (0b011 << 10) | 0b1111111000);
VSLLI_D(d2, d2, 48);
VBITSEL_V(q0, q0, d2, d0);
}
break;
case 0xD1:
INST_NAME("PSRLW Gx, Ex");
+1 -1
View File
@@ -381,7 +381,7 @@ uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
IFXORNAT (X_ALL | X_PEND) {
BSTRPICK_D(x6, x1, 15, 0);
emit_add16(dyn, ninst, x6, gd, x3, x4, x5);
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
}
BSTRINS_D(gd, x1, 15, 0);
}
+32 -4
View File
@@ -354,14 +354,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, d0, v1, v2, cUN);
VFCMPxy(S, q0, v1, v1, cUN);
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, q1, q1, 20);
VOR_Vxy(q1, v1, q1);
}
VFADDxy(S, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -372,14 +379,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, d0, v1, v2, cUN);
VFCMPxy(S, q0, v1, v1, cUN);
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, q1, q1, 20);
VOR_Vxy(q1, v1, q1);
}
VFMULxy(S, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -425,14 +439,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, d0, v1, v2, cUN);
VFCMPxy(S, q0, v1, v1, cUN);
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, q1, q1, 20);
VOR_Vxy(q1, v1, q1);
}
VFSUBxy(S, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -452,14 +473,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, d0, v1, v2, cUN);
VFCMPxy(S, q0, v1, v1, cUN);
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, q1, q1, 20);
VOR_Vxy(q1, v1, q1);
}
VFDIVxy(S, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
+4 -1
View File
@@ -78,6 +78,9 @@ uintptr_t dynarec64_AVX_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
BNEZ(gd, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
}
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
SPILL_EFLAGS();
break;
case 0xF3:
@@ -199,7 +202,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
break;
case 0xF7:
INST_NAME("BEXTR Gd, Vd, Ed");
INST_NAME("BEXTR Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETGD;
+60 -14
View File
@@ -327,14 +327,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, d0, v1, v2, cUN);
VFCMPxy(D, q0, v1, v1, cUN);
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, q1, q1, 48);
VOR_Vxy(q1, v1, q1);
}
VFADDxy(D, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -345,14 +352,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, d0, v1, v2, cUN);
VFCMPxy(D, q0, v1, v1, cUN);
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, q1, q1, 48);
VOR_Vxy(q1, v1, q1);
}
VFMULxy(D, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -420,14 +434,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, d0, v1, v2, cUN);
VFCMPxy(D, q0, v1, v1, cUN);
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, q1, q1, 48);
VOR_Vxy(q1, v1, q1);
}
VFSUBxy(D, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -447,14 +468,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, d0, v1, v2, cUN);
VFCMPxy(D, q0, v1, v1, cUN);
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, q1, q1, 48);
VOR_Vxy(q1, v1, q1);
}
VFDIVxy(D, v0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, q1, q0);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -793,10 +821,16 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
VFADDxy(D, v0, q0, v0);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, q1, q0, q0, cUN);
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, d1, d1, 48);
VOR_Vxy(d1, q0, d1);
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -814,10 +848,16 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
VFSUBxy(D, v0, q0, v0);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, q1, q0, q0, cUN);
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, d1, d1, 48);
VOR_Vxy(d1, q0, d1);
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -945,17 +985,23 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(D, d0, v1, v2, cUN);
VFCMPxy(D, q1, v1, v1, cUN);
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
VSLLIxy(D, d1, d1, 48);
VOR_Vxy(d1, v1, d1);
}
q0 = fpu_get_scratch(dyn);
VFSUBxy(D, q0, v1, v2);
VFADDxy(D, v0, v1, v2);
VEXTRINSxy(D, v0, q0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(D, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b011 << 9) | 0b111111000);
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
VSLLIxy(D, d1, d1, 48);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
+62 -14
View File
@@ -220,13 +220,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FADD_D(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_D(v0, d0, 0);
break;
@@ -239,13 +246,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FMUL_D(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_D(v0, d0, 0);
break;
@@ -269,13 +283,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FSUB_D(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_D(v0, d0, 0);
break;
@@ -304,13 +325,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FDIV_D(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_D(v0, d0, 0);
break;
@@ -358,10 +386,16 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
VFADDxy(S, v0, q0, v0);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, q1, q0, q0, cUN);
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, d1, d1, 20);
VOR_Vxy(d1, q0, d1);
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -379,10 +413,16 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
VFSUBxy(S, v0, q0, v0);
if (!BOX64ENV(dynarec_fastnan)) {
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, q1, q0, q0, cUN);
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, d1, d1, 20);
VOR_Vxy(d1, q0, d1);
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -422,7 +462,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VFCMPxy(S, d0, v1, v2, cUN);
VFCMPxy(S, q1, v1, v1, cUN);
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
VSLLIxy(W, d1, d1, 20);
VOR_Vxy(d1, v1, d1);
}
q0 = fpu_get_scratch(dyn);
VFSUBxy(S, q0, v1, v2);
@@ -430,10 +475,11 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(0, 0));
VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(2, 2));
if (!BOX64ENV(dynarec_fastnan)) {
VFCMPxy(S, d1, v0, v0, cUN);
VANDN_Vxy(d0, d0, d1);
VBITSEL_Vxy(v0, v0, d1, q1);
VFCMPxy(S, q1, v0, v0, cUN);
VANDN_Vxy(d0, d0, q1);
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
VSLLIxy(W, d1, d1, 20);
VBITSEL_Vxy(v0, v0, d1, d0);
}
break;
@@ -445,21 +491,23 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
u8 = sse_setround(dyn, ninst, x1, x2);
d0 = fpu_get_scratch(dyn);
if (vex.l) {
XVXOR_V(d0, d0, d0);
XVFTINT_W_D(v0, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
if (!BOX64ENV(dynarec_fastround)) {
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
q2 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
XVFTINT_L_D(q2, v1);
XVFCMP_D(d1, v1, v1, cUN); // get NaN mask
}
XVXOR_V(d0, d0, d0);
XVFTINT_W_D(v0, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
if (!BOX64ENV(dynarec_fastround)) {
XVLDI(q0, 0b1001110000000); // broadcast 0x80000000 to all
MOV32w(x5, 0x7FFFFFFF);
BSTRPICK_D(x5, x5, 31, 0);
XVREPLGR2VR_D(q1, x5);
XVFCMP_D(d0, v1, v1, cUN); // get Nan mask
XVSLT_D(d1, q1, q2); // get +inf mask
XVOR_V(d0, d1, d0);
XVSLT_D(d0, q1, q2); // get +inf mask
XVOR_V(d0, d0, d1); // combine with NaN mask
XVSRLNI_W_D(d0, d0, 0); // [A,B,C,D] => [a,b,--,--,c,d,--,--]
XVBITSEL_V(v0, v0, q0, d0);
}
+32 -4
View File
@@ -242,13 +242,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FADD_S(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_S(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_W(v0, d0, 0);
break;
@@ -266,8 +273,15 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
FCMP_S(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d0, d0);
MARK;
d1 = fpu_get_scratch(dyn);
MOVFR2GR_D(x4, v1);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_S(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_W(v0, d0, 0);
break;
@@ -325,13 +339,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FSUB_S(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_S(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_W(v0, d0, 0);
break;
@@ -356,13 +377,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
d0 = fpu_get_scratch(dyn);
FDIV_S(d0, v1, v2);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v1, v2, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d0, d0);
MARK;
MOVFR2GR_D(x4, v1);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_S(fcc0, v1, v1, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_W(v0, d0, 0);
break;
+2
View File
@@ -78,6 +78,8 @@ uintptr_t getConst(la64_consts_t which)
case const_native_fstp: return (uintptr_t)native_fstp;
case const_native_frstor: return (uintptr_t)native_frstor;
case const_native_next: return (uintptr_t)native_next;
case const_native_next_invalid: return (uintptr_t)la64_next_invalid;
case const_la64_crc_autocrc: return (uintptr_t)la64_crc_autocrc;
case const_int3: return (uintptr_t)EmuInt3;
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
+2
View File
@@ -48,6 +48,8 @@ typedef enum la64_consts_s {
const_native_fstp,
const_native_frstor,
const_native_next,
const_native_next_invalid,
const_la64_crc_autocrc,
const_int3,
const_x86syscall,
const_x64syscall,
+1 -1
View File
@@ -1675,7 +1675,7 @@ void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
}
}
IFX (X_SF) {
BSTRPICK_D(s5, s1, 31, 31);
BSTRPICK_D(s5, s1, rex.w ? 63 : 31, rex.w ? 63 : 31);
BSTRINS_D(xFlags, s5, F_SF, F_SF);
}
if (!rex.w) ZEROUP(s1);
+6 -1
View File
@@ -58,6 +58,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
AMADD_DB_B(x1, gd, wback);
ANDI(x1, x1, 0xff);
} else {
LOCK_8_OP(ADD_D(x4, x1, gd), x1, wback, x3, x4, x5, x6);
}
@@ -1132,6 +1133,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("LOCK ADC Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (cpuext.lbt) {
@@ -1192,6 +1194,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("LOCK SBB Ed, Ib");
}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
if (cpuext.lbt) {
@@ -1524,7 +1527,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (cpuext.lamcas) {
LD_WU(x1, wback, 0);
SUB_W(x4, xZR, x1);
MV(x6, x1);
SEXT_W(x6, x1);
AMCAS_DB_W(x1, x4, wback);
BNE(x6, x1, -4 * 3);
} else {
@@ -1573,6 +1576,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
AMADD_DB_B(x1, x7, wback);
ANDI(x1, x1, 0xff);
} else {
LOCK_8_OP(ADD_D(x4, x1, x7), x1, wback, x3, x4, x5, x6);
}
@@ -1594,6 +1598,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lam_bh) {
AMADD_DB_B(x1, x7, wback);
ANDI(x1, x1, 0xff);
} else {
LOCK_8_OP(ADD_D(x4, x1, x7), x1, wback, x3, x4, x5, x6);
}
+84 -4
View File
@@ -220,13 +220,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d0 = fpu_get_scratch(dyn);
FADD_D(d0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v0);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v0, v0, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x59:
@@ -237,13 +244,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d0 = fpu_get_scratch(dyn);
FMUL_D(d0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v0);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v0, v0, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5A:
@@ -263,13 +277,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d0 = fpu_get_scratch(dyn);
FSUB_D(d0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v0);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v0, v0, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5D:
@@ -293,13 +314,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d0 = fpu_get_scratch(dyn);
FDIV_D(d0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
FCMP_D(fcc0, v0, v1, cUN);
BCNEZ_MARK(fcc0);
FCMP_D(fcc1, d0, d0, cOR);
BCNEZ_MARK(fcc1);
FNEG_D(d0, d0);
MARK;
MOVFR2GR_D(x4, v0);
MOV64x(x5, 0x0008000000000000LL);
OR(x4, x4, x5);
MOVGR2FR_D(d1, x4);
FCMP_D(fcc0, v0, v0, cUN);
FSEL(d0, d0, d1, fcc0);
}
MARK;
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
break;
case 0x5F:
@@ -339,7 +367,24 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
v1 = fpu_get_scratch(dyn);
VPICKEV_W(v0, q1, q0);
VPICKOD_W(v1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_S(d0, v0, v0, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(d1, x5);
VOR_V(d1, v0, d1);
}
VFADD_S(q0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q0, q0, d1, d0);
VFCMP_S(d1, q0, q0, cUN);
VFCMP_S(d0, v0, v1, cUN);
VANDN_V(d0, d0, d1);
VLDI(d1, 0b011111111100);
VSLLI_W(d1, d1, 20);
VBITSEL_V(q0, q0, d1, d0);
}
break;
case 0x7D:
INST_NAME("HSUBPS Gx, Ex");
@@ -350,7 +395,24 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
v1 = fpu_get_scratch(dyn);
VPICKEV_W(v0, q1, q0);
VPICKOD_W(v1, q1, q0);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFCMP_S(d0, v0, v0, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(d1, x5);
VOR_V(d1, v0, d1);
}
VFSUB_S(q0, v0, v1);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q0, q0, d1, d0);
VFCMP_S(d1, q0, q0, cUN);
VFCMP_S(d0, v0, v1, cUN);
VANDN_V(d0, d0, d1);
VLDI(d1, 0b011111111100);
VSLLI_W(d1, d1, 20);
VBITSEL_V(q0, q0, d1, d0);
}
break;
case 0xAE:
nextop = F8;
@@ -391,11 +453,29 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
if (!BOX64ENV(dynarec_fastnan)) {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
VFCMP_S(d0, q0, q1, cUN);
VFCMP_S(d1, q0, q0, cUN);
MOV32w(x5, 0x00400000);
VREPLGR2VR_W(v1, x5);
VOR_V(v1, q0, v1);
}
v0 = fpu_get_scratch(dyn);
VFSUB_S(v0, q0, q1);
VFADD_S(q0, q0, q1);
VEXTRINS_W(q0, v0, 0);
VEXTRINS_W(q0, v0, 0b00100010);
if (!BOX64ENV(dynarec_fastnan)) {
VBITSEL_V(q0, q0, v1, d1);
VFCMP_S(d1, q0, q0, cUN);
VANDN_V(d0, d0, d1);
VLDI(d1, 0b011111111100);
VSLLI_W(d1, d1, 20);
VBITSEL_V(q0, q0, d1, d0);
}
break;
case 0xD6:
INST_NAME("MOVDQ2Q Gm, Ex");
+53 -1
View File
@@ -308,6 +308,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FADD_S(d1, v0, d0);
if (!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v0, d0, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d1, d1, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d1, d1);
MARK;
MOVFR2GR_D(x4, v0);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(q0, x4);
FCMP_S(fcc0, v0, v0, cUN);
FSEL(d1, d1, q0, fcc0);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x59:
@@ -317,6 +332,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FMUL_S(d1, v0, d0);
if (!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v0, d0, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d1, d1, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d1, d1);
MARK;
MOVFR2GR_D(x4, v0);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(q0, x4);
FCMP_S(fcc0, v0, v0, cUN);
FSEL(d1, d1, q0, fcc0);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x5A:
@@ -360,6 +390,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
d1 = fpu_get_scratch(dyn);
GETEXSS(d0, 0, 0);
FSUB_S(d1, v0, d0);
if (!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v0, d0, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d1, d1, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d1, d1);
MARK;
MOVFR2GR_D(x4, v0);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(q0, x4);
FCMP_S(fcc0, v0, v0, cUN);
FSEL(d1, d1, q0, fcc0);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x5D:
@@ -380,13 +425,20 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEXSS(d0, 0, 0);
FDIV_S(d1, v0, d0);
if (!BOX64ENV(dynarec_fastnan)) {
q0 = fpu_get_scratch(dyn);
FCMP_S(fcc0, v0, d0, cUN);
BCNEZ_MARK(fcc0);
FCMP_S(fcc1, d1, d1, cOR);
BCNEZ_MARK(fcc1);
FNEG_S(d1, d1);
MARK;
MOVFR2GR_D(x4, v0);
MOV32w(x5, 0x00400000);
OR(x4, x4, x5);
MOVGR2FR_D(q0, x4);
FCMP_S(fcc0, v0, v0, cUN);
FSEL(d1, d1, q0, fcc0);
}
MARK;
VEXTRINS_W(v0, d1, 0);
break;
case 0x5F:
+21
View File
@@ -2280,3 +2280,24 @@ void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val)
}
LU52I_D(reg, reg, (val >> 52) & 0xfff);
}
void checkCRC(dynarec_la64_t* dyn, int ninst)
{
// la64_crc_autocrc will use x1-x5 instead of A0-A4 to avoind having to move around the regs
// grab the dynablock address in x6, as this on will not be erased by crc functions
int delta = -(dyn->native_size + sizeof(void*));
PCADDU12I(x6, SPLIT20(delta));
LD_D(x6, x6, SPLIT12(delta));
// prepare and call the crc function
TABLE64C(x3, const_la64_crc_autocrc);
LD_D(x1, x6, offsetof(dynablock_t, x64_addr));
LD_WU(x2, x6, offsetof(dynablock_t, x64_size));
JIRL(xRA, x3, 0x0);
// done, result in x1, load the stored hash (sign extended, as the crc will also be sign extended)
LD_W(x2, x6, offsetof(dynablock_t, hash));
// compare computed crc with stored one, jump to continue is equal
BEQ(x1, x2, 4+3*4); // TABLE64C generates 2 opcodes...
TABLE64C(x3, const_native_next_invalid);
JIRL(xRA, x3, 0x0);
}
+19 -1
View File
@@ -1028,6 +1028,15 @@
#ifndef SET_HASCALLRET
#define SET_HASCALLRET()
#endif
#ifndef CALLRET_RET
#define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0)
#endif
#ifndef CALLRET_GETRET
#define CALLRET_GETRET() (dyn->callrets?(dyn->callrets[dyn->callret_size].offs-dyn->native_size):0)
#endif
#ifndef CALLRET_LOOP
#define CALLRET_LOOP() NOP()
#endif
#define UFLAG_OP1(A) \
if (dyn->insts[ninst].x64.gen_flags) { SDxw(A, xEmu, offsetof(x64emu_t, op1)); }
#define UFLAG_OP2(A) \
@@ -1066,6 +1075,11 @@
#define ARCH_RESET()
#undef PREFLAGSNEEDED
#define PREFLAGSNEEDED() \
if(dyn->always_test && ninst && (dyn->insts[ninst].sep || (ninst && dyn->insts[ninst-1].x64.has_callret))) \
checkCRC(dyn, ninst);
#if STEP < 2
#define GETIP(A, scratch)
#define GETIP_(A, scratch)
@@ -1310,7 +1324,6 @@
#define avx_reflect_reg_upper128 STEPNAME(avx_reflect_reg_upper128)
#define avx_cleancache STEPNAME(avx_cleancache)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
@@ -1320,6 +1333,8 @@
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
#define checkCRC STEPNAME(checkCRC)
#define CacheTransform STEPNAME(CacheTransform)
#define la64_move64 STEPNAME(la64_move64)
#define la64_move32 STEPNAME(la64_move32)
@@ -1530,6 +1545,9 @@ void avx_reflect_reg(dynarec_la64_t* dyn, int ninst, int a);
void avx_reflect_reg_upper128(dynarec_la64_t* dyn, int ninst, int a, int forwrite);
void avx_cleancache(dynarec_la64_t* dyn, int ninst);
// in case of always_test, this insert a check of crc of the dynablock (and exit to ArmNext if wrong)
void checkCRC(dynarec_la64_t* dyn, int ninst);
void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val);
+9
View File
@@ -57,3 +57,12 @@
EMIT(0); \
EMIT(0); \
} while (0)
#define CALLRET_RET(A) do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
} \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
} \
} while(0)
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
+18
View File
@@ -63,3 +63,21 @@
PCADDU12I(A, SPLIT20(val64offset)); \
LD_D(A, A, SPLIT12(val64offset)); \
} while (0)
#define CALLRET_RET(A) \
do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
MESSAGE(LOG_DUMP, " Dynablock*\n"); \
dyn->block += sizeof(void*); \
dyn->native_size+=sizeof(void*); \
dyn->insts[ninst].size2 += sizeof(void*); \
dyn->sep[dyn->sep_size].x64_offs = addr - dyn->start; \
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
++dyn->sep_size; \
} \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; \
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
EMIT(ARCH_NOP); \
} \
} while(0)
#define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
+3 -1
View File
@@ -110,7 +110,9 @@ typedef struct instruction_la64_s {
uint8_t will_read:1; // [strongmem] will read from memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t df_notneeded;
uint8_t df_needed:1;
uint8_t df_notneeded:1;
uint8_t sep:1; // opcode is a secondary entry point
uint8_t nat_flags_fusion:1;
uint8_t nat_flags_nofusion:1;
uint8_t nat_flags_carry:1;
+23
View File
@@ -32,6 +32,7 @@
.global la64_lock_get_d
.global la64_lock_get_dd
.global la64_crc
.global la64_crc_autocrc
la64_lock_xchg_b:
.word 0x385e1486 // amswap_db.b $a2, $a1, $a0
@@ -252,5 +253,27 @@ la64_crc:
addi.d $a2, $a2, 1
addi.w $a1, $a1, -1
bnez $a1, 3b
4:
ret
la64_crc_autocrc:
move $t4, $t2
xor $t2, $t2, $t2
li.d $t5, 8
1:
bltu $t3, $t5, 2f
ld.d $t6, $t4, 0
crc.w.d.w $t2, $t6, $t2
addi.d $t4, $t4, 8
addi.w $t3, $t3, -8
bnez $t3, 1b
2:
beqz $t3, 4f
3:
ld.bu $t6, $t4, 0
crc.w.b.w $t2, $t6, $t2
addi.d $t4, $t4, 1
addi.w $t3, $t3, -1
bnez $t3, 3b
4:
ret
+42
View File
@@ -11,8 +11,10 @@
.align 4
.extern LinkNext
.extern LinkNextInvalid
.global la64_next
.global la64_next_invalid
.8byte 0 // NULL pointer before la64_next, for getDB
la64_next:
@@ -54,3 +56,43 @@ la64_next:
addi.d $sp, $sp, (8 * 11)
// return offset is jump address
jr $r16
la64_next_invalid:
// move emu to a0
// move IP address to a1
addi.d $sp, $sp, -(8 * 11)
st.d RDI, $sp, 0
st.d RSI, $sp, 8
st.d RDX, $sp, 16
st.d RCX, $sp, 24
st.d R8, $sp, 32
st.d R9, $sp, 40
st.d RAX, $sp, 48
st.d RBX, $sp, 56
st.d RSP, $sp, 64
st.d RBP, $sp, 72
st.d RIP, $sp, 80 // also save r29(rip) to allow change in LinkNext
move $a0, Emu
move $a1, RIP
move $a2, $ra // "from" is in ra, so put in a2
addi.d $a3, $sp, 80 // a3 is address to change rip
// call the function
bl LinkNextInvalid
// preserve return value
move $r16, $a0
// pop regs
ld.d RDI, $sp, 0
ld.d RSI, $sp, 8
ld.d RDX, $sp, 16
ld.d RCX, $sp, 24
ld.d R8, $sp, 32
ld.d R9, $sp, 40
ld.d RAX, $sp, 48
ld.d RBX, $sp, 56
ld.d RSP, $sp, 64
ld.d RBP, $sp, 72
ld.d RIP, $sp, 80
addi.d $sp, $sp, (8 * 11)
// return offset is jump address
jr $r16
+1 -1
View File
@@ -539,7 +539,7 @@ uintptr_t dynarec64_00(dynarec_ppc64le_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGD;
GETED(4);
i64 = F32S;
MOV64xw(x4, i64);
MOV64x(x4, i64);
CLEAR_FLAGS(x3);
if (rex.w) {
UFLAG_IF {
@@ -124,6 +124,7 @@ typedef struct instruction_ppc64le_s {
uint8_t will_read:1; // [strongmem] will read from memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t df_needed:1;
uint8_t df_notneeded:1;
uint8_t nat_flags_fusion:1;
uint8_t nat_flags_nofusion:1;
+1 -1
View File
@@ -226,7 +226,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGD;
GETED(4);
i64 = F32S;
MOV64xw(x4, i64);
MOV64x(x4, i64);
if (rex.w) {
// 64bits imul
UFLAG_IF {
+163 -20
View File
@@ -10,6 +10,7 @@
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "../dynablock_private.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
@@ -37,6 +38,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
int64_t i64, j64;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint16_t u16;
uint32_t u32;
uint64_t u64;
uint8_t wback, wb1, wb2, wb;
@@ -283,9 +285,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (BOX64DRENV(dynarec_safeflags)) {
READFLAGS(X_PEND); // lets play safe here too
}
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
i32 = F16;
retn_to_epilog(dyn, ip, ninst, rex, i32);
BARRIER(BARRIER_FLOAT);
u16 = F16;
POP1z(xRIP);
if (u16 < 0x7ff)
ADDIz(xRSP, xRSP, u16);
else {
MOV32w(x1, u16);
ADDz(xRSP, xRSP, x1);
}
ret_to_next(dyn, ip, ninst, rex);
*need_epilog = 0;
*ok = 0;
break;
@@ -295,8 +304,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (BOX64DRENV(dynarec_safeflags)) {
READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost
}
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
ret_to_epilog(dyn, ip, ninst, rex);
BARRIER(BARRIER_FLOAT);
POP1z(xRIP);
ret_to_next(dyn, ip, ninst, rex);
*need_epilog = 0;
*ok = 0;
break;
@@ -432,7 +442,45 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
MVz(xRSP, xRBP);
POP1z(xRBP);
break;
case 0xCA:
INST_NAME("FAR RETN");
u16 = F16;
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
if (rex.w) {
POP1(xRIP);
POP1(x3);
} else {
POP1_32(xRIP);
POP1_32(x3);
}
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
if (u16 < 2048)
ADDIz(xRSP, xRSP, u16);
else {
MOV32w(x1, u16);
ADDz(xRSP, xRSP, x1);
}
ret_to_next(dyn, ip, ninst, rex);
*need_epilog = 0;
*ok = 0;
break;
case 0xCB:
INST_NAME("FAR RET");
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
if (rex.w) {
POP1(xRIP);
POP1(x3);
} else {
POP1_32(xRIP);
POP1_32(x3);
}
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
ret_to_next(dyn, ip, ninst, rex);
*need_epilog = 0;
*ok = 0;
break;
case 0xCC:
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack, set all flags (to an unknown state...)
SKIPTEST(x1);
@@ -559,7 +607,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("IRET");
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored
BARRIER(BARRIER_FLOAT);
iret_to_epilog(dyn, ip, ninst, rex.w);
iret_to_next(dyn, ip, ninst, rex.is32bits, rex.w);
*need_epilog = 0;
*ok = 0;
break;
@@ -1093,13 +1141,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
}
fpu_purgecache(dyn, ninst, 1, x1, x3, x4);
PUSH1z(x2);
int can_continue = (addr < (dyn->start + dyn->isize));
if (BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
// Push actual return address
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
if(can_continue) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
ADDI(xSP, xSP, -16);
SD(x4, xSP, 0);
SD(x2, xSP, 8);
@@ -1112,10 +1172,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
else
j64 = addr + i32;
jump_to_next(dyn, j64, 0, ninst, rex.is32bits);
CALLRET_RET(can_continue);
MARK;
if (BOX64DRENV(dynarec_callret) && dyn->vector_sew != VECTOR_SEWNA)
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
if (BOX64DRENV(dynarec_callret) && !can_continue) {
// jumps out of current dynablock...
j64 = getJumpTableAddress64(addr);
if (dyn->need_reloc) {
@@ -1127,6 +1188,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
LD(x4, x4, 0);
BR(x4);
}
CLEARIP();
break;
}
break;
@@ -1649,27 +1711,108 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETIP_(addr, x7);
if (BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff);
ADDI(x4, x4, j64 & 0xfff);
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
ADDI(xSP, xSP, -16);
SD(x4, xSP, 0);
SD(xRIP, xSP, 8);
}
PUSH1z(xRIP);
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
int can_continue = (addr < (dyn->start + dyn->isize));
CALLRET_RET(can_continue);
MARK;
if (BOX64DRENV(dynarec_callret) && dyn->vector_sew != VECTOR_SEWNA)
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
if (BOX64DRENV(dynarec_callret) && !can_continue) {
// jumps out of current dynablock...
j64 = getJumpTableAddress64(addr);
if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
TABLE64_(x4, j64);
LD(x4, x4, 0);
BR(x4);
}
CLEARIP();
break;
case 3: // CALL FAR Ed
if(MODREG) {
DEFAULT;
} else {
INST_NAME("CALL FAR Ed");
PASS2IF ((BOX64DRENV(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, NAT_FLAGS_NOFUSION); // Hack to put flag in "don't care" state
}
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
LDz(x1, wback, 0);
ed = x1;
LHU(x3, wback, rex.w?8:4);
LHU(x5, xEmu, offsetof(x64emu_t, segs[_CS]));
if (BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock) > 1) {
BARRIER(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
GETIP_(addr, x7);
if (BOX64DRENV(dynarec_callret)) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
j64 = CALLRET_GETRET();
else
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
} else {
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
AUIPC(x4, SPLIT20(j64));
ADDI(x4, x4, SPLIT12(j64));
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
}
ADDI(xSP, xSP, -16);
SD(x4, xSP, 0);
SD(xRIP, xSP, 8);
}
PUSH1z(x5);
PUSH1z(xRIP);
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
int can_continue = (addr < (dyn->start + dyn->isize));
CALLRET_RET(can_continue);
MARK;
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
if (BOX64DRENV(dynarec_callret) && !can_continue) {
// jumps out of current dynablock...
j64 = getJumpTableAddress64(addr);
if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
TABLE64_(x4, j64);
LD(x4, x4, 0);
BR(x4);
}
CLEARIP();
}
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
+1 -2
View File
@@ -2460,9 +2460,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (ed != gd)
MV(x7, ed);
emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
if (ed != gd)
MVxw(gd, x7);
WBACK;
if (ed != gd) MVxw(gd, x7);
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
+5 -1
View File
@@ -260,7 +260,11 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0x29:
INST_NAME("MOVAPS Ex, Gx");
nextop = F8;
SET_ELEMENT_WIDTH(x1, VECTOR_SEWANY, 1);
// on SteamRT3 with Gameoverlay, repear will crash immediatly on a Milk-V Pioneer machine
// doing movaps xmmword ptr ss:[rsp+0x10], xmm4 with rsp that seems 4-bytes aligned
// so changed VECTOR_SEWANY to VECTOR_SEW32 instead (to also be coherent with PS size)
//TODO: check what is really happening here
SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1);
GETGX_vector(v0, 0, dyn->vector_eew);
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
+12 -49
View File
@@ -487,19 +487,18 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
#endif
}
void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
{
MAYUSE(dyn);
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Ret to epilog\n");
POP1z(xRIP);
MESSAGE(LOG_DUMP, "Ret to next\n");
MVz(x1, xRIP);
SMEND();
if (BOX64DRENV(dynarec_callret)) {
// pop the actual return address from RV64 stack
LD(xRA, xSP, 0); // native addr
LD(x6, xSP, 8); // x86 addr
ADDI(xSP, xSP, 16); // pop
// pop the actual return address from LA64 stack
LD(xRA, xSP, 0); // native addr
LD(x6, xSP, 8); // x86 addr
ADDI(xSP, xSP, 16); // pop
BNE(x6, xRIP, 2 * 4); // is it the right address?
BR(xRA);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
@@ -512,43 +511,10 @@ void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
CLEARIP();
}
void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n)
void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits)
{
MAYUSE(dyn);
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Retn to epilog\n");
POP1z(xRIP);
if (n > 0x7ff) {
MOV64x(x1, n);
ADDz(xRSP, xRSP, x1);
} else {
ADDIz(xRSP, xRSP, n);
}
MVz(x1, xRIP);
SMEND();
if (BOX64DRENV(dynarec_callret)) {
// pop the actual return address from RV64 stack
LD(xRA, xSP, 0); // native addr
LD(x6, xSP, 8); // x86 addr
ADDI(xSP, xSP, 16); // pop
BNE(x6, xRIP, 2 * 4); // is it the right address?
BR(xRA);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
LD(xSP, xEmu, offsetof(x64emu_t, xSPSave));
ADDI(xSP, xSP, -16);
}
NOTEST(x2);
int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3);
BR(dest);
CLEARIP();
}
void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits)
{
// #warning TODO: is64bits
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
NOTEST(x2);
MESSAGE(LOG_DUMP, "IRet to next\n");
if (is64bits) {
POP1(xRIP);
POP1(x2);
@@ -579,13 +545,10 @@ void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits)
// set new RSP
MV(xRSP, x3);
// Ret....
// epilog on purpose, CS might have changed!
if (dyn->need_reloc)
TABLE64C(x2, const_epilog);
else
MOV64x(x2, getConst(const_epilog));
SMEND();
BR(x2);
rex_t dummy = { 0 };
dummy.is32bits = is32bits;
dummy.w = is64bits;
ret_to_next(dyn, ip, ninst, dummy);
CLEARIP();
}
+13 -6
View File
@@ -1096,6 +1096,15 @@
#ifndef SET_HASCALLRET
#define SET_HASCALLRET()
#endif
#ifndef CALLRET_RET
#define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0)
#endif
#ifndef CALLRET_GETRET
#define CALLRET_GETRET() (dyn->callrets?(dyn->callrets[dyn->callret_size].offs-dyn->native_size):0)
#endif
#ifndef CALLRET_LOOP
#define CALLRET_LOOP() NOP()
#endif
#define UFLAG_OP1(A) \
if (dyn->insts[ninst].x64.gen_flags) { SDxw(A, xEmu, offsetof(x64emu_t, op1)); }
#define UFLAG_OP2(A) \
@@ -1253,9 +1262,8 @@
#define jump_to_epilog STEPNAME(jump_to_epilog)
#define jump_to_epilog_fast STEPNAME(jump_to_epilog_fast)
#define jump_to_next STEPNAME(jump_to_next)
#define ret_to_epilog STEPNAME(ret_to_epilog)
#define retn_to_epilog STEPNAME(retn_to_epilog)
#define iret_to_epilog STEPNAME(iret_to_epilog)
#define ret_to_next STEPNAME(ret_to_next)
#define iret_to_next STEPNAME(iret_to_next)
#define call_c STEPNAME(call_c)
#define call_n STEPNAME(call_n)
#define grab_segdata STEPNAME(grab_segdata)
@@ -1420,9 +1428,8 @@ uintptr_t geted16(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits);
void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex);
void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n);
void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits);
void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex);
void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits);
void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w);
void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
+9
View File
@@ -55,3 +55,12 @@
EMIT(0); \
EMIT(0); \
} while (0)
#define CALLRET_RET(A) do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
} \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
} \
} while(0)
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
+18
View File
@@ -78,3 +78,21 @@
dynarec_log_prefix(0, LOG_NONE, "\n"); \
} \
return 0
#define CALLRET_RET(A) \
do { \
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) {\
MESSAGE(LOG_DUMP, " Dynablock*\n"); \
dyn->block += sizeof(void*); \
dyn->native_size+=sizeof(void*); \
dyn->insts[ninst].size2 += sizeof(void*); \
dyn->sep[dyn->sep_size].x64_offs = addr - dyn->start; \
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
++dyn->sep_size; \
} \
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
dyn->callrets[dyn->callret_size].type = 0; \
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
EMIT(ARCH_NOP); \
} \
} while(0)
#define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
+3 -1
View File
@@ -121,7 +121,9 @@ typedef struct instruction_rv64_s {
uint8_t will_read:1; // [strongmem] will read from memory
uint8_t last_write:1; // [strongmem] the last write in a SEQ
uint8_t lock:1; // [strongmem] lock semantic
uint8_t df_notneeded;
uint8_t df_needed:1;
uint8_t df_notneeded:1;
uint8_t sep:1; // opcode is a secondary entry point
uint8_t nat_flags_fusion:1;
uint8_t nat_flags_nofusion:1;
uint8_t nat_flags_carry:1;
-24
View File
@@ -90,30 +90,6 @@
#define MODREG ((nextop&0xC0)==0xC0)
#if defined(__riscv)
#define NAN_PROPAGATION(dest, src, break_or_continue) \
if (isnan(dest)) { \
break_or_continue; \
} else if (isnan(src)) { \
(dest) = (src); \
break_or_continue; \
}
#else
#define NAN_PROPAGATION(dest, src, break_or_continue)
#endif
#define MARK_NAN_VF_2(A, B) for(int idx=0; idx<4; ++idx) mask_nan[idx] = isnanf(A->f[idx]) || isnanf(B->f[idx])
#define CHECK_NAN_VF(A) for(int idx=0; idx<4; ++idx) if(!mask_nan[idx] && isnanf(A->f[idx])) A->f[idx] = -NAN
#define MARK_NAN_VD_2(A, B) for(int idx=0; idx<2; ++idx) mask_nan[idx] = isnan(A->d[idx]) || isnan(B->d[idx])
#define CHECK_NAN_VD(A) for(int idx=0; idx<2; ++idx) if(!mask_nan[idx] && isnan(A->d[idx])) A->d[idx] = -NAN
#define MARK_NAN_F_2(A, B) is_nan = isnanf(A->f[0]) || isnanf(B->f[0])
#define CHECK_NAN_F(A) if(!is_nan && isnanf(A->f[0])) A->f[0] = -NAN
#define MARK_NAN_D_2(A, B) is_nan = isnan(A->d[0]) || isnan(B->d[0])
#define CHECK_NAN_D(A) if(!is_nan && isnan(A->d[0])) A->d[0] = -NAN
#define GOCOND(BASE, PREFIX, COND, NOTCOND, POST)\
case BASE+0x0: \
PREFIX \
+8 -4
View File
@@ -53,10 +53,14 @@ uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* mem, int l
{
// get number of packed byte/word
int n_packed = (imm8&1)?8:16;
if(lreg<0) lreg = -lreg;
if(lmem<0) lmem = -lmem;
if(lreg>n_packed) lreg = n_packed;
if(lmem>n_packed) lmem = n_packed;
if (lreg<-n_packed || lreg>n_packed)
lreg = n_packed;
else if (lreg<0)
lreg = -lreg;
if (lmem<-n_packed || lmem>n_packed)
lmem = n_packed;
else if (lmem<0)
lmem = -lmem;
// aggregate to intres1
uint32_t intres1 = 0;
switch((imm8>>2)&3) {
+1 -1
View File
@@ -194,7 +194,7 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr)
tmp = (char*)(R_RDI);
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (void*)(R_RSI));
perr = 1;
} else if (strstr(s, "mkdir")==s) {
} else if (!strcmp(s, "mkdir")) {
tmp = (char*)(R_RDI);
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
perr = 1;
+86 -14
View File
@@ -485,6 +485,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
} else if (w == WFpi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI);
} else if (w == WFpW) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI);
} else if (w == WFpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
} else if (w == uFEp) {
@@ -567,6 +569,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI);
} else if (w == fFpu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI);
} else if (w == fFpf) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0]);
} else if (w == fFpL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI);
} else if (w == fFpp) {
@@ -687,6 +691,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI);
} else if (w == pFuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI);
} else if (w == pFud) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, emu->xmm[0].d[0]);
} else if (w == pFul) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (intptr_t)R_RSI);
} else if (w == pFuL) {
@@ -885,8 +891,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, (void*)R_RSI, (void*)R_RDX);
} else if (w == vFLup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX);
} else if (w == vFLpi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
} else if (w == vFLpL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX);
} else if (w == vFLpp) {
@@ -1157,6 +1161,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX);
} else if (w == iFpuU) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint64_t)R_RDX);
} else if (w == iFpuf) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].f[0]);
} else if (w == iFpul) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX);
} else if (w == iFpuL) {
@@ -1347,6 +1353,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (int32_t)R_RDX);
} else if (w == uFplu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (uint32_t)R_RDX);
} else if (w == uFpLi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (int32_t)R_RDX);
} else if (w == uFpLu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (uint32_t)R_RDX);
} else if (w == uFpLL) {
@@ -1365,6 +1373,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX);
} else if (w == UFpup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX);
} else if (w == UFpUU) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX);
} else if (w == UFppi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
} else if (w == fFuii) {
@@ -1639,6 +1649,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX);
} else if (w == pFpuf) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].f[0]);
} else if (w == pFpud) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].d[0]);
} else if (w == pFpul) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX);
} else if (w == pFpuL) {
@@ -2451,6 +2463,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX);
} else if (w == iFpppU) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX);
} else if (w == iFpppd) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, emu->xmm[0].d[0]);
} else if (w == iFpppL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
} else if (w == iFpppp) {
@@ -2495,8 +2509,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
} else if (w == uFiiuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX);
} else if (w == uFiipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == uFifff) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0]);
} else if (w == uFippp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == uFuipi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX);
} else if (w == uFuuuu) {
@@ -2537,8 +2555,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == uFpiii) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
} else if (w == uFpiiu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX);
} else if (w == uFpiip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
} else if (w == uFpiup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX);
} else if (w == uFpipi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX);
} else if (w == uFpipu) {
@@ -2633,6 +2655,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
} else if (w == UFppuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX);
} else if (w == dFppdd) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0]);
} else if (w == dFpppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == lFEipV) {
@@ -2713,6 +2737,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
} else if (w == LFpipl) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (intptr_t)R_RCX);
} else if (w == LFpipL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
} else if (w == LFpCii) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
} else if (w == LFpupL) {
@@ -2777,6 +2803,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)(R_RSP + 8));
} else if (w == pFEpCL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (uintptr_t)R_RDX);
} else if (w == pFEplp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (void*)R_RDX);
} else if (w == pFEppi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
} else if (w == pFEppu) {
@@ -2849,6 +2877,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0]);
} else if (w == pFLiip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
} else if (w == pFLupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == pFLLup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uintptr_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX);
} else if (w == pFLLLL) {
@@ -2883,8 +2913,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX);
} else if (w == pFpipd) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, emu->xmm[0].d[0]);
} else if (w == pFpipL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
} else if (w == pFpipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
} else if (w == pFpCip) {
@@ -3553,6 +3581,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8);
} else if (w == iFpiuLi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uintptr_t)R_RCX, (int32_t)R_R8);
} else if (w == iFpiupi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (int32_t)R_R8);
} else if (w == iFpiupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == iFpiUpi) {
@@ -3653,6 +3683,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0], emu->xmm[3].f[0]);
} else if (w == iFpffpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], (void*)R_RSI, (void*)R_RDX);
} else if (w == iFpdddd) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0]);
} else if (w == iFplupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == iFplluu) {
@@ -3833,10 +3865,10 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (int32_t)R_R8);
} else if (w == uFipupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFipLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFuiiii) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8);
} else if (w == uFupLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFULCLL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu64 ", %" PRIu8 ", %" PRIu64 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uint64_t)R_RDI, (uintptr_t)R_RSI, (uint8_t)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8);
} else if (w == uFULWLL) {
@@ -3871,6 +3903,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFpupuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8);
} else if (w == uFpupLp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (void*)R_R8);
} else if (w == uFpuppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFpULuU) {
@@ -3911,6 +3945,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uintptr_t)R_RCX, (void*)R_R8);
} else if (w == uFppLpu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8);
} else if (w == uFppLpL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
} else if (w == uFppLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
} else if (w == uFpppip) {
@@ -3939,6 +3975,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
} else if (w == dFlplpl) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIp ", %" PRIi64 ", %" PRIp ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, (void*)R_RSI, (intptr_t)R_RDX, (void*)R_RCX, (intptr_t)R_R8);
} else if (w == dFppddd) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0]);
} else if (w == dFppppL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
} else if (w == lFEippL) {
@@ -4719,6 +4757,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
} else if (w == iFpiuupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9);
} else if (w == iFpiupip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (int32_t)R_R8, (void*)R_R9);
} else if (w == iFpipipi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (void*)R_R8, (int32_t)R_R9);
} else if (w == iFpipipp) {
@@ -5027,10 +5067,14 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
} else if (w == uFpuUppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
} else if (w == uFpupuup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
} else if (w == uFpupupu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9);
} else if (w == uFpupupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9);
} else if (w == uFpupppu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9);
} else if (w == uFpupppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
} else if (w == uFppiiii) {
@@ -5223,6 +5267,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9);
} else if (w == pFpupuui) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (int32_t)R_R9);
} else if (w == pFpupuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9);
} else if (w == pFpupuup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
} else if (w == pFpuppip) {
@@ -5687,12 +5733,14 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu16 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(uint16_t*)(R_RSP + 8));
} else if (w == iFpWppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpuiiuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8));
} else if (w == iFpuiCuCp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIu8 ", %" PRIu32 ", %" PRIu8 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (uint8_t)R_RCX, (uint32_t)R_R8, (uint8_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpuiuupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpuuuuup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpuuuupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpupuupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFpupuLpL) {
@@ -5733,8 +5781,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8));
} else if (w == iFppiiiip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFppiiuup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == iFppiiLll) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIi64 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uintptr_t)R_R8, (intptr_t)R_R9, *(intptr_t*)(R_RSP + 8));
} else if (w == iFppiipii) {
@@ -5915,6 +5961,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == pFuupupup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
} else if (w == pFudddduu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0], (uint32_t)R_RSI, (uint32_t)R_RDX);
} else if (w == pFfiiiiid) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIf ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, emu->xmm[0].f[0], (int32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, emu->xmm[1].d[0]);
} else if (w == pFduuulul) {
@@ -5979,6 +6027,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8));
} else if (w == pFppuippp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
} else if (w == pFppuuuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8));
} else if (w == pFppuuupu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8));
} else if (w == pFppuuupp) {
@@ -6263,6 +6313,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIu8 ", %" PRIu16 ", %" PRIu16 ", %" PRIp ", %" PRIu16 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (uint8_t)R_RDX, (uint16_t)R_RCX, (uint16_t)R_R8, (void*)R_R9, *(uint16_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
} else if (w == iFpWCuWCuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIu8 ", %" PRIu32 ", %" PRIu16 ", %" PRIu8 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (uint8_t)R_RDX, (uint32_t)R_RCX, (uint16_t)R_R8, (uint8_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
} else if (w == iFpuiiipip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFpuiipppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFpuippLpp) {
@@ -6277,6 +6329,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16));
} else if (w == iFpuuuuuup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFpuuuuppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFpuuupupu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
} else if (w == iFpuupuupp) {
@@ -6315,8 +6369,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
} else if (w == iFpLpppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFppiiipip) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFppillppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi64 ", %" PRIi64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (intptr_t)R_RCX, (intptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFppipiipi) {
@@ -6455,8 +6507,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == pFpuuuupup) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == pFpudddduu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0], (uint32_t)R_RDX, (uint32_t)R_RCX);
} else if (w == pFpuLdiiLi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ", %" PRIf ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uintptr_t)R_RDX, emu->xmm[0].d[0], (int32_t)R_RCX, (int32_t)R_R8, (uintptr_t)R_R9, *(int32_t*)(R_RSP + 8));
} else if (w == pFpupupuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
} else if (w == pFpupLLLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == pFpupppppp) {
@@ -6621,6 +6677,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
} else if (w == vFpppiiiipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == vFpppuuuuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
} else if (w == vFpppUupppU) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(uint64_t*)(R_RSP + 24));
} else if (w == vFpppffffff) {
@@ -6647,6 +6705,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFEppplPPPP) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (intptr_t)R_RCX, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32));
} else if (w == iFEpppLpLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFEppppLppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
} else if (w == iFEpppppupp) {
@@ -6753,6 +6813,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIi64 ", %" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIi32 ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX, (void*)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(int32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), emu->xmm[0].f[0]);
} else if (w == uFpuupuppuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
} else if (w == uFpLiipLLLp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(uintptr_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == uFppLpLuppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == uFppppppppp) {
@@ -6799,6 +6861,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
} else if (w == pFpLppLLiLi) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(int32_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
} else if (w == pFppupupuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
} else if (w == pFppupppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == pFpppiiiiii) {
@@ -6929,6 +6993,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == iFEppLuppupp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == iFEppppLpppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == iFEppppppipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
} else if (w == iFEpppppppip) {
@@ -7113,6 +7179,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(void**)(R_RSP + 24), *(int32_t*)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFpippupppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFpuuiiuuiiuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
} else if (w == iFpuppppppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFpLipiiiippp) {
@@ -7127,8 +7195,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(uintptr_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(uint32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFppLLupppLpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uintptr_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(uintptr_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFpppiiuuiiuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
} else if (w == iFpppippppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == iFpppppiiuupp) {
@@ -7159,6 +7225,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32));
} else if (w == pFEpppppppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32));
} else if (w == pFpupppppuuuu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
} else if (w == pFpppppppuipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
} else if (w == pFppppppppppp) {
@@ -7309,6 +7377,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == iFpippuuuiipppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == iFpupiwwWWwwWWu) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIi32 ", %" PRIi16 ", %" PRIi16 ", %" PRIu16 ", %" PRIu16 ", %" PRIi16 ", %" PRIi16 ", %" PRIu16 ", %" PRIu16 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int16_t)R_R8, (int16_t)R_R9, *(uint16_t*)(R_RSP + 8), *(uint16_t*)(R_RSP + 16), *(int16_t*)(R_RSP + 24), *(int16_t*)(R_RSP + 32), *(uint16_t*)(R_RSP + 40), *(uint16_t*)(R_RSP + 48), *(uint32_t*)(R_RSP + 56));
} else if (w == iFpLLlliiLppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (uintptr_t)R_RDX, (intptr_t)R_RCX, (intptr_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == iFppppppLLLLupp) {
@@ -7317,6 +7387,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == uFippuuuulllipp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(intptr_t*)(R_RSP + 16), *(intptr_t*)(R_RSP + 24), *(intptr_t*)(R_RSP + 32), *(int32_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == uFpiipupLpLpLpL) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uintptr_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(uintptr_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(uintptr_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(uintptr_t*)(R_RSP + 56));
} else if (w == uFpppppuupppppp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
} else if (w == LFEpLiiuuuiupLp) {
+34 -14
View File
@@ -770,7 +770,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
GETGX;
for(int i=0; i<4; ++i)
if (isnan(EX->f[i]))
GX->f[i] = EX->f[i];
GX->ud[i] = EX->ud[i] | 0x00400000;
else
GX->f[i] = (EX->f[i] < 0) ? (-NAN) : sqrtf(EX->f[i]);
break;
@@ -784,7 +784,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
else if (EX->f[i]<0)
GX->f[i] = -NAN;
else if (isnan(EX->f[i]))
GX->f[i] = EX->f[i];
GX->ud[i] = EX->ud[i] | 0x00400000;
else if (isinf(EX->f[i]))
GX->f[i] = 0.0;
else
@@ -832,9 +832,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
GX->f[i] += EX->f[i];
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
if(isnanf(GX->f[i])) {
GX->ud[i] |= 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] += EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
}
break;
case 0x59: /* MULPS Gx, Ex */
@@ -842,9 +847,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
GX->f[i] *= EX->f[i];
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
if(isnanf(GX->f[i])) {
GX->ud[i] |= 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] *= EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
}
break;
case 0x5A: /* CVTPS2PD Gx, Ex */
@@ -868,9 +878,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
GX->f[i] -= EX->f[i];
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
if(isnanf(GX->f[i])) {
GX->ud[i] |= 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] -= EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
}
break;
case 0x5D: /* MINPS Gx, Ex */
@@ -887,9 +902,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
GX->f[i] /= EX->f[i];
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
if(isnanf(GX->f[i])) {
GX->ud[i] |= 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] /= EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
}
break;
case 0x5F: /* MAXPS Gx, Ex */
+79 -43
View File
@@ -1292,10 +1292,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
GETEX(0);
GETGX;
for (int i=0; i<2; ++i) {
if(EX->d[i]<0.0) // on x86, default nan are negative
GX->d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
if(EX->d[i]<0.0)
GX->d[i] = -NAN;
else if(isnan(EX->d[i]))
GX->d[i] = EX->d[i];
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
else
GX->d[i] = sqrt(EX->d[i]);
}
@@ -1333,21 +1333,31 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_VD_2(GX, EX);
for(int i=0; i<2; ++i) {
GX->d[i] += EX->d[i];
for (int i=0; i<2; ++i) {
if(isnan(GX->d[i])) {
GX->q[i] |= 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] += EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
break;
case 0x59: /* MULPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_VD_2(GX, EX);
for(int i=0; i<2; ++i) {
GX->d[i] *= EX->d[i];
for (int i=0; i<2; ++i) {
if(isnan(GX->d[i])) {
GX->q[i] |= 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] *= EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
break;
case 0x5A: /* CVTPD2PS Gx, Ex */
nextop = F8;
@@ -1394,11 +1404,16 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_VD_2(GX, EX);
for(int i=0; i<2; ++i) {
GX->d[i] -= EX->d[i];
for (int i=0; i<2; ++i) {
if(isnan(GX->d[i])) {
GX->q[i] |= 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] -= EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
break;
case 0x5D: /* MINPD Gx, Ex */
nextop = F8;
@@ -1414,10 +1429,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
GETEX(0);
GETGX;
for (int i=0; i<2; ++i) {
is_nan = isnan(GX->d[i]) || isnan(EX->d[i]);
GX->d[i] /= EX->d[i];
if(!is_nan && isnan(GX->d[i]))
GX->d[i] = -NAN;
if(isnan(GX->d[i])) {
GX->q[i] |= 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] /= EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
break;
case 0x5F: /* MAXPD Gx, Ex */
@@ -1738,34 +1757,50 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
nextop = F8;
GETEX(0);
GETGX;
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
GX->d[0] += GX->d[1];
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
if(EX==GX) {
GX->d[1] = GX->d[0];
if(isnan(GX->d[0])) {
GX->q[0] |= 0x0008000000000000ULL;
} else if(isnan(GX->d[1])) {
GX->q[0] = GX->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
GX->d[1] = EX->d[0] + EX->d[1];
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
GX->d[0] += GX->d[1];
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
}
if(EX==GX) {
GX->q[1] = GX->q[0];
} else {
if(isnan(EX->d[0])) {
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
} else if(isnan(EX->d[1])) {
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
} else {
GX->d[1] = EX->d[0] + EX->d[1];
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
}
}
break;
case 0x7D: /* HSUBPD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
GX->d[0] -= GX->d[1];
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
if(EX==GX) {
GX->d[1] = GX->d[0];
if(isnan(GX->d[0])) {
GX->q[0] |= 0x0008000000000000ULL;
} else if(isnan(GX->d[1])) {
GX->q[0] = GX->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
GX->d[1] = EX->d[0] - EX->d[1];
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
GX->d[0] -= GX->d[1];
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
}
if(EX==GX) {
GX->q[1] = GX->q[0];
} else {
if(isnan(EX->d[0])) {
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
} else if(isnan(EX->d[1])) {
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
} else {
GX->d[1] = EX->d[0] - EX->d[1];
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
}
}
break;
case 0x7E: /* MOVD Ed, Gx */
@@ -2284,10 +2319,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_VD_2(GX, EX);
GX->d[0] -= EX->d[0];
GX->d[1] += EX->d[1];
CHECK_NAN_VD(GX);
for(int i=0; i<2; ++i) {
if(isnan(GX->d[i])) GX->q[i] |= 0x0008000000000000ULL;
else if(isnan(EX->d[i])) GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
else { if(i==0) GX->d[0] -= EX->d[0]; else GX->d[1] += EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; }
}
break;
case 0xD1: /* PSRLW Gx, Ex */
nextop = F8;
+14 -11
View File
@@ -39,6 +39,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2;
x64flags_t eflags;
reg64_t *oped, *opgd;
#ifdef USE_CAS
uint64_t tmpcas;
@@ -280,7 +281,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
break;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
#define GO(B, OP) \
#define GO(B, OP, F) \
case B+1: \
nextop = F8; \
if(MODREG) { \
@@ -289,13 +290,15 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
} \
GETEW(0); \
GETGW; \
if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;} \
do { \
if(F) emu->eflags = eflags; \
tmp16u = native_lock_read_h(ED); \
tmp16u = OP##16(emu, tmp16u, GW->word[0]); \
} while (native_lock_write_h(ED, tmp16u)); \
break;
#else
#define GO(B, OP) \
#define GO(B, OP, F) \
case B+1: \
nextop = F8; \
if(MODREG) { \
@@ -309,13 +312,13 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
pthread_mutex_unlock(&my_context->mutex_lock); \
break;
#endif
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
GO(0x00, add, 0) /* ADD 0x00 -> 0x05 */
GO(0x08, or, 0) /* OR 0x08 -> 0x0D */
GO(0x10, adc, 1) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb, 1) /* SBB 0x18 -> 0x1D */
GO(0x20, and, 0) /* AND 0x20 -> 0x25 */
GO(0x28, sub, 0) /* SUB 0x28 -> 0x2D */
GO(0x30, xor, 0) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x81: /* GRP Ew,Iw */
@@ -332,8 +335,8 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
switch((nextop>>3)&7) {
case 0: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = add16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 1: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = or16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 2: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 3: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 2: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 3: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 4: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = and16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 5: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sub16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
case 6: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = xor16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
+60 -72
View File
@@ -262,14 +262,14 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX; GETGY;
for (int i = 0; i < 4; ++i)
if (isnan(EX->f[i]))
GX->f[i] = EX->f[i];
GX->ud[i] = EX->ud[i] | 0x00400000;
else
GX->f[i] = (EX->f[i] < 0) ? (-NAN) : sqrtf(EX->f[i]);
if(vex.l) {
GETEY;
for (int i = 0; i < 4; ++i)
if (isnan(EY->f[i]))
GY->f[i] = EY->f[i];
GY->ud[i] = EY->ud[i] | 0x00400000;
else
GY->f[i] = (EY->f[i] < 0) ? (-NAN) : sqrtf(EY->f[i]);
} else
@@ -282,13 +282,11 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGY;
for(int i=0; i<4; ++i) {
if (isnan(EX->f[i]))
GX->f[i] = EX->f[i];
GX->ud[i] = EX->ud[i] | 0x00400000;
else if (EX->f[i] == 0)
GX->f[i] = 1.0f/EX->f[i];
else if (EX->f[i]<0)
GX->f[i] = -NAN;
else if (isnan(EX->f[i]))
GX->f[i] = EX->f[i];
else if (isinf(EX->f[i]))
GX->f[i] = 0.0;
else
@@ -298,13 +296,11 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETEY;
for(int i=0; i<4; ++i) {
if (isnan(EY->f[i]))
GY->f[i] = EY->f[i];
GY->ud[i] = EY->ud[i] | 0x00400000;
else if (EY->f[i] == 0)
GY->f[i] = 1.0f/EY->f[i];
else if (EY->f[i]<0)
GY->f[i] = -NAN;
else if (isnan(EY->f[i]))
GY->f[i] = EY->f[i];
else if (isinf(EY->f[i]))
GY->f[i] = 0.0;
else
@@ -398,29 +394,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETVX;
GETGY;
for(int i=0; i<4; ++i) {
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
if (isnan(VX->f[i]))
GX->f[i] = VX->f[i];
else
GX->f[i] = EX->f[i];
continue;
if(isnanf(VX->f[i])) {
GX->ud[i] = VX->ud[i] | 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] = VX->f[i] + EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
GX->f[i] = VX->f[i] + EX->f[i];
if(isnan(GX->f[i])) GX->f[i] = -NAN;
}
if(vex.l) {
GETEY;
GETVY;
for(int i=0; i<4; ++i) {
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
if (isnan(VY->f[i]))
GY->f[i] = VY->f[i];
else
GY->f[i] = EY->f[i];
continue;
if(isnanf(VY->f[i])) {
GY->ud[i] = VY->ud[i] | 0x00400000;
} else if(isnanf(EY->f[i])) {
GY->ud[i] = EY->ud[i] | 0x00400000;
} else {
GY->f[i] = VY->f[i] + EY->f[i];
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
}
GY->f[i] = VY->f[i] + EY->f[i];
if(isnan(GY->f[i])) GY->f[i] = -NAN;
}
} else
GY->u128 = 0;
@@ -432,29 +426,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETVX;
GETGY;
for(int i=0; i<4; ++i) {
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
if (isnan(VX->f[i]))
GX->f[i] = VX->f[i];
else
GX->f[i] = EX->f[i];
continue;
if(isnanf(VX->f[i])) {
GX->ud[i] = VX->ud[i] | 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] = VX->f[i] * EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
GX->f[i] = VX->f[i] * EX->f[i];
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
}
if(vex.l) {
GETEY;
GETVY;
for(int i=0; i<4; ++i) {
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
if (isnan(VY->f[i]))
GY->f[i] = VY->f[i];
else
GY->f[i] = EY->f[i];
continue;
if(isnanf(VY->f[i])) {
GY->ud[i] = VY->ud[i] | 0x00400000;
} else if(isnanf(EY->f[i])) {
GY->ud[i] = EY->ud[i] | 0x00400000;
} else {
GY->f[i] = VY->f[i] * EY->f[i];
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
}
GY->f[i] = VY->f[i] * EY->f[i];
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
}
} else
GY->u128 = 0;
@@ -497,29 +489,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETVX;
GETGY;
for(int i=0; i<4; ++i) {
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
if (isnan(VX->f[i]))
GX->f[i] = VX->f[i];
else
GX->f[i] = EX->f[i];
continue;
if(isnanf(VX->f[i])) {
GX->ud[i] = VX->ud[i] | 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] = VX->f[i] - EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
GX->f[i] = VX->f[i] - EX->f[i];
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
}
if(vex.l) {
GETEY;
GETVY;
for(int i=0; i<4; ++i) {
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
if (isnan(VY->f[i]))
GY->f[i] = VY->f[i];
else
GY->f[i] = EY->f[i];
continue;
if(isnanf(VY->f[i])) {
GY->ud[i] = VY->ud[i] | 0x00400000;
} else if(isnanf(EY->f[i])) {
GY->ud[i] = EY->ud[i] | 0x00400000;
} else {
GY->f[i] = VY->f[i] - EY->f[i];
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
}
GY->f[i] = VY->f[i] - EY->f[i];
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
}
} else
GY->u128 = 0;
@@ -553,29 +543,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETVX;
GETGY;
for(int i=0; i<4; ++i) {
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
if (isnan(VX->f[i]))
GX->f[i] = VX->f[i];
else
GX->f[i] = EX->f[i];
continue;
if(isnanf(VX->f[i])) {
GX->ud[i] = VX->ud[i] | 0x00400000;
} else if(isnanf(EX->f[i])) {
GX->ud[i] = EX->ud[i] | 0x00400000;
} else {
GX->f[i] = VX->f[i] / EX->f[i];
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
}
GX->f[i] = VX->f[i] / EX->f[i];
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
}
if(vex.l) {
GETEY;
GETVY;
for(int i=0; i<4; ++i) {
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
if (isnan(VY->f[i]))
GY->f[i] = VY->f[i];
else
GY->f[i] = EY->f[i];
continue;
if(isnanf(VY->f[i])) {
GY->ud[i] = VY->ud[i] | 0x00400000;
} else if(isnanf(EY->f[i])) {
GY->ud[i] = EY->ud[i] | 0x00400000;
} else {
GY->f[i] = VY->f[i] / EY->f[i];
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
}
GY->f[i] = VY->f[i] / EY->f[i];
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
}
} else
GY->u128 = 0;
+7 -3
View File
@@ -75,7 +75,11 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_AF); // Undef
CLEAR_FLAG(F_PF); // Undef
if (BOX64ENV(cputype)) {
CLEAR_FLAG(F_PF);
} else {
CONDITIONAL_SET_FLAG(PARITY(GD->byte[0] & 0xff), F_PF);
}
break;
case 0xF3:
nextop = F8;
@@ -152,6 +156,7 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
case 0xF5: /* BZHI Gd, Ed, Vd */
nextop = F8;
if(vex.l) EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0);
ResetFlags(emu);
GETGD;
GETED(0);
GETVD;
@@ -200,8 +205,7 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GD->dword[0] = (ED->dword[0]>>tmp32u)&tmp64u;
else
GD->dword[0] = 0;
if(MODREG)
GD->dword[1] = 0;
GD->dword[1] = 0;
}
ResetFlags(emu);
CONDITIONAL_SET_FLAG(rex.w?(GD->q[0]==0):(GD->dword[0]==0), F_ZF);
+160 -80
View File
@@ -237,8 +237,10 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETEX(0);
GETGX; GETGY;
for (int i=0; i<2; ++i) {
if(EX->d[i]<0.0) // on x86, default nan are negative
GX->d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
if(EX->d[i]<0.0)
GX->d[i] = -NAN;
else if(isnan(EX->d[i]))
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
else
GX->d[i] = sqrt(EX->d[i]);
}
@@ -247,6 +249,8 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
for (int i=0; i<2; ++i) {
if(EY->d[i]<0.0)
GY->d[i] = -NAN;
else if(isnan(EY->d[i]))
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
else
GY->d[i] = sqrt(EY->d[i]);
}
@@ -319,20 +323,30 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
GETVX;
MARK_NAN_VD_2(VX, EX);
for(int i=0; i<2; ++i) {
GX->d[i] = VX->d[i] + EX->d[i];
for (int i=0; i<2; ++i) {
if(isnan(VX->d[i])) {
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] = VX->d[i] + EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
GETGY;
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VD_2(VY, EY);
for(int i=0; i<2; ++i) {
GY->d[i] = VY->d[i] + EY->d[i];
for (int i=0; i<2; ++i) {
if(isnan(VY->d[i])) {
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
} else if(isnan(EY->d[i])) {
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
} else {
GY->d[i] = VY->d[i] + EY->d[i];
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GY);
} else {
GY->u128 = 0;
}
@@ -343,19 +357,29 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_VD_2(VX, EX);
for(int i=0; i<2; ++i) {
GX->d[i] = VX->d[i] * EX->d[i];
for (int i=0; i<2; ++i) {
if(isnan(VX->d[i])) {
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] = VX->d[i] * EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VD_2(VY, EY);
for(int i=0; i<2; ++i) {
GY->d[i] = VY->d[i] * EY->d[i];
for (int i=0; i<2; ++i) {
if(isnan(VY->d[i])) {
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
} else if(isnan(EY->d[i])) {
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
} else {
GY->d[i] = VY->d[i] * EY->d[i];
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GY);
} else
GY->u128 = 0;
break;
@@ -445,18 +469,30 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETEX(0);
GETGX;
GETVX;
MARK_NAN_VD_2(VX, EX);
GX->d[0] = VX->d[0] - EX->d[0];
GX->d[1] = VX->d[1] - EX->d[1];
CHECK_NAN_VD(GX);
for (int i=0; i<2; ++i) {
if(isnan(VX->d[i])) {
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] = VX->d[i] - EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
GETGY;
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VD_2(VY, EY);
GY->d[0] = VY->d[0] - EY->d[0];
GY->d[1] = VY->d[1] - EY->d[1];
CHECK_NAN_VD(GY);
for (int i=0; i<2; ++i) {
if(isnan(VY->d[i])) {
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
} else if(isnan(EY->d[i])) {
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
} else {
GY->d[i] = VY->d[i] - EY->d[i];
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
}
}
} else {
GY->u128 = 0;
}
@@ -489,19 +525,29 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_VD_2(VX, EX);
for (int i=0; i<2; ++i) {
GX->d[i] = VX->d[i] / EX->d[i];
if(isnan(VX->d[i])) {
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
} else if(isnan(EX->d[i])) {
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
} else {
GX->d[i] = VX->d[i] / EX->d[i];
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GX);
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VD_2(VY, EY);
for (int i=0; i<2; ++i) {
GY->d[i] = VY->d[i] / EY->d[i];
if(isnan(VY->d[i])) {
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
} else if(isnan(EY->d[i])) {
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
} else {
GY->d[i] = VY->d[i] / EY->d[i];
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
}
}
CHECK_NAN_VD(GY);
} else
GY->u128 = 0;
break;
@@ -1086,17 +1132,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
eax1 = *EX;
EX = &eax1;
}
is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
GX->d[0] = VX->d[0] + VX->d[1];
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
if(EX==VX) {
GX->d[1] = GX->d[0];
if(isnan(VX->d[0])) {
GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
} else if(isnan(VX->d[1])) {
GX->q[0] = VX->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
GX->d[1] = EX->d[0] + EX->d[1];
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
GX->d[0] = VX->d[0] + VX->d[1];
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
}
if(EX==VX) {
GX->q[1] = GX->q[0];
} else {
if(isnan(EX->d[0])) {
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
} else if(isnan(EX->d[1])) {
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
} else {
GX->d[1] = EX->d[0] + EX->d[1];
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
}
}
if(vex.l) {
if(GY==EY) {
@@ -1104,17 +1158,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
EY = &eay1;
}
GETVY;
is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
GY->d[0] = VY->d[0] + VY->d[1];
if(!is_nan && isnan(GY->d[0]))
GY->d[0] = -NAN;
if(EY==VY) {
GY->d[1] = GY->d[0];
if(isnan(VY->d[0])) {
GY->q[0] = VY->q[0] | 0x0008000000000000ULL;
} else if(isnan(VY->d[1])) {
GY->q[0] = VY->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
GY->d[1] = EY->d[0] + EY->d[1];
if(!is_nan && isnan(GY->d[1]))
GY->d[1] = -NAN;
GY->d[0] = VY->d[0] + VY->d[1];
if(isnan(GY->d[0])) GY->q[0] |= 0x8000000000000000ULL;
}
if(EY==VY) {
GY->q[1] = GY->q[0];
} else {
if(isnan(EY->d[0])) {
GY->q[1] = EY->q[0] | 0x0008000000000000ULL;
} else if(isnan(EY->d[1])) {
GY->q[1] = EY->q[1] | 0x0008000000000000ULL;
} else {
GY->d[1] = EY->d[0] + EY->d[1];
if(isnan(GY->d[1])) GY->q[1] |= 0x8000000000000000ULL;
}
}
} else
GY->u128 = 0;
@@ -1130,17 +1192,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
eax1 = *EX;
EX = &eax1;
}
is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
GX->d[0] = VX->d[0] - VX->d[1];
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
if(EX==VX) {
GX->d[1] = GX->d[0];
if(isnan(VX->d[0])) {
GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
} else if(isnan(VX->d[1])) {
GX->q[0] = VX->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
GX->d[1] = EX->d[0] - EX->d[1];
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
GX->d[0] = VX->d[0] - VX->d[1];
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
}
if(EX==VX) {
GX->q[1] = GX->q[0];
} else {
if(isnan(EX->d[0])) {
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
} else if(isnan(EX->d[1])) {
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
} else {
GX->d[1] = EX->d[0] - EX->d[1];
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
}
}
if(vex.l) {
if(GY==EY) {
@@ -1148,17 +1218,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
EY = &eay1;
}
GETVY;
is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
GY->d[0] = VY->d[0] - VY->d[1];
if(!is_nan && isnan(GY->d[0]))
GY->d[0] = -NAN;
if(EY==VY) {
GY->d[1] = GY->d[0];
if(isnan(VY->d[0])) {
GY->q[0] = VY->q[0] | 0x0008000000000000ULL;
} else if(isnan(VY->d[1])) {
GY->q[0] = VY->q[1] | 0x0008000000000000ULL;
} else {
is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
GY->d[1] = EY->d[0] - EY->d[1];
if(!is_nan && isnan(GY->d[1]))
GY->d[1] = -NAN;
GY->d[0] = VY->d[0] - VY->d[1];
if(isnan(GY->d[0])) GY->q[0] |= 0x8000000000000000ULL;
}
if(EY==VY) {
GY->q[1] = GY->q[0];
} else {
if(isnan(EY->d[0])) {
GY->q[1] = EY->q[0] | 0x0008000000000000ULL;
} else if(isnan(EY->d[1])) {
GY->q[1] = EY->q[1] | 0x0008000000000000ULL;
} else {
GY->d[1] = EY->d[0] - EY->d[1];
if(isnan(GY->d[1])) GY->q[1] |= 0x8000000000000000ULL;
}
}
} else
GY->u128 = 0;
@@ -1297,17 +1375,19 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_VD_2(VX, EX);
GX->d[0] = VX->d[0] - EX->d[0];
GX->d[1] = VX->d[1] + EX->d[1];
CHECK_NAN_VD(GX);
for(int i=0; i<2; ++i) {
if(isnan(VX->d[i])) { GX->q[i] = VX->q[i] | 0x0008000000000000ULL; }
else if(isnan(EX->d[i])) { GX->q[i] = EX->q[i] | 0x0008000000000000ULL; }
else { if(i==0) GX->d[0] = VX->d[0] - EX->d[0]; else GX->d[1] = VX->d[1] + EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; }
}
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VD_2(VY, EY);
GY->d[0] = VY->d[0] - EY->d[0];
GY->d[1] = VY->d[1] + EY->d[1];
CHECK_NAN_VD(GY);
for(int i=0; i<2; ++i) {
if(isnan(VY->d[i])) { GY->q[i] = VY->q[i] | 0x0008000000000000ULL; }
else if(isnan(EY->d[i])) { GY->q[i] = EY->q[i] | 0x0008000000000000ULL; }
else { if(i==0) GY->d[0] = VY->d[0] - EY->d[0]; else GY->d[1] = VY->d[1] + EY->d[1]; if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL; }
}
} else
GY->u128 = 0;
break;
+79 -80
View File
@@ -189,7 +189,7 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
if(EX->d[0]<0.0 )
GX->d[0] = -NAN;
else if(isnan(EX->d[0]))
GX->d[0] = EX->d[0];
GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else
GX->d[0] = sqrt(EX->d[0]);
GX->q[1] = VX->q[1];
@@ -202,9 +202,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_D_2(VX, EX);
GX->d[0] = VX->d[0] + EX->d[0];
CHECK_NAN_D(GX);
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] = VX->d[0] + EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
GX->q[1] = VX->q[1];
GY->u128 = 0;
break;
@@ -214,9 +214,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_D_2(VX, EX);
GX->d[0] = VX->d[0] * EX->d[0];
CHECK_NAN_D(GX);
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] = VX->d[0] * EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
if(GX!=VX) {
GX->q[1] = VX->q[1];
}
@@ -240,7 +240,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
GX->d[0] = VX->d[0] - EX->d[0];
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] = VX->d[0] - EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
GX->q[1] = VX->q[1];
GY->u128 = 0;
break;
@@ -263,14 +265,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
#ifndef NOALIGN
is_nan = isnan(VX->d[0]) || isnan(EX->d[0]);
#endif
GX->d[0] = VX->d[0] / EX->d[0];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
#endif
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] = VX->d[0] / EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
GX->q[1] = VX->q[1];
GY->u128 = 0;
break;
@@ -328,44 +325,46 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
eax1 = *EX;
EX = &eax1;
}
mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] + VX->f[1]));
GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] + VX->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000;
else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000;
else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
}
if(EX==VX) {
GX->f[2] = GX->f[0];
GX->f[3] = GX->f[1];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
GX->ud[2] = GX->ud[0];
GX->ud[3] = GX->ud[1];
} else {
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] + EX->f[1]));
GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] + EX->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000;
else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000;
else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; }
}
}
CHECK_NAN_VF(GX);
if(vex.l) {
if(GY==EY) {
eay1 = *EY;
EY = &eay1;
}
GETVY;
mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] + VY->f[1]));
GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] + VY->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000;
else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000;
else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
}
if(EY==VY) {
GY->f[2] = GY->f[0];
GY->f[3] = GY->f[1];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
GY->ud[2] = GY->ud[0];
GY->ud[3] = GY->ud[1];
} else {
mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] + EY->f[1]));
GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] + EY->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000;
else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000;
else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; }
}
}
CHECK_NAN_VF(GY);
} else
GY->u128 = 0;
break;
@@ -380,44 +379,46 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
eax1 = *EX;
EX = &eax1;
}
mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] - VX->f[1]));
GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] - VX->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000;
else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000;
else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
}
if (EX == VX) {
GX->f[2] = GX->f[0];
GX->f[3] = GX->f[1];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
GX->ud[2] = GX->ud[0];
GX->ud[3] = GX->ud[1];
} else {
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] - EX->f[1]));
GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] - EX->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000;
else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000;
else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; }
}
}
CHECK_NAN_VF(GX);
if (vex.l) {
if (GY == EY) {
eay1 = *EY;
EY = &eay1;
}
GETVY;
mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] - VY->f[1]));
GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] - VY->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000;
else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000;
else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
}
if (EY == VY) {
GY->f[2] = GY->f[0];
GY->f[3] = GY->f[1];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
GY->ud[2] = GY->ud[0];
GY->ud[3] = GY->ud[1];
} else {
mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] - EY->f[1]));
GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] - EY->f[3]));
for(int i=0; i<2; ++i) {
int j = i*2;
if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000;
else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000;
else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; }
}
}
CHECK_NAN_VF(GY);
} else
GY->u128 = 0;
break;
@@ -460,21 +461,19 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_VF_2(VX, EX);
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(EX->f[0]) ? EX->f[0] : (VX->f[0] - EX->f[0]));
GX->f[1] = isnan(VX->f[1]) ? VX->f[1] : (isnan(EX->f[1]) ? EX->f[1] : (VX->f[1] + EX->f[1]));
GX->f[2] = isnan(VX->f[2]) ? VX->f[2] : (isnan(EX->f[2]) ? EX->f[2] : (VX->f[2] - EX->f[2]));
GX->f[3] = isnan(VX->f[3]) ? VX->f[3] : (isnan(EX->f[3]) ? EX->f[3] : (VX->f[3] + EX->f[3]));
CHECK_NAN_VF(GX);
for(int i=0; i<4; ++i) {
if(isnanf(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; }
else if(isnanf(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; }
else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
}
if(vex.l) {
GETEY;
GETVY;
MARK_NAN_VF_2(VY, EY);
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(EY->f[0]) ? EY->f[0] : (VY->f[0] - EY->f[0]));
GY->f[1] = isnan(VY->f[1]) ? VY->f[1] : (isnan(EY->f[1]) ? EY->f[1] : (VY->f[1] + EY->f[1]));
GY->f[2] = isnan(VY->f[2]) ? VY->f[2] : (isnan(EY->f[2]) ? EY->f[2] : (VY->f[2] - EY->f[2]));
GY->f[3] = isnan(VY->f[3]) ? VY->f[3] : (isnan(EY->f[3]) ? EY->f[3] : (VY->f[3] + EY->f[3]));
CHECK_NAN_VF(GY);
for(int i=0; i<4; ++i) {
if(isnanf(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; }
else if(isnanf(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; }
else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
}
} else
GY->u128 = 0;
break;
+14 -12
View File
@@ -211,7 +211,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
if(EX->f[0]<0.0 )
GX->f[0] = -NAN;
else if(isnanf(EX->f[0]))
GX->f[0] = EX->f[0];
GX->ud[0] = EX->ud[0] | 0x00400000;
else
GX->f[0] = sqrt(EX->f[0]);
if(GX!=VX) {
@@ -229,7 +229,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
else if (EX->f[0]<0)
GX->f[0] = -NAN;
else if (isnan(EX->f[0]))
GX->f[0] = EX->f[0];
GX->ud[0] = EX->ud[0] | 0x00400000;
else if (isinf(EX->f[0]))
GX->f[0] = 0.0;
else
@@ -258,9 +258,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_F_2(VX, EX);
GX->f[0] = VX->f[0] + EX->f[0];
CHECK_NAN_F(GX);
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
if(GX!=VX) {
GX->ud[1] = VX->ud[1];
GX->q[1] = VX->q[1];
@@ -273,9 +273,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_F_2(VX, EX);
GX->f[0] = VX->f[0] * EX->f[0];
CHECK_NAN_F(GX);
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
if(GX!=VX) {
GX->ud[1] = VX->ud[1];
GX->q[1] = VX->q[1];
@@ -330,7 +330,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
GX->f[0] = VX->f[0] - EX->f[0];
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
if(GX!=VX) {
GX->ud[1] = VX->ud[1];
GX->q[1] = VX->q[1];
@@ -360,13 +362,13 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
GETGX;
GETVX;
GETGY;
MARK_NAN_F_2(VX, EX);
GX->f[0] = VX->f[0] / EX->f[0];
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
if(GX!=VX) {
GX->ud[1] = VX->ud[1];
GX->q[1] = VX->q[1];
}
CHECK_NAN_F(GX);
GY->u128 = 0;
break;
case 0x5F: /* VMAXSS Gx, Vx, Ex */
+92 -54
View File
@@ -187,7 +187,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETED(0);
GETGD;
tmp64u = ED->q[0];
tmp64u = rex.w ? ED->q[0] : ED->dword[0];
for(int j=0; j<4*(rex.w+1); ++j) {
GD->dword[0] ^= (tmp64u >> (j * 8)) & 0xff;
for (int i = 0; i < 8; i++) {
@@ -212,7 +212,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
if(EX->d[0]<0.0 )
GX->d[0] = -NAN;
else if(isnan(EX->d[0]))
GX->d[0] = EX->d[0];
GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else
GX->d[0] = sqrt(EX->d[0]);
break;
@@ -221,24 +221,17 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETEX(0);
GETGX;
MARK_NAN_D_2(GX, EX);
{
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
GX->d[0] += EX->d[0];
}
CHECK_NAN_D(GX);
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] += EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
break;
case 0x59: /* MULSD Gx, Ex */
nextop = F8;
_GETEX(0);
GETGX;
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
MARK_NAN_D_2(GX, EX);
{
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
GX->d[0] *= EX->d[0];
}
CHECK_NAN_D(GX);
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] *= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
break;
case 0x5A: /* CVTSD2SS Gx, Ex */
nextop = F8;
@@ -251,12 +244,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETEX(0);
GETGX;
MARK_NAN_D_2(GX, EX);
{
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
GX->d[0] -= EX->d[0];
}
CHECK_NAN_D(GX);
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] -= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
break;
case 0x5D: /* MINSD Gx, Ex */
nextop = F8;
@@ -269,10 +259,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETEX(0);
GETGX;
MARK_NAN_D_2(GX, EX);
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
GX->d[0] /= EX->d[0];
CHECK_NAN_D(GX);
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
else { GX->d[0] /= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
break;
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
@@ -339,41 +328,85 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETEX(0);
GETGX;
mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);
mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);
GX->f[0] += GX->f[1];
GX->f[1] = GX->f[2] + GX->f[3];
eax1 = *GX;
if(isnanf(eax1.f[0])) {
GX->ud[0] = eax1.ud[0] | 0x00400000;
} else if(isnanf(eax1.f[1])) {
GX->ud[0] = eax1.ud[1] | 0x00400000;
} else {
GX->f[0] = eax1.f[0] + eax1.f[1];
if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000;
}
if(isnanf(eax1.f[2])) {
GX->ud[1] = eax1.ud[2] | 0x00400000;
} else if(isnanf(eax1.f[3])) {
GX->ud[1] = eax1.ud[3] | 0x00400000;
} else {
GX->f[1] = eax1.f[2] + eax1.f[3];
if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000;
}
if(EX==GX) {
GX->q[1] = GX->q[0];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
} else {
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
GX->f[2] = EX->f[0] + EX->f[1];
GX->f[3] = EX->f[2] + EX->f[3];
if(isnanf(EX->f[0])) {
GX->ud[2] = EX->ud[0] | 0x00400000;
} else if(isnanf(EX->f[1])) {
GX->ud[2] = EX->ud[1] | 0x00400000;
} else {
GX->f[2] = EX->f[0] + EX->f[1];
if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000;
}
if(isnanf(EX->f[2])) {
GX->ud[3] = EX->ud[2] | 0x00400000;
} else if(isnanf(EX->f[3])) {
GX->ud[3] = EX->ud[3] | 0x00400000;
} else {
GX->f[3] = EX->f[2] + EX->f[3];
if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000;
}
}
CHECK_NAN_VF(GX);
break;
case 0x7D: /* HSUBPS Gx, Ex */
nextop = F8;
_GETEX(0);
GETGX;
mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);
mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);
GX->f[0] -= GX->f[1];
GX->f[1] = GX->f[2] - GX->f[3];
eax1 = *GX;
if(isnanf(eax1.f[0])) {
GX->ud[0] = eax1.ud[0] | 0x00400000;
} else if(isnanf(eax1.f[1])) {
GX->ud[0] = eax1.ud[1] | 0x00400000;
} else {
GX->f[0] = eax1.f[0] - eax1.f[1];
if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000;
}
if(isnanf(eax1.f[2])) {
GX->ud[1] = eax1.ud[2] | 0x00400000;
} else if(isnanf(eax1.f[3])) {
GX->ud[1] = eax1.ud[3] | 0x00400000;
} else {
GX->f[1] = eax1.f[2] - eax1.f[3];
if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000;
}
if(EX==GX) {
GX->q[1] = GX->q[0];
mask_nan[2] = mask_nan[0];
mask_nan[3] = mask_nan[1];
} else {
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
GX->f[2] = EX->f[0] - EX->f[1];
GX->f[3] = EX->f[2] - EX->f[3];
if(isnanf(EX->f[0])) {
GX->ud[2] = EX->ud[0] | 0x00400000;
} else if(isnanf(EX->f[1])) {
GX->ud[2] = EX->ud[1] | 0x00400000;
} else {
GX->f[2] = EX->f[0] - EX->f[1];
if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000;
}
if(isnanf(EX->f[2])) {
GX->ud[3] = EX->ud[2] | 0x00400000;
} else if(isnanf(EX->f[3])) {
GX->ud[3] = EX->ud[3] | 0x00400000;
} else {
GX->f[3] = EX->f[2] - EX->f[3];
if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000;
}
}
CHECK_NAN_VF(GX);
break;
GOCOND(0x80
@@ -382,15 +415,21 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
,,STEP3
) /* 0x80 -> 0x8F Jxx */
case 0xA4: // ignore F2 prefix
case 0xA3: // ignore F2 prefix
case 0xA4:
case 0xA5:
case 0xAB:
case 0xAC:
case 0xAD:
case 0xAF:
case 0xB3:
case 0xB7:
case 0xBA:
case 0xBB:
case 0xBC: // this one is still BSR, not TZCNT
case 0xBD: // and this one is still BSF, not LZCNT
case 0xC1:
case 0xCD:
#ifdef TEST_INTERPRETER
return Test0F(test, rex, addr-1, step);
#else
@@ -420,12 +459,11 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
nextop = F8;
_GETEX(0);
GETGX;
MARK_NAN_VF_2(GX, EX);
GX->f[0] -= EX->f[0];
GX->f[1] += EX->f[1];
GX->f[2] -= EX->f[2];
GX->f[3] += EX->f[3];
CHECK_NAN_VF(GX);
for(int i=0; i<4; ++i) {
if(isnanf(GX->f[i])) GX->ud[i] |= 0x00400000;
else if(isnanf(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000;
else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
}
break;
case 0xD6: /* MOVDQ2Q Gm, Ex */
+28 -24
View File
@@ -228,7 +228,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
if (EX->f[0]<0)
GX->f[0] = -NAN;
else if (isnanf(EX->f[0]))
GX->f[0] = EX->f[0];
GX->ud[0] = EX->ud[0] | 0x00400000;
else
GX->f[0] = sqrtf(EX->f[0]);
break;
@@ -241,37 +241,35 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
else if (EX->f[0]<0)
GX->f[0] = -NAN;
else if (isnan(EX->f[0]))
GX->f[0] = EX->f[0];
GX->ud[0] = EX->ud[0] | 0x00400000;
else if (isinf(EX->f[0]))
GX->f[0] = 0.0;
else
GX->f[0] = 1.0f/sqrtf(EX->f[0]);
break;
case 0x53: /* RCPSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
GX->f[0] = 1.0f/EX->f[0];
break;
case 0x53: /* RCPSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] = 1.0f/EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
break;
case 0x58: /* ADDSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_F_2(GX, EX);
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
GX->f[0] += EX->f[0];
CHECK_NAN_F(GX);
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] += EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
break;
case 0x59: /* MULSS Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_F_2(GX, EX);
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
GX->f[0] *= EX->f[0];
CHECK_NAN_F(GX);
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] *= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
break;
case 0x5A: /* CVTSS2SD Gx, Ex */
nextop = F8;
@@ -299,8 +297,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
nextop = F8;
GETEX(0);
GETGX;
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
GX->f[0] -= EX->f[0];
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] -= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
break;
case 0x5D: /* MINSS Gx, Ex */
nextop = F8;
@@ -313,10 +312,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
nextop = F8;
GETEX(0);
GETGX;
MARK_NAN_F_2(GX, EX);
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
GX->f[0] /= EX->f[0];
CHECK_NAN_F(GX);
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
else { GX->f[0] /= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
break;
case 0x5F: /* MAXSS Gx, Ex */
nextop = F8;
@@ -362,13 +360,19 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
memcpy(EX, GX, 16); // unaligned...
break;
case 0xA4: // ignore F3 prefix
case 0xA3: // ignore F3 prefix
case 0xA4:
case 0xA5:
case 0xAC:
case 0xAD:
case 0xAF:
case 0xB3:
case 0xB7:
case 0xBA:
case 0xBB:
case 0xBF:
case 0xC1:
case 0xCD:
#ifdef TEST_INTERPRETER
return Test0F(test, rex, addr-1, step);
#else
+79 -51
View File
@@ -581,9 +581,11 @@ uint32_t cvtf16_32(uint16_t v)
ret.exponant = 126 - s;
ret.fraction = in.fraction << s;
}
} else if(in.exponant==0b11111)
} else if(in.exponant==0b11111) {
ret.exponant = 0b11111111;
else {
if(in.fraction)
ret.fraction |= (1 << 22); // SNaN -> QNaN
} else {
int e = in.exponant - 15;
ret.exponant = e + 127;
}
@@ -607,61 +609,87 @@ uint16_t cvtf32_16(uint32_t v, uint8_t rounding)
// nan and infinites
ret.exponant = 0b11111;
ret.fraction = in.fraction >> 13;
if(in.fraction && !ret.fraction)
ret.fraction = 0b1000000000;
if(in.fraction)
ret.fraction |= 0b1000000000; // SNaN -> QNaN
return ret.u16;
} else {
// regular numbers
int e = in.exponant - 127;
uint16_t f = (in.fraction>>13)|0b10000000000; // add back implicit msb
uint16_t r = in.fraction&0b1111111111111;
switch(rounding) {
case 0: // nearest even
if(r>=0b1000000000000)
++f;
break;
case 1: // round down
f += r?ret.sign:0;
break;
case 2: // round up
f += r?(1-ret.sign):0;
break;
case 3: // truncate
break;
}
if(f>0b11111111111) { // implicit msb included
++e;
f>>=1;
}
// remove implicit msb
if(f) {
while(!(f&0b10000000000)) {
f<<=1;
--e;
}
}
// there is no msb to remove, as it's implicit and was not added back before
if(!f) e = -15;
else if(e<-14) {
// flush to zero
f >>= (-15-e);
e = -15;
if((rounding==1 && ret.sign) || ((rounding==2) && !ret.sign))
f = 1; // rounding artifact
}
else if(e>15) {
if((rounding==1 && !in.sign) || (rounding==2 && in.sign) || (rounding==3)) {
// Clamp to max
f=0b1111111111;
e = 15;
if(e < -14) {
// result is a half-precision denormal (or zero)
int shift = -14 - e;
uint32_t mantissa = (1u << 23) | in.fraction;
// total right shift to align 24-bit mantissa into 10-bit fraction
int total_shift = 13 + shift;
uint16_t fraction;
int guard, sticky;
if(total_shift >= 25) {
fraction = 0;
guard = 0;
sticky = 1; // mantissa always nonzero (has implicit bit)
} else {
// overflow to inifity
f=0;
e = 16;
fraction = (mantissa >> total_shift) & 0x3FF;
guard = (mantissa >> (total_shift - 1)) & 1;
sticky = (total_shift >= 2) ? ((mantissa & ((1u << (total_shift - 1)) - 1)) ? 1 : 0) : 0;
}
} else f&=0b1111111111; // remove implicit msb (bit 11)
ret.fraction = f;
ret.exponant = e+15;
switch(rounding) {
case 0: // nearest even
if(guard && (sticky || (fraction & 1)))
++fraction;
break;
case 1: // round down
if((guard || sticky) && ret.sign)
++fraction;
break;
case 2: // round up
if((guard || sticky) && !ret.sign)
++fraction;
break;
case 3: // truncate
break;
}
if(fraction >= 0x400) {
// rounding promoted denormal to smallest normal
ret.fraction = 0;
ret.exponant = 1;
} else {
ret.fraction = fraction;
ret.exponant = 0;
}
} else {
// normal result (e >= -14)
uint16_t f = (in.fraction>>13)|0b10000000000;
uint16_t r = in.fraction&0b1111111111111;
switch(rounding) {
case 0: // nearest even
if(r > 0b1000000000000 || (r == 0b1000000000000 && (f & 1)))
++f;
break;
case 1: // round down
f += r?ret.sign:0;
break;
case 2: // round up
f += r?(1-ret.sign):0;
break;
case 3: // truncate
break;
}
if(f>0b11111111111) {
++e;
f>>=1;
}
if(e>15) {
if((rounding==1 && !in.sign) || (rounding==2 && in.sign) || (rounding==3)) {
f=0b1111111111;
e = 15;
} else {
f=0;
e = 16;
}
} else f&=0b1111111111;
ret.fraction = f;
ret.exponant = e+15;
}
}
return ret.u16;
+3
View File
@@ -13,5 +13,8 @@ void addCheckAlternate(void* addr, void* alt);
void cleanAlternate(void);
#ifdef HAVE_ALTJUMP
uintptr_t getAlternateJump(void* addr, int is32bits);
// will return MAP_FAIL (void*)-1LL if there no alternate at addr
void* getAlternateData(void* addr);
void setAlternateData(void* addr, void* data);
#endif
#endif //__ALTERNATE_H__
+2
View File
@@ -8,6 +8,7 @@ uint32_t X31_hash_code(void* addr, int len);
void FreeDynablock(dynablock_t* db, int need_lock, int need_remove);
void MarkDynablock(dynablock_t* db);
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
void MarkCRCRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
void FreeInvalidDynablock(dynablock_t* db, int need_lock);
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock);
@@ -30,5 +31,6 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t native_addr);
int getX64AddressInst(dynablock_t* db, uintptr_t x64pc);
uintptr_t getX64InstAddress(dynablock_t* db, int inst);
dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits);
#endif //__DYNABLOCK_H_
+1 -1
View File
@@ -10,6 +10,6 @@ typedef struct instsize_s instsize_t;
void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size);
void CancelBlock64(int need_lock);
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new);
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt);
#endif //__DYNAREC_ARM_H_
-1
View File
@@ -55,7 +55,6 @@ extern char* ftrace_name;
INTEGER(BOX64_DYNAREC_SEP, dynarec_sep, 1, 0, 2, 1) \
BOOLEAN(BOX64_DYNAREC_DF, dynarec_df, 1, 1) \
INTEGER(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0, 0, 2, 0) \
BOOLEAN(BOX64_DYNAREC_HOTPAGE_ALT, dynarec_hotpage_alt, 1, 0) \
BOOLEAN(BOX64_DYNAREC_NOHOTPAGE, dynarec_nohotpage, 0, 0) \
BOOLEAN(BOX64_DYNAREC_DIV0, dynarec_div0, 0, 1) \
INTEGER(BOX64_DYNAREC_DUMP, dynarec_dump, 0, 0, 2, 1) \
+1
View File
@@ -227,6 +227,7 @@ GO("libselinux.so.1", selinux)
GO("libsecret-1.so.0", secret1)
GO("libpci.so.3", libpci)
GO("libgmp.so.10", gmp)
GO("libgmp.so", gmp)
GO("libFAudio.so.0", faudio)
GO("libgstallocators-1.0.so.0", gstallocators)
GO("libgstapp-1.0.so.0", gstapp)
+7
View File
@@ -621,6 +621,13 @@ int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigin
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14;
if(!mmapped) info2->si_code = 1;
info2->si_errno = 0;
} else if (info->si_errno==0xb09d) {
// bound exception
sigcontext->uc_mcontext.gregs[I386_ERR] = 0;
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 5;
info2->si_errno = 0;
info2->si_code = 128;
info2->_sifields._sigfault.__si_addr = 0;
}else {
sigcontext->uc_mcontext.gregs[I386_ERR] = 0x14|((sysmapped && !(real_prot&PROT_READ))?0:1);
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14;
+2 -2
View File
@@ -800,8 +800,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
// check if block is still valid
int is_hotpage = checkInHotPage(x64pc);
uint32_t hash = (db->gone || is_hotpage)?0:X31_hash_code(db->x64_addr, db->x64_size);
if(!db->gone && !is_hotpage && hash==db->hash) {
dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, always_test=%d) is clean, %s continuing at %p (%p)!\n", db, db->x64_addr, db->always_test, type_callret?"self-loop":"ret from callret", (void*)x64pc, (void*)addr);
if(!db->gone && (!is_hotpage || db->autocrc) && hash==db->hash) {
dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, always_test=%d, autocrc=%d) is clean, %s continuing at %p (%p)!\n", db, db->x64_addr, db->always_test, db->autocrc, type_callret?"self-loop":"ret from callret", (void*)x64pc, (void*)addr);
// it's good! go next opcode
CONTEXT_PC(p)+=4;
if(db->always_test)
+4 -4
View File
@@ -89,8 +89,8 @@ void getUnalignedRange(uintptr_t start, size_t size, uintptr_t addrs[])
int mark_db_unaligned(dynablock_t* db, uintptr_t x64pc)
{
add_unaligned_address(x64pc);
db->hash++; // dirty the block
MarkDynablock(db); // and mark it
db->to_delete = 1; // mark block for deletion
MarkDynablock(db); // and mark it as dirty
if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as needing unaligned handling\n", db, (void*)x64pc);
return 2; // marked, exit handling...
}
@@ -98,8 +98,8 @@ if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address
int mark_db_autosmc(dynablock_t* db, uintptr_t x64pc)
{
add_autosmc_address(x64pc);
db->hash++; // dirty the block
MarkDynablock(db); // and mark it
db->to_delete = 1; // mark block for deletion
MarkDynablock(db); // and mark it as dirty
if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as creating internal SMC\n", db, (void*)x64pc);
return 2; // marked, exit handling...
}
+3
View File
@@ -298,6 +298,7 @@ void freeVulkanOverlay(my_vulkanoverlay_t* v)
#define GO_uFpubp(A, B, N) static uint32_t my_##A##_##N(void* a, uint32_t b, void* c, void* d) {return (uint32_t)F4(A, #B +2, N);}
#define GO_UFpp(A, B, N) static uint64_t my_##A##_##N(void* a, void* b) {return (uint64_t)F2(A, #B +2, N);}
#define GO_UFpu(A, B, N) static uint64_t my_##A##_##N(void* a, uint32_t b) {return (uint64_t)F2(A, #B +2, N);}
#define GO_UFpUU(A, B, N) static uint64_t my_##A##_##N(void* a, uint64_t b, uint64_t c) {return (uint64_t)F3(A, #B +2, N);}
#define GO_UFppuu(A, B, N) static uint64_t my_##A##_##N(void* a, void* b, uint32_t c, uint32_t d) {return (uint64_t)F4(A, #B +2, N);}
#define GO_UFpUui(A, B, N) static uint64_t my_##A##_##N(void* a, uint64_t b, uint32_t c, int d) {return (uint64_t)F4(A, #B +2, N);}
@@ -628,6 +629,7 @@ CREATE(vkCreateDebugReportCallbackEXT) // needs better wrapping because of Debu
CREATE(vkCreateDebugUtilsMessengerEXT) // Needs better wrapping?
CREATE(vkRegisterDeviceEventEXT)
CREATE(vkCreateWin32SurfaceKHR)
CREATE(vkCreateShaderInstrumentationARM)
#undef CREATE
#undef GO
// DESTROY64
@@ -699,6 +701,7 @@ DESTROY(vkDestroyPipelineBinaryKHR)
DESTROY(vkDestroyTensorARM)
DESTROY(vkDestroyTensorViewARM)
DESTROY(vkDestroyDataGraphPipelineSessionARM)
DESTROY(vkDestroyShaderInstrumentationARM)
#undef DESTROY
#undef GO
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more