Compare commits

...
71 Commits
Author SHA1 Message Date
ptitSeb 2f130fab1d Bumped version to v0.4.4 2026-08-02 11:31:59 +02:00
Yang Liu 08f8666596 [RV64_DYNAREC] Restored vector SEW after cache transform (#4175) 2026-08-02 11:16:02 +02:00
Mikura Kyouka fb5294a125 [SIGNAL] Preserve TF handling when resuming signals with Dynarec (#4174)
When a signal handler restores a context with TF set, resume through the interpreter for one instruction so no_tf can suppress the initial spurious SIGTRAP.

This fixes the issue exposed after commit 38d64ba when running Syringe.exe from the Ares expansion platform.
2026-08-02 09:00:50 +02:00
Yang Liu b3384b5c81 [RV64_DYNAREC] Fixed more GETEX mistakes (#4173) 2026-08-02 08:56:17 +02:00
Yang Liu 7058d990c4 [RV64_DYNAREC] Fixed PACKSSDW opcode (#4172) 2026-08-02 08:56:05 +02:00
Yang Liu 8557ede0e9 [RV64_DYNAREC] Flush pending double reg on size change (#4171) 2026-08-02 08:55:36 +02:00
Yang Liu 78383901f2 [RV64_DYNAREC] Fixed PEXT opcode (#4170) 2026-08-01 17:43:51 +02:00
Yang Liu ebccae45e3 [RV64_DYNAREC] Fixed a long standing typo in CALL opcode (#4168) 2026-08-01 11:40:18 +02:00
Yang Liu 80b5e387d2 [RV64_DYNAREC] Fixed PDEP opcode (#4167) 2026-08-01 08:49:59 +02:00
Yang Liu 15e065ae5d [WRAPPER] Wrapped isoc23_[v]scanf (#4162)
* [WRAPPER] Wrapped isoc23_[v]scanf

* Fixed scanf wrapping
2026-07-31 13:44:09 +02:00
Yang Liu 00ca85606d [SYSCALL] Added a few more syscalls (#4163) 2026-07-31 13:43:21 +02:00
Yang Liu bc181e7812 [SYSCALL] Fixed a bad bad bug (#4161)
It seems that back in 2019, when `fchmodat4` syscall was introduced, it did get the number 434:
https://lists.openwall.net/linux-kernel/2019/07/17/25, but that patch was rejected and 434 was assigned to `pidfd_open` later.
2026-07-31 12:08:38 +02:00
Luke Short 0f6b8ccc68 [DOCS] Recommend SteamRT3/SteamRT64 (#4157)
when Box86 is unavailable.
2026-07-31 08:56:12 +02:00
Luke Short ffeff6599b [SYSCALL] Add various simple syscalls (#4144) 2026-07-30 16:35:32 +02:00
ptitSeb 3e71996209 Fixed potential overflow on cpu brand for cpuid opcode 2026-07-30 16:33:10 +02:00
ptitSeb bbb2560ff8 [RCFILE] Added 1 more game profile 2026-07-30 14:48:18 +02:00
Zane 30b1bf210d [SYSCALL] Add syscall 32 (#4156) 2026-07-30 11:27:01 +02:00
Luke Short 178e344b98 [RCFILE] Added game profile for VRChat (#4153)
Resolves #1996
2026-07-29 21:04:20 +02:00
Luke Short 1c2fc72c20 [RCFILE] Added game profile for Jetboard Joust (#4152)
Related #1462
2026-07-29 21:03:46 +02:00
Luke Short b7ed2c57f5 [BUNDLE] Generate checksums (#4151)
for both files and symlinks. This will eventually be used to see if
an update of the bundle is required or not.

Related #3564
2026-07-29 17:48:30 +02:00
Zhijin Zeng 23f8db631d [RV64_DYNAREC] Support HSUBPS and MOVDQ2Q (#4141) 2026-07-29 10:13:00 +02:00
Yang Liu f22f5adb55 [RV64_DYNAREC] Fixed MIN/MAX opcodes (#4148) 2026-07-29 09:44:20 +02:00
Yang Liu f02526fdbb [RV64_DYNAREC] Refactored (safe) flags emulation (#4147)
* [RV64_DYNAREC] Refactored (safe) flags emulation

* more
2026-07-29 09:42:37 +02:00
Zhijin Zeng 675814f912 [RV64_DYNAREC] Support VMOVLPS/VMOVHPS Ex,Gx instruction (#4140) 2026-07-29 09:39:17 +02:00
Zhijin Zeng c44264eba0 [RV64_DYNAREC] Support MOVQ2DQ and ADOX instruction (#4146) 2026-07-29 09:36:38 +02:00
Yang Liu 35ea2eedcd [RV64_DYNAREC] Fixed VPADDQ opcode (#4138) 2026-07-28 09:01:47 +02:00
Yang Liu 25f49cbf25 [RV64_DYNAREC] Fixed PCMPSTR opcodes (#4137) 2026-07-28 09:01:06 +02:00
Luke Short 2dd1600cdd [SYSCALL] Add more syscalls for Magisk (#4136)
95, 115, and 269.

Resolves #1497
2026-07-28 00:24:26 +02:00
Luke Short 327b0870f0 [SYSCALL] Add syscall 40 (#4135)
Resolves #3535
2026-07-28 00:23:54 +02:00
Yang Liu 7097ead476 [RV64_DYNAREC] Added 0F C7 /1 CMPXCHG8B opcode (#4134) 2026-07-27 19:47:07 +02:00
Yang Liu 887d5ca523 [RV64_DYNAREC] Fixed VPSUBQ opcode (#4133) 2026-07-27 19:05:37 +02:00
Yang Liu 54c35ef172 [RV64_DYNAREC] Fixed HADDPD opcode (#4132) 2026-07-27 18:52:48 +02:00
ptitSeb a78eec4ebf [RV64_DYNAREC] Fixed F0 C7 /0 opcode 2026-07-27 18:22:32 +02:00
Yang Liu ed140eade7 [RV64_DYNAREC] Fixed RORX opcode (#4131) 2026-07-27 18:19:18 +02:00
Yang Liu 7c6c963168 [RV64_DYNAREC] Fixed conditional move macros again (#4130) 2026-07-27 18:15:05 +02:00
Yang Liu e058be73ca [RV64_DYNAREC] Fixed VSQRTPD opcode (#4129) 2026-07-27 17:28:11 +02:00
Zhijin Zeng d9a136d31c [RV64_DYNAREC] Change some BNEZ+ORI to SET_FLAGS_EQZ (#4126) 2026-07-27 16:24:19 +02:00
Zhijin Zeng 5910a52a60 [RV64_DYNAREC] Support POPCNT/TZCNT/LZCNT 16 bit operand (#4125) 2026-07-27 21:43:51 +08:00
Yang Liu e67bd4b6f6 [RV64_DYNAREC] Fixed conditional move macros (#4124) 2026-07-27 13:10:19 +02:00
Yang Liu 9270fc3727 [RV64_DYNAREC] Fixed CRC opcodes (#4123) 2026-07-27 13:05:40 +02:00
Yang Liu 5101489d21 [RV64_DYNAREC] Refined rotate opcodes (#4122) 2026-07-27 10:42:26 +02:00
Yang Liu 41c3a0caa5 [RV64_DYNAREC] Restored vector width before XMM cache accesses (#4121) 2026-07-27 10:41:16 +02:00
ptitSeb 382065544d [RCFILE] Added a new game profile 2026-07-27 09:49:48 +02:00
Zhijin Zeng e2a2c801f2 [RV64_DYNAREC] Fix RORX if cpu don't support zbb (#4120) 2026-07-27 08:51:40 +02:00
ptitSeb 9e2fa9e360 [RCFILE] Added 1 more game profile 2026-07-26 15:35:21 +02:00
Yang Liu 588f1d9c93 [LA64_DYNAREC] Optimized jump safe macros (#4114) 2026-07-25 10:59:17 +02:00
Zhijin Zeng 347f3b1a13 [RV64_DYNAREC] Support bmi2 PEXT/SARX/RORX instruction (#4116) 2026-07-25 10:58:10 +02:00
Yang Liu c32ebc76fd [LA64_DYNAREC] Extended nativeflags SF fusion (#4115) 2026-07-25 09:06:58 +02:00
Yang Liu a2ae0500d8 [LA64_DYNAREC] Extended nativeflags to 1+N pattern (#4113) 2026-07-24 21:10:46 +02:00
Yang Liu 478972a34b [TLS] Kept x86 TCB self consistent with pthread_self() (#4112) 2026-07-24 20:51:14 +02:00
Zhijin Zeng f4ee1c1b53 [RV64_DYNAREC] Support bmi2 PDEP/MULX/SHRX instruction (#4110)
Implement by referencing the LA64 implementation.
2026-07-25 02:05:17 +08:00
Zhijin Zeng 93fe536549 [RV64_DYNAREC] Add Zicbom and Zicbop disassemble case (#4111) 2026-07-24 14:24:01 +02:00
yzewei 3698562aae [INTERPRETER] Improve x87 long double classification (#4107)
Keep the existing raw 80-bit x87 shadow aligned through FLD ST(i), FXCH,
FST/FSTP, FCMOV, FABS, and FCHS, and use it for FCOMI/FUCOMI/FUCOMIP when
the shadow is still valid.

This avoids falling back to the double representation for long double
classification, where large finite values such as LDBL_MAX may collapse to
inf and break isinf/isnan/isfinite-style checks

Signed-off-by: Zewei Yang <[email protected]>
2026-07-24 11:09:40 +02:00
Yang Liu d8df33a9cb [LA64_DYNAREC] Added simplewrapper float parameter support (#4109) 2026-07-24 09:24:57 +02:00
Zhijin Zeng 0de71be3e5 [RV64_DYNAREC] Use risc-v zicond to eliminate some branchs for setting flag (#4099)
* [RV64_DYNAREC] Support risc-v zicond extension

* [RV64_DYNAREC] Use risc-v zicond to eliminate some branchs
2026-07-24 09:10:25 +02:00
Yang Liu fd895bd142 [LA64_DYNAREC] Cached MXCSR rounding mode in FCSR3 (#4108) 2026-07-24 09:07:16 +02:00
Yang Liu edc68c032a [LA64_DYNAREC] Fixed ARPL opcode (regression of fd6bdfe6) (#4106) 2026-07-24 08:14:53 +02:00
Yang Liu 40a841df8f Small tweaks to the profile (#4105)
* [LA64_DYNAREC] Small tweaks to the profile

* more
2026-07-23 20:03:04 +02:00
Yang Liu df697c683c [LA64_DYNAREC] Added F0 F6 /2 LOCK NOT opcode (#4104) 2026-07-23 19:31:07 +02:00
Yang Liuandphorcys e3cb94f490 [LA64_DYNAREC] Optimized SHA1 opcodes (#4102)
Co-authored-by: phorcys <[email protected]>
2026-07-23 19:05:13 +02:00
Yang Liu 88f6cb97c7 [LA64_DYNAREC] Fixed scratch register shortage in certain VAES opcodes (#4103) 2026-07-23 18:53:16 +02:00
Zhijin Zeng bdd226b9d3 [RV64_DYNAREC] Remove redundant SMREAD (#4100)
GETEX includes SMREAD, and GETGX has no need for SMREAD.
2026-07-24 00:25:16 +08:00
Yang Liu 537d92bf57 [LA64_DYNAREC] Fixed a typo in VPXOR opcode (#4101) 2026-07-23 17:10:39 +02:00
Zhijin Zeng c08644a729 [RV64_DYNAREC] Support some bmi and bmi2 instructions for risc-v (#4098)
Implement by referencing the LA64 implementation.

BMI: ANDN, BLSI, BLSR, BLSMSK, BEXTR
BMI2: BZHI
2026-07-23 09:09:35 +02:00
Yang Liu 7b07789173 [LA64_DYNAREC] Optimized SHA1 opcodes (#4097) 2026-07-23 08:15:19 +02:00
Yang Liu 585e0a6308 [LA64_DYNAREC] Fixed inlined updateflags (#4096) 2026-07-23 08:11:13 +02:00
Yang Liu fd6bdfe69e [LA64_DYNAREC] Added ARPL opcode (#4095) 2026-07-23 08:10:38 +02:00
Yang Liu 654e36622f [DYNAREC] Fixed 16-bit XADD register clobbering (#4094) 2026-07-23 08:08:29 +02:00
Yang Liu 38df9afcf2 Optimized sha1rnds4 helper function utilizing loop-unrolling (#4093)
10% performance gain in Geekbench6 geekbench_x86_64 Single-Core File Compression.
2026-07-23 08:07:07 +02:00
ptitSeb b442786811 [RCFILE] Updated 2 profiles (for UPlay games) 2026-07-22 17:28:08 +02:00
Yang Liu ff943b5d5a Removed useless files (#4092) 2026-07-22 15:16:06 +02:00
92 changed files with 2301 additions and 613 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
{ "contextFileName": "AGENTS.md" }
+3 -2
View File
@@ -51,7 +51,7 @@ Module.symvers
Mkfile.old
dkms.conf
# from box86
# Box64
build/
build*/
.vscode
@@ -60,6 +60,7 @@ build*/
src/git_head.h
src/dynacache_hashes.h
backup/
box64-bundle-x86-libs.sha256
# Wrapper helper
/wrapperhelper/bin
@@ -92,4 +93,4 @@ backup/
*.zstd
# Python
__pycache__/
__pycache__/
-1
View File
@@ -1 +0,0 @@
IMPORTANT: Ensure you’ve thoroughly reviewed the [AGENTS.md](AGENTS.md) file before beginning any work.
+4
View File
@@ -1148,6 +1148,10 @@ if(RV64_DYNAREC)
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_66_0f3a.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f2_0f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f3_0f.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_0f38.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f2_0f38.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f3_0f38.c"
"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_avx_f2_0f3a.c"
)
endif()
+5
View File
@@ -130,5 +130,10 @@ for dir_lib in "${dir_tmp}"/bundle-libs/usr/lib/box64-*-linux-gnu; do
done
done
# generate a SHA256 checksum of every file and symlink in the bundle
cd "${dir_tmp}"/bundle-libs
find usr \( -type f -o -type l \) -exec "${sha256sum}" {} + \
| LC_ALL=C sort --key 2 > "${current_dir}"/box64-bundle-x86-libs.sha256
# generate the bundle libraries archive
tar -C "${dir_tmp}"/bundle-libs -czvf "${current_dir}"/box64-bundle-x86-libs.tar.gz .
-2
View File
@@ -110,7 +110,6 @@ PROFILE_SETTINGS = {
),
"fast": (
("BOX64_DYNAREC_CALLRET", "1"),
("BOX64_DYNAREC_SEP", "1"),
("BOX64_DYNAREC_BIGBLOCK", "3"),
("BOX64_DYNAREC_SAFEFLAGS", "0"),
("BOX64_DYNAREC_STRONGMEM", "1"),
@@ -119,7 +118,6 @@ PROFILE_SETTINGS = {
),
"fastest": (
("BOX64_DYNAREC_CALLRET", "1"),
("BOX64_DYNAREC_SEP", "2"),
("BOX64_DYNAREC_BIGBLOCK", "3"),
("BOX64_DYNAREC_SAFEFLAGS", "0"),
("BOX64_DYNAREC_STRONGMEM", "0"),
+10
View File
@@ -1,3 +1,13 @@
box64 (0.4.4) unstable; urgency=low
This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features!
=> A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese.
=> DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space.
=> You can use box64-configurator on the special `[*]` profile to change default values
=> More improvements on emulation accuracy that help running more DRM'd games
-- Sebastien Chevalier <[email protected]> Mon, 2 Aug 2026 10:30:33 -0100
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.
+61
View File
@@ -1,3 +1,64 @@
v0.4.4
======
Highlights:
* This version adds a lot of refactor and speed improvements to the LoongArch backend, so more opcodes on the RISC-V backend, and many QoL new features!
=> A new box64-configurator is now present (a python app) to help managing custom RCFILE profiles. It is available in both english and chinese.
=> DynaCache is now enabled by default. It will compress the files and use up to 2GB of disk space.
=> You can use box64-configurator on the special `[*]` profile to change default values
=> More improvements on emulation accuracy that help running more DRM'd games
Version summary:
* RCFILE: Created a new GUI tools to edit custom rcfile: box64-configurator
* RCFILE: Created a KDE plugin to quickly set box64 properties for an executable file
* RCFILE: Added more profiles
* RCFILE: Added BOX64_SKIPCPU to avoid using N first cores (for big.LITTLE configuration)
* ELF: Some more Relocation handling
* Wrapping: Improved MALLOC_HACK=2 behaviour
* Wrapping: more fixes to some functions signatures
* Wrapping: added more wrapped functions
* Wrapping: added some more wrapped libraries
* Wrapping: Added more Syscall
* Wrapping: Some rework on the bridges to avoid unexpected reuse of bridges for different function signature
* Wrapping: Box32: Some fixes and improvement on some wrapped functions
* Emulation: Some improvement on handling of x87 80bits values
* Emulation: Added some deferred signal support for improved stability
* Emulation: Improved TF handling
* Emulation: Improved CPUID handling
* Emulation: optimised some sha1 function
* Emulation: LA64: Enabled AVX by default (on par with ARM64)
* Interpreter: A few fixes in some opcodes
* Interpreter: Added unaligned handling of more lock opcodes
* DynaCache: many improvements and fixes
* DynaCache: added libz compression of the dynacache files
* DynaCache: added disk size limit, to purge old/outdated dynacache once a threshold is reached
* Dynarec: Many small opcodes optimisation here and there
* Dynarec: Some improvement on handling of x87 80bits values
* Dynarec: Optimised the internal jump handling while building a dynablock
* Dynarec: Improved TF handling
* Dynarec: Reworked Alt Address handling
* Dynarec: Reworked a bit the jump table to save some memory
* Dynarec: Made BOX64_CALLRET=2 default
* Dynarec: ARM64: Some improvement in some x87 opcodes handling
* Dynarec: ARM64: A few fixes to some opcodes
* Dynarec: LA64: Added optimisation on the zeroing out of the upper 32 bits of registers
* Dynarec: LA64: Added a Dynarec version of UpdateFlags (on par with ARM64)
* Dynarec: LA64: More work FASTNAN / FASTROUND handling
* Dynarec: LA64: Many fixes on many opcodes
* Dynarec: LA64: Added a few opcodes
* Dynarec: LA64: Added fastpath on many logical opcodes (when no flags are needed)
* Dynarec: LA64: AES opcodes optimisations
* Dynarec: LA64: Improved Native flags use for more cases
* Dynarec: LA64: Improved jump_safe macro (removing many useless NOP)
* Dynarec: RV64: Improvement on flags handling (on par with ARM64 & LA64)
* Dynarec: RV64: Many fixes on NaN handling
* Dynarec: RV64: Some fixes to various opcodes
* Dynarec: RV64: Improved Native Flags handling
* Dynarec: RV64: Added some opcodes
* Dynarec: RV64: Detect and use the new Zicbop/Zicond/Zicbom cpu extension when available
* WrapperHelper: some more improvements and fixes
v0.4.2
======
+5
View File
@@ -14,6 +14,11 @@ Linux Steam requires Box86 or Box32 and it's binfmt enabled, check [Compilation
steam
```
For additional stability with Box64 when Box86 is unavailable, it is recommended to use the new 64-bit-only runtime for the Steam client.
- Steam > Settings > Interface > Client Beta Participation: Steam Beta > Restart Now
- Steam > Settings > Interface > Use experimental SteamRT3 Steam Client: On > Restart Now
## Install and run Windows Steam
It's simple, just download it from Steam website and install it like other Windows applications.
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 4
#define BOX64_REVISION 3
#define BOX64_REVISION 4
#endif //__BOX64_VERSION_H_
+4 -2
View File
@@ -2058,7 +2058,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 1);
v1 = fpu_get_scratch(dyn, ninst);
v1 = fpu_get_scratch(dyn, ninst);
}
u8 = F8;
GETGX_empty(v0);
@@ -2923,9 +2923,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
BFIx(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), ed, 0, 16);
u8 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
if (!(MODREG && wback == u8)) MOVx_REG(x6, ed);
emit_add16(dyn, ninst, ed, gd, x4, x5);
EWBACK;
if (!(MODREG && wback == u8)) BFIx(u8, x6, 0, 16);
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex, Ib");
+23 -14
View File
@@ -751,8 +751,21 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x63:
if (rex.is32bits) {
// this is ARPL opcode
DEFAULT;
INST_NAME("ARPL Ew, Gw");
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
ANDI(x6, ed, 3);
ANDI(x4, gd, 3);
SLTU(x5, x6, x4);
BSTRINS_D(xFlags, x5, F_ZF, F_ZF);
if (cpuext.lbt) X64_SET_EFLAGS(xFlags, X_ZF);
BEQZ_MARK(x5);
BSTRINS_D(ed, gd, 1, 0);
EWBACK;
MARK;
} else {
INST_NAME("MOVSXD Gd, Ed");
nextop = F8;
@@ -957,13 +970,13 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
/* out of block */ \
i32 = dyn->insts[ninst].epilog - (dyn->native_size); \
if (COMIS_FUSED()) { \
COMIS_BRANCH_NOT_TAKEN(i32); \
COMIS_BRANCH_NOT_TAKEN(i32, ninst); \
} else if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATNO, i32); \
NATIVEJUMP_safe(NATNO, i32, ninst); \
} else if (cpuext.lbt) \
BEQZ_safe(tmp1, i32); \
BEQZ_safe(tmp1, i32, ninst); \
else \
B##NO##_safe(tmp1, i32); \
B##NO##_safe(tmp1, i32, ninst); \
if (dyn->insts[ninst].x64.jmp_insts == -1) { \
if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, tmp1, tmp2, tmp3); \
@@ -977,13 +990,13 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
if (COMIS_FUSED()) { \
COMIS_BRANCH_TAKEN(i32); \
COMIS_BRANCH_TAKEN(i32, dyn->insts[ninst].x64.jmp_insts); \
} else if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATYES, i32); \
NATIVEJUMP_safe(NATYES, i32, dyn->insts[ninst].x64.jmp_insts); \
} else if (cpuext.lbt) \
BNEZ_safe(tmp1, i32); \
BNEZ_safe(tmp1, i32, dyn->insts[ninst].x64.jmp_insts); \
else \
B##YES##_safe(tmp1, i32); \
B##YES##_safe(tmp1, i32, dyn->insts[ninst].x64.jmp_insts); \
}
GOCOND(0x70, "J", "ib");
@@ -2868,8 +2881,6 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (isRetX87Wrapper(*(wrapper_t*)(addr)))
// return value will be on the stack, so the stack depth needs to be updated
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
if (tmp < 0 || (tmp & 15) > 1)
tmp = 0; // TODO: removed when FP is in place
if ((BOX64ENV(log) < 2 && !BOX64ENV(rolling_log)) && tmp) {
call_n(dyn, ninst, (void*)(addr + 8), tmp);
SMWRITE2();
@@ -3602,8 +3613,6 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
tmp = isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall + 2));
} else
tmp = 0;
if (tmp < 0 || (tmp & 15) > 1)
tmp = 0; // TODO: removed when FP is in place
if (dyn->insts[ninst].natcall && isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall + 2)))
// return value will be on the stack, so the stack depth needs to be updated
x87_purgecache(dyn, ninst, 0, x3, x1, x4);
+125 -45
View File
@@ -357,9 +357,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETGX(v0, 1);
GETEM(v1, 0);
q0 = fpu_get_scratch(dyn);
u8 = sse_setround(dyn, ninst, x1, x2);
VFFINT_S_W(q0, v1);
x87_restoreround(dyn, ninst, u8);
VEXTRINS_D(v0, q0, VEXTRINS_IMM_4_0(0, 0));
break;
case 0x2B:
@@ -406,7 +404,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
nextop = F8;
GETGM(v0);
GETEXSD(v1, 0, 0);
u8 = sse_setround(dyn, ninst, x4, x6);
if (BOX64ENV(dynarec_fastround)) {
VFTINTRZ_W_S(v0, v1);
} else {
@@ -439,7 +436,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MARK3;
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x2E:
// no special check...
@@ -639,18 +635,47 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
GETEM(q1, 0);
VABSD_W(q0, q1, VZERO);
break;
case 0xC8 ... 0xCD:
case 0xC8:
INST_NAME("SHA1NEXTE Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = fpu_get_scratch(dyn);
VROTRI_W(d0, q0, 2);
VADD_W(d0, d0, q1);
if (q0 != q1) VOR_V(q0, q1, q1);
VEXTRINS_W(q0, d0, VEXTRINS_IMM_4_0(3, 3));
break;
case 0xC9:
INST_NAME("SHA1MSG1 Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = fpu_get_scratch(dyn);
VOR_V(d0, q0, q0);
VPERMI_W(d0, q1, 0x4e);
VXOR_V(q0, q0, d0);
break;
case 0xCA:
INST_NAME("SHA1MSG2 Gx, Ex");
u8 = nextop;
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0, 0);
d0 = fpu_get_scratch(dyn);
VBSLL_V(d0, q1, 4);
VXOR_V(d0, d0, q0);
VROTRI_W(q0, d0, 31);
VBSRL_V(d0, q0, 12);
VROTRI_W(d0, d0, 31);
VXOR_V(q0, q0, d0);
break;
case 0xCB ... 0xCD:
u8 = nextop;
switch (u8) {
case 0xC8:
INST_NAME("SHA1NEXTE Gx, Ex");
break;
case 0xC9:
INST_NAME("SHA1MSG1 Gx, Ex");
break;
case 0xCA:
INST_NAME("SHA1MSG2 Gx, Ex");
break;
case 0xCB:
INST_NAME("SHA256RNDS2 Gx, Ex");
break;
@@ -676,15 +701,6 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
ADDI_D(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
sse_reflect_reg(dyn, ninst, 0);
switch (u8) {
case 0xC8:
CALL(const_sha1nexte, -1, x1, ed);
break;
case 0xC9:
CALL(const_sha1msg1, -1, x1, ed);
break;
case 0xCA:
CALL(const_sha1msg2, -1, x1, ed);
break;
case 0xCB:
CALL(const_sha256rnds2, -1, x1, ed);
break;
@@ -748,25 +764,86 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
VEXTRINS_D(q0, d0, 0);
}
break;
#define EMIT_SHA1_F(MODE, VF, VB, VC, VD) \
do { \
switch (MODE) { \
case 0: \
VBITSEL_V(VF, VD, VC, VB); \
break; \
case 1: \
case 3: \
VXOR_V(VF, VB, VC); \
VXOR_V(VF, VF, VD); \
break; \
case 2: \
VXOR_V(VF, VB, VD); \
VBITSEL_V(VF, VB, VC, VF); \
break; \
} \
} while (0)
case 0xCC:
INST_NAME("SHA1RNDS4 Gx, Ex, Ib");
nextop = F8;
if (MODREG) {
ed = (nextop & 7) + (rex.b << 3);
sse_reflect_reg(dyn, ninst, ed);
ADDI_D(x2, xEmu, offsetof(x64emu_t, xmm[ed]));
wback = x2;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 1);
}
GETGX(q0, 1);
GETEX(q1, 0, 1);
u8 = F8;
GETG;
sse_forget_reg(dyn, ninst, gd);
ADDI_D(x1, xEmu, offsetof(x64emu_t, xmm[gd]));
MOV32w(x3, u8);
CALL4(const_sha1rnds4, -1, x1, wback, x3, 0);
static const uint32_t sha1_k[4] = {
0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
};
int vA = fpu_get_scratch(dyn);
int vB = fpu_get_scratch(dyn);
int vC = fpu_get_scratch(dyn);
int vD = fpu_get_scratch(dyn);
int vM = fpu_get_scratch(dyn);
// reuse q1 as vT if Ex is mem operand
int vT = MODREG ? fpu_get_scratch(dyn) : q1;
int vU = SCRATCH;
VSHUF4I_W(vA, q0, 0xff);
VSHUF4I_W(vB, q0, 0xaa);
VSHUF4I_W(vC, q0, 0x55);
VSHUF4I_W(vD, q0, 0x00);
MOV32w(x7, sha1_k[u8 & 3]);
VREPLGR2VR_W(vM, x7);
VADD_W(vM, q1, vM);
EMIT_SHA1_F(u8 & 3, q0, vB, vC, vD);
VROTRI_W(vB, vB, 2);
VROTRI_W(vT, vA, 2);
EMIT_SHA1_F(u8 & 3, vU, vA, vB, vC);
VADD_W(vU, vU, vD);
VREPLVEI_W(vD, vM, 3);
VADD_W(q0, q0, vD);
VREPLVEI_W(vD, vM, 2);
VADD_W(vU, vU, vD);
VROTRI_W(vA, vA, 27);
VREPLVEI_W(vD, vM, 1);
VADD_W(vC, vC, vD);
VREPLVEI_W(vM, vM, 0);
VADD_W(vA, vA, q0);
VROTRI_W(q0, vA, 27);
EMIT_SHA1_F(u8 & 3, vD, vA, vT, vB);
VADD_W(q0, q0, vU);
VADD_W(vD, vD, vC);
VADD_W(vB, vB, vM);
VROTRI_W(vA, vA, 2);
VROTRI_W(vU, q0, 2);
EMIT_SHA1_F(u8 & 3, vC, q0, vA, vT);
VROTRI_W(vM, q0, 27);
VADD_W(vC, vC, vB);
VILVL_W(q0, vU, vA);
VADD_W(vM, vM, vD);
VEXTRINS_W(q0, vM, VEXTRINS_IMM_4_0(2, 0));
VROTRI_W(vD, vM, 27);
VADD_W(vD, vD, vC);
VEXTRINS_W(q0, vD, VEXTRINS_IMM_4_0(3, 0));
break;
#undef EMIT_SHA1_F
default:
DEFAULT;
}
@@ -1372,14 +1449,14 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
/* out of the block */ \
i32 = dyn->insts[ninst].epilog - (dyn->native_size); \
if (COMIS_FUSED()) { \
COMIS_BRANCH_NOT_TAKEN(i32); \
COMIS_BRANCH_NOT_TAKEN(i32, ninst); \
} else if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATNO, i32); \
NATIVEJUMP_safe(NATNO, i32, ninst); \
} else { \
if (cpuext.lbt) \
BEQZ_safe(x1, i32); \
BEQZ_safe(x1, i32, ninst); \
else \
B##NO##_safe(x1, i32); \
B##NO##_safe(x1, i32, ninst); \
} \
if (dyn->insts[ninst].x64.jmp_insts == -1) { \
if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \
@@ -1394,14 +1471,14 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
if (COMIS_FUSED()) { \
COMIS_BRANCH_TAKEN(i32); \
COMIS_BRANCH_TAKEN(i32, dyn->insts[ninst].x64.jmp_insts); \
} else if (dyn->insts[ninst].nat_flags_fusion) { \
NATIVEJUMP_safe(NATYES, i32); \
NATIVEJUMP_safe(NATYES, i32, dyn->insts[ninst].x64.jmp_insts); \
} else { \
if (cpuext.lbt) \
BNEZ_safe(tmp1, i32); \
BNEZ_safe(tmp1, i32, dyn->insts[ninst].x64.jmp_insts); \
else \
B##YES##_safe(tmp1, i32); \
B##YES##_safe(tmp1, i32, dyn->insts[ninst].x64.jmp_insts); \
} \
}
@@ -1643,11 +1720,13 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
BARRIER(BARRIER_FLOAT);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x3, &fixedaddress, rex, NULL, 0, 0);
CALL(rex.is32bits ? const_fpu_fxrstor32 : const_fpu_fxrstor64, -1, ed, 0);
sse_fcsr3_from_mxcsr(dyn, ninst, x3);
break;
case 2:
INST_NAME("LDMXCSR Md");
GETED(0);
ST_W(ed, xEmu, offsetof(x64emu_t, mxcsr));
sse_fcsr3_from_mxcsr(dyn, ninst, x3);
if (BOX64ENV(sse_flushto0)) {
/* LA <-> x86
16/24 <-> 5 inexact
@@ -1707,6 +1786,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 0);
MOV32w(x2, rex.is32bits);
CALL(const_fpu_xrstor, -1, ed, x2);
sse_fcsr3_from_mxcsr(dyn, ninst, x3);
break;
case 7:
INST_NAME("CLFLUSH Ed");
+11 -27
View File
@@ -280,7 +280,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETGM(v0);
GETEX(v1, 0, 0);
u8 = sse_setround(dyn, ninst, x4, x6);
if (BOX64ENV(dynarec_fastround)) {
VFTINT_W_D(v0, v1, v1);
} else {
@@ -314,7 +313,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VEXTRINS_W(v0, q0, VEXTRINS_IMM_4_0(1, 0));
MARK3;
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x2E:
// no special check...
@@ -815,12 +813,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_V(d0, q1, q1);
} else
d0 = -1;
GETGX(q0, 1);
la64_aese_lsx(dyn, ninst, q0);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
break;
@@ -829,12 +827,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_V(d0, q1, q1);
} else
d0 = -1;
GETGX(q0, 1);
la64_aeselast_lsx(dyn, ninst, q0);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
break;
@@ -843,12 +841,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_V(d0, q1, q1);
} else
d0 = -1;
GETGX(q0, 1);
la64_aesd_lsx(dyn, ninst, q0);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
break;
@@ -857,12 +855,12 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETG;
GETEX(q1, 0, 0);
GETGX(q0, 1);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_V(d0, q1, q1);
} else
d0 = -1;
GETGX(q0, 1);
la64_aesdlast_lsx(dyn, ninst, q0);
VXOR_V(q0, q0, (d0 != -1) ? d0 : q1);
break;
@@ -940,9 +938,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_S(q0, q1);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_S(q0, q1, round_round[u8 & 3]);
}
@@ -955,9 +951,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_D(q0, q1);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_D(q0, q1, round_round[u8 & 3]);
}
@@ -970,9 +964,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_S(v1, q1);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_S(v1, q1, round_round[u8 & 3]);
}
@@ -986,9 +978,7 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
u8 = F8;
v1 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_D(v1, q1);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_D(v1, q1, round_round[u8 & 3]);
}
@@ -1649,23 +1639,16 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x6, x4);
}
q0 = fpu_get_scratch(dyn);
VFCVT_S_D(q0, v1, v1);
VXOR_V(v0, v0, v0);
VEXTRINS_D(v0, q0, 0);
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
break;
case 0x5B:
INST_NAME("CVTPS2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x6, x4);
if (v0 == v1 && !BOX64ENV(dynarec_fastround)) {
v1 = fpu_get_scratch(dyn);
VOR_V(v1, v0, v0);
@@ -1685,7 +1668,6 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VSRLI_W(q0, q0, 31);
VADD_W(v0, v0, q0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
@@ -2689,9 +2671,11 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
nextop = F8;
GETGWEW(x1, x2, 0);
BSTRINS_D(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), ed, 15, 0);
u8 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3));
if (!(MODREG && wback == u8)) MV(x7, ed);
emit_add16(dyn, ninst, ed, gd, x4, x5, x6);
EWBACK;
if (!(MODREG && wback == u8)) BSTRINS_D(u8, x7, 15, 0);
break;
case 0xC2:
INST_NAME("CMPPD Gx, Ex, Ib");
+1 -6
View File
@@ -380,9 +380,6 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
GETEYSD(v1, 0, 0);
}
GETGYxy_empty(v0);
if(!BOX64ENV(dynarec_fastround)) {
u8 = sse_setround(dyn, ninst, x6, x4);
}
d0 = fpu_get_scratch(dyn);
if(vex.l) {
XVFCVTH_D_S(d0, v1);
@@ -391,9 +388,6 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
} else {
VFCVTL_D_S(v0, v1);
}
if(!BOX64ENV(dynarec_fastround)) {
x87_restoreround(dyn, ninst, u8);
}
break;
case 0x5B:
INST_NAME("VCVTDQ2PS Gx, Ex");
@@ -512,6 +506,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
INST_NAME("VLDMXCSR Md");
GETED(0);
ST_W(ed, xEmu, offsetof(x64emu_t, mxcsr));
sse_fcsr3_from_mxcsr(dyn, ninst, x3);
if (BOX64ENV(sse_flushto0)) {
/* LA <-> x86
16/24 <-> 5 inexact
+1 -9
View File
@@ -350,9 +350,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETEYxy(v1, 0, 0);
GETGYx_empty(v0);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x6, x4);
}
if (vex.l) {
XVFCVT_S_D(v0, VZERO, v1);
XVPERMI_D(v0, v0, 0b11011000);
@@ -361,15 +358,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
VFCVT_S_D(d0, v1, v1);
XVPICKVE_D(v0, d0, 0);
}
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
break;
case 0x5B:
INST_NAME("VCVTPS2DQ Gx, Ex");
nextop = F8;
GETGY_empty_EY_xy(v0, v1, 0);
u8 = sse_setround(dyn, ninst, x6, x4);
if (vex.l) {
if (!BOX64ENV(dynarec_fastround)) {
d1 = fpu_get_scratch(dyn);
@@ -399,7 +392,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
VFTINT_W_S(v0, v1);
}
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x5C:
INST_NAME("VSUBPD Gx, Vx, Ex");
@@ -1249,7 +1241,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VPXOR Gx, Vx, Ex");
nextop = F8;
GETGY_empty_VYEY_xy(v0, v1, v2, 0);
VXOR_Vxy(v0, v1, v2);
XVXOR_V(v0, v1, v2);
if (v0 == v1 && v0 == v2) YMM_UNMARK_UPPER_ZERO(v0);
break;
case 0xF1:
+4 -4
View File
@@ -1299,7 +1299,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
@@ -1318,7 +1318,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
@@ -1337,7 +1337,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
@@ -1356,7 +1356,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
nextop = F8;
GETGY_empty_VYEY_xy(q0, q1, q2, 0);
if (MODREG && (gd == (nextop & 7) + (rex.b << 3))) {
d0 = fpu_get_scratch(dyn);
d0 = SCRATCH;
VOR_Vxy(d0, q2, q2);
} else
d0 = -1;
+2 -13
View File
@@ -178,13 +178,11 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETGY_empty_EY_xy(v0, v1, 1);
u8 = F8;
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
if (vex.l) {
XVFRINT_S(v0, v1);
} else {
VFRINT_S(v0, v1);
}
x87_restoreround(dyn, ninst, u8);
} else {
if (vex.l) {
XVFRINTRRD_S(v0, v1, round_round[u8 & 3]);
@@ -199,13 +197,11 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETGY_empty_EY_xy(v0, v1, 1);
u8 = F8;
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
if (vex.l) {
XVFRINT_D(v0, v1);
} else {
VFRINT_D(v0, v1);
}
x87_restoreround(dyn, ninst, u8);
} else {
if (vex.l) {
XVFRINTRRD_D(v0, v1, round_round[u8 & 3]);
@@ -223,9 +219,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
u8 = F8;
d0 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_S(d0, v2);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_S(d0, v2, round_round[u8 & 3]);
}
@@ -241,9 +235,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
u8 = F8;
d0 = fpu_get_scratch(dyn);
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x1, x2);
VFRINT_D(d0, v2);
x87_restoreround(dyn, ninst, u8);
} else {
VFRINTRRD_D(d0, v2, round_round[u8 & 3]);
}
@@ -509,13 +501,10 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
GETEYSD(v1, 1, 1);
}
u8 = F8;
if (u8 & 4) {
u8 = sse_setround(dyn, ninst, x4, x5);
} else {
if (!(u8 & 4)) {
MOVFCSR2GR(x4, FCSR3);
ORI(x5, xZR, ((-(u8 & 3)) & 3) << 8);
MOVGR2FCSR(FCSR3, x5);
u8 = x4;
}
if (vex.l) {
XVFCVT_H_S(v1, VZERO, v0);
@@ -525,7 +514,7 @@ uintptr_t dynarec64_AVX_66_0F3A(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t i
VFCVT_H_S(v1, VZERO, v0);
PUTEYSD(v1);
}
x87_restoreround(dyn, ninst, u8);
if (!(u8 & 4)) x87_restoreround(dyn, ninst, x4);
break;
case 0x20:
INST_NAME("VPINSRB Gx, Vx, ED, Ib");
-16
View File
@@ -117,9 +117,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETVYx(v1, 0);
GETGYx_empty(v0);
d1 = fpu_get_scratch(dyn);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
if (rex.w) {
MOVGR2FR_D(d1, ed);
FFINT_D_L(d1, d1);
@@ -127,9 +124,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVGR2FR_W(d1, ed);
FFINT_D_W(d1, d1);
}
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_D(v0, d1, 0);
break;
@@ -171,7 +165,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
d1 = fpu_get_scratch(dyn);
u8 = sse_setround(dyn, ninst, x2, x3);
if (rex.w) {
FTINT_L_D(d1, q0);
MOVFR2GR_D(gd, d1);
@@ -180,7 +173,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
@@ -268,13 +260,7 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETVYx(v1, 0);
GETGYx_empty(v0);
d0 = fpu_get_scratch(dyn);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
FCVT_S_D(d0, v2);
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
if (v0 != v1) VOR_V(v0, v1, v1);
XVINSVE0_W(v0, d0, 0);
break;
@@ -492,7 +478,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
nextop = F8;
GETEYxy(v1, 0, 0);
GETGYx_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2);
if (vex.l) {
if (!BOX64ENV(dynarec_fastround)) {
q0 = fpu_get_scratch(dyn);
@@ -536,7 +521,6 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
}
XVPICKVE_D(v0, d0, 0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
INST_NAME("VLDDQU Gx, Ex");
-10
View File
@@ -107,9 +107,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
GETVYx(v1, 0);
GETGYx_empty(v0);
d1 = fpu_get_scratch(dyn);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
if (rex.w) {
MOVGR2FR_D(d1, ed);
FFINT_S_L(d1, d1);
@@ -117,9 +114,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVGR2FR_W(d1, ed);
FFINT_S_W(d1, d1);
}
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
if (v0 != v1) VOR_V(v0, v1, v1);
VEXTRINS_W(v0, d1, 0);
break;
@@ -131,7 +125,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
u8 = sse_setround(dyn, ninst, x5, x6);
d1 = fpu_get_scratch(dyn);
if (rex.w) {
FTINTRZ_L_S(d1, d0);
@@ -141,7 +134,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
@@ -162,7 +154,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
u8 = sse_setround(dyn, ninst, x5, x6);
d1 = fpu_get_scratch(dyn);
if (rex.w) {
FTINT_L_S(d1, d0);
@@ -172,7 +163,6 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
MOVFR2GR_S(gd, d1);
ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
+3 -3
View File
@@ -437,12 +437,12 @@ void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
NAT_FLAGS_ENABLE_SIGN();
NAT_FLAGS_ENABLE_SF();
if (cpuext.lbt) {
IFX(X_ALL) {
X64_AND_B(s1, s2);
}
if (s1 == s2) {
NAT_FLAGS_ENABLE_SF();
int r = s1;
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
@@ -561,13 +561,13 @@ void emit_test16(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4,
}
NAT_FLAGS_ENABLE_SIGN();
NAT_FLAGS_ENABLE_SF();
if (cpuext.lbt) {
IFX (X_ALL) {
X64_AND_H(s1, s2);
}
if (s1 == s2) {
NAT_FLAGS_ENABLE_SF();
int r = s1;
if (dyn->insts[ninst].nat_flags_fusion) {
if (dyn->insts[ninst].nat_flags_needsign) {
@@ -630,6 +630,7 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
}
NAT_FLAGS_ENABLE_SIGN();
NAT_FLAGS_ENABLE_SF();
if (cpuext.lbt) {
IFX(X_ALL) {
if (rex.w)
@@ -639,7 +640,6 @@ void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int
}
if (s1 == s2) {
NAT_FLAGS_ENABLE_SF();
int r = s1;
if (dyn->insts[ninst].nat_flags_fusion) {
if (!rex.w) {
+35
View File
@@ -1452,6 +1452,41 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
MVxw(gd, x1);
}
break;
case 0xF6:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 2:
if (MODREG) {
INST_NAME("Invalid LOCK");
UDF();
*need_epilog = 1;
*ok = 0;
} else {
INST_NAME("LOCK NOT Eb");
addr = geted(dyn, addr, ninst, nextop, &wback, x5, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
if (cpuext.lamcas) {
LD_BU(x3, wback, 0);
MARKLOCK2;
MV(x2, x3);
XORI(x1, x3, 0xff);
AMCAS_DB_B(x3, x1, wback);
BSTRPICK_D(x3, x3, 7, 0);
BNE_MARKLOCK2(x3, x2);
} else {
ANDI(x2, wback, 3);
SLLI_D(x2, x2, 3);
MV(x3, wback);
BSTRINS_D(x3, xZR, 1, 0);
ADDI_D(x1, xZR, 0xff);
SLL_W(x1, x1, x2);
AMXOR_DB_W(x4, x1, x3);
}
}
break;
default:
DEFAULT;
}
break;
case 0xF7:
nextop = F8;
switch ((nextop >> 3) & 7) {
-16
View File
@@ -98,9 +98,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(v0, 1);
GETED(0);
d1 = fpu_get_scratch(dyn);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
if (rex.w) {
MOVGR2FR_D(d1, ed);
FFINT_D_L(d1, d1);
@@ -108,9 +105,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MOVGR2FR_W(d1, ed);
FFINT_D_W(d1, d1);
}
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
VEXTRINS_D(v0, d1, 0);
break;
case 0x2C:
@@ -151,7 +145,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
d1 = fpu_get_scratch(dyn);
u8 = sse_setround(dyn, ninst, x2, x3);
if (rex.w) {
FTINT_L_D(d1, q0);
MOVFR2GR_D(gd, d1);
@@ -160,7 +153,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MOVFR2GR_S(gd, d1);
if (NEED_ZEROUP(gd)) ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
@@ -273,13 +265,7 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGX(v0, 1);
GETEXSD(d0, 0, 0);
d1 = fpu_get_scratch(dyn);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x2, x3);
}
FCVT_S_D(d1, d0);
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x5C:
@@ -521,7 +507,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
nextop = F8;
GETEX(v1, 0, 0);
GETGX_empty(v0);
u8 = sse_setround(dyn, ninst, x1, x2);
if (BOX64ENV(dynarec_fastround)) {
VFTINT_W_D(v0, v1, v1);
} else {
@@ -536,7 +521,6 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
VSHUF4I_W(q1, q1, 0b00001000);
VBITSEL_V(v0, d0, q0, q1);
}
x87_restoreround(dyn, ninst, u8);
VINSGR2VR_D(v0, xZR, 1);
break;
case 0xF0:
-8
View File
@@ -105,17 +105,11 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETED(0);
d1 = fpu_get_scratch(dyn);
MOVGR2FR_D(d1, ed);
if (BOX64ENV(dynarec_fastround) <= 1) {
u8 = sse_setround(dyn, ninst, x5, x6);
}
if (rex.w) {
FFINT_S_L(d1, d1);
} else {
FFINT_S_W(d1, d1);
}
if (BOX64ENV(dynarec_fastround) <= 1) {
x87_restoreround(dyn, ninst, u8);
}
VEXTRINS_W(v0, d1, 0);
break;
case 0x2C:
@@ -157,7 +151,6 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64ENV(dynarec_fastround)) {
MOVGR2FCSR(FCSR2, xZR); // reset all bits
}
u8 = sse_setround(dyn, ninst, x5, x6);
d1 = fpu_get_scratch(dyn);
if (rex.w) {
FTINT_L_S(d1, d0);
@@ -167,7 +160,6 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
MOVFR2GR_S(gd, d1);
if (NEED_ZEROUP(gd)) ZEROUP(gd);
}
x87_restoreround(dyn, ninst, u8);
if (!BOX64ENV(dynarec_fastround)) {
MOVFCSR2GR(x5, FCSR2); // get back FPSR to check
MOV32w(x3, (1 << FR_V) | (1 << FR_O));
+20 -5
View File
@@ -836,20 +836,35 @@ void updateNativeFlags(dynarec_la64_t* dyn)
if (dyn->insts[i].nat_flags_fusion) {
int j = i - 1;
int found = 0;
int last_fused = 0;
if (hasLinearPredecessor(dyn, i)) {
while (j >= 0) {
if (dyn->insts[j].x64.set_flags && (dyn->insts[i].x64.use_flags & dyn->insts[j].x64.set_flags) == dyn->insts[i].x64.use_flags) {
int needsign = (dyn->insts[i].x64.use_flags & X_SF) ? 1 : 0;
int needunsigned = (dyn->insts[i].x64.use_flags & X_CF) ? 1 : 0;
if (dyn->insts[j].nat_flags_fusion && ((needsign && dyn->insts[j].nat_flags_needunsigned) || (needunsigned && dyn->insts[j].nat_flags_needsign)))
break; // not compatible, stop here
dyn->insts[j].nat_flags_fusion = 1;
if (dyn->insts[i].x64.use_flags & X_SF) {
if (needsign)
dyn->insts[j].nat_flags_needsign = 1;
}
if (needunsigned)
dyn->insts[j].nat_flags_needunsigned = 1;
dyn->insts[i].x64.use_flags = 0;
dyn->insts[j].nat_next_inst = i;
if (last_fused) {
dyn->insts[last_fused].nat_next_inst = i;
} else {
uint16_t* next = &dyn->insts[j].nat_next_inst;
while (*next) next = &dyn->insts[*next].nat_next_inst;
*next = i;
}
dyn->insts[i].up32_read |= dyn->insts[j].up32_write32;
found = 1;
break;
} else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].no_scratch_usage
&& !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) {
} else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].nat_flags_fusion && dyn->insts[j].x64.jmp && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) {
// already fused Jcc consumer
if (!last_fused) last_fused = j;
j -= 1;
} else if (hasLinearPredecessor(dyn, j) && dyn->insts[j].no_scratch_usage && !dyn->insts[j].x64.set_flags && !dyn->insts[j].x64.use_flags) {
j -= 1;
} else
break;
+20 -12
View File
@@ -26,6 +26,8 @@
#include "../dynarec_helper.h"
#include "dynarec_la64_helper.h"
static_assert(offsetof(x64emu_t, mxcsr) == EMU_MXCSR, "EMU_MXCSR out of sync with x64emu_t");
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted(dynarec_la64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta)
{
@@ -389,7 +391,7 @@ static int indirect_lookup(dynarec_la64_t* dyn, int ninst, int is32bits, int s1,
MAYUSE(dyn);
if (!is32bits) {
SRLI_D(s1, xRIP, 48);
BNEZ_safe(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block);
BNEZ_safe_(s1, (intptr_t)dyn->jmp_next - (intptr_t)dyn->block);
if (dyn->need_reloc) {
TABLE64C(s2, const_jmptbl48);
} else {
@@ -587,8 +589,10 @@ void call_c(dynarec_la64_t* dyn, int ninst, la64_consts_t fnc, int reg, int ret,
if (arg5) MV(A5, arg5);
if (arg6) MV(A6, arg6);
MV(A0, xEmu);
if (!dyn->x87round_active) MOVGR2FCSR(FCSR3, xZR);
JIRL(xRA, reg, 0);
LA64_RESTORE_VZERO();
if (!dyn->x87round_active) sse_fcsr3_from_mxcsr(dyn, ninst, x2);
if (ret >= 0) {
MV(ret, A0);
}
@@ -633,6 +637,11 @@ void call_n(dynarec_la64_t* dyn, int ninst, void* fnc, int w)
ST_D(xRSP, xEmu, offsetof(x64emu_t, regs[_SP]));
ST_D(xRBP, xEmu, offsetof(x64emu_t, regs[_BP]));
ST_D(xRBX, xEmu, offsetof(x64emu_t, regs[_BX]));
int nfp = (abs(w) & 15) - 1;
if (nfp > 0)
for (int i = 0; i < nfp; ++i)
sse_get_reg(dyn, ninst, x3, i, w);
if (w < 0) sse_get_reg_empty(dyn, ninst, x3, 0);
// check if additional sextw needed
int sextw_mask = ((w > 0 ? w : -w) >> 4) & 0b111111;
for (int i = 0; i < 6; i++) {
@@ -645,8 +654,10 @@ void call_n(dynarec_la64_t* dyn, int ninst, void* fnc, int w)
// Note that if need_reloc is active, the TABLE64 will trigger cancel block,
// because native function might be very different on a next run: different function address, different brick, different everything basicaly
// and we don't have a relocation mecanism here, it's too complex
MOVGR2FCSR(FCSR3, xZR);
JIRL(xRA, x3, 0x0);
LA64_RESTORE_VZERO();
sse_fcsr3_from_mxcsr(dyn, ninst, x2);
// put return value in x64 regs
if (w > 0) {
MV(xRAX, A0);
@@ -895,6 +906,7 @@ int x87_setround(dynarec_la64_t* dyn, int ninst, int s1, int s2)
MAYUSE(ninst);
MAYUSE(s1);
MAYUSE(s2);
dyn->x87round_active = 1;
LD_W(s1, xEmu, offsetof(x64emu_t, cw));
BSTRPICK_W(s1, s1, 11, 10);
// MMX/x87 Round mode: 0..3: Nearest, Down, Up, Chop
@@ -909,25 +921,20 @@ int x87_setround(dynarec_la64_t* dyn, int ninst, int s1, int s2)
return s2;
}
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_la64_t* dyn, int ninst, int s1, int s2)
// Sync FCSR3 round mode from emu->mxcsr, destroying s1
// MMX/x87 Round mode: 0..3: Nearest, Down, Up, Chop
// LA64: 0..3: Nearest, TowardZero, TowardsPositive, TowardsNegative
// 0->0, 1->3, 2->2, 3->1
void sse_fcsr3_from_mxcsr(dynarec_la64_t* dyn, int ninst, int s1)
{
MAYUSE(dyn);
MAYUSE(ninst);
MAYUSE(s1);
MAYUSE(s2);
LD_W(s1, xEmu, offsetof(x64emu_t, mxcsr));
BSTRPICK_W(s1, s1, 14, 13);
// MMX/x87 Round mode: 0..3: Nearest, Down, Up, Chop
// LA64: 0..3: Nearest, TowardZero, TowardsPositive, TowardsNegative
// 0->0, 1->3, 2->2, 3->1
SUB_W(s1, xZR, s1);
ANDI(s1, s1, 3);
// done
SLLI_D(s1, s1, 8);
MOVFCSR2GR(s2, FCSR3);
MOVGR2FCSR(FCSR3, s1); // exchange RM with current
return s2;
MOVGR2FCSR(FCSR3, s1);
}
int lsxcache_st_coherency(dynarec_la64_t* dyn, int ninst, int a, int b)
@@ -1324,6 +1331,7 @@ void x87_restoreround(dynarec_la64_t* dyn, int ninst, int s1)
MAYUSE(dyn);
MAYUSE(ninst);
MAYUSE(s1);
dyn->x87round_active = 0;
MOVGR2FCSR(FCSR3, s1);
}
+44 -33
View File
@@ -135,19 +135,19 @@ static inline int comis_fuse_inverted(int condition)
#define COMIS_FUSED() (dyn->insts[ninst].comis_fusion >= 0)
#endif
#define COMIS_BRANCH_NOT_TAKEN(offset) \
#define COMIS_BRANCH_NOT_TAKEN(offset, jmp) \
do { \
if (comis_fuse_inverted(dyn->insts[ninst].comis_fusion)) \
BCNEZ_safe(COMIS_FCC, offset); \
BCNEZ_safe(COMIS_FCC, offset, jmp); \
else \
BCEQZ_safe(COMIS_FCC, offset); \
BCEQZ_safe(COMIS_FCC, offset, jmp); \
} while (0)
#define COMIS_BRANCH_TAKEN(offset) \
#define COMIS_BRANCH_TAKEN(offset, jmp) \
do { \
if (comis_fuse_inverted(dyn->insts[ninst].comis_fusion)) \
BCEQZ_safe(COMIS_FCC, offset); \
BCEQZ_safe(COMIS_FCC, offset, jmp); \
else \
BCNEZ_safe(COMIS_FCC, offset); \
BCNEZ_safe(COMIS_FCC, offset, jmp); \
} while (0)
#define COMIS_SPILL_S() \
@@ -1214,24 +1214,36 @@ static inline int comis_fuse_inverted(int condition)
READFLAGS(A)
#endif
#define NAT_FLAGS_OPS(op1, op2, s1, s2) \
do { \
dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = op1; \
dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = op2; \
if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op1)) { \
if (dyn->insts[ninst].up32_read & (1 << TO_X64(op1))) \
MV(s1, op1); \
else \
ZEROUP2(s1, op1); \
dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op1 = s1; \
} \
if (dyn->insts[ninst + 1].no_scratch_usage && IS_GPR(op2)) { \
if (dyn->insts[ninst].up32_read & (1 << TO_X64(op2))) \
MV(s2, op2); \
else \
ZEROUP2(s2, op2); \
dyn->insts[dyn->insts[ninst].nat_next_inst].nat_flags_op2 = s2; \
} \
#define NAT_FLAGS_OPS(op1, op2, s1, s2) \
do { \
int nat_op1 = op1; \
int nat_op2 = op2; \
int nat_next = dyn->insts[ninst].nat_next_inst; \
int nat_last = nat_next; \
while (nat_last && dyn->insts[nat_last].nat_next_inst) \
nat_last = dyn->insts[nat_last].nat_next_inst; \
int nat_copy = 0; \
for (int nat_i = ninst + 1; nat_i < nat_last; ++nat_i) \
if (dyn->insts[nat_i].no_scratch_usage) \
nat_copy = 1; \
if (nat_copy && IS_GPR(nat_op1)) { \
if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op1))) \
MV(s1, nat_op1); \
else \
ZEROUP2(s1, nat_op1); \
nat_op1 = s1; \
} \
if (nat_copy && IS_GPR(nat_op2)) { \
if (dyn->insts[ninst].up32_read & (1 << TO_X64(nat_op2))) \
MV(s2, nat_op2); \
else \
ZEROUP2(s2, nat_op2); \
nat_op2 = s2; \
} \
for (int nat_i = nat_next; nat_i; nat_i = dyn->insts[nat_i].nat_next_inst) { \
dyn->insts[nat_i].nat_flags_op1 = nat_op1; \
dyn->insts[nat_i].nat_flags_op2 = nat_op2; \
} \
} while (0)
#define NAT_FLAGS_ENABLE_CARRY() dyn->insts[ninst].nat_flags_carry = 1
@@ -1558,7 +1570,7 @@ static inline int comis_fuse_inverted(int condition)
#define x87_unreflectcount STEPNAME(x87_unreflectcount)
#define x87_purgecache STEPNAME(x87_purgecache)
#define sse_setround STEPNAME(sse_setround)
#define sse_fcsr3_from_mxcsr STEPNAME(sse_fcsr3_from_mxcsr)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_purge07cache STEPNAME(sse_purge07cache)
@@ -1762,8 +1774,7 @@ void fpu_reflectcache(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_unreflectcache(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_pushcache(dynarec_la64_t* dyn, int ninst, int s1, int not07);
void fpu_popcache(dynarec_la64_t* dyn, int ninst, int s1, int not07);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_la64_t* dyn, int ninst, int s1, int s2);
void sse_fcsr3_from_mxcsr(dynarec_la64_t* dyn, int ninst, int s1);
// SSE/SSE2 helpers
// purge the XMM0..XMM7 cache (before function call)
@@ -1966,13 +1977,13 @@ uintptr_t dynarec64_DF(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break
// Dummy macros
#define B__safe(a, b, c) XOR(xZR, xZR, xZR)
#define B_(a, b, c) XOR(xZR, xZR, xZR)
#define S_(a, b, c) XOR(xZR, xZR, xZR)
#define MV_(a, b, c, d) XOR(xZR, xZR, xZR)
#define B__safe(a, b, c, d) XOR(xZR, xZR, xZR)
#define B_(a, b, c) XOR(xZR, xZR, xZR)
#define S_(a, b, c) XOR(xZR, xZR, xZR)
#define MV_(a, b, c, d) XOR(xZR, xZR, xZR)
#define NATIVEJUMP_safe(COND, val) \
B##COND##_safe(dyn->insts[ninst].nat_flags_op1, dyn->insts[ninst].nat_flags_op2, val);
#define NATIVEJUMP_safe(COND, val, jmp) \
B##COND##_safe(dyn->insts[ninst].nat_flags_op1, dyn->insts[ninst].nat_flags_op2, val, jmp);
#define NATIVEJUMP(COND, val) \
B##COND(dyn->insts[ninst].nat_flags_op1, dyn->insts[ninst].nat_flags_op2, val);
+1 -1
View File
@@ -18,7 +18,7 @@
#define READFLAGS_FUSION(A, s1, s2, s3, s4, s5) \
if (BOX64ENV(dynarec_nativeflags) && ninst > 0) { \
int prev = ninst - 1; \
while (prev && dyn->insts[prev].no_scratch_usage) \
while (prev && (dyn->insts[prev].no_scratch_usage || dyn->insts[prev].nat_flags_fusion)) \
prev -= 1; \
if (!dyn->insts[prev].nat_flags_nofusion) { \
if ((A) == (X_ZF)) \
+3 -1
View File
@@ -123,6 +123,7 @@ typedef struct instruction_la64_s {
uint8_t nat_flags_sign:1;
uint8_t nat_flags_sf:1;
uint8_t nat_flags_needsign:1;
uint8_t nat_flags_needunsigned:1;
uint8_t no_scratch_usage : 1; // this opcode does not use scratch register
uint8_t nat_flags_op1;
uint8_t nat_flags_op2;
@@ -132,7 +133,7 @@ typedef struct instruction_la64_s {
unsigned x87_used:1; // no fine tracking, just a global "any reg used"
unsigned fpu_used:1; // any xmm/ymm/x87/mmx reg used
unsigned fpupurge:1; // this opcode will purge all fpu regs
uint16_t nat_next_inst;
uint16_t nat_next_inst; // for producer: first consumer; for consumer: next consumer
uint16_t up32_read; // bitmask of GPRs whose upper 32 bits are read by this instruction
uint16_t up32_write64; // bitmask of GPRs written as 64-bit by this instruction (upper 32 become defined)
uint16_t up32_write32; // bitmask of GPRs written as 32-bit by this instruction
@@ -198,6 +199,7 @@ typedef struct dynarec_la64_s {
uint8_t is_file_mapped:1;
void* gdbjit_block;
uint32_t need_x87check; // x87 low precision check
int x87round_active; // we are in the middle of x87_setround and x87_restoreround
uint32_t need_dump; // need to dump the block
int need_reloc; // does the dynablock need relocations
int reloc_size;
+203 -14
View File
@@ -566,7 +566,10 @@
#define B(imm28) EMIT(type_I26(0b010100, ((imm28) >> 2)))
#define B__(reg1, reg2, imm28) B(imm28)
#define BEQ_safe(rj, rd, imm) \
#define NEAR_JUMP_INSTS 100
#define NEAR_JUMPZ_INSTS 300
#define BEQ_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BEQ(rj, rd, imm); \
@@ -577,7 +580,20 @@
} \
} while (0)
#define BNE_safe(rj, rd, imm) \
#define BEQ_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BEQ_safe_(rj, rd, imm); \
else \
BEQ(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BEQ(rj, rd, imm); \
else \
BEQ_safe_(rd, rj, imm); \
} while (0)
#define BNE_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BNE(rj, rd, imm); \
@@ -588,7 +604,20 @@
} \
} while (0)
#define BLT_safe(rj, rd, imm) \
#define BNE_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BNE_safe_(rj, rd, imm); \
else \
BNE(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BNE(rj, rd, imm); \
else \
BNE_safe_(rj, rd, imm); \
} while (0)
#define BLT_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BLT(rj, rd, imm); \
@@ -599,7 +628,20 @@
} \
} while (0)
#define BGE_safe(rj, rd, imm) \
#define BLT_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BLT_safe_(rj, rd, imm); \
else \
BLT(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BLT(rj, rd, imm); \
else \
BLT_safe_(rj, rd, imm); \
} while (0)
#define BGE_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BGE(rj, rd, imm); \
@@ -610,7 +652,20 @@
} \
} while (0)
#define BLTU_safe(rj, rd, imm) \
#define BGE_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BGE_safe_(rj, rd, imm); \
else \
BGE(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BGE(rj, rd, imm); \
else \
BGE_safe_(rj, rd, imm); \
} while (0)
#define BLTU_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BLTU(rj, rd, imm); \
@@ -621,7 +676,20 @@
} \
} while (0)
#define BGEU_safe(rj, rd, imm) \
#define BLTU_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BLTU_safe_(rj, rd, imm); \
else \
BLTU(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BLTU(rj, rd, imm); \
else \
BLTU_safe_(rj, rd, imm); \
} while (0)
#define BGEU_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BGEU(rj, rd, imm); \
@@ -632,7 +700,20 @@
} \
} while (0)
#define BGT_safe(rj, rd, imm) \
#define BGEU_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BGEU_safe_(rj, rd, imm); \
else \
BGEU(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BGEU(rj, rd, imm); \
else \
BGEU_safe_(rj, rd, imm); \
} while (0)
#define BGT_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BGT(rj, rd, imm); \
@@ -643,7 +724,20 @@
} \
} while (0)
#define BLE_safe(rj, rd, imm) \
#define BGT_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BGT_safe_(rj, rd, imm); \
else \
BGT(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BGT(rj, rd, imm); \
else \
BGT_safe_(rj, rd, imm); \
} while (0)
#define BLE_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BLE(rj, rd, imm); \
@@ -654,7 +748,20 @@
} \
} while (0)
#define BGTU_safe(rj, rd, imm) \
#define BLE_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BLE_safe_(rj, rd, imm); \
else \
BLE(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BLE(rj, rd, imm); \
else \
BLE_safe_(rj, rd, imm); \
} while (0)
#define BGTU_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BGTU(rj, rd, imm); \
@@ -665,7 +772,20 @@
} \
} while (0)
#define BLEU_safe(rj, rd, imm) \
#define BGTU_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BGTU_safe_(rj, rd, imm); \
else \
BGTU(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BGTU(rj, rd, imm); \
else \
BGTU_safe_(rj, rd, imm); \
} while (0)
#define BLEU_safe_(rj, rd, imm) \
do { \
if ((imm) > -0x20000 && (imm) < 0x20000) { \
BLEU(rj, rd, imm); \
@@ -676,7 +796,20 @@
} \
} while (0)
#define BEQZ_safe(rj, imm) \
#define BLEU_safe(rj, rd, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x20000) \
BLEU_safe_(rj, rd, imm); \
else \
BLEU(rj, rd, imm); \
} else if (jmp - ninst < NEAR_JUMP_INSTS) \
BLEU(rj, rd, imm); \
else \
BLEU_safe_(rj, rd, imm); \
} while (0)
#define BEQZ_safe_(rj, imm) \
do { \
if ((imm) > -0x70000 && (imm) < 0x70000) { \
BEQZ(rj, imm); \
@@ -687,7 +820,20 @@
} \
} while (0)
#define BNEZ_safe(rj, imm) \
#define BEQZ_safe(rj, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x70000) \
BEQZ_safe_(rj, imm); \
else \
BEQZ(rj, imm); \
} else if (jmp - ninst < NEAR_JUMPZ_INSTS) \
BEQZ(rj, imm); \
else \
BEQZ_safe_(rj, imm); \
} while (0)
#define BNEZ_safe_(rj, imm) \
do { \
if ((imm) > -0x70000 && (imm) < 0x70000) { \
BNEZ(rj, imm); \
@@ -698,7 +844,20 @@
} \
} while (0)
#define BCEQZ_safe(rj, imm) \
#define BNEZ_safe(rj, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x70000) \
BNEZ_safe_(rj, imm); \
else \
BNEZ(rj, imm); \
} else if (jmp - ninst < NEAR_JUMPZ_INSTS) \
BNEZ(rj, imm); \
else \
BNEZ_safe_(rj, imm); \
} while (0)
#define BCEQZ_safe_(rj, imm) \
do { \
if ((imm) > -0x70000 && (imm) < 0x70000) { \
BCEQZ(rj, imm); \
@@ -709,7 +868,20 @@
} \
} while (0)
#define BCNEZ_safe(rj, imm) \
#define BCEQZ_safe(rj, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x70000) \
BCEQZ_safe_(rj, imm); \
else \
BCEQZ(rj, imm); \
} else if (jmp - ninst < NEAR_JUMPZ_INSTS) \
BCEQZ(rj, imm); \
else \
BCEQZ_safe_(rj, imm); \
} while (0)
#define BCNEZ_safe_(rj, imm) \
do { \
if ((imm) > -0x70000 && (imm) < 0x70000) { \
BCNEZ(rj, imm); \
@@ -720,6 +892,19 @@
} \
} while (0)
#define BCNEZ_safe(rj, imm, jmp) \
do { \
if (jmp < ninst) { \
if ((imm) < -0x70000) \
BCNEZ_safe_(rj, imm); \
else \
BCNEZ(rj, imm); \
} else if (jmp - ninst < NEAR_JUMPZ_INSTS) \
BCNEZ(rj, imm); \
else \
BCNEZ_safe_(rj, imm); \
} while (0)
// vaddr = GR[rj] + SignExtend(imm12, GRLEN)
// AddressComplianceCheck(vaddr)
// paddr = AddressTranslation(vaddr)
@@ -1283,6 +1468,10 @@ LSX instruction starts with V, LASX instruction starts with XV.
#define VROTR_H(vd, vj, vk) EMIT(type_3R(0b01110000111011101, vk, vj, vd))
#define VROTR_W(vd, vj, vk) EMIT(type_3R(0b01110000111011110, vk, vj, vd))
#define VROTR_D(vd, vj, vk) EMIT(type_3R(0b01110000111011111, vk, vj, vd))
#define VROTRI_B(vd, vj, imm3) EMIT(type_2RI3(0b111001010100000001, imm3, vj, vd))
#define VROTRI_H(vd, vj, imm4) EMIT(type_2RI4(0b11100101010000001, imm4, vj, vd))
#define VROTRI_W(vd, vj, imm5) EMIT(type_2RI5(0b1110010101000001, imm5, vj, vd))
#define VROTRI_D(vd, vj, imm6) EMIT(type_2RI6(0b111001010100001, imm6, vj, vd))
#define VSRLR_B(vd, vj, vk) EMIT(type_3R(0b01110000111100000, vk, vj, vd))
#define VSRLR_H(vd, vj, vk) EMIT(type_3R(0b01110000111100001, vk, vj, vd))
#define VSRLR_W(vd, vj, vk) EMIT(type_3R(0b01110000111100010, vk, vj, vd))
+9
View File
@@ -45,6 +45,15 @@ la64_epilog:
st.d RIP, Emu, (8 * 17) // put back reg value in emu, including EIP (so $r29 must be EIP now)
// fallback to epilog_fast now, just restoring saved regs
la64_epilog_fast:
// spill FCSR3 round mode back to mxcsr
movfcsr2gr $r19, $fcsr3
bstrpick.w $r19, $r19, 9, 8
sub.w $r19, $r0, $r19
andi $r19, $r19, 3
ld.w $r20, Emu, EMU_MXCSR
bstrins.d $r20, $r19, 14, 13
st.w $r20, Emu, EMU_MXCSR
movgr2fcsr $fcsr3, $r0
addi.d $sp, SavedSP, 0 // restore save sp from xSavedSP
// restore all used register
ld.d $r1, $sp, (8 * 0) // load ra
+2
View File
@@ -176,4 +176,6 @@ r31 s8 xEmu Saved register The Emu struct
#endif // ASM_MAPPING
#define EMU_MXCSR 800
#endif //__LA64_MAPPING_H__
+8
View File
@@ -76,6 +76,14 @@ la64_prolog:
beqz $r19, 1f
x86mtflag Flags, 0b111111
1:
// map mxcsr round mode to FCSR3
// x86 RC: 0..3: Nearest, Down, Up, Chop -> LA64 RM: 0->0, 1->3, 2->2, 3->1
ld.w $r19, Emu, EMU_MXCSR
bstrpick.w $r19, $r19, 14, 13
sub.w $r19, $r0, $r19
andi $r19, $r19, 3
slli.d $r19, $r19, 8
movgr2fcsr $fcsr3, $r19
// push sentinel onto the stack
st.d $r0, $sp, -16
st.d $r0, $sp, -8
+2
View File
@@ -610,6 +610,7 @@ SETMARK(d_adc8b);
LD_BU(x2, xEmu, offsetof(x64emu_t, op1));
LD_BU(x3, xEmu, offsetof(x64emu_t, op2));
ADD_D(x4, x2, x3);
ANDI(x4, x4, 0xff);
SUB_D(x4, x1, x4);
SNEZ(x4, x4);
ADD_D(x1, x2, x3);
@@ -667,6 +668,7 @@ SETMARK(d_adc16b);
LD_HU(x2, xEmu, offsetof(x64emu_t, op1));
LD_HU(x3, xEmu, offsetof(x64emu_t, op2));
ADD_D(x4, x2, x3);
BSTRPICK_D(x4, x4, 15, 0);
SUB_D(x4, x1, x4);
SNEZ(x4, x4);
ADD_D(x1, x2, x3);
+21 -9
View File
@@ -600,7 +600,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
POP1z(xFlags);
FLAGS_ADJUST_FROM11(xFlags, xFlags, x2);
MOV32w(x1, 0x3E7FF7);
@@ -816,8 +816,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
INST_NAME("REPZ CMPSB");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
if (rex.is67 && !rex.is32bits) {
ZEROUP(xRSI);
@@ -878,8 +881,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
INST_NAME("REPZ CMPSD");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
if (rex.is67 && !rex.is32bits) {
ZEROUP(xRSI);
@@ -1044,8 +1050,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
INST_NAME("REPZ SCASB");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
ANDI(x1, xRAX, 0xff);
if (rex.is67 && !rex.is32bits) {
@@ -1100,8 +1109,11 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
INST_NAME("REPZ SCASD");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
if (rex.w) {
MV(x1, xRAX);
+91 -26
View File
@@ -624,8 +624,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("ROL Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
if (opcode == 0xD2 && BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
CALL_(const_rol8, ed, x3, x1, x2);
EBBACK(x5, 0);
@@ -639,8 +643,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("ROR Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
if (opcode == 0xD2 && BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
CALL_(const_ror8, ed, x3, x1, x2);
EBBACK(x5, 0);
@@ -654,9 +662,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("RCL Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
if (opcode == 0xD2 && BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
CALL_(const_rcl8, ed, x3, x1, x2);
EBBACK(x5, 0);
@@ -670,9 +683,14 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("RCR Eb, CL");
GETEB(x1, 0);
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
if (opcode == 0xD2 && BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
CALL_(const_rcr8, ed, x3, x1, x2);
EBBACK(x5, 0);
@@ -689,9 +707,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
if (opcode == 0xD2) {
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
emit_shl8(dyn, ninst, x1, x2, x5, x4, x6);
@@ -708,9 +729,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
ANDI(x2, xRCX, 0x1F);
BEQ_NEXT(x2, xZR);
}
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
if (opcode == 0xD2) {
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
emit_shr8(dyn, ninst, x1, x2, x5, x4, x6);
@@ -727,9 +751,12 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
}
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
if (opcode == 0xD2) {
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
emit_sar8(dyn, ninst, x1, x2, x5, x4, x6);
@@ -812,7 +839,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Ed, CL");
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETED(0);
ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f);
emit_rol32(dyn, ninst, rex, ed, x6, x3, x4);
@@ -821,7 +851,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 1:
INST_NAME("ROR Ed, CL");
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETED(0);
ANDI(x6, xRCX, rex.w ? 0x3f : 0x1f);
emit_ror32(dyn, ninst, rex, ed, x6, x3, x4);
@@ -831,7 +864,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 2:
INST_NAME("RCL Ed, CL");
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
ANDI(x2, xRCX, rex.w ? 0x3f : 0x1f);
GETEDW(x4, x1, 0);
@@ -842,7 +879,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 3:
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
ANDI(x2, xRCX, rex.w ? 0x3f : 0x1f);
GETEDW(x4, x1, 0);
@@ -853,7 +894,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 4:
case 6:
INST_NAME("SHL Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
if (!dyn->insts[ninst].x64.gen_flags) {
GETED(0);
if (rex.w)
@@ -878,7 +923,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 5:
INST_NAME("SHR Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
if (!dyn->insts[ninst].x64.gen_flags) {
GETED(0);
if (rex.w)
@@ -903,7 +952,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 7:
INST_NAME("SAR Ed, CL");
SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
ANDI(x3, xRCX, rex.w ? 0x3f : 0x1f);
GETED(0);
if (!rex.w && MODREG) { ZEROUP(ed); }
@@ -1143,7 +1196,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
MOV64x(x2, addr);
}
fpu_purgecache(dyn, ninst, 1, x1, x3, x4);
fpu_purgecache(dyn, ninst, 0, x1, x3, x4);
PUSH1z(x2);
int can_continue = (addr < (dyn->start + dyn->isize));
if (BOX64DRENV(dynarec_callret)) {
@@ -1339,7 +1392,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 6:
INST_NAME("DIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
GETEB(x1, 0);
ZEXTH(x2, xRAX);
if (BOX64ENV(dynarec_div0)) {
@@ -1370,7 +1423,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("IDIV Eb");
SKIPTEST(x1);
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else if (BOX64ENV(cputype)) {
SETFLAGS(X_SF | X_PF | X_ZF | X_AF, SF_SUBSET, NAT_FLAGS_NOFUSION);
}
GETEB(x1, 0);
CALL(const_idiv8, -1, x1, 0);
break;
@@ -1404,7 +1461,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
CLEAR_FLAGS();
SET_DFNONE();
GETED(0);
@@ -1446,7 +1503,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
CLEAR_FLAGS();
SET_DFNONE();
GETSED(0);
@@ -1477,10 +1534,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
OR(xFlags, xFlags, x6);
}
}
IFX (X_SF) {
SRLI(x6, xRAX, rex.w ? 63 : 31);
SLLI(x6, x6, F_SF);
OR(xFlags, xFlags, x6);
}
IFX (X_PF) emit_pf(dyn, ninst, xRAX, x6, x4);
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
if (!rex.w) {
GETED(0);
@@ -1565,8 +1628,10 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 7:
INST_NAME("IDIV Ed");
SKIPTEST(x1);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
}
if (!rex.w) {
GETSED(0);
if (BOX64ENV(dynarec_div0)) {
+41 -16
View File
@@ -292,7 +292,6 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
INST_NAME("MOVLHPS Gx,Ex");
} else {
INST_NAME("MOVHPS Gx,Ex");
SMREAD();
}
GETGX();
GETEX(x2, 0, 1);
@@ -1242,12 +1241,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
for (int i = 0; i < 4; ++i) {
FLW(s0, wback, fixedaddress + i * 4);
FLW(s1, gback, gdoffset + i * 4);
FEQS(x3, s0, s0);
FEQS(x4, s1, s1);
AND(x3, x3, x4);
BEQZ(x3, 12);
FLTS(x3, s0, s1);
BEQZ(x3, 8);
FLTS(x3, s1, s0);
BNEZ(x3, 8);
FSW(s0, gback, gdoffset + i * 4);
}
break;
@@ -1293,7 +1288,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
FEQS(x4, s1, s1);
AND(x3, x3, x4);
BEQZ(x3, 12);
FLTS(x3, s1, s0);
FLES(x3, s1, s0);
BEQZ(x3, 8);
FSW(s0, gback, gdoffset + i * 4);
}
@@ -1931,9 +1926,11 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
GETGD;
GETED(0);
if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); }
@@ -1997,9 +1994,11 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1)
MAYSETFLAGS();
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETGD;
GETED(0);
if (!rex.w && !rex.is32bits && MODREG) { ZEROUP(ed); }
@@ -2392,7 +2391,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
CLEAR_FLAGS();
@@ -2424,7 +2423,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
CLEAR_FLAGS();
@@ -2635,6 +2634,32 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
}
} else {
switch ((nextop >> 3) & 7) {
case 1:
if (rex.w) {
DEFAULT;
} else {
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, NULL, 0, 0);
ANDI(xFlags, xFlags, ~(1 << F_ZF));
ZEXTW2(x3, xRAX);
SLLI(x2, xRDX, 32);
OR(x3, x3, x2); // x3 is edx:eax
LD(x2, wback, fixedaddress);
BNE_MARK(x2, x3);
ZEXTW2(x4, xRBX);
SLLI(x5, xRCX, 32);
OR(x4, x4, x5); // x4 is ecx:ebx
SD(x4, wback, fixedaddress);
SMWRITE();
ORI(xFlags, xFlags, 1 << F_ZF);
B_NEXT_nocond;
MARK;
SRLI(xRDX, x2, 32);
ZEXTW2(xRAX, x2);
}
break;
case 4:
INST_NAME("Unsupported XSAVEC Ed");
FAKEED;
+2 -10
View File
@@ -661,11 +661,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1);
GETGX_vector(q0, 1, VECTOR_SEW32);
GETEX_vector(q1, 0, 0, VECTOR_SEW32);
v0 = fpu_get_scratch(dyn);
VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED);
VMFEQ_VV(v0, q1, q1, VECTOR_UNMASKED);
VFMIN_VV(q0, q0, q1, VECTOR_UNMASKED);
VMAND_MM(VMASK, v0, VMASK);
VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED);
VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED);
VADD_VX(q0, q1, xZR, VECTOR_MASKED);
break;
@@ -684,11 +680,7 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1);
GETGX_vector(q0, 1, VECTOR_SEW32);
GETEX_vector(q1, 0, 0, VECTOR_SEW32);
v0 = fpu_get_scratch(dyn);
VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED);
VMFEQ_VV(v0, q1, q1, VECTOR_UNMASKED);
VFMAX_VV(q0, q0, q1, VECTOR_UNMASKED);
VMAND_MM(VMASK, v0, VMASK);
VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED);
VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED);
VADD_VX(q0, q1, xZR, VECTOR_MASKED);
break;
+52 -25
View File
@@ -461,7 +461,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("IMUL Gw, Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
nextop = F8;
GETSEW(x1, (opcode == 0x69) ? 2 : 1);
if (opcode == 0x69)
@@ -842,7 +842,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
POP1_16(x1);
FLAGS_ADJUST_FROM11(x1, x1, x2);
LUI(x2, 0xffff0);
@@ -955,8 +955,11 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("REPZ CMPSW");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
if (rex.is67 && !rex.is32bits) {
ZEROUP(xRSI);
@@ -1071,8 +1074,11 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("REPZ SCASW");
}
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
CBZ_NEXT(xRCX);
GETDIR(x3, x1, rex.w ? 8 : 2);
if (rex.is67 && !rex.is32bits) {
@@ -1346,52 +1352,65 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
switch ((nextop >> 3) & 7) {
case 0:
INST_NAME("ROL Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
ANDI(x2, xRCX, 0x1f);
GETEW(x1, 0);
CALL_(const_rol16, x1, x3, x1, x2);
EWBACK;
break;
case 1:
INST_NAME("ROR Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
ANDI(x2, xRCX, 0x1f);
GETEW(x1, 0);
CALL_(const_ror16, x1, x3, x1, x2);
EWBACK;
break;
case 2:
INST_NAME("RCL Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
ANDI(x2, xRCX, 0x1f);
GETEW(x1, 0);
CALL_(const_rcl16, x1, x3, x1, x2);
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, CL");
ANDI(x2, xRCX, 0x1f);
MESSAGE("LOG_DUMP", "Need optimization\n");
READFLAGS(X_CF);
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_OF | X_CF);
} else {
READFLAGS(X_CF);
}
SETFLAGS(X_OF | X_CF, SF_SET_DF, NAT_FLAGS_NOFUSION);
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
ANDI(x2, xRCX, 0x1f);
GETEW(x1, 0);
CALL_(const_rcr16, x1, x3, x1, x2);
EWBACK;
break;
case 5:
INST_NAME("SHR Ew, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 0);
emit_shr16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
@@ -1399,20 +1418,26 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 4:
case 6:
INST_NAME("SHL Ew, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETEW(x1, 0);
emit_shl16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
break;
case 7:
INST_NAME("SAR Ew, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION); // some flags are left undefined
ANDI(x2, xRCX, 0x1f);
BEQ_NEXT(x2, xZR);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined
if (BOX64DRENV(dynarec_safeflags) > 1) MAYSETFLAGS();
GETSEW(x1, 0);
emit_sar16(dyn, ninst, x1, x2, x5, x4, x6);
EWBACK;
@@ -1488,7 +1513,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 6:
INST_NAME("DIV Ew");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
GETEW(x1, 0);
ZEXTH(x2, xRAX);
@@ -1517,8 +1542,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 7:
INST_NAME("IDIV Ew");
NOTEST(x1);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
}
GETSEW(x1, 0);
if (BOX64ENV(dynarec_div0)) {
BNE_MARK3(ed, xZR);
+12 -12
View File
@@ -244,7 +244,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
} else {
INST_NAME("UCOMISD Gx, Ex");
}
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGXSD(d0);
@@ -499,8 +499,8 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FEQD(x4, d1, d1);
AND(x3, x3, x4);
BEQ(x3, xZR, 12);
FLTD(x3, d1, d0);
BEQ(x3, xZR, 8); // continue
FLTD(x3, d0, d1);
BNE(x3, xZR, 8); // continue
FSD(d1, gback, gdoffset + 8 * i);
}
break;
@@ -545,7 +545,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FEQD(x4, d1, d1);
AND(x3, x3, x4);
BEQ(x3, xZR, 12);
FLTD(x3, d0, d1);
FLED(x3, d0, d1);
BEQ(x3, xZR, 8); // continue
FSD(d1, gback, gdoffset + 8 * i);
}
@@ -796,7 +796,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
for (int i = 0; i < 4; ++i) {
// GX->sw[i] = (GX->sd[i]<-32768)?-32768:((GX->sd[i]>32767)?32767:GX->sd[i]);
LW(x3, gback, gdoffset + i * 4);
BGE(x5, x3, 8);
BGT(x5, x3, 8);
ADDI(x3, x5, -1);
BGE(x3, x6, 8);
MV(x3, x6);
@@ -811,7 +811,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
for (int i = 0; i < 4; ++i) {
// GX->sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
LW(x3, wback, fixedaddress + i * 4);
BGE(x5, x3, 8);
BGT(x5, x3, 8);
ADDI(x3, x5, -1);
BGE(x3, x6, 8);
MV(x3, x6);
@@ -1250,9 +1250,9 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("SHLD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETGW(x2);
GETEW(x1, 0);
ANDI(x4, xRCX, 0x1f);
@@ -1323,9 +1323,9 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
INST_NAME("SHRD Ew, Gw, CL");
if (BOX64DRENV(dynarec_safeflags) > 1) {
READFLAGS(X_ALL);
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_FUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
} else
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_NOFUSION);
GETGW(x2);
GETEW(x1, 0);
ANDI(x4, xRCX, 0x1f);
@@ -1596,7 +1596,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xBC:
INST_NAME("BSF Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
IFX (X_ALL) CLEAR_FLAGS();
} else
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
@@ -1626,7 +1626,7 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
case 0xBD:
INST_NAME("BSR Gw, Ew");
if (BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
IFX (X_ALL) CLEAR_FLAGS();
} else
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
+7 -9
View File
@@ -317,7 +317,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode,
case 0x17:
INST_NAME("PTEST Gx, Ex");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
GETGX();
GETEX(x1, 0, 8);
CLEAR_FLAGS();
@@ -332,8 +332,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode,
AND(x6, x4, x2);
AND(x7, x5, x3);
OR(x6, x6, x7);
BNEZ(x6, 4 + 4);
ORI(xFlags, xFlags, 1 << F_ZF);
SET_FLAGS_EQZ(x6, F_ZF, x7);
}
IFX (X_CF) {
NOT(x4, x4);
@@ -341,8 +340,7 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode,
AND(x6, x4, x2);
AND(x7, x5, x3);
OR(x6, x6, x7);
BNEZ(x6, 4 + 4);
ORI(xFlags, xFlags, 1 << F_CF);
SET_FLAGS_EQZ(x6, F_CF, x7);
}
}
break;
@@ -1196,8 +1194,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode,
} 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;
ADDI(x5, xZR, u8);
CALL6(const_sse42_compare_string_explicit_len, x1, ed, x2, x3, x4, x5, 0);
@@ -1242,8 +1240,8 @@ uintptr_t dynarec64_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 1);
}
ZEXTW2(x2, xRDX);
ZEXTW2(x4, xRAX);
SEXT_W(x2, xRDX);
SEXT_W(x4, xRAX);
u8 = F8;
ADDI(x5, xZR, u8);
CALL6(const_sse42_compare_string_explicit_len, x1, ed, x2, x3, x4, x5, 0);
+6 -16
View File
@@ -445,7 +445,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
case 0x17:
INST_NAME("PTEST Gx, Ex");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1);
GETGX_vector(q0, 0, VECTOR_SEW64);
GETEX_vector(q1, 0, 0, VECTOR_SEW64);
@@ -464,8 +464,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
}
VMV_X_S(x4, VMASK);
if (!cpuext.xtheadvector) ANDI(x4, x4, 0b11);
BNEZ(x4, 8);
ORI(xFlags, xFlags, 1 << F_ZF);
SET_FLAGS_EQZ(x4, F_ZF, x3);
}
IFX (X_CF) {
VXOR_VI(v0, q0, 0x1F, VECTOR_UNMASKED);
@@ -480,8 +479,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
}
VMV_X_S(x4, VMASK);
if (!cpuext.xtheadvector) ANDI(x4, x4, 0b11);
BNEZ(x4, 8);
ORI(xFlags, xFlags, 1 << F_CF);
SET_FLAGS_EQZ(x4, F_CF, x3);
}
break;
case 0x1C ... 0x1E:
@@ -1213,11 +1211,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1);
GETGX_vector(q0, 1, VECTOR_SEW64);
GETEX_vector(q1, 0, 0, VECTOR_SEW64);
v0 = fpu_get_scratch(dyn);
VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED);
VMFEQ_VV(v0, q1, q1, VECTOR_UNMASKED);
VFMIN_VV(q0, q0, q1, VECTOR_UNMASKED);
VMAND_MM(VMASK, v0, VMASK);
VMFLT_VV(VMASK, q0, q1, VECTOR_UNMASKED);
VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED);
VADD_VX(q0, q1, xZR, VECTOR_MASKED);
break;
@@ -1236,11 +1230,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1);
GETGX_vector(q0, 1, VECTOR_SEW64);
GETEX_vector(q1, 0, 0, VECTOR_SEW64);
v0 = fpu_get_scratch(dyn);
VMFEQ_VV(VMASK, q0, q0, VECTOR_UNMASKED);
VMFEQ_VV(v0, q1, q1, VECTOR_UNMASKED);
VFMAX_VV(q0, q0, q1, VECTOR_UNMASKED);
VMAND_MM(VMASK, v0, VMASK);
VMFLT_VV(VMASK, q1, q0, VECTOR_UNMASKED);
VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED);
VADD_VX(q0, q1, xZR, VECTOR_MASKED);
break;
@@ -1743,7 +1733,7 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL2, 2);
VSLIDEUP_VI(v0, (q1 & 1) ? d1 : q1, 2, VECTOR_UNMASKED);
VCOMPRESS_VM(d0, v0, VMASK);
VXOR_VI(VMASK, VMASK, 0x1F, VECTOR_UNMASKED);
VMNAND_MM(VMASK, VMASK, VMASK);
VCOMPRESS_VM(d1, v0, VMASK);
vector_vsetvli(dyn, ninst, x1, VECTOR_SEW64, VECTOR_LMUL1, 1);
if (!BOX64ENV(dynarec_fastnan)) {
+1
View File
@@ -59,6 +59,7 @@ uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in
GETGD;
GETEW(x1, 0);
MV(x5, ed);
ZEROUP(gd);
MOV32w(x2, 0x82f63b78);
for (int j = 0; j < 2; ++j) {
SRLI(x6, x5, 8 * j);
+116
View File
@@ -49,6 +49,122 @@ uintptr_t dynarec64_66F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in
static const int8_t round_round[] = { RD_RNE, RD_RDN, RD_RUP, RD_RTZ };
switch (opcode) {
case 0xB8:
INST_NAME("POPCNT Gw, Ew");
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
CLEAR_FLAGS();
if (cpuext.zbb) {
CPOPW(gd, ed);
} else {
// w = ed - ((ed >> 1) & 0x5555)
SRLI(x4, ed, 1);
MOV64x(x5, 0x5555);
AND(x4, x4, x5);
SUB(x3, ed, x4);
// w = (w & 0x3333) + ((w >> 2) & 0x3333)
SRLI(x4, x3, 2);
MOV64x(x5, 0x3333);
AND(x6, x3, x5);
AND(x4, x4, x5);
ADD(x3, x6, x4);
// w = (w + (w >> 4)) & 0x0F0F
SRLI(x4, x3, 4);
MOV64x(x5, 0x0F0F);
ADD(x3, x3, x4);
AND(x3, x3, x5);
// w = (w + (w >> 8)) & 0xFF
SRLI(x4, x3, 8);
ADD(x3, x3, x4);
ANDI(gd, x3, 0xFF);
}
IFX (X_ALL) {
CLEAR_FLAGS();
SET_FLAGS_EQZ(gd, F_ZF, x7);
}
GWBACK;
break;
case 0xBC:
INST_NAME("TZCNT Gw, Ew");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
CLEAR_FLAGS();
IFX (X_CF) {
SEQZ(x3, ed);
OR(xFlags, xFlags, x3); // F_CF at bit0.
}
if (cpuext.zbs) {
BSETI(x6, ed, 16);
} else {
ADDI(x6, xZR, 1);
SLLI(x6, x6, 16);
OR(x6, ed, x6);
}
if (cpuext.zbb) {
CTZW(gd, x6);
} else {
ADDI(gd, xZR, 0);
MARK;
ANDI(x5, x6, 1);
BNEZ_MARK3(x5);
ADDI(gd, gd, 1);
SRLI(x6, x6, 1);
B_MARK_nocond;
MARK3;
}
IFX (X_ZF) SET_FLAGS_EQZ(gd, F_ZF, x3);
GWBACK;
break;
case 0xBD:
INST_NAME("LZCNT Gw, Ew");
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
CLEAR_FLAGS();
IFX (X_CF) {
SEQZ(x3, ed);
OR(xFlags, xFlags, x3); // F_CF at bit0.
}
if (cpuext.zbb) {
CLZW(gd, ed);
ADDI(gd, gd, -16);
} else {
BEQZ_MARK2(ed);
ADDI(gd, xZR, 0);
MV(x4, ed);
MOV64x(x6, 0x8000);
MARK;
AND(x5, x4, x6);
BNEZ_MARK3(x5);
ADDI(gd, gd, 1);
SLLI(x4, x4, 1);
B_MARK_nocond;
MARK2;
ADDI(gd, xZR, 16);
MARK3;
}
IFX (X_ZF) SET_FLAGS_EQZ(gd, F_ZF, x3);
GWBACK;
break;
default:
DEFAULT;
}
+8
View File
@@ -58,8 +58,16 @@ uintptr_t dynarec64_AVX(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int n
addr = dynarec64_AVX_F3_0F(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_66))
addr = dynarec64_AVX_66_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_NONE))
addr = dynarec64_AVX_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F2))
addr = dynarec64_AVX_F2_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F38) && (vex.p == VEX_P_F3))
addr = dynarec64_AVX_F3_0F38(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_66))
addr = dynarec64_AVX_66_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else if ((vex.m == VEX_M_0F3A) && (vex.p == VEX_P_F2))
addr = dynarec64_AVX_F2_0F3A(dyn, addr, ip, ninst, vex, ok, need_epilog);
else {
DEFAULT;
}
+29 -1
View File
@@ -103,6 +103,20 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in
SD(x3, gback, gdoffset + 8);
YMM0(gd);
break;
case 0x13:
INST_NAME("VMOVLPS Ex, Gx");
nextop = F8;
GETGX();
GETEX(x2, 0, 8);
if (MODREG) {
DEFAULT;
return addr;
} else {
LD(x3, gback, gdoffset);
SD(x3, wback, fixedaddress);
SMWRITE2();
}
break;
case 0x14:
INST_NAME("VUNPCKLPS Gx, Vx, Ex");
nextop = F8;
@@ -179,6 +193,20 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in
SD(x4, gback, gdoffset);
YMM0(gd);
break;
case 0x17:
INST_NAME("VMOVHPS Ex, Gx");
nextop = F8;
GETGX();
GETEX(x2, 0, 8);
if (MODREG) {
DEFAULT;
return addr;
} else {
LD(x3, gback, gdoffset + 8);
SD(x3, wback, fixedaddress);
SMWRITE2();
}
break;
case 0x28:
INST_NAME("VMOVAPS Gx, Ex");
nextop = F8;
@@ -225,7 +253,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, in
} else {
INST_NAME("UCOMISS Gx, Ex");
}
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGXSS(d0);
+250
View File
@@ -0,0 +1,250 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch (opcode) {
case 0xF2:
INST_NAME("ANDN Gd, Vd, Ed");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETGD;
GETED(0);
GETVD;
if (cpuext.zbb) {
ANDN(gd, ed, vd);
} else {
NOT(x5, vd);
AND(gd, ed, vd);
}
if (!rex.w) {
ZEROUP(gd);
}
CLEAR_FLAGS();
IFX (X_SF) {
SRLI(x5, gd, rex.w ? 63 : 31);
SLLI(x5, x5, F_SF);
OR(xFlags, xFlags, x5);
}
IFX (X_ZF) {
SET_FLAGS_EQZ(gd, F_ZF, x5);
}
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
}
break;
case 0xF3:
nextop = F8;
switch ((nextop >> 3) & 7) {
case 1:
INST_NAME("BLSR Vd, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETED(0);
GETVD;
if (!rex.w) {
ZEXTW2(x4, ed);
ed = x4;
}
CLEAR_FLAGS();
IFX (X_CF) {
SET_FLAGS_EQZ(ed, F_CF, x5);
}
ADDIxw(x3, ed, -1);
AND(vd, ed, x3);
if (!rex.w) ZEROUP(vd);
IFX (X_ZF) {
SET_FLAGS_EQZ(vd, F_ZF, x5);
}
IFX (X_SF) {
SRLI(x5, vd, rex.w ? 63 : 31);
SLLI(x5, x5, F_SF);
OR(xFlags, xFlags, x5);
}
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, vd, x3, x5);
}
break;
case 2:
INST_NAME("BLSMSK Vd, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETED(0);
GETVD;
if (!rex.w) {
ZEXTW2(x4, ed);
ed = x4;
}
CLEAR_FLAGS();
IFX (X_CF) {
SET_FLAGS_EQZ(ed, F_CF, x5);
}
ADDIxw(x3, ed, -1);
XOR(vd, ed, x3);
if (!rex.w) ZEROUP(vd);
IFX (X_SF) {
SRLI(x5, vd, rex.w ? 63 : 31);
SLLI(x5, x5, F_SF);
OR(xFlags, xFlags, x5);
}
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, vd, x3, x5);
}
break;
case 3:
INST_NAME("BLSI Vd, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETED(0);
GETVD;
if (!rex.w) {
ZEXTW2(x4, ed);
ed = x4;
}
CLEAR_FLAGS();
IFX (X_CF) {
SET_FLAGS_NEZ(ed, F_CF, x5);
}
SUBxw(x3, xZR, ed);
AND(vd, ed, x3);
if (!rex.w) ZEROUP(vd);
IFX (X_ZF) {
SET_FLAGS_EQZ(vd, F_ZF, x5);
}
IFX (X_SF) {
SRLI(x5, vd, rex.w ? 63 : 31);
SLLI(x5, x5, F_SF);
OR(xFlags, xFlags, x5);
}
if (BOX64DRENV(dynarec_safeflags)) {
IFX (X_PF) emit_pf(dyn, ninst, vd, x3, x5);
}
break;
default:
DEFAULT;
}
break;
case 0xF5:
INST_NAME("BZHI Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETGD;
GETED(0);
GETVD;
CLEAR_FLAGS();
ANDI(x4, vd, 0xff);
ADDI(x5, xZR, rex.w ? 64 : 32);
BGE_MARK(x4, x5);
ADDI(x6, xZR, -1);
SLL(x6, x6, x4);
ANDN(gd, ed, x6);
if (cpuext.zbb) {
ANDN(gd, ed, x6);
} else {
NOT(x6, x6);
AND(gd, ed, vd);
}
B_MARK2_nocond;
MARK;
MV(gd, ed);
IFX (X_CF) {
ORI(xFlags, xFlags, 1 << F_CF);
}
MARK2;
if (!rex.w) {
ZEROUP(gd);
}
IFX (X_ZF) {
SET_FLAGS_EQZ(gd, F_ZF, x5);
}
IFX (X_SF) {
SRLI(x5, gd, rex.w ? 63 : 31);
SLLI(x5, x5, F_SF);
OR(xFlags, xFlags, x5);
}
break;
case 0xF7:
INST_NAME("BEXTR Gd, Ed, Vd");
nextop = F8;
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
GETGD;
GETED(0);
GETVD;
ANDI(x4, vd, 0xff); // start
SRLI(x3, vd, 8);
ANDI(x3, x3, 0xff); // length
XOR(x5, x5, x5);
BEQZ_MARK(x3);
ADDI(x6, xZR, rex.w ? 64 : 32);
BGE_MARK(x4, x6);
SRLxw(x5, ed, x4);
BLT_MARK(x6, x3);
SUBxw(x6, x6, x3);
SLLxw(x5, x5, x6);
SRLxw(x5, x5, x6);
MARK;
OR(gd, x5, x5);
if (!rex.w) {
ZEROUP(gd);
}
CLEAR_FLAGS();
IFX (X_ZF) {
SET_FLAGS_EQZ(gd, F_ZF, x5);
}
break;
default:
DEFAULT;
}
return addr;
}
+7 -6
View File
@@ -192,7 +192,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
} else {
INST_NAME("VUCOMISD Gx, Ex");
}
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETGXSD(d0);
@@ -250,7 +250,8 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
INST_NAME("VSQRTPD Gx, Ex");
nextop = F8;
GETGX();
GETEX(x2, 0, 8);
GETGY();
GETEX(x2, 0, vex.l ? 24 : 8);
d0 = fpu_get_scratch(dyn);
if (!BOX64ENV(dynarec_fastnan)) {
d1 = fpu_get_scratch(dyn);
@@ -1848,7 +1849,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xD4:
INST_NAME("VPADDQ Gx, Vx, Ex");
nextop = F8;
GETEX(x2, 0, 8);
GETEX(x2, 0, vex.l ? 24 : 8);
GETGX();
GETGY();
GETVX();
@@ -2025,7 +2026,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xDB:
INST_NAME("VPAND Gx, Vx, Ex");
nextop = F8;
GETEX(x2, 0, 8);
GETEX(x2, 0, vex.l ? 24 : 8);
GETGX();
GETGY();
GETVX();
@@ -2161,7 +2162,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xDF:
INST_NAME("VPANDN Gx, Vx, Ex");
nextop = F8;
GETEX(x2, 0, 8);
GETEX(x2, 0, vex.l ? 24 : 8);
GETGX();
GETGY();
GETVX();
@@ -2869,7 +2870,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
case 0xFB:
INST_NAME("VPSUBQ Gx, Vx, Ex");
nextop = F8;
GETEX(x2, 0, 8);
GETEX(x2, 0, vex.l ? 24 : 8);
GETGX();
GETGY();
GETVX();
+2 -4
View File
@@ -581,8 +581,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
AND(x6, x4, x2);
AND(x7, x5, x3);
OR(x6, x6, x7);
BNEZ(x6, 4 + 4);
ORI(xFlags, xFlags, 1 << F_ZF);
SET_FLAGS_EQZ(x6, F_ZF, x7);
}
IFX (X_CF) {
NOT(x4, x4);
@@ -590,8 +589,7 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
AND(x6, x4, x2);
AND(x7, x5, x3);
OR(x6, x6, x7);
BNEZ(x6, 4 + 4);
ORI(xFlags, xFlags, 1 << F_CF);
SET_FLAGS_EQZ(x6, F_CF, x7);
}
}
if (vex.l) {
+130
View File
@@ -0,0 +1,130 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch (opcode) {
case 0xF5:
INST_NAME("PDEP Gd, Vd, Ed");
nextop = F8;
GETGD;
GETVD;
GETED(0);
if (gd == ed || gd == vd) {
gb1 = gd;
gd = x6;
} else {
gb1 = 0;
}
ADDI(gd, xZR, 0);
ADDI(x3, xZR, 1);
ADDI(x4, xZR, 1);
MARK;
AND(x5, ed, x4);
BEQZ_MARK2(x5);
AND(x5, vd, x3);
if (cpuext.zicond) {
CZERO_EQZ(x5, x4, x5);
OR(gd, gd, x5);
} else {
BEQZ_MARK3(x5);
OR(gd, gd, x4);
}
MARK3;
SLLIxw(x3, x3, 1);
MARK2;
SLLIxw(x4, x4, 1);
BNEZ_MARK(x4);
if (gb1)
MV(gb1, gd);
break;
case 0xF6:
INST_NAME("MULX Gd, Vd, Ed (,RDX)");
nextop = F8;
GETGD;
GETED(0);
GETVD;
if (rex.w) {
if ((gd == xRDX) || (gd == ed) || (gd == vd))
gb1 = x3;
else
gb1 = gd;
MULHU(gb1, xRDX, ed);
if (gd != vd) { MUL(vd, xRDX, ed); }
if (gb1 == x3) {
MV(gd, gb1);
}
} else {
ZEXTW2(x4, xRDX);
ZEXTW2(x5, ed);
MUL(x3, x4, x5);
if (gd != vd) { ZEXTW2(vd, x3); }
SRLI(gd, x3, 32);
}
break;
case 0xF7:
INST_NAME("SHRX Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
ANDI(x5, vd, rex.w ? 0x3f : 0x1f);
SRLxw(gd, ed, x5);
break;
default:
DEFAULT;
}
return addr;
}
@@ -0,0 +1,84 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F2_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch (opcode) {
case 0xF0:
INST_NAME("RORX Gd, Ed, Ib");
nextop = F8;
GETGD;
GETED(1);
u8 = F8;
if (cpuext.zbb) {
RORIxw(gd, ed, u8 & (rex.w ? 0x3f : 0x1f));
} else {
uint8_t count = u8 & (rex.w ? 0x3f : 0x1f);
if (count) {
SLLIxw(x4, ed, (rex.w ? 64 : 32) - count);
SRLIxw(gd, ed, count);
OR(gd, x4, gd);
} else {
MVxw(gd, ed);
}
}
if (!rex.w)
ZEROUP(gd);
break;
default:
DEFAULT;
}
return addr;
}
+107
View File
@@ -0,0 +1,107 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "box64cpu.h"
#include "emu/x64emu_private.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_native.h"
#include "rv64_printer.h"
#include "dynarec_rv64_private.h"
#include "dynarec_rv64_functions.h"
#include "../dynarec_helper.h"
uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog)
{
(void)ip;
(void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t gd, ed, vd;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2, gb1, gb2;
int32_t i32, i32_;
int cacheupd = 0;
int v0, v1, v2;
int q0, q1, q2;
int d0, d1, d2;
int s0;
uint64_t tmp64u;
int64_t j64;
int64_t fixedaddress;
int unscaled;
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(j64);
MAYUSE(cacheupd);
rex_t rex = vex.rex;
switch (opcode) {
case 0xF5:
INST_NAME("PEXT Gd, Vd, Ed");
nextop = F8;
GETGD;
GETVD;
GETED(0);
if (gd == ed || gd == vd) {
gb1 = gd;
gd = x6;
} else {
gb1 = 0;
}
ADDI(gd, xZR, 0);
ADDI(x3, xZR, 1);
ADDI(x4, xZR, 1);
MARK;
AND(x5, ed, x4);
BEQZ_MARK2(x5);
AND(x5, vd, x4);
if (cpuext.zicond) {
CZERO_EQZ(x5, x3, x5);
OR(gd, gd, x5);
} else {
BEQZ_MARK3(x5);
OR(gd, gd, x3);
}
MARK3;
SLLIxw(x3, x3, 1);
MARK2;
SLLIxw(x4, x4, 1);
BNEZ_MARK(x4);
if (gb1)
MV(gb1, gd);
break;
case 0xF7:
INST_NAME("SARX Gd, Ed, Vd");
nextop = F8;
GETGD;
GETED(0);
GETVD;
ANDI(x5, vd, rex.w ? 0x3f : 0x1f);
SRAxw(gd, ed, x5);
break;
default:
DEFAULT;
}
return addr;
}
+2 -2
View File
@@ -115,7 +115,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xE8 ... 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
@@ -127,7 +127,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
break;
case 0xF0 ... 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
if (ST_IS_F(0)) {
+1 -1
View File
@@ -68,7 +68,7 @@ uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
} else {
INST_NAME("FCOMIP ST0, STx");
}
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop & 7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop & 7, X87_COMBINE(0, nextop & 7));
+2
View File
@@ -318,6 +318,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
case 0:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(xFlags, xFlags, ~(1 << F_ZF));
@@ -363,6 +364,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
PASS3(if (!warned) dynarec_log(LOG_INFO, "Warning, LOCK CMPXCHG16B is not well supported on RISC-V and issues are expected.\n"));
PASS3(warned = 1);
SETFLAGS(X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, x2, &fixedaddress, rex, LOCK_LOCK, 0, 0);
ANDI(xFlags, xFlags, ~(1 << F_ZF));
+98
View File
@@ -152,6 +152,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETEB(x1, 0);
GETGD;
MV(x5, ed);
ZEROUP(gd);
XOR(gd, gd, x5);
MOV32w(x2, 0x82f63b78);
for (int i = 0; i < 8; i++) {
@@ -167,6 +168,7 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
GETGD;
GETED(0);
MV(x5, ed);
ZEROUP(gd);
MOV32w(x2, 0x82f63b78);
for (int j = 0; j < 4 * (rex.w + 1); ++j) {
SRLI(x3, x5, 8 * j);
@@ -422,6 +424,94 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FSW(s0, gback, gdoffset + 12);
}
break;
case 0x7D:
INST_NAME("HSUBPS Gx, Ex");
nextop = F8;
GETGX();
GETEX(x2, 0, 12);
s0 = fpu_get_scratch(dyn);
s1 = fpu_get_scratch(dyn);
// GX->f[0] = GX->f[0] - GX->f[1];
FLW(s0, gback, gdoffset + 0);
FLW(s1, gback, gdoffset + 4);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x3, s0, s0);
FEQS(x4, s1, s1);
AND(x5, x3, x4);
BEQZ(x5, 4 + 4 * 4);
}
FSUBS(s0, s0, s1);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x5, s0, s0);
BNEZ(x5, 4 + 4 * 3);
FNEGS(s0, s0);
BNEZ(x4, 4 + 4);
FMVS(s0, s1);
}
FSW(s0, gback, gdoffset + 0);
// GX->f[1] = GX->f[2] - GX->f[3];
FLW(s0, gback, gdoffset + 8);
FLW(s1, gback, gdoffset + 12);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x3, s0, s0);
FEQS(x4, s1, s1);
AND(x5, x3, x4);
BEQZ(x5, 4 + 4 * 4);
}
FSUBS(s0, s0, s1);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x5, s0, s0);
BNEZ(x5, 4 + 4 * 3);
FNEGS(s0, s0);
BNEZ(x4, 4 + 4);
FMVS(s0, s1);
}
FSW(s0, gback, gdoffset + 4);
if (MODREG && gd == (nextop & 7) + (rex.b << 3)) {
// GX->f[2] = GX->f[0];
FLW(s1, gback, gdoffset + 0);
FSW(s1, gback, gdoffset + 8);
// GX->f[3] = GX->f[1];
FSW(s0, gback, gdoffset + 12);
} else {
// GX->f[2] = EX->f[0] - EX->f[1];
FLW(s0, wback, fixedaddress + 0);
FLW(s1, wback, fixedaddress + 4);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x3, s0, s0);
FEQS(x4, s1, s1);
AND(x5, x3, x4);
BEQZ(x5, 4 + 4 * 4);
}
FSUBS(s0, s0, s1);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x5, s0, s0);
BNEZ(x5, 4 + 4 * 3);
FNEGS(s0, s0);
BNEZ(x4, 4 + 4);
FMVS(s0, s1);
}
FSW(s0, gback, gdoffset + 8);
// GX->f[3] = EX->f[2] - EX->f[3];
FLW(s0, wback, fixedaddress + 8);
FLW(s1, wback, fixedaddress + 12);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x3, s0, s0);
FEQS(x4, s1, s1);
AND(x5, x3, x4);
BEQZ(x5, 4 + 4 * 4);
}
FSUBS(s0, s0, s1);
if (!BOX64ENV(dynarec_fastnan)) {
FEQS(x5, s0, s0);
BNEZ(x5, 4 + 4 * 3);
FNEGS(s0, s0);
BNEZ(x4, 4 + 4);
FMVS(s0, s1);
}
FSW(s0, gback, gdoffset + 12);
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
@@ -473,6 +563,14 @@ uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
NEG(x2, x2);
FMVDX(d0, x2);
break;
case 0xD6:
INST_NAME("MOVDQ2Q Gm, Ex");
nextop = F8;
GETGM();
GETEX(x2, 0, 1);
LD(x3, wback, fixedaddress);
SD(x3, gback, gdoffset);
break;
case 0xD0:
INST_NAME("ADDSUBPS Gx, Ex");
nextop = F8;
@@ -353,10 +353,6 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMV_S_X(v1, x4);
GETGX_vector(v0, 1, VECTOR_SEW64);
}
if (BOX64ENV(dynarec_fastnan)) {
VECTOR_LOAD_VMASK(0b01, x4, 1);
VFMIN_VV(v0, v0, v1, VECTOR_MASKED);
} else {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFMV_F_S(d0, v0);
@@ -376,7 +372,6 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMERGE_VVM(v0, v0, d0); // implies VMASK
} else {
VFMV_S_F(v0, d0);
}
}
break;
case 0x5E:
@@ -413,10 +408,6 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMV_S_X(v1, x4);
GETGX_vector(v0, 1, VECTOR_SEW64);
}
if (BOX64ENV(dynarec_fastnan)) {
VECTOR_LOAD_VMASK(0b01, x4, 1);
VFMAX_VV(v0, v0, v1, VECTOR_MASKED);
} else {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFMV_F_S(d0, v0);
@@ -436,7 +427,6 @@ uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMERGE_VVM(v0, v0, d0); // implies VMASK
} else {
VFMV_S_F(v0, d0);
}
}
break;
case 0x70:
+55 -3
View File
@@ -541,7 +541,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
break;
case 0xB8:
INST_NAME("POPCNT Gd, Ed");
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
SET_DFNONE();
nextop = F8;
GETED(0);
@@ -647,7 +647,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
@@ -672,7 +672,7 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
if (!BOX64DRENV(dynarec_safeflags)) {
SETFLAGS(X_CF | X_ZF, SF_SUBSET, NAT_FLAGS_NOFUSION);
} else {
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION);
}
SET_DFNONE();
nextop = F8;
@@ -745,6 +745,16 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FMVWX(d0, x2);
break;
case 0xD6:
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX();
GETEM(x2, 0, 1);
LD(x3, wback, fixedaddress);
SD(x3, gback, gdoffset);
SD(xZR, gback, gdoffset + 8);
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
@@ -760,6 +770,48 @@ uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
FSD(q1, gback, gdoffset + 8);
break;
case 0x38:
opcode = F8;
switch (opcode) {
case 0xF6:
INST_NAME("ADOX Gd, Ed");
nextop = F8;
READFLAGS(X_OF);
SETFLAGS(X_OF, SF_SUBSET, NAT_FLAGS_NOFUSION);
GETGD;
GETED(0);
SRLI(x3, xFlags, F_OF2);
ANDI(x3, x3, 1);
IFX (X_OF) {
if (rex.w) {
ADD(x4, gd, ed);
SLTU(x5, x4, gd);
ADD(gd, x4, x3);
SLTU(x6, gd, x4);
} else {
ADDW(x4, gd, ed);
ZEXTW2(x4, x4);
ZEXTW2(gd, gd);
SLTU(x5, x4, gd);
ADDW(gd, x4, x3);
ZEXTW2(gd, gd);
SLTU(x6, gd, x4);
}
OR(x5, x5, x6);
ANDI(xFlags, xFlags, ~(1 << F_OF2));
SLLI(x5, x5, F_OF2);
OR(xFlags, xFlags, x5);
} else {
ADDxw(x5, gd, ed);
ADDxw(gd, x5, x3);
if (!rex.w) ZEROUP(gd);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
@@ -389,10 +389,6 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMV_S_X(v1, x4);
GETGX_vector(v0, 1, VECTOR_SEW32);
}
if (BOX64ENV(dynarec_fastnan)) {
VECTOR_LOAD_VMASK(0b0001, x4, 1);
VFMIN_VV(v0, v0, v1, VECTOR_MASKED);
} else {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFMV_F_S(d0, v0);
@@ -412,7 +408,6 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMERGE_VVM(v0, v0, d0); // implies VMASK
} else {
VFMV_S_F(v0, d0);
}
}
break;
case 0x5E:
@@ -449,10 +444,6 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMV_S_X(v1, x4);
GETGX_vector(v0, 1, VECTOR_SEW32);
}
if (BOX64ENV(dynarec_fastnan)) {
VECTOR_LOAD_VMASK(0b0001, x4, 1);
VFMAX_VV(v0, v0, v1, VECTOR_MASKED);
} else {
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VFMV_F_S(d0, v0);
@@ -472,7 +463,6 @@ uintptr_t dynarec64_F30F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
VMERGE_VVM(v0, v0, d0); // implies VMASK
} else {
VFMV_S_F(v0, d0);
}
}
break;
case 0x6F:
+1 -2
View File
@@ -697,12 +697,11 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
if (!dyn->need_dump && !BOX64ENV(dynarec_gdbjit) && !BOX64ENV(dynarec_perf_map)) return;
static char buf[4096];
int length = sprintf(buf, "barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d), sew@entry=%d, sew@exit=%d",
int length = sprintf(buf, "barrier=%d state=%d/%d(%d), set=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d), sew@entry=%d, sew@exit=%d",
dyn->insts[ninst].x64.barrier,
dyn->insts[ninst].x64.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].x64.may_set ? "may" : "set",
dyn->insts[ninst].x64.set_flags,
dyn->insts[ninst].x64.gen_flags,
dyn->insts[ninst].x64.use_flags,
+12 -9
View File
@@ -1612,11 +1612,10 @@ int sse_get_reg_empty(dynarec_rv64_t* dyn, int ninst, int s1, int a, int single)
}
if (dyn->e.ssecache[a].single != single) {
if (single) {
// writing back the float
if (dyn->e.ssecache[a].single)
FSW(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
// there is no need to clear upper bits, it's cleared manually when needed.
}
else
FSD(dyn->e.ssecache[a].reg, xEmu, offsetof(x64emu_t, xmm[a]));
dyn->e.olds[a].changed = 1;
dyn->e.olds[a].purged = 0;
dyn->e.olds[a].reg = EXTIDX(dyn->e.ssecache[a].reg);
@@ -2079,12 +2078,13 @@ static int findCacheSlot(dynarec_rv64_t* dyn, int ninst, int t, int n, extcache_
return -1;
}
static void swapCache(dynarec_rv64_t* dyn, int ninst, int i, int j, extcache_t* cache)
static void swapCache(dynarec_rv64_t* dyn, int ninst, int s1, int i, int j, extcache_t* cache)
{
if (i == j) return;
if (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW
|| cache->extcache[j].t == EXT_CACHE_XMMR || cache->extcache[j].t == EXT_CACHE_XMMW) {
SET_CACHE_VECTOR_WIDTH(s1);
int reg_i = EXTREG(i);
int reg_j = EXTREG(j);
if (!cache->extcache[i].v) {
@@ -2143,6 +2143,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int
{
int reg = EXTREG(i);
if (cache->extcache[i].v && (cache->extcache[i].t == EXT_CACHE_XMMR || cache->extcache[i].t == EXT_CACHE_XMMW)) {
SET_CACHE_VECTOR_WIDTH(s1);
int j = i + 1;
while (cache->extcache[j].v)
++j;
@@ -2170,7 +2171,7 @@ static void loadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, int
case EXT_CACHE_XMMR:
case EXT_CACHE_XMMW:
MESSAGE(LOG_DUMP, "\t - Loading %s\n", getCacheName(t, n));
SET_ELEMENT_WIDTH(s1, VECTOR_SEWANY, 0);
SET_CACHE_VECTOR_WIDTH(s1);
ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n]));
VLE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1);
break;
@@ -2240,7 +2241,7 @@ static void unloadCache(dynarec_rv64_t* dyn, int ninst, int stack_cnt, int s1, i
break;
case EXT_CACHE_XMMW:
MESSAGE(LOG_DUMP, "\t - Unloading %s\n", getCacheName(t, n));
SET_ELEMENT_WIDTH(s1, VECTOR_SEWANY, 0);
SET_CACHE_VECTOR_WIDTH(s1);
ADDI(s1, xEmu, offsetof(x64emu_t, xmm[n]));
VSE_V(reg, s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1);
break;
@@ -2376,7 +2377,7 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in
else {
// it's here, lets swap if needed
if (j != i)
swapCache(dyn, ninst, i, j, &cache);
swapCache(dyn, ninst, s1, i, j, &cache);
}
}
if (cache.extcache[i].t != cache_i2.extcache[i].t) {
@@ -2413,7 +2414,7 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in
} else if (cache.extcache[i].t == EXT_CACHE_XMMW && cache_i2.extcache[i].t == EXT_CACHE_XMMR) {
// refresh cache...
MESSAGE(LOG_DUMP, "\t - Refreh %s\n", getCacheName(cache.extcache[i].t, cache.extcache[i].n));
SET_ELEMENT_WIDTH(s1, VECTOR_SEWANY, 0);
SET_CACHE_VECTOR_WIDTH(s1);
ADDI(s1, xEmu, offsetof(x64emu_t, xmm[cache.extcache[i].n]));
VSE_V(EXTREG(i), s1, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1);
cache.extcache[i].t = EXT_CACHE_XMMR;
@@ -2446,6 +2447,8 @@ static void fpuCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1, int s2, in
s3_top = 0;
stack_cnt = cache_i2.stack;
}
if (dyn->vector_sew != VECTOR_SEWNA)
dyn->vector_eew = vector_vsetvli(dyn, ninst, s1, dyn->vector_sew, VECTOR_LMUL1, 1);
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
}
static void flagsCacheTransform(dynarec_rv64_t* dyn, int ninst, int s1)
+37 -14
View File
@@ -38,6 +38,7 @@
// GETGD get x64 register in gd
#define GETGD gd = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3))
#define GETVD vd = TO_NAT(vex.v)
// GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETED(D) \
if (MODREG) { \
@@ -754,6 +755,8 @@
#define BLTU_MARK3(reg1, reg2) Bxx_gen(LTU, MARK3, reg1, reg2)
// Branch to MARK3 if reg1!=0 (use j64)
#define BNEZ_MARK3(reg) BNE_MARK3(reg, xZR)
// Branch to MARK2 if reg1==0 (use j64)
#define BEQZ_MARK2(reg) BEQ_MARK2(reg, xZR)
// Branch to MARK3 if reg1==0 (use j64)
#define BEQZ_MARK3(reg) BEQ_MARK3(reg, xZR)
// Branch to MARK3 instruction unconditionnal (use j64)
@@ -869,14 +872,12 @@
#define FORCE_DFNONE() SW(xZR, xEmu, offsetof(x64emu_t, df))
#define SET_DFNONE() \
do { \
if (!dyn->f.dfnone) { \
FORCE_DFNONE(); \
} \
if (!dyn->insts[ninst].x64.may_set) { \
dyn->f.dfnone = 1; \
} \
#define SET_DFNONE() \
do { \
if (!dyn->f.dfnone) { \
FORCE_DFNONE(); \
} \
dyn->f.dfnone = 1; \
} while (0)
#define SET_DF(S, N) \
@@ -903,6 +904,10 @@
if (cpuext.xtheadcondmov) { \
ORI(scratch, xFlags, 1 << F); \
TH_MVNEZ(xFlags, scratch, reg); \
} else if (cpuext.zicond) { \
ADDI(scratch, xZR, 1 << F); \
CZERO_EQZ(scratch, scratch, reg); \
OR(xFlags, xFlags, scratch); \
} else { \
BEQZ(reg, 8); \
ORI(xFlags, xFlags, 1 << F); \
@@ -914,6 +919,10 @@
if (cpuext.xtheadcondmov) { \
ORI(scratch, xFlags, 1 << F); \
TH_MVEQZ(xFlags, scratch, reg); \
} else if (cpuext.zicond) { \
ADDI(scratch, xZR, 1 << F); \
CZERO_NEZ(scratch, scratch, reg); \
OR(xFlags, xFlags, scratch); \
} else { \
BNEZ(reg, 8); \
ORI(xFlags, xFlags, 1 << F); \
@@ -926,6 +935,11 @@
SLT(scratch1, reg, xZR); \
ORI(scratch2, xFlags, 1 << F); \
TH_MVNEZ(xFlags, scratch2, scratch1); \
} else if (cpuext.zicond) { \
SLT(scratch1, reg, xZR); \
ADDI(scratch2, xZR, 1 << F); \
CZERO_EQZ(scratch2, scratch2, scratch1); \
OR(xFlags, xFlags, scratch2); \
} else { \
BGE(reg, xZR, 8); \
ORI(xFlags, xFlags, 1 << F); \
@@ -1012,12 +1026,6 @@
x87_do_pop(dyn, ninst, scratch);
#endif
#ifndef MAYSETFLAGS
#define MAYSETFLAGS() \
do { \
} while (0)
#endif
#ifndef READFLAGS
#define READFLAGS(A) \
if (((A) != X_PEND && dyn->f.pending != SF_SET) \
@@ -1214,6 +1222,13 @@
} while (0)
#endif
#define SET_CACHE_VECTOR_WIDTH(S1) \
do { \
int sew = dyn->vector_sew; \
if (sew == VECTOR_SEWNA || sew == VECTOR_SEWANY) sew = VECTOR_SEW8; \
dyn->vector_eew = vector_vsetvli(dyn, ninst, (S1), sew, VECTOR_LMUL1, 1); \
} while (0)
#ifndef STEPNAME
#define STEPNAME3(N, M) N##M
#define STEPNAME2(N, M) STEPNAME3(N, M)
@@ -1259,6 +1274,10 @@
#define dynarec64_AVX_66_0F3A STEPNAME(dynarec64_AVX_66_0F3A)
#define dynarec64_AVX_F2_0F STEPNAME(dynarec64_AVX_F2_0F)
#define dynarec64_AVX_F3_0F STEPNAME(dynarec64_AVX_F3_0F)
#define dynarec64_AVX_0F38 STEPNAME(dynarec64_AVX_0F38)
#define dynarec64_AVX_F2_0F38 STEPNAME(dynarec64_AVX_F2_0F38)
#define dynarec64_AVX_F3_0F38 STEPNAME(dynarec64_AVX_F3_0F38)
#define dynarec64_AVX_F2_0F3A STEPNAME(dynarec64_AVX_F2_0F3A)
#define geted STEPNAME(geted)
#define geted16 STEPNAME(geted16)
@@ -1701,6 +1720,10 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i
uintptr_t dynarec64_AVX_66_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_F2_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_F3_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_F2_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_F3_0F38(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
uintptr_t dynarec64_AVX_F2_0F3A(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, vex_t vex, int* ok, int* need_epilog);
#if STEP < 2
#define PASS2(A)
+18 -7
View File
@@ -8,7 +8,6 @@
#define MESSAGE(A, ...) \
do { \
} while (0)
#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1
#define READFLAGS(A) \
dyn->insts[ninst].x64.use_flags = A; \
dyn->f.dfnone = 1; \
@@ -30,12 +29,24 @@
} \
READFLAGS(A);
#define SETFLAGS(A, B, FUSION) \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B) & ~SF_DF; \
dyn->f.pending = (B) & SF_SET_PENDING; \
dyn->f.dfnone = ((B) & SF_SET) ? (((B) == SF_SET_NODF) ? 0 : 1) : 0; \
dyn->insts[ninst].nat_flags_nofusion = (FUSION)
/* SF_SET_NODF and SF_SET_PENDING may leave the incoming deferred flags untouched. */
#define SETFLAGS(A, B, FUSION) \
do { \
dyn->insts[ninst].x64.set_flags = A; \
dyn->insts[ninst].x64.state_flags = (B) & ~SF_DF; \
if (((B) & SF_SET_PENDING) != SF_SET_PENDING) { \
if ((B) & SF_SET) { \
if ((B) != SF_SET_NODF) { \
dyn->f.pending = SF_SET; \
dyn->f.dfnone = 1; \
} \
} else if (!dyn->f.dfnone) { \
dyn->f.pending = SF_SET; \
dyn->f.dfnone = 0; \
} \
} \
dyn->insts[ninst].nat_flags_nofusion = (FUSION); \
} while (0)
#define EMIT(A) dyn->native_size += 4
#define JUMP(A, C) \
+80 -48
View File
@@ -38,16 +38,16 @@
} while (0)
// ZERO the upper part, compatible to zba, xtheadbb, and rv64gc
#define ZEXTW2(rd, rs1) \
do { \
if (cpuext.zba) { \
ZEXTW(rd, rs1); \
} else if (cpuext.xtheadbb) {\
TH_EXTU(rd, rs1, 31, 0); \
} else { \
SLLI(rd, rs1, 32); \
SRLI(rd, rd, 32); \
} \
#define ZEXTW2(rd, rs1) \
do { \
if (cpuext.zba) { \
ZEXTW(rd, rs1); \
} else if (cpuext.xtheadbb) { \
TH_EXTU(rd, rs1, 31, 0); \
} else { \
SLLI(rd, rs1, 32); \
SRLI(rd, rd, 32); \
} \
} while (0)
#define ZEROUP(r) ZEXTW2(r, r)
@@ -182,22 +182,22 @@
// rd = rs1 (pseudo instruction)
#define MV(rd, rs1) ADDI(rd, rs1, 0)
// rd = rs1 (pseudo instruction)
#define MVxw(rd, rs1) \
do { \
if (rex.w) { \
MV(rd, rs1); \
} else { \
ZEXTW2(rd, rs1); \
} \
#define MVxw(rd, rs1) \
do { \
if (rex.w) { \
MV(rd, rs1); \
} else { \
ZEXTW2(rd, rs1); \
} \
} while (0)
// rd = rs1 (pseudo instruction)
#define MVz(rd, rs1) \
do { \
if (rex.is32bits) { \
ZEXTW2(rd, rs1); \
} else { \
MV(rd, rs1); \
} \
#define MVz(rd, rs1) \
do { \
if (rex.is32bits) { \
ZEXTW2(rd, rs1); \
} else { \
MV(rd, rs1); \
} \
} while (0)
// rd = !rs1
#define NOT(rd, rs1) XORI(rd, rs1, -1)
@@ -274,20 +274,46 @@
#define SGTU(rd, rs1, rs2) SLTU(rd, rs2, rs1);
#define SLEU(rd, rs1, rs2) SGEU(rd, rs2, rs1);
#define MVEQ(rd, rs1, rs2, rs3) \
if (cpuext.xtheadcondmov && (rs2 == xZR || rs3 == xZR)) { \
TH_MVEQZ(rd, rs1, ((rs2 == xZR) ? rs3 : rs2)); \
} else { \
BNE(rs2, rs3, 8); \
MV(rd, rs1); \
}
#define MVNE(rd, rs1, rs2, rs3) \
if (cpuext.xtheadcondmov && (rs2 == xZR || rs3 == xZR)) { \
TH_MVNEZ(rd, rs1, ((rs2 == xZR) ? rs3 : rs2)); \
} else { \
BEQ(rs2, rs3, 8); \
MV(rd, rs1); \
}
// Zicond conditional MV safe condition
// - A scratch register.
// - Different from the destination.
// - Different from the source.
#define ZICOND_MV_SAFE(rd, rs1, rs2, rs3) \
((rs2 == xZR || rs3 == xZR) && IS_SCRATCH((rs2 == xZR) ? rs3 : rs2) \
&& ((rs2 == xZR) ? rs3 : rs2) != rd && ((rs2 == xZR) ? rs3 : rs2) != rs1)
#define MVEQ(rd, rs1, rs2, rs3) \
do { \
if (rd != rs1) { \
if (cpuext.xtheadcondmov && (rs2 == xZR || rs3 == xZR)) { \
TH_MVEQZ(rd, rs1, ((rs2 == xZR) ? rs3 : rs2)); \
} else if (cpuext.zicond && ZICOND_MV_SAFE(rd, rs1, rs2, rs3)) { \
int cond_ = (rs2 == xZR) ? rs3 : rs2; \
CZERO_EQZ(rd, rd, cond_); \
CZERO_NEZ(cond_, rs1, cond_); \
OR(rd, rd, cond_); \
} else { \
BNE(rs2, rs3, 8); \
MV(rd, rs1); \
} \
} \
} while (0)
#define MVNE(rd, rs1, rs2, rs3) \
do { \
if (rd != rs1) { \
if (cpuext.xtheadcondmov && (rs2 == xZR || rs3 == xZR)) { \
TH_MVNEZ(rd, rs1, ((rs2 == xZR) ? rs3 : rs2)); \
} else if (cpuext.zicond && ZICOND_MV_SAFE(rd, rs1, rs2, rs3)) { \
int cond_ = (rs2 == xZR) ? rs3 : rs2; \
CZERO_NEZ(rd, rd, cond_); \
CZERO_EQZ(cond_, rs1, cond_); \
OR(rd, rd, cond_); \
} else { \
BEQ(rs2, rs3, 8); \
MV(rd, rs1); \
} \
} \
} while (0)
#define MVLT(rd, rs1, rs2, rs3) \
BGE(rs2, rs3, 8); \
MV(rd, rs1);
@@ -443,14 +469,14 @@
SUBI(xRSP, xRSP, 8); \
} \
} while (0)
#define POP1(reg) \
do { \
if (cpuext.xtheadmemidx && reg != xRSP) { \
TH_LDIA(reg, xRSP, 8, 0); \
} else { \
LD(reg, xRSP, 0); \
if (reg != xRSP) ADDI(xRSP, xRSP, 8); \
} \
#define POP1(reg) \
do { \
if (cpuext.xtheadmemidx && reg != xRSP) { \
TH_LDIA(reg, xRSP, 8, 0); \
} else { \
LD(reg, xRSP, 0); \
if (reg != xRSP) ADDI(xRSP, xRSP, 8); \
} \
} while (0)
#define PUSH1_32(reg) \
do { \
@@ -523,7 +549,7 @@
#define CBO_INVAL(rs1) EMIT((0b000000000000 << 20) | CBOM_BASE(rs1))
// Zicbop
#define CBOP_BASE(rs1, imm12) (((((imm12) >> 5) & 0x7F) << 25) | ((rs1) << 15) | (0b110 << 12) | (0b00000 << 7) | 0b0010011)
#define CBOP_BASE(rs1, imm12) (((((imm12) >> 5) & 0x7F) << 25) | ((rs1) << 15) | (0b110 << 12) | (0b00000 << 7) | 0b0010011)
#define CBO_PREFETCH_I(rs1, imm12) EMIT(CBOP_BASE(rs1, imm12) | (0b00000 << 20))
#define CBO_PREFETCH_R(rs1, imm12) EMIT(CBOP_BASE(rs1, imm12) | (0b00001 << 20))
#define CBO_PREFETCH_W(rs1, imm12) EMIT(CBOP_BASE(rs1, imm12) | (0b00011 << 20))
@@ -1219,6 +1245,12 @@
ANDI(rd, rd, 1); \
}
// Zicond
// rd = (rs2 == 0) ? 0 : rs1
#define CZERO_EQZ(rd, rs1, rs2) EMIT(R_type(0b0000111, rs2, rs1, 0b101, rd, 0b0110011))
// rd = (rs2 != 0) ? 0 : rs1
#define CZERO_NEZ(rd, rs1, rs2) EMIT(R_type(0b0000111, rs2, rs1, 0b111, rd, 0b0110011))
/// THead vendor extension
/// https://github.com/T-head-Semi/thead-extension-spec/releases
@@ -1644,7 +1676,7 @@
#define VFSLIDE1DOWN_VF(vd, vs2, rs1, vm) EMIT(R_type(0b0011110 | (vm), vs2, rs1, 0b101, vd, 0b1010111)) // 001111...........101.....1010111
#define VFMV_S_F(vd, rs1) EMIT(I_type((cpuext.xtheadvector ? 0b001101100000 : 0b010000100000), rs1, 0b101, vd, 0b1010111)) // 010000100000.....101.....1010111
#define VFMV_V_F(vd, rs1) EMIT(I_type(0b010111100000, rs1, 0b101, vd, 0b1010111)) // 010111100000.....101.....1010111
#define VFMV_V_F(vd, rs1) EMIT(I_type(0b010111100000, rs1, 0b101, vd, 0b1010111)) // 010111100000.....101.....1010111
#define VFMERGE_VFM(vd, vs2, rs1) EMIT(R_type(0b0101110, vs2, rs1, 0b101, vd, 0b1010111)) // 0101110..........101.....1010111
+47 -1
View File
@@ -1189,7 +1189,7 @@ const char* rv64_print(uint32_t opcode, uintptr_t addr)
/****************
* Generated by https://github.com/ksco/riscv-opcodes/tree/box64_printer
* Command: python parse.py -box64 rv_a rv_d rv_f rv_i rv_m rv_v rv_zba rv_zbb rv_zbc rv_zicsr rv_zbs rv64_a rv64_d rv64_f rv64_i rv64_m rv64_zba rv64_zbb rv64_zbs > code.c
* Command: python parse.py -box64 rv_a rv_d rv_f rv_i rv_m rv_v rv_zba rv_zbb rv_zbc rv_zicsr rv_zbs rv64_a rv64_d rv64_f rv64_i rv64_m rv64_zba rv64_zbb rv64_zbs rv_zicond rv_zicbo > code.c
* Please do NOT edit the following code manually.
*/
@@ -1633,6 +1633,34 @@ const char* rv64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// rv_zicbo, CBO.CLEAN
if ((opcode & 0xfff07fff) == 0x10200f) {
a.rs1 = FX(opcode, 19, 15);
snprintf(buff, sizeof(buff), "%-15s %s", "CBO.CLEAN", gpr[a.rs1]);
return buff;
}
// rv_zicbo, CBO.FLUSH
if ((opcode & 0xfff07fff) == 0x20200f) {
a.rs1 = FX(opcode, 19, 15);
snprintf(buff, sizeof(buff), "%-15s %s", "CBO.FLUSH", gpr[a.rs1]);
return buff;
}
// rv_zicbo, CBO.INVAL
if ((opcode & 0xfff07fff) == 0x200f) {
a.rs1 = FX(opcode, 19, 15);
snprintf(buff, sizeof(buff), "%-15s %s", "CBO.INVAL", gpr[a.rs1]);
return buff;
}
// rv_zicbo, CBO.ZERO
if ((opcode & 0xfff07fff) == 0x40200f) {
a.rs1 = FX(opcode, 19, 15);
snprintf(buff, sizeof(buff), "%-15s %s", "CBO.ZERO", gpr[a.rs1]);
return buff;
}
// rv_zbc, CLMUL
if ((opcode & 0xfe00707f) == 0xa001033) {
a.rd = FX(opcode, 11, 7);
@@ -1762,6 +1790,24 @@ const char* rv64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// rv_zicond, CZERO.EQZ
if ((opcode & 0xfe00707f) == 0xe005033) {
a.rd = FX(opcode, 11, 7);
a.rs1 = FX(opcode, 19, 15);
a.rs2 = FX(opcode, 24, 20);
snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "CZERO.EQZ", gpr[a.rd], gpr[a.rs1], gpr[a.rs2]);
return buff;
}
// rv_zicond, CZERO.NEZ
if ((opcode & 0xfe00707f) == 0xe007033) {
a.rd = FX(opcode, 11, 7);
a.rs1 = FX(opcode, 19, 15);
a.rs2 = FX(opcode, 24, 20);
snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "CZERO.NEZ", gpr[a.rd], gpr[a.rs1], gpr[a.rs2]);
return buff;
}
// rv_m, DIV
if ((opcode & 0xfe00707f) == 0x2004033) {
a.rd = FX(opcode, 11, 7);
+1 -1
View File
@@ -448,7 +448,7 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip, int is32bits)
int stack = emu->fpu_stack;
if(stack>8) stack = 8;
for (int i=0; i<stack; i++) {
sprintf(tmp, "ST%d=%f(0x%" PRIx64 "%s)", i, ST(i).d, ST(i).q, (ST(i).q==STld(i).uref)?PrintLD(&STld(i).ld, " / "):"");
sprintf(tmp, "ST%d=%f(0x%" PRIx64 "%s)", i, ST(i).d, ST(i).q, fpu_ld80_raw_valid(emu, i)?PrintLD(&STld(i).ld, " / "):"");
strcat(buff, tmp);
int c = 20-strlen(tmp);
if(c<1) c=1;
-2
View File
@@ -435,8 +435,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 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI);
} else if (w == iFpp) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
} else if (w == iFpV) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)(R_RSP + 8));
} else if (w == iFpA) {
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
} else if (w == IFEf) {
+48 -14
View File
@@ -50,10 +50,19 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xC5:
case 0xC6:
case 0xC7: /* FLD STx */
ll = ST(nextop&7).q;
fpu_do_push(emu);
ST0.q = ll;
break;
{
int i = nextop&7;
fpu_ld_t ld = STld(i);
int ld_valid = fpu_ld80_raw_valid(emu, i);
ll = ST(i).q;
fpu_do_push(emu);
ST0.q = ll;
if(ld_valid)
STld(0) = ld;
else
fpu_ld80_clear(emu, 0);
break;
}
case 0xC8:
case 0xC9:
case 0xCA:
@@ -62,10 +71,11 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xCD:
case 0xCE:
case 0xCF: /* FXCH STx */
ll = ST(nextop&7).q;
ST(nextop&7).q = ST0.q;
ST0.q = ll;
break;
{
int i = nextop&7;
fpu_ld80_swap(emu, 0, i);
break;
}
case 0xD0: /* FNOP */
break;
@@ -78,15 +88,39 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xDD:
case 0xDE:
case 0xDF:
ST(nextop&7).q = ST0.q;
fpu_ld80_copy(emu, nextop&7, 0);
fpu_do_pop(emu);
break;
case 0xE0: /* FCHS */
ST0.d = -ST0.d;
break;
{
int i = fpu_ld80_raw_valid(emu, 0);
ST0.d = -ST0.d;
if(i) {
#ifdef HAVE_LD80BITS
STld(0).ld = -STld(0).ld;
#else
STld(0).ld.l.upper ^= 0x8000;
#endif
STld(0).uref = ST0.q;
} else
fpu_ld80_clear(emu, 0);
break;
}
case 0xE1: /* FABS */
ST0.d = fabs(ST0.d);
break;
{
int i = fpu_ld80_raw_valid(emu, 0);
ST0.d = fabs(ST0.d);
if(i) {
#ifdef HAVE_LD80BITS
STld(0).ld = fabsl(STld(0).ld);
#else
STld(0).ld.l.upper &= 0x7fff;
#endif
STld(0).uref = ST0.q;
} else
fpu_ld80_clear(emu, 0);
break;
}
case 0xE4: /* FTST */
fpu_ftst(emu);
@@ -206,7 +240,7 @@ uintptr_t RunD9(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xF8: /* FPREM */
{
int go = 1;
if(STld(0).uref==ST0.q && STld(1).uref==ST1.q) {
if(fpu_ld80_raw_valid(emu, 0) && fpu_ld80_raw_valid(emu, 1)) {
// try a full precision fpre alternative
if(full_ld_fprem(emu))
go = 0;
+4 -4
View File
@@ -48,7 +48,7 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xC7:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_CF))
ST0.q = ST(nextop&7).q;
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xC8: /* FCMOVE ST(0), ST(i) */
case 0xC9:
@@ -60,7 +60,7 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xCF:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_ZF))
ST0.q = ST(nextop&7).q;
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xD0: /* FCMOVBE ST(0), ST(i) */
case 0xD1:
@@ -72,7 +72,7 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xD7:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))
ST0.q = ST(nextop&7).q;
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xD8: /* FCMOVU ST(0), ST(i) */
case 0xD9:
@@ -84,7 +84,7 @@ uintptr_t RunDA(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xDF:
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_PF))
ST0.q = ST(nextop&7).q;
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xE9: /* FUCOMPP */
+38 -32
View File
@@ -47,11 +47,11 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_CF))
ST0.q = ST(nextop&7).q;
break;
case 0xC7:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_CF))
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xC8: /* FCMOVNE ST(0), ST(i) */
case 0xC9:
case 0xCA:
@@ -59,11 +59,11 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_ZF))
ST0.q = ST(nextop&7).q;
break;
case 0xCF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_ZF))
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xD0: /* FCMOVNBE ST(0), ST(i) */
case 0xD1:
case 0xD2:
@@ -71,11 +71,11 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
CHECK_FLAGS(emu);
if(!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
ST0.q = ST(nextop&7).q;
break;
case 0xD7:
CHECK_FLAGS(emu);
if(!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)))
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xD8: /* FCMOVNU ST(0), ST(i) */
case 0xD9:
case 0xDA:
@@ -83,11 +83,11 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_PF))
ST0.q = ST(nextop&7).q;
break;
case 0xDF:
CHECK_FLAGS(emu);
if(!ACCESS_FLAG(F_PF))
fpu_ld80_copy(emu, 0, nextop&7);
break;
case 0xE1: /* FDISI8087_NOP */
break;
@@ -112,22 +112,28 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
break;
case 0xED:
case 0xEE:
case 0xEF:
#ifndef HAVE_LD80BITS
if (!fpu_fcomi_ld80(emu, nextop&7))
#endif
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
break;
case 0xF0: /* FCOMI ST0, STx */
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
fpu_fcomi(emu, ST(nextop&7).d);
break;
case 0xF5:
case 0xF6:
case 0xF7:
#ifndef HAVE_LD80BITS
if (!fpu_fcomi_ld80(emu, nextop&7))
#endif
fpu_fcomi(emu, ST(nextop&7).d);
break;
default:
fesetround(oldround);
@@ -178,8 +184,8 @@ uintptr_t RunDB(x64emu_t *emu, rex_t rex, uintptr_t addr)
break;
case 7: /* FSTP tbyte */
GETET(0);
if(STld(0).uref && (ST0.q==STld(0).uref))
memcpy(ED, &STld(0).ld, 10);
if(fpu_ld80_raw_valid(emu, 0))
memcpy(ED, &STld(0).ld, 10);
else
D2LD(&ST0.d, ED);
fpu_do_pop(emu);
+11 -11
View File
@@ -52,22 +52,22 @@ uintptr_t RunDD(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
ST(nextop&7).q = ST0.q;
break;
case 0xD5:
case 0xD6:
case 0xD7:
fpu_ld80_copy(emu, nextop&7, 0);
break;
case 0xD8: /* FSTP ST0, STx */
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
ST(nextop&7).q = ST0.q;
fpu_do_pop(emu);
break;
case 0xDD:
case 0xDE:
case 0xDF:
fpu_ld80_copy(emu, nextop&7, 0);
fpu_do_pop(emu);
break;
case 0xE0: /* FUCOM ST0, STx */
case 0xE1:
case 0xE2:
+15 -12
View File
@@ -55,12 +55,12 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
ST(nextop&7).q = ST0.q;
fpu_do_pop(emu);
break;
case 0xD5:
case 0xD6:
case 0xD7:
fpu_ld80_copy(emu, nextop&7, 0);
fpu_do_pop(emu);
break;
case 0xE0: /* FNSTSW AX */
emu->sw.f.F87_TOP = emu->top&7;
@@ -72,12 +72,15 @@ uintptr_t RunDF(x64emu_t *emu, rex_t rex, uintptr_t addr)
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
fpu_do_pop(emu);
break;
case 0xED:
case 0xEE:
case 0xEF:
#ifndef HAVE_LD80BITS
if (!fpu_fcomi_ld80(emu, nextop&7))
#endif
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
fpu_do_pop(emu);
break;
case 0xF0: /* FCOMIP ST0, STx */
case 0xF1:
+30 -16
View File
@@ -138,27 +138,41 @@ void sha256msg2(x64emu_t* emu, sse_regs_t* xmm1, sse_regs_t* xmm2)
void sha1rnds4(x64emu_t* emu, sse_regs_t* xmm1, sse_regs_t* xmm2, uint8_t ib)
{
uint32_t K = Ks[ib&3];
uint32_t(*f)(uint32_t , uint32_t , uint32_t) = NULL;
switch (ib&3) {
case 0: f = f0; break;
case 1: f = f1; break;
case 2: f = f2; break;
case 3: f = f3; break;
}
uint32_t kind = ib & 3;
uint32_t K = Ks[kind];
uint32_t A = xmm1->ud[3];
uint32_t B = xmm1->ud[2];
uint32_t C = xmm1->ud[1];
uint32_t D = xmm1->ud[0];
uint32_t E = 0;
for(int i=0; i<4; ++i) {
uint32_t new_A = f(B, C, D) + rol(A, 5) + xmm2->ud[3-i] + E + K;
E = D;
D = C;
C = rol(B, 30);
B = A;
A = new_A;
#define SHA1_ROUND(F, W) \
do { \
uint32_t new_A = F(B, C, D) + rol(A, 5) + xmm2->ud[W] + E + K; \
E = D; \
D = C; \
C = rol(B, 30); \
B = A; \
A = new_A; \
} while (0)
#define SHA1_ROUNDS(F) \
do { \
SHA1_ROUND(F, 3); \
SHA1_ROUND(F, 2); \
SHA1_ROUND(F, 1); \
SHA1_ROUND(F, 0); \
} while (0)
switch (kind) {
case 0: SHA1_ROUNDS(f0); break;
case 1: SHA1_ROUNDS(f1); break;
case 2: SHA1_ROUNDS(f2); break;
case 3: SHA1_ROUNDS(f3); break;
}
#undef SHA1_ROUNDS
#undef SHA1_ROUND
xmm1->ud[3] = A;
xmm1->ud[2] = B;
xmm1->ud[1] = C;
@@ -191,4 +205,4 @@ void sha256rnds2(x64emu_t* emu, sse_regs_t* xmm1, sse_regs_t* xmm2)
xmm1->ud[2] = B;
xmm1->ud[1] = E;
xmm1->ud[0] = F;
}
}
+41 -14
View File
@@ -50,7 +50,6 @@ typedef struct x64_stack_s x64_stack_t;
extern int mkdir(const char *path, mode_t mode);
extern int mknod(const char *path, mode_t mode, dev_t dev);
extern int chmod(const char *path, mode_t mode);
extern int fchmodat (int __fd, const char *__file, mode_t __mode, int __flag);
//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
@@ -134,6 +133,9 @@ static const scwrap_t syscallwrap[] = {
//[25] = {__NR_mremap, 5}, // wrapped to track protection
[27] = {__NR_mincore, 3},
[28] = {__NR_madvise, 3},
#ifdef __NR_dup
[32] = {__NR_dup, 1},
#endif
#ifdef __NR_dup2
[33] = {__NR_dup2, 2},
#endif
@@ -141,8 +143,10 @@ static const scwrap_t syscallwrap[] = {
[34] = {__NR_pause, 0},
#endif
[35] = {__NR_nanosleep, 2},
[36] = {__NR_getitimer, 2},
[38] = {__NR_setitimer, 3},
[39] = {__NR_getpid, 0},
[40] = {__NR_sendfile, 4},
[41] = {__NR_socket, 3},
[42] = {__NR_connect, 3},
[43] = {__NR_accept, 3},
@@ -197,11 +201,15 @@ static const scwrap_t syscallwrap[] = {
[90] = {__NR_chmod, 2},
#endif
[91] = {__NR_fchmod, 2},
[93] = {__NR_fchown, 3},
[95] = {__NR_umask, 1},
[96] = {__NR_gettimeofday, 2},
#ifdef __NR_getrlimit
[97] = {__NR_getrlimit, 2},
#endif
[98] = {__NR_getrusage, 2},
[99] = {__NR_sysinfo, 1},
[100] = {__NR_times, 1},
[101] = {__NR_ptrace, 4},
[102] = {__NR_getuid, 0},
[104] = {__NR_getgid, 0},
@@ -215,10 +223,13 @@ static const scwrap_t syscallwrap[] = {
[112] = {__NR_setsid, 0},
[113] = {__NR_setreuid, 2},
[114] = {__NR_setregid, 2},
[115] = {__NR_getgroups, 2},
#ifdef __NR_setgroups
[116] = {__NR_setgroups, 2},
#endif
[117] = {__NR_setresuid, 3},
[118] = {__NR_getresuid, 3},
[119] = {__NR_setresgid, 3},
[120] = {__NR_getresgid, 3},
[121] = {__NR_getpgid, 1},
[122] = {__NR_setfsuid, 1},
@@ -235,7 +246,13 @@ static const scwrap_t syscallwrap[] = {
[137] = {__NR_statfs, 2},
[138] = {__NR_fstatfs, 2},
[140] = {__NR_getpriority, 2},
[141] = {__NR_setpriority, 3},
[142] = {__NR_sched_setparam, 2},
[143] = {__NR_sched_getparam, 2},
[144] = {__NR_sched_setscheduler, 3},
[145] = {__NR_sched_getscheduler, 1},
[146] = {__NR_sched_get_priority_max, 1},
[147] = {__NR_sched_get_priority_min, 1},
[148] = {__NR_sched_rr_get_interval, 2},
[149] = {__NR_mlock, 2},
[150] = {__NR_munlock, 2},
@@ -270,6 +287,7 @@ static const scwrap_t syscallwrap[] = {
[217] = {__NR_getdents64, 3},
[218] = {__NR_set_tid_address, 1},
[220] = {__NR_semtimedop, 4},
[221] = {__NR_fadvise64, 4},
[228] = {__NR_clock_gettime, 2},
[229] = {__NR_clock_getres, 2},
[230] = {__NR_clock_nanosleep, 4},
@@ -286,6 +304,7 @@ static const scwrap_t syscallwrap[] = {
[239] = {__NR_get_mempolicy, 5},
[247] = {__NR_waitid, 5},
[251] = {__NR_ioprio_set, 3},
[252] = {__NR_ioprio_get, 2},
#ifdef __NR_inotify_init
[253] = {__NR_inotify_init, 0}, //0xFD
#endif
@@ -304,6 +323,7 @@ static const scwrap_t syscallwrap[] = {
[266] = {__NR_symlinkat, 3},
//[267] = {__NR_readlinkat, 4},
[268] = {__NR_fchmodat, 3},
[269] = {__NR_faccessat, 3},
[270] = {__NR_pselect6, 6},
[272] = {__NR_unshare, 1},
[273] = {__NR_set_robust_list, 2},
@@ -332,6 +352,7 @@ static const scwrap_t syscallwrap[] = {
[298] = {__NR_perf_event_open, 5},
[302] = {__NR_prlimit64, 4},
[309] = {__NR_getcpu, 3}, // need wrapping?
[312] = {__NR_kcmp, 5},
[314] = {__NR_sched_setattr, 3},
[315] = {__NR_sched_getattr, 4},
[316] = {__NR_renameat2, 5},
@@ -344,6 +365,12 @@ static const scwrap_t syscallwrap[] = {
// TODO: call back if unavailable?
[326] = {__NR_copy_file_range, 6},
#endif
#ifdef __NR_preadv2
[327] = {__NR_preadv2, 6},
#endif
#ifdef __NR_pwritev2
[328] = {__NR_pwritev2, 6},
#endif
#ifdef __NR_statx
// TODO: implement fallback if __NR_statx is not defined
[332] = {__NR_statx, 5},
@@ -357,8 +384,8 @@ static const scwrap_t syscallwrap[] = {
#ifdef __NR_io_uring_register
[427] = {__NR_io_uring_register, 4},
#endif
#ifdef __NR_fchmodat4
[434] = {__NR_fchmodat4, 4},
#ifdef __NR_pidfd_open
[434] = {__NR_pidfd_open, 2},
#endif
#ifdef __NR_close_range
[436] = {__NR_close_range, 3},
@@ -687,6 +714,13 @@ void EXPORT x64Syscall_linux(x64emu_t *emu)
case 25: // sys_mremap
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
break;
#ifndef __NR_dup
case 32: // sys_dup
S_RAX = dup(S_EDI);
if(S_RAX==-1)
S_RAX = -errno;
break;
#endif
#ifndef __NR_dup2
case 33: // sys_dup2
S_RAX = dup2(S_EDI, S_ESI);
@@ -997,13 +1031,6 @@ void EXPORT x64Syscall_linux(x64emu_t *emu)
case 334: // It is helpeful to run static binary
R_RAX = -ENOSYS;
break;
#ifndef __NR_fchmodat4
case 434:
S_RAX = fchmodat(S_EDI, (void*)R_RSI, (mode_t)R_RDX, S_R10d);
if(S_RAX==-1)
S_RAX = -errno;
break;
#endif
#ifndef __NR_faccessat2
case 439:
S_RAX = faccessat(S_EDI, (void*)R_RSI, (mode_t)R_RDX, S_R10d);
@@ -1141,6 +1168,10 @@ long EXPORT my_syscall(x64emu_t *emu)
#endif
case 25: // sys_mremap
return (intptr_t)my_mremap(emu, (void*)R_RSI, R_RDX, R_RCX, R_R8d, (void*)R_R9);
#ifndef __NR_dup
case 32:
return dup(S_ESI);
#endif
#ifndef __NR_dup2
case 33:
return dup2(S_ESI, S_EDX);
@@ -1362,10 +1393,6 @@ long EXPORT my_syscall(x64emu_t *emu)
#endif
case 317: // sys_seccomp
return 0; // ignoring call
#ifndef __NR_fchmodat4
case 434:
return fchmodat(S_ESI, (void*)R_RDX, (mode_t)R_RCX, S_R8d);
#endif
#ifndef __NR_faccessat2
case 439:
return faccessat(S_ESI, (void*)R_RDX, (mode_t)R_RCX, S_R8d);
+8 -5
View File
@@ -2,6 +2,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
@@ -51,11 +52,11 @@ uint32_t my_set_thread_area_32(x64emu_t* emu, thread_area_32_t* td)
int isempty = 0;
// first, check if the "user_desc", here td, is "empty"
if(td->read_exec_only==1 && td->seg_not_present==1)
if( !td->base_addr
if( !td->base_addr
&& !td->limit
&& !td->seg_32bit
&& !td->contents
&& !td->limit_in_pages
&& !td->seg_32bit
&& !td->contents
&& !td->limit_in_pages
&& !td->useable)
isempty = 1;
int idx = td->entry_number;
@@ -297,7 +298,9 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
memcpy((void*)((uintptr_t)ptr+0x28), context->canary, sizeof(void*)); // put canary in place
uintptr_t tlsptr = (uintptr_t)ptr;
memcpy((void*)((uintptr_t)ptr+0x0), &tlsptr, sizeof(void*));
memcpy((void*)((uintptr_t)ptr+0x10), &tlsptr, sizeof(void*)); // set tcb and self same address
// Wrapped pthread symbols expose native pthread_t handles, so keep the fast self slot consistent.
uintptr_t pthread_self_value = (uintptr_t)pthread_self();
memcpy((void*)((uintptr_t)ptr+0x10), &pthread_self_value, sizeof(void*));
uintptr_t dtp = (uintptr_t)ptr+POS_TLS;
memcpy((void*)(tlsptr+sizeof(void*)), &dtp, sizeof(void*));
if(dtssize) {
+4 -1
View File
@@ -13,6 +13,7 @@
void fpu_do_free(x64emu_t* emu, int i)
{
fpu_ld80_clear(emu, i);
emu->fpu_tags |= 0b11 << (i*2); // empty
// check if all empty
if(emu->fpu_tags != TAGS_EMPTY)
@@ -24,9 +25,11 @@ void reset_fpu(x64emu_t* emu)
{
memset(emu->x87, 0, sizeof(emu->x87));
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
emu->top = 0;
for(int i=0; i<8; ++i)
fpu_ld80_clear(emu, i);
emu->cw.x16 = 0x37F;
emu->sw.x16 = 0x0000;
emu->top = 0;
emu->fpu_stack = 0;
emu->fpu_tags = TAGS_EMPTY;
}
+106
View File
@@ -24,6 +24,37 @@ typedef struct x64emu_s x64emu_t;
#define STld(a) emu->fpu_ld[(emu->top+(a))&7]
#define STll(a) emu->fpu_ll[(emu->top+(a))&7]
// Use a NaN payload as invalid marker so a valid +0.0 reference stays usable.
#define FPU_LD80_INVALID_REF UINT64_C(0x7ff8deadbeefc0de)
static inline void fpu_ld80_clear(x64emu_t* emu, int i)
{
STld(i).uref = FPU_LD80_INVALID_REF;
}
static inline int fpu_ld80_raw_valid(x64emu_t* emu, int i)
{
return STld(i).uref != FPU_LD80_INVALID_REF && ST(i).q==STld(i).uref;
}
static inline void fpu_ld80_copy(x64emu_t* emu, int dst, int src)
{
ST(dst).q = ST(src).q;
if(fpu_ld80_raw_valid(emu, src))
STld(dst) = STld(src);
else
fpu_ld80_clear(emu, dst);
}
static inline void fpu_ld80_swap(x64emu_t* emu, int a, int b)
{
uint64_t q = ST(a).q;
fpu_ld_t tmp = STld(a);
ST(a).q = ST(b).q;
ST(b).q = q;
STld(a) = STld(b);
STld(b) = tmp;
}
static inline void fpu_do_push(x64emu_t* emu)
{
int newtop = (emu->top-1)&7;
@@ -37,6 +68,7 @@ static inline void fpu_do_push(x64emu_t* emu)
emu->fpu_tags<<=2; // st0 full
emu->fpu_tags &= TAGS_EMPTY;
emu->top = newtop;
fpu_ld80_clear(emu, 0);
}
static inline void fpu_do_pop(x64emu_t* emu)
@@ -52,6 +84,7 @@ static inline void fpu_do_pop(x64emu_t* emu)
emu->fpu_tags>>=2;
emu->fpu_tags |= 0b1100000000000000; // top empty
fpu_ld80_clear(emu, 0);
emu->top = (emu->top+1)&7;
// check tags
/*while((emu->fpu_tags&0b11) && emu->fpu_stack) {
@@ -89,6 +122,79 @@ static inline void fpu_fcom(x64emu_t* emu, double b)
}
}
#ifndef HAVE_LD80BITS
// 1 => a > b
// 0 => a == b
// -1 => a < b
// 2 => unordered
static inline int fpu_ld80_raw_cmp(const longdouble_t* a, const longdouble_t* b)
{
uint16_t a_upper = a->l.upper, b_upper = b->l.upper;
uint64_t a_lower = a->l.lower, b_lower = b->l.lower;
int a_sign = a_upper >> 15, b_sign = b_upper >> 15;
int a_exponent = a_upper & 0x7fff, b_exponent = b_upper & 0x7fff;
int a_zero = (a_exponent == 0 && a_lower == 0);
int b_zero = (b_exponent == 0 && b_lower == 0);
int a_nan = (a_exponent == 0x7fff && a_lower != 0x8000000000000000ULL);
int b_nan = (b_exponent == 0x7fff && b_lower != 0x8000000000000000ULL);
if (a_nan || b_nan)
return 2; /* unordered */
if (a_zero && b_zero)
return 0;
if (a_sign != b_sign)
return a_sign ? -1 : 1;
int mag;
if (a_exponent != b_exponent)
mag = (a_exponent > b_exponent) ? 1 : -1;
else if (a_lower != b_lower)
mag = (a_lower > b_lower) ? 1 : -1;
else
mag = 0;
return a_sign ? -mag : mag;
}
static inline int fpu_fcomi_ld80(x64emu_t* emu, int i)
{
if (!fpu_ld80_raw_valid(emu, i) || !fpu_ld80_raw_valid(emu, 0))
return 0;
int cmp = fpu_ld80_raw_cmp(&STld(0).ld, &STld(i).ld);
RESET_FLAGS(emu);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
emu->sw.f.F87_C1 = 0;
if (cmp == 2) {
SET_FLAG(F_CF);
SET_FLAG(F_PF);
SET_FLAG(F_ZF);
} else if (cmp > 0) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
} else if (cmp < 0) {
SET_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
} else {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
SET_FLAG(F_ZF);
}
return 1;
}
#endif
static inline void fpu_fcomi(x64emu_t* emu, double b)
{
RESET_FLAGS(emu);
+1
View File
@@ -38,6 +38,7 @@ typedef union cpu_ext_s {
uint64_t xtheadfmv : 1;
uint64_t zicbom : 1;
uint64_t zicbop : 1;
uint64_t zicond : 1;
#elif defined(LA64)
uint64_t lbt : 1; // it's important it's stay the 1st bit
uint64_t lam_bh : 1;
+3 -1
View File
@@ -745,7 +745,9 @@ int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigin
#undef GO
// flags
emu->eflags.x64=sigcontext->uc_mcontext.gregs[I386_EFL];
if((skip==1) && (emu->ip.q[0]!=sigcontext->uc_mcontext.gregs[I386_EIP]) && !ACCESS_FLAG(F_TF))
if(ACCESS_FLAG(F_TF))
skip = 1; // no_tf may not be consumed in dynarec, force to use interpreter
else if((skip==1) && (emu->ip.q[0]!=sigcontext->uc_mcontext.gregs[I386_EIP]))
skip = 3; // if it jumps elsewhere, it can resume with dynarec...
emu->ip.q[0]=sigcontext->uc_mcontext.gregs[I386_EIP];
if (ACCESS_FLAG(F_TF) && skip == 1) emu->flags.no_tf = 1;
+3 -1
View File
@@ -581,7 +581,9 @@ int my_sigactionhandler_oldcode_64(x64emu_t* emu, int32_t sig, int simple, sigin
#ifndef DYNAREC
mctx2emu(emu, &sigcontext->uc_mcontext);
#endif
if((skip==1) && (emu->ip.q[0]!=sigcontext->uc_mcontext.gregs[X64_RIP]) && !ACCESS_FLAG(F_TF))
if(ACCESS_FLAG(F_TF))
skip = 1; // no_tf may not be consumed in dynarec, force to use interpreter
else if((skip==1) && (emu->ip.q[0]!=sigcontext->uc_mcontext.gregs[X64_RIP]))
skip = 3; // if it jumps elsewhere, it can resume with dynarec...
if (ACCESS_FLAG(F_TF) && skip == 1) emu->flags.no_tf = 1;
printf_log((sig==10)?LOG_DEBUG:log_minimum, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu at %p, RSP=%p (resume with %s)\n", (void*)R_RIP, (void*)R_RSP, (skip==3)?"Dynarec":"Interp");
+1
View File
@@ -54,6 +54,7 @@ void PrintHostCpuFeatures(void)
if (cpuext.zbs) printf_log_prefix(0, LOG_INFO, "_zbs");
if (cpuext.zicbom) printf_log_prefix(0, LOG_INFO, "_zicbom");
if (cpuext.zicbop) printf_log_prefix(0, LOG_INFO, "_zicbop");
if (cpuext.zicond) printf_log_prefix(0, LOG_INFO, "_zicond");
if (cpuext.vector && !cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "_zvl%d", cpuext.vlen * 8);
if (cpuext.xtheadba) printf_log_prefix(0, LOG_INFO, "_xtheadba");
if (cpuext.xtheadbb) printf_log_prefix(0, LOG_INFO, "_xtheadbb");
+8
View File
@@ -124,6 +124,13 @@ void rv64Detect(void)
BR(xRA);
cpuext.zicbop = Check(my_block);
// Test Zicond with CZERO.EQZ
block = (uint32_t*)my_block;
CZERO_EQZ(A0, A0, A1);
ADDI(A0, xZR, 42);
BR(xRA);
cpuext.zicond = Check(my_block);
block = (uint32_t*)my_block;
CSRRS(xZR, xZR, 0xc22 /* vlenb */);
ADDI(A0, xZR, 42);
@@ -273,6 +280,7 @@ int DetectHostCpuFeatures(void)
if (!strcasecmp(p, "xtheadcondmov")) cpuext.xtheadcondmov = 0;
if (!strcasecmp(p, "zicbom")) cpuext.zicbom = 0;
if (!strcasecmp(p, "zicbop")) cpuext.zicbop = 0;
if (!strcasecmp(p, "zicond")) cpuext.zicond = 0;
p = strtok(NULL, ",");
}
}
+4 -4
View File
@@ -185,14 +185,14 @@ void InitializeSystemInfo(void)
sysinfo_t info = { 0 };
readCpuinfo(&box64_sysinfo);
char branding[3 * 4 * 4 + 1];
char branding[3 * 4 * 4 + 1] = {0};
if (strstr(box64_sysinfo.cpuname, "MHz") || strstr(box64_sysinfo.cpuname, "GHz")) {
snprintf(branding, sizeof(branding), BOX64_BUILD_INFO_STRING_SHORT " on %.*s", 39, box64_sysinfo.cpuname);
snprintf(branding, sizeof(branding)-1, BOX64_BUILD_INFO_STRING_SHORT " on %.*s", 32, box64_sysinfo.cpuname);
} else {
if (box64_sysinfo.frequency > 1500000) {
snprintf(branding, sizeof(branding), BOX64_BUILD_INFO_STRING_SHORT " on %.*s @%1.2f GHz", 28, box64_sysinfo.cpuname, box64_sysinfo.frequency / 1000000000.);
snprintf(branding, sizeof(branding)-1, BOX64_BUILD_INFO_STRING_SHORT " on %.*s @%1.2f GHz", 28, box64_sysinfo.cpuname, box64_sysinfo.frequency / 1000000000.);
} else {
snprintf(branding, sizeof(branding), BOX64_BUILD_INFO_STRING_SHORT " on %.*s @%04" PRIu64 " MHz", 28, box64_sysinfo.cpuname, box64_sysinfo.frequency / 1000000);
snprintf(branding, sizeof(branding)-1, BOX64_BUILD_INFO_STRING_SHORT " on %.*s @%04" PRIu64 " MHz", 28, box64_sysinfo.cpuname, box64_sysinfo.frequency / 1000000);
}
}
box64_sysinfo.box64_cpuname = (char*)calloc(strlen(branding) + 1, 1);
-2
View File
@@ -245,7 +245,6 @@ static void applyCustomRules()
} else if (!strcasecmp(box64env.profile, "default")) {
} else if (!strcasecmp(box64env.profile, "fast")) {
SET_BOX64ENV_IF_EMPTY(dynarec_callret, 1);
SET_BOX64ENV_IF_EMPTY(dynarec_sep, 1);
SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 3);
SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 0);
SET_BOX64ENV_IF_EMPTY(dynarec_strongmem, 1);
@@ -253,7 +252,6 @@ static void applyCustomRules()
SET_BOX64ENV_IF_EMPTY(dynarec_forward, 1024);
} else if (!strcasecmp(box64env.profile, "fastest")) {
SET_BOX64ENV_IF_EMPTY(dynarec_callret, 1);
SET_BOX64ENV_IF_EMPTY(dynarec_sep, 2);
SET_BOX64ENV_IF_EMPTY(dynarec_bigblock, 3);
SET_BOX64ENV_IF_EMPTY(dynarec_safeflags, 0);
SET_BOX64ENV_IF_EMPTY(dynarec_strongmem, 0);
+2 -1
View File
@@ -243,7 +243,6 @@
#() iFpl
#() iFpL
#() iFpp
#() iFpV
#() iFpO
#() iFpS
#() iFpH
@@ -5569,6 +5568,7 @@ wrappedlibc:
- swapcontext
- tss_create
- iFpV:
- __isoc23_scanf
- __isoc99_scanf
- execl
- execle
@@ -5578,6 +5578,7 @@ wrappedlibc:
- wprintf
- wscanf
- iFpA:
- __isoc23_vscanf
- __isoc99_vscanf
- vprintf
- vscanf
+2
View File
@@ -200,6 +200,7 @@ typedef int32_t (*iFppipppp_t)(void*, void*, int32_t, void*, void*, void*, void*
GO(stat64, iFpp_t) \
GO(swapcontext, iFpp_t) \
GO(tss_create, iFpp_t) \
GO(__isoc23_scanf, iFpV_t) \
GO(__isoc99_scanf, iFpV_t) \
GO(execl, iFpV_t) \
GO(execle, iFpV_t) \
@@ -208,6 +209,7 @@ typedef int32_t (*iFppipppp_t)(void*, void*, int32_t, void*, void*, void*, void*
GO(scanf, iFpV_t) \
GO(wprintf, iFpV_t) \
GO(wscanf, iFpV_t) \
GO(__isoc23_vscanf, iFpA_t) \
GO(__isoc99_vscanf, iFpA_t) \
GO(vprintf, iFpA_t) \
GO(vscanf, iFpA_t) \
-2
View File
@@ -288,7 +288,6 @@ typedef int32_t (*iFpd_t)(void*, double);
typedef int32_t (*iFpl_t)(void*, intptr_t);
typedef int32_t (*iFpL_t)(void*, uintptr_t);
typedef int32_t (*iFpp_t)(void*, void*);
typedef int32_t (*iFpV_t)(void*, void*);
typedef int32_t (*iFpO_t)(void*, int32_t);
typedef int32_t (*iFpS_t)(void*, void*);
typedef int32_t (*iFpH_t)(void*, unsigned __int128);
@@ -4544,7 +4543,6 @@ void iFpd(x64emu_t *emu, uintptr_t fcn) { iFpd_t fn = (iFpd_t)fcn; R_RAX=(int)fn
void iFpl(x64emu_t *emu, uintptr_t fcn) { iFpl_t fn = (iFpl_t)fcn; R_RAX=(int)fn((void*)R_RDI, (intptr_t)R_RSI); }
void iFpL(x64emu_t *emu, uintptr_t fcn) { iFpL_t fn = (iFpL_t)fcn; R_RAX=(int)fn((void*)R_RDI, (uintptr_t)R_RSI); }
void iFpp(x64emu_t *emu, uintptr_t fcn) { iFpp_t fn = (iFpp_t)fcn; R_RAX=(int)fn((void*)R_RDI, (void*)R_RSI); }
void iFpV(x64emu_t *emu, uintptr_t fcn) { iFpV_t fn = (iFpV_t)fcn; R_RAX=(int)fn((void*)R_RDI, (void*)(R_RSP + 8)); }
void iFpO(x64emu_t *emu, uintptr_t fcn) { iFpO_t fn = (iFpO_t)fcn; R_RAX=(int)fn((void*)R_RDI, of_convert((int32_t)R_RSI)); }
void iFpS(x64emu_t *emu, uintptr_t fcn) { iFpS_t fn = (iFpS_t)fcn; R_RAX=(int)fn((void*)R_RDI, io_convert((void*)R_RSI)); }
void iFpH(x64emu_t *emu, uintptr_t fcn) { iFpH_t fn = (iFpH_t)fcn; R_RAX=(int)fn((void*)R_RDI, (unsigned __int128)R_RSI + ((unsigned __int128)R_RDX << 64)); }
-1
View File
@@ -280,7 +280,6 @@ void iFpd(x64emu_t *emu, uintptr_t fnc);
void iFpl(x64emu_t *emu, uintptr_t fnc);
void iFpL(x64emu_t *emu, uintptr_t fnc);
void iFpp(x64emu_t *emu, uintptr_t fnc);
void iFpV(x64emu_t *emu, uintptr_t fnc);
void iFpO(x64emu_t *emu, uintptr_t fnc);
void iFpS(x64emu_t *emu, uintptr_t fnc);
void iFpH(x64emu_t *emu, uintptr_t fnc);
+3 -1
View File
@@ -1053,6 +1053,8 @@ GOM(__isoc99_vsscanf, iFEppA)
GOM(__isoc99_vswscanf, iFEppA)
//GO(__isoc99_vwscanf, iFpA)
//GO(__isoc99_wscanf, iFpV)
GO2(__isoc23_scanf, iFEpV, my___isoc99_scanf)
GO2(__isoc23_vscanf, iFEpA, my___isoc99_vscanf)
GO(isprint, iFi)
//GO(__isprint_l,
GOW(isprint_l, iFip)
@@ -1745,7 +1747,7 @@ GOWM(scandir, iFEpppp)
GOWM(scandir64, iFEpppp)
GOWM(scandirat, iFipppp)
GOM(scandirat64, iFEipppp)
GOM(scanf, iFpV)
GOM(scanf, iFEpV)
GO(__sched_cpualloc, pFL)
GO(__sched_cpucount, iFLp)
GO(__sched_cpufree, vFp)
+26 -1
View File
@@ -297,6 +297,12 @@ BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_CALLRET=1
BOX64_DYNAREC_FASTROUND=0
[PRAGMATA_SKETCHBOOK.exe]
BOX64_DYNAREC_SAFEFLAGS=2
BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_CALLRET=0
BOX64_DYNAREC_DIRTY=2
[pressure-vessel-wrap]
BOX64_NOGTK=1
@@ -544,6 +550,9 @@ BOX64_DYNAREC_SEP=2
BOX64_DYNAREC_DIRTY=1
BOX64_SSE_FLUSHTO0=1
[BangBangRacing.exe]
BOX64_DYNAREC_STRONGMEM=2
[BatmanAK.exe]
BOX64_DYNAREC_STRONGMEM=1
BOX64_DYNAREC_ALIGNED_ATOMICS=1
@@ -874,6 +883,9 @@ BOX64_DYNAREC_NOHOTPAGE=1
[INSIDE.exe]
BOX64_DYNAREC_STRONGMEM=1
[JetboardJoust]
BOX64_PREFER_WRAPPED=1
[JWE.exe]
BOX64_DYNAREC_SAFEFLAGS=2
@@ -1098,6 +1110,12 @@ BOX64_DYNAREC_FASTROUND=0
BOX64_DYNAREC_SAFEFLAGS=2
BOX64_DYNAREC_STRONGMEM=1
[SamSM.exe]
BOX64_DYNAREC_SAFEFLAGS=1
BOX64_DYNAREC_CALLRET=1
BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_FASTROUND=0 #needed or cutscene will not show and many other game behaviour issues
[SandFall-Win64-Shipping.exe]
BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_CALLRET=1
@@ -1304,7 +1322,7 @@ BOX64_DYNAREC_FASTROUND=2
BOX64_DYNAREC_STRONGMEM=1
BOX64_DYNAREC_SAFEFLAGS=2
BOX64_DYNAREC_DIV0=1
BOX64_DYNAREC_CALLRET=0
[UbisoftConnectInstaller.exe]
BOX64_DYNAREC_STRONGMEM=1
@@ -1325,6 +1343,7 @@ BOX64_DYNAREC_PURGE=1
BOX64_DYNAREC_SAFEFLAGS=2
BOX64_DYNAREC_STRONGMEM=1
BOX64_DYNAREC_DIV0=1
BOX64_DYNAREC_CALLRET=0
[UbisoftConnect.exe]
BOX64_DYNAREC_SAFEFLAGS=2
@@ -1378,6 +1397,12 @@ BOX64_DYNAREC_STRONGMEM=1
#BOX64_DYNAREC_CALLRET=1 #nope
#BOX64_DYNAREC_BIGBLOCK=3
[VRChat.exe]
BOX64_DYNAREC_BIGBLOCK=3
BOX64_DYNAREC_CALLRET=1
BOX64_DYNAREC_SAFEFLAGS=0
BOX64_DYNAREC_STRONGMEM=1
[witcher3.exe]
BOX64_DYNAREC_STRONGMEM=1
BIN
View File
Binary file not shown.
+13
View File
@@ -1,5 +1,6 @@
#define _MULTI_THREADED
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
@@ -40,11 +41,23 @@ typedef struct {
int data2;
} threadparm_t;
static uintptr_t fast_pthread_self(void)
{
uintptr_t self;
__asm__ volatile("movq %%fs:0x10, %0" : "=r"(self));
return self;
}
void *thread_run(void *parm)
{
int rc;
threadparm_t *gData;
if (fast_pthread_self() != (uintptr_t)pthread_self()) {
fprintf(stderr, "TLS self pointer does not match pthread_self()\n");
exit(1);
}
pthread_mutex_lock(mutex_ptr);
if (pthread_self()==thread[0]) {
printf("Thread 1: Entered (%d/%d)\n", TLS_data1, TLS_data2);