mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-12 18:57:06 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f130fab1d | ||
|
|
08f8666596 | ||
|
|
fb5294a125 | ||
|
|
b3384b5c81 | ||
|
|
7058d990c4 | ||
|
|
8557ede0e9 | ||
|
|
78383901f2 | ||
|
|
ebccae45e3 | ||
|
|
80b5e387d2 | ||
|
|
15e065ae5d | ||
|
|
00ca85606d | ||
|
|
bc181e7812 | ||
|
|
0f6b8ccc68 | ||
|
|
ffeff6599b | ||
|
|
3e71996209 | ||
|
|
bbb2560ff8 | ||
|
|
30b1bf210d | ||
|
|
178e344b98 | ||
|
|
1c2fc72c20 | ||
|
|
b7ed2c57f5 | ||
|
|
23f8db631d | ||
|
|
f22f5adb55 | ||
|
|
f02526fdbb | ||
|
|
675814f912 | ||
|
|
c44264eba0 | ||
|
|
35ea2eedcd | ||
|
|
25f49cbf25 | ||
|
|
2dd1600cdd | ||
|
|
327b0870f0 | ||
|
|
7097ead476 | ||
|
|
887d5ca523 | ||
|
|
54c35ef172 | ||
|
|
a78eec4ebf | ||
|
|
ed140eade7 | ||
|
|
7c6c963168 | ||
|
|
e058be73ca | ||
|
|
d9a136d31c | ||
|
|
5910a52a60 | ||
|
|
e67bd4b6f6 | ||
|
|
9270fc3727 | ||
|
|
5101489d21 | ||
|
|
41c3a0caa5 | ||
|
|
382065544d | ||
|
|
e2a2c801f2 | ||
|
|
9e2fa9e360 | ||
|
|
588f1d9c93 | ||
|
|
347f3b1a13 | ||
|
|
c32ebc76fd | ||
|
|
a2ae0500d8 | ||
|
|
478972a34b | ||
|
|
f4ee1c1b53 | ||
|
|
93fe536549 | ||
|
|
3698562aae | ||
|
|
d8df33a9cb | ||
|
|
0de71be3e5 | ||
|
|
fd895bd142 | ||
|
|
edc68c032a | ||
|
|
40a841df8f | ||
|
|
df697c683c | ||
|
|
e3cb94f490 | ||
|
|
88f6cb97c7 | ||
|
|
bdd226b9d3 | ||
|
|
537d92bf57 | ||
|
|
c08644a729 | ||
|
|
7b07789173 | ||
|
|
585e0a6308 | ||
|
|
fd6bdfe69e | ||
|
|
654e36622f | ||
|
|
38df9afcf2 | ||
|
|
b442786811 | ||
|
|
ff943b5d5a |
No files matched your search
@@ -1 +0,0 @@
|
||||
{ "contextFileName": "AGENTS.md" }
|
||||
+3
-2
@@ -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 +0,0 @@
|
||||
IMPORTANT: Ensure you’ve thoroughly reviewed the [AGENTS.md](AGENTS.md) file before beginning any work.
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 .
|
||||
@@ -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"),
|
||||
|
||||
Vendored
+10
@@ -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.
|
||||
|
||||
@@ -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
|
||||
======
|
||||
|
||||
|
||||
@@ -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
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 4
|
||||
#define BOX64_REVISION 3
|
||||
#define BOX64_REVISION 4
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) \
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -176,4 +176,6 @@ r31 s8 xEmu Saved register The Emu struct
|
||||
|
||||
#endif // ASM_MAPPING
|
||||
|
||||
#define EMU_MXCSR 800
|
||||
|
||||
#endif //__LA64_MAPPING_H__
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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)); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
Binary file not shown.
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user