mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-10 17:38:02 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7eeb501649 | ||
|
|
fe6b9327d1 | ||
|
|
d43e64ee46 | ||
|
|
e477ccdb19 | ||
|
|
d0c1ec5c8c | ||
|
|
274946acf5 | ||
|
|
3c976b1ffb | ||
|
|
48c1f8fb11 | ||
|
|
599360ce07 | ||
|
|
b41c3f22be | ||
|
|
13cb80d1b7 | ||
|
|
a4479a9ac0 | ||
|
|
7edd021c17 | ||
|
|
f6beb4320e | ||
|
|
55e8ebf525 | ||
|
|
f388a8f493 | ||
|
|
3e71087a87 | ||
|
|
24e4039d1f | ||
|
|
fc8a05e693 | ||
|
|
ee99b5b167 | ||
|
|
2f23572e02 | ||
|
|
21d66686da | ||
|
|
01af6f3164 | ||
|
|
c845ab01c4 | ||
|
|
13c9fdaa40 | ||
|
|
0bc4d5b532 | ||
|
|
18a3f1b039 | ||
|
|
b99dde293d | ||
|
|
ff634b1e0c | ||
|
|
657d69aa3b | ||
|
|
913abd14f0 | ||
|
|
1a7ea1c09a | ||
|
|
08934a3b0c | ||
|
|
55c967fe9d | ||
|
|
dea4646116 | ||
|
|
c90a2ab5a4 | ||
|
|
06f5fa3e6c | ||
|
|
2260cf8a48 | ||
|
|
5571c43de6 | ||
|
|
91b32b01d5 | ||
|
|
95b4d665cf | ||
|
|
ac35b41b9d | ||
|
|
2db72f51be | ||
|
|
3c266d33e3 | ||
|
|
feaf6ffbd0 | ||
|
|
91788694ba | ||
|
|
1f921abaec | ||
|
|
0874bb4d01 | ||
|
|
6b32d6159f | ||
|
|
83336bcb9f | ||
|
|
fe556e957e | ||
|
|
cbcd11894c | ||
|
|
29bf151ed9 | ||
|
|
95b68190b3 | ||
|
|
c596f176bf | ||
|
|
74fd2a0a5d | ||
|
|
f20db6caae | ||
|
|
dd75b58943 | ||
|
|
17a84fcc51 | ||
|
|
eef68182b3 | ||
|
|
43dcbf3773 | ||
|
|
b1a706a650 | ||
|
|
ce14608947 | ||
|
|
dc53da7252 | ||
|
|
9e2779267f | ||
|
|
0416caa95a | ||
|
|
7e2528c538 | ||
|
|
58fb00b5f7 | ||
|
|
1957721f37 | ||
|
|
132d40108b | ||
|
|
c843a2df6a | ||
|
|
58542e4a72 | ||
|
|
ba20a27530 | ||
|
|
4743babdf2 | ||
|
|
c0c2780db4 | ||
|
|
97edb1092f | ||
|
|
3697d82ad1 | ||
|
|
df00419f69 | ||
|
|
11bb70178b | ||
|
|
5e03e18c68 | ||
|
|
a696462cc3 | ||
|
|
cda0c94b83 | ||
|
|
9a1fcc84b0 | ||
|
|
9571135b8d | ||
|
|
95bd956af8 | ||
|
|
6ebd9c3b32 | ||
|
|
0b9df5d5a0 | ||
|
|
c52f2fd01a | ||
|
|
0a60b449ca | ||
|
|
b3056386f2 | ||
|
|
63feea5fc4 | ||
|
|
f4f17b7751 | ||
|
|
7750e75bcf | ||
|
|
d0d32e763d | ||
|
|
e68b1f7584 | ||
|
|
beaa2c8a3a | ||
|
|
c48c60a814 | ||
|
|
7688169969 | ||
|
|
aebde89ba3 | ||
|
|
7f96fa4334 | ||
|
|
3206d6a76a | ||
|
|
a613ff8277 | ||
|
|
489bd8de29 | ||
|
|
d5a1864cfa |
No files matched your search
@@ -183,6 +183,9 @@ jobs:
|
||||
echo "BOX64_COMPILER=$PWD/android-ndk-r26b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android31-clang" >> $GITHUB_ENV
|
||||
echo "BOX64_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=1 -DBAD_SIGNAL=1" >> $GITHUB_ENV
|
||||
git clone https://github.com/termux/termux-docker.git
|
||||
cd termux-docker
|
||||
git checkout 148b93d989cbc572719e050135b3e13f115f2a8e~1
|
||||
cd ..
|
||||
sudo cp -rf termux-docker/system/arm /system
|
||||
sudo chown -R $(whoami):$(whoami) /system
|
||||
sudo chmod 755 -R /system
|
||||
|
||||
Vendored
+10
@@ -1,3 +1,13 @@
|
||||
box64 (0.4.2) unstable; urgency=low
|
||||
|
||||
This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning.
|
||||
=> Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work.
|
||||
=> Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility.
|
||||
=> Support for SteamRT3 & new Proton 11
|
||||
=> New PCC64LE in the work. Not finished, but should be usable already (but the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm). Note that main Box64 mainteners don't have access to relevent hardware, so support will be limited.
|
||||
|
||||
-- Sebastien Chevalier <[email protected]> Mon, 20 Apr 2026 10:30:33 -0100
|
||||
|
||||
box64 (0.4.0) unstable; urgency=low
|
||||
|
||||
This version added many important refactors: the opcode prefix decoder for Dynarec, libGL and Vulkan, the FSGSBASE support, making segments handling easier and faster.
|
||||
|
||||
@@ -1,3 +1,50 @@
|
||||
v0.4.2
|
||||
======
|
||||
|
||||
Highlights:
|
||||
* This version add lots on unconnected new things, like a PPC64LE backend, Vulkan overlay support or more Dynarec finetunning!
|
||||
=> Vulkan x64 overlay support. That means using the linux version of Steam, Fossilize & GameOverlayUI will work.
|
||||
=> Many dynarec refactors, especialy on ARM64 & LA64 with fixes to speed regression introduced with the the last 2 releases and improved compatibility.
|
||||
=> Support for SteamRT3 & new Proton 11
|
||||
=> New PCC64LE in the work. Not finished, but usable already. Note that the platform seems to use a 64k pagesize by default, so compatibility will suffer on this platformm.
|
||||
|
||||
Version summary:
|
||||
|
||||
* New RISC-V support for the script to denerate Debian .deb package
|
||||
* Improved the way system informations (like cpu brand and number of cores) is gathered and cpuid opcode handled
|
||||
* Improved support for Steam and new SteamRT3 64bit version
|
||||
* Elf: Improved handling of large pagesize (usefull for PPC64LE with its 64k pagesize)
|
||||
* Elf: Improved support for AppImage
|
||||
* Wrapping: Vulkan: Added support wor x64 overlay
|
||||
* Wrapping; Vulkan: Added BOX64_NOVULKANOVERLAY to disable x64 overlay handling
|
||||
* Wrapping: more wrapped functions, reworked some existing one with wrapperhelper
|
||||
* Wrapping: Added more wrapped libs
|
||||
* Wrapping: BOX32: more wrapped function and some fixes to existing ones
|
||||
* Wrapping: PPC64: Better handling of ioctl
|
||||
* Interpreter: Added a few more exotic opcodes
|
||||
* Dynarec: Added support for STRONGMEM=4
|
||||
* Dynarec: Improved TF flag handling
|
||||
* Dynarec: Reworked HotPage detection and handling
|
||||
* Dynarec: Reworked dynarec generation to batter handle abort mid-block
|
||||
* Dynarec: Rework how "Alt" addresses are handled
|
||||
* Dynarec: Removed BOX64_DYNAREC_HOTPAGE_ALT
|
||||
* Dynarec: Added support for Secondary Entry Point on dynablock when using CALLRET=1
|
||||
* Dynarec: Improve CALL FAR / RET FAR opcodes handling, adding CALLRET optimisation support
|
||||
* Dynarec: Improve IRET opcodes handling, adding CALLRET optimisation support
|
||||
* Dynarec: ARM64: Some new fixes for existing opcodes
|
||||
* Dynarec: ARM64: Reworked XMM/YMM register handling
|
||||
* Dynarec: ARM64: Reworked DIRTY=2 with AutoCRC Dynablock
|
||||
* Dynarec: LA64: Lots of new opcodes added & fixes
|
||||
* Dynarec: LA64: Added full support for SAFEFLAGS=2
|
||||
* Dynarec: LA64: Lots of fixes & improvements for FASTNAN=0
|
||||
* Dynarec: LA64: Refactor opcode printer
|
||||
* Dynarec: LA64: Reworked DIRTY=2 with AutoCRC Dynablock
|
||||
* Dynarec: LA64: Added CALLRET=2 support
|
||||
* Dynarec: RV64: A few fixes to existing opcodes
|
||||
* Dynarec: RV64: Added CALLRET=2 support
|
||||
* Dynarec: PPC64: Created a new backend for PPC64LE, with some opcodes already (still WIP)
|
||||
* WOWBOX64: Some small fixes
|
||||
|
||||
v0.4.0
|
||||
======
|
||||
|
||||
|
||||
+1
-1
@@ -3,6 +3,6 @@
|
||||
|
||||
#define BOX64_MAJOR 0
|
||||
#define BOX64_MINOR 4
|
||||
#define BOX64_REVISION 1
|
||||
#define BOX64_REVISION 2
|
||||
|
||||
#endif //__BOX64_VERSION_H_
|
||||
+10
-1
@@ -497,6 +497,8 @@ void LoadLDPath(box64context_t *context)
|
||||
AddPath("/usr/lib/i386-linux-gnu", &context->box64_ld_lib, 1);
|
||||
if(FileExist("/usr/i386-linux-gnu/lib", 0))
|
||||
AddPath("/usr/i386-linux-gnu/lib", &context->box64_ld_lib, 1);
|
||||
if(FileExist("/usr/i686-linux-gnu/lib", 0))
|
||||
AddPath("/usr/i686-linux-gnu/lib", &context->box64_ld_lib, 1);
|
||||
if(FileExist("/usr/lib/box64-i386-linux-gnu", 0))
|
||||
AddPath("/usr/lib/box64-i386-linux-gnu", &context->box64_ld_lib, 1);
|
||||
if(FileExist("/opt/box64/lib32", 0))
|
||||
@@ -796,7 +798,14 @@ int initialize(int argc, const char **argv, char** env, x64emu_t** emulator, elf
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc >= 3 && (!strcmp(argv[1], "--test") || !strcmp(argv[1], "-t"))) {
|
||||
int is_test = 0;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--test") || !strcmp(argv[i], "-t")) {
|
||||
is_test = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_test) {
|
||||
box64_unittest_mode = 1;
|
||||
exit(unittest(argc, argv));
|
||||
}
|
||||
|
||||
+49
-102
@@ -1850,7 +1850,7 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
|
||||
int cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
{
|
||||
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
|
||||
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?((destroy==2)?"invalidCRC":"destroy"):"mark");
|
||||
dynablock_t* db = NULL;
|
||||
uintptr_t end = addr+size;
|
||||
int ret = 0;
|
||||
@@ -1858,10 +1858,12 @@ int cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
|
||||
start_addr = getDBSize(start_addr, end-start_addr, &db);
|
||||
if(db) {
|
||||
ret = 1;
|
||||
if(destroy)
|
||||
FreeRangeDynablock(db, addr, size);
|
||||
else
|
||||
MarkRangeDynablock(db, addr, size);
|
||||
switch(destroy) {
|
||||
case 0: MarkRangeDynablock(db, addr, size); break;
|
||||
case 1: FreeRangeDynablock(db, addr, size); break;
|
||||
case 2: MarkCRCRangeDynablock(db, addr, size); break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -2390,11 +2392,11 @@ void neverprotectDB(uintptr_t addr, size_t size, int mark)
|
||||
if(prot&PROT_DYNAREC) {
|
||||
prot&=~PROT_DYN;
|
||||
if(mark)
|
||||
cleanDBFromAddressRange(cur, bend-cur, 0);
|
||||
cleanDBFromAddressRange(cur, bend-cur, (mark==2)?2:0);
|
||||
mprotect((void*)cur, bend-cur, prot);
|
||||
} else if(prot&PROT_DYNAREC_R) {
|
||||
if(mark)
|
||||
cleanDBFromAddressRange(cur, bend-cur, 0);
|
||||
cleanDBFromAddressRange(cur, bend-cur, (mark==2)?2:0);
|
||||
prot &= ~PROT_DYN;
|
||||
}
|
||||
prot |= PROT_NEVERCLEAN;
|
||||
@@ -2467,18 +2469,22 @@ typedef union hotpage_s {
|
||||
} hotpage_t;
|
||||
#define HOTPAGE_MAX ((1<<28)-1)
|
||||
#define N_HOTPAGE 32
|
||||
#define N_HOTPAGE_ALT 8
|
||||
#define HOTPAGE_MARK 64
|
||||
#define HOTPAGE_DIRTY 128
|
||||
#define HOTPAGE_DIRTY_ALT 1024
|
||||
#define HOTPAGE_DIRTY2 16
|
||||
static hotpage_t hotpage[N_HOTPAGE] = {0};
|
||||
void SetHotPage(int idx, uintptr_t page)
|
||||
{
|
||||
hotpage_t tmp = hotpage[idx];
|
||||
tmp.addr = page;
|
||||
tmp.cnt = BOX64ENV(dynarec_dirty)?(BOX64ENV(dynarec_hotpage_alt)?HOTPAGE_DIRTY_ALT:HOTPAGE_DIRTY):HOTPAGE_MARK;
|
||||
tmp.cnt = 0;
|
||||
switch(BOX64ENV(dynarec_dirty)) {
|
||||
case 0: tmp.cnt = HOTPAGE_MARK; break;
|
||||
case 1: tmp.cnt = HOTPAGE_DIRTY; break;
|
||||
case 2: tmp.cnt = HOTPAGE_DIRTY2; break;
|
||||
}
|
||||
//TODO: use Atomics to update hotpage?
|
||||
native_lock_store_dd(hotpage+idx, tmp.x);
|
||||
native_lock_store_dd(&hotpage[idx], tmp.x);
|
||||
}
|
||||
int IdxHotPage(uintptr_t page)
|
||||
{
|
||||
@@ -2487,36 +2493,14 @@ int IdxHotPage(uintptr_t page)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
void CancelHotPage(uintptr_t page)
|
||||
{
|
||||
unneverprotectDB(page<<12, box64_pagesize);
|
||||
}
|
||||
int IdxOldestHotPage(uintptr_t page)
|
||||
{
|
||||
int best_idx = -1;
|
||||
uint32_t best_cnt = HOTPAGE_MAX+1;
|
||||
if(BOX64ENV(dynarec_hotpage_alt)) {
|
||||
hotpage_t tmp;
|
||||
tmp.addr = page;
|
||||
tmp.cnt = HOTPAGE_MAX;
|
||||
for(int i=0; i<N_HOTPAGE_ALT; ++i) {
|
||||
if(!hotpage[i].cnt) {
|
||||
native_lock_store_dd(hotpage+i, tmp.x);
|
||||
return i;
|
||||
}
|
||||
uint32_t cnt = hotpage[i].cnt;
|
||||
if(cnt==HOTPAGE_MAX) cnt = 0;
|
||||
if(cnt < best_cnt) {
|
||||
best_idx = i;
|
||||
best_cnt = cnt;
|
||||
}
|
||||
}
|
||||
hotpage_t old = hotpage[best_idx];
|
||||
native_lock_store_dd(hotpage+best_idx, tmp.x);
|
||||
if(old.cnt && old.cnt!=HOTPAGE_MAX && BOX64ENV(dynarec_dirty)==1)
|
||||
CancelHotPage(old.addr);
|
||||
} else {
|
||||
for(int i=0; i<N_HOTPAGE && best_cnt; ++i) {
|
||||
for(int i=0; i<N_HOTPAGE; ++i) {
|
||||
if(!hotpage[i].x) {
|
||||
return i;
|
||||
} else {
|
||||
uint32_t cnt = hotpage[i].cnt;
|
||||
if(cnt < best_cnt) {
|
||||
best_idx = i;
|
||||
@@ -2524,6 +2508,7 @@ int IdxOldestHotPage(uintptr_t page)
|
||||
}
|
||||
}
|
||||
}
|
||||
dynarec_log(LOG_INFO, "%04d|No more live Hotpage slot for %p, recycling idx=%d (%p)\n", GetTID(), (void*)(page<<12), best_idx, (void*)(uintptr_t)(hotpage[best_idx].addr<<12));
|
||||
return best_idx;
|
||||
}
|
||||
// this function will create a new HotPage, or re-arm it if it's already registered
|
||||
@@ -2536,42 +2521,20 @@ void CheckHotPage(uintptr_t addr, uint32_t prot)
|
||||
if(BOX64ENV(dynarec_nohotpage))
|
||||
return;
|
||||
uintptr_t page = addr>>12;
|
||||
if(!BOX64ENV(dynarec_hotpage_alt)) {
|
||||
if(!(prot&PROT_EXEC))
|
||||
return; // needs to be an executable page
|
||||
/*if(BOX64ENV(dynarec_dirty)>1) {
|
||||
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p, marking page as NEVERCLEAN\n", (void*)(page<<12));
|
||||
neverprotectDB(page<<12, box64_pagesize, 1);
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
// look for idx
|
||||
int idx = IdxHotPage(page);
|
||||
if(BOX64ENV(dynarec_hotpage_alt)) {
|
||||
if(idx==-1) { IdxOldestHotPage(page); return; }
|
||||
hotpage_t hp = hotpage[idx];
|
||||
/*if(hp.cnt==HOTPAGE_MAX)*/ {
|
||||
if(BOX64ENV(dynarec_dirty)>1) {
|
||||
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d), marking page as NEVERCLEAN\n", (void*)(page<<12), idx);
|
||||
neverprotectDB(page<<12, box64_pagesize, 1);
|
||||
hp.cnt = 0;
|
||||
native_lock_store_dd(hotpage+idx, hp.x); // free slot
|
||||
} else {
|
||||
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
|
||||
SetHotPage(idx, page);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(idx!=-1 && BOX64ENV(dynarec_dirty)>1 && !hotpage[idx].cnt) {
|
||||
// Re-arming, so put the page as NEVERCLEAN and stop bothering
|
||||
neverprotectDB(page<<12, box64_pagesize, 1);
|
||||
return;
|
||||
}
|
||||
if(idx==-1) idx = IdxOldestHotPage(page);
|
||||
if(idx==-1) return;
|
||||
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d)\n", (void*)(page<<12), idx);
|
||||
SetHotPage(idx, page);
|
||||
if(idx!=-1 && (BOX64ENV(dynarec_dirty)>1)) {
|
||||
// Re-arming, so put the page as NEVERCLEAN and stop bothering
|
||||
dynarec_log(LOG_INFO, "Detecting a Hotpage at %p (idx=%d) again, switching the page to NEVERCLEAN\n", (void*)(page<<12), idx);
|
||||
neverprotectDB(page<<12, box64_pagesize, 2);
|
||||
hotpage_t hp = {0};
|
||||
native_lock_store_dd(hotpage+idx, hp.x); // free slot
|
||||
return;
|
||||
}
|
||||
if(idx==-1) idx = IdxOldestHotPage(page);
|
||||
if(idx==-1) return;
|
||||
dynarec_log(LOG_INFO, "%04d|Detecting a Hotpage at %p (idx=%d)\n", GetTID(), (void*)(page<<12), idx);
|
||||
SetHotPage(idx, page);
|
||||
}
|
||||
int isInHotPage(uintptr_t addr)
|
||||
{
|
||||
@@ -2580,45 +2543,29 @@ int isInHotPage(uintptr_t addr)
|
||||
return 0;
|
||||
uintptr_t page = addr>>12;
|
||||
int idx = IdxHotPage(page);
|
||||
if(BOX64ENV(dynarec_hotpage_alt)) {
|
||||
if(idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))
|
||||
return 0;
|
||||
//TODO: do Atomic stuffs instead
|
||||
hotpage_t hp = hotpage[idx];
|
||||
--hp.cnt;
|
||||
native_lock_store_dd(hotpage+idx, hp.x);
|
||||
if(!hp.cnt && BOX64ENV(dynarec_dirty)==1)
|
||||
CancelHotPage(hp.addr);
|
||||
return 1;
|
||||
} else {
|
||||
int ret = ((idx==-1) || !hotpage[idx].cnt)?0:1;
|
||||
// decrement all hotpage, it's a hotpage "tick"
|
||||
for(int i=0; i<N_HOTPAGE; ++i) {
|
||||
int ok = 0;
|
||||
do {
|
||||
hotpage_t hp = hotpage[i];
|
||||
hotpage_t old = hp;
|
||||
if(!hp.cnt || (hp.cnt==HOTPAGE_MAX)) {
|
||||
ok = 1;
|
||||
} else {
|
||||
--hp.cnt;
|
||||
ok = native_lock_storeifref2(hotpage+i, (void*)hp.x, (void*)old.x)==(void*)old.x;
|
||||
}
|
||||
} while(!ok);
|
||||
}
|
||||
return ret;
|
||||
int ret = ((idx==-1) || !hotpage[idx].cnt)?0:1;
|
||||
// decrement all hotpage, it's a hotpage "tick"
|
||||
for(int i=0; i<N_HOTPAGE; ++i) {
|
||||
int ok = 0;
|
||||
do {
|
||||
hotpage_t hp = hotpage[i];
|
||||
hotpage_t old = hp;
|
||||
if(!hp.cnt || (hp.cnt==HOTPAGE_MAX)) {
|
||||
ok = 1;
|
||||
} else {
|
||||
--hp.cnt;
|
||||
ok = native_lock_storeifref2(hotpage+i, (void*)hp.x, (void*)old.x)==(void*)old.x;
|
||||
}
|
||||
} while(!ok);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int checkInHotPage(uintptr_t addr)
|
||||
{
|
||||
if(addr>0x1000000000000LL) return 0;
|
||||
uintptr_t page = addr>>12;
|
||||
int idx = IdxHotPage(page);
|
||||
if(BOX64ENV(dynarec_hotpage_alt)) {
|
||||
return (idx==-1 || !hotpage[idx].cnt || (hotpage[idx].cnt==HOTPAGE_MAX))?0:1;
|
||||
} else {
|
||||
return ((idx==-1) || !hotpage[idx].cnt)?0:1;
|
||||
}
|
||||
return ((idx==-1) || !hotpage[idx].cnt)?0:1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1221,6 +1221,11 @@ int convert_bitmask(uint64_t bitmask);
|
||||
#define FCMPS_0(Sn) FEMIT(FCMP_scalar(0b00, Sn, 0, 0b01))
|
||||
#define FCMPD_0(Dn) FEMIT(FCMP_scalar(0b01, Dn, 0, 0b01))
|
||||
|
||||
// CCMP . CMP if cond is pass, else use nzcv as new flags
|
||||
#define FCCMP_scalar(type, Rm, cond, Rn, op, nzcv) (0b00011110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | ((cond)<<12 | 0b01<<10 | (Rn)<<5 | (op)<<4 | (nzcv)))
|
||||
#define FCCMPS(Sn, Sm, nzcv, cond) FEMIT(FCCMP_scalar(0b00, Sm, cond, Sn, 0, nzcv))
|
||||
#define FCCMPD(Dn, Dm, nzcv, cond) FEMIT(FCCMP_scalar(0b01, Dm, cond, Dn, 0, nzcv))
|
||||
|
||||
// CVT
|
||||
#define FCVT_scalar(sf, type, rmode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (rmode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
|
||||
// Floating-point Convert to Signed integer, rounding to nearest with ties to Away
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
.align 4
|
||||
|
||||
.extern LinkNext
|
||||
.extern LinkNextInvalid
|
||||
|
||||
.global arm64_next
|
||||
.global arm64_next_invalid
|
||||
|
||||
.8byte 0 // NULL pointer before arm64_next, for getDB
|
||||
arm64_next:
|
||||
@@ -41,3 +43,36 @@ arm64_next:
|
||||
// return offset is jump address
|
||||
br x3
|
||||
|
||||
|
||||
arm64_next_invalid:
|
||||
// emu is r0
|
||||
// IP address is r1
|
||||
sub sp, sp, (8 * 12)
|
||||
stp x0, x1, [sp, (8 * 0)]
|
||||
stp x10, x11, [sp, (8 * 2)]
|
||||
stp x12, x13, [sp, (8 * 4)]
|
||||
stp x14, x15, [sp, (8 * 6)]
|
||||
stp x16, x17, [sp, (8 * 8)]
|
||||
stp x18, x27, [sp, (8 * 10)] // also save x27(rip) to allow change in LinkNext
|
||||
|
||||
#ifdef _WIN32
|
||||
ldr x18, [x0, 3104]
|
||||
#endif
|
||||
mov x1, x27 // xRIP, should not be needed most of the time
|
||||
mov x2, x30 // "from" is in lr, so put in x2
|
||||
add x3, sp, 8*11 // x3 is address to change rip
|
||||
// call the function
|
||||
bl LinkNextInvalid
|
||||
// preserve return value
|
||||
mov x3, x0
|
||||
// pop regs
|
||||
ldp x0, x1, [sp, (8 * 0)]
|
||||
ldp x10, x11, [sp, (8 * 2)]
|
||||
ldp x12, x13, [sp, (8 * 4)]
|
||||
ldp x14, x15, [sp, (8 * 6)]
|
||||
ldp x16, x17, [sp, (8 * 8)]
|
||||
ldp x18, x27, [sp, (8 * 10)]
|
||||
add sp, sp, (8 * 12)
|
||||
// return offset is jump address
|
||||
br x3
|
||||
|
||||
@@ -2936,6 +2936,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
LDRx_REG(x3, x1, x2);
|
||||
//LDRx_U12(x3, x1, offsetof(box64context_t, signals[X64_SIGTRAP]));
|
||||
CMPSx_U12(x3, 0);
|
||||
// commit df before branch, CALL_S in int3 path has FORCE_DFNONE
|
||||
CHECK_DFNONE(0);
|
||||
B_MARK(cEQ);
|
||||
GETIP(addr); // update RIP
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
@@ -3823,17 +3825,14 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1)
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
if(BOX64DRENV(dynarec_callret)>1)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
}
|
||||
@@ -4534,7 +4533,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1)
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
@@ -4589,14 +4588,17 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
// Push actual return address. Note that CS will not be tested, but that should be ok?
|
||||
if(can_continue) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1)
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
ADR_S20(x4, j64);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
uint8_t eb1, eb2, gb1, gb2;
|
||||
int32_t i32, i32_;
|
||||
int cacheupd = 0;
|
||||
int v0, v1;
|
||||
int v0, v1, v2;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int s0;
|
||||
@@ -504,12 +504,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VFCVTZSS(q0, q0);
|
||||
} else {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
if (i) {
|
||||
VMOVeS(d0, 0, v1, i);
|
||||
FRINTZS(d0, d0);
|
||||
@@ -542,12 +541,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VFCVTZSS(q0, q0);
|
||||
} else {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
if (i) {
|
||||
VMOVeS(d0, 0, v1, i);
|
||||
FRINTIS(d0, d0);
|
||||
@@ -572,10 +570,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
GETEXSS(s0, 0, 0);
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
FCMPS(v0, s0);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMIS(x1, x2, v0, s0);
|
||||
break;
|
||||
case 0x30:
|
||||
INST_NAME("WRMSR");
|
||||
@@ -1224,6 +1219,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1234,6 +1231,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -1244,6 +1245,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1254,6 +1257,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -1278,6 +1285,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1288,6 +1297,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -1309,6 +1322,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1319,6 +1334,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(v1, 0x40, 2); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -2152,9 +2171,9 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
CMPSxw_REG(xRAX, ed);
|
||||
}
|
||||
MOVxw_REG(x1, ed); // save value
|
||||
Bcond(cNE, 4 + (rex.w ? 4 : 8));
|
||||
Bcond(cNE, 4 + 8);
|
||||
MOVxw_REG(ed, gd);
|
||||
if (!rex.w) { B_NEXT_nocond; }
|
||||
B_NEXT_nocond;
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, 0);
|
||||
LDxw(x1, wback, fixedaddress);
|
||||
@@ -2408,10 +2427,18 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
|
||||
IFX(X_PF)
|
||||
MOV32w(x3, 0); // PF uses 0 when the source is zero
|
||||
}
|
||||
TSTxw_REG(ed, ed);
|
||||
B_MARK(cEQ);
|
||||
RBITxw(x1, ed); // reverse
|
||||
CLZxw(gd, x1); // x2 gets leading 0 == BSF
|
||||
RBITxw(gd, ed); // reverse
|
||||
CLZxw(gd, gd); // gd gets leading 0 == BSF
|
||||
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
|
||||
IFX(X_PF)
|
||||
MOVxw_REG(x3, gd);
|
||||
}
|
||||
MARK;
|
||||
IFX(X_ZF) {
|
||||
IFNATIVE(NF_EQ) {} else {
|
||||
@@ -2424,7 +2451,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
IFX(X_AF) BFCw(xFlags, F_AF, 1);
|
||||
IFX(X_SF) BFCw(xFlags, F_SF, 1);
|
||||
IFX(X_OF) BFCw(xFlags, F_OF, 1);
|
||||
IFX(X_PF) emit_pf(dyn, ninst, gd, x2);
|
||||
IFX(X_PF) emit_pf(dyn, ninst, x3, x2);
|
||||
}
|
||||
break;
|
||||
case 0xBD:
|
||||
@@ -2438,11 +2465,19 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
nextop = F8;
|
||||
GETED(0);
|
||||
GETGD;
|
||||
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
|
||||
IFX(X_PF)
|
||||
MOV32w(x3, 0); // PF uses 0 when the source is zero
|
||||
}
|
||||
TSTxw_REG(ed, ed);
|
||||
B_MARK(cEQ);
|
||||
CLZxw(gd, ed); // x2 gets leading 0
|
||||
CLZxw(gd, ed); // gd gets leading 0
|
||||
SUBxw_U12(gd, gd, rex.w?63:31);
|
||||
NEGxw_REG(gd, gd); // complement
|
||||
if (BOX64DRENV(dynarec_safeflags) && !BOX64ENV(cputype)) {
|
||||
IFX(X_PF)
|
||||
MOVxw_REG(x3, gd);
|
||||
}
|
||||
MARK;
|
||||
IFX(X_ZF) {
|
||||
IFNATIVE(NF_EQ) {} else {
|
||||
@@ -2455,7 +2490,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
IFX(X_AF) BFCw(xFlags, F_AF, 1);
|
||||
IFX(X_SF) BFCw(xFlags, F_SF, 1);
|
||||
IFX(X_OF) BFCw(xFlags, F_OF, 1);
|
||||
IFX(X_PF) emit_pf(dyn, ninst, gd, x2);
|
||||
IFX(X_PF) emit_pf(dyn, ninst, x3, x2);
|
||||
}
|
||||
break;
|
||||
case 0xBE:
|
||||
@@ -2492,7 +2527,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
break;
|
||||
case 0xC0:
|
||||
INST_NAME("XADD Gb, Eb");
|
||||
INST_NAME("XADD Eb, Gb");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGB(x1);
|
||||
@@ -2503,16 +2538,15 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
EBBACK; // eb gets x1 (sum)
|
||||
break;
|
||||
case 0xC1:
|
||||
INST_NAME("XADD Gd, Ed");
|
||||
INST_NAME("XADD Ed, Gd");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGD;
|
||||
GETED(0);
|
||||
MOVxw_REG(x3, ed);
|
||||
MOVxw_REG(ed, gd);
|
||||
MOVxw_REG(gd, x3);
|
||||
if (ed != gd) MOVx_REG(x3, ed);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x4, x5);
|
||||
WBACK;
|
||||
if (ed != gd) MOVxw_REG(gd, x3);
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPS Gx, Ex, Ib");
|
||||
@@ -2679,6 +2713,8 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, NULL, 0, 0);
|
||||
if(rex.w && BOX64DRENV(dynarec_safeflags)>1) {
|
||||
// unaligned memory cause a GPF
|
||||
// commit df before branch, CALL_S in GPF path has FORCE_DFNONE
|
||||
CHECK_DFNONE(0);
|
||||
TSTx_mask(wback, 1, 0, 3);
|
||||
B_MARK2(cEQ); // alligned, continue...
|
||||
STORE_XEMU_CALL(xRIP);
|
||||
|
||||
@@ -1612,6 +1612,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
UXTHw(x2, xRAX);
|
||||
BFIw(x2, xRDX, 16, 16);
|
||||
if(BOX64ENV(dynarec_div0)) {
|
||||
// commit df before branch, CALL_S in div0 path has FORCE_DFNONE
|
||||
CHECK_DFNONE(0);
|
||||
CBNZw_MARK3(ed);
|
||||
MARK2;
|
||||
GETIP_(ip);
|
||||
@@ -1651,6 +1653,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
}
|
||||
GETSEW(x1, 0);
|
||||
if(BOX64ENV(dynarec_div0)) {
|
||||
// commit df before branch, CALL_S in div0 path has FORCE_DFNONE
|
||||
CHECK_DFNONE(0);
|
||||
CBNZw_MARK3(ed);
|
||||
MARK2;
|
||||
GETIP_(ip);
|
||||
|
||||
@@ -32,7 +32,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
int64_t j64;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
int mask;
|
||||
int v0, v1;
|
||||
int v0, v1, v2;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress;
|
||||
@@ -240,12 +240,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQXTN_32(q0, q0);
|
||||
} else {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
if (i) {
|
||||
VMOVeD(d0, 0, v1, i);
|
||||
FRINTZD(d0, d0);
|
||||
@@ -280,12 +279,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SQXTN_32(q0, q0);
|
||||
} else {
|
||||
MRS_fpsr(x5);
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
ORRw_mask(x2, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
for (int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
MSR_fpsr(x5);
|
||||
if (i) {
|
||||
VMOVeD(d0, 0, v1, i);
|
||||
FRINTID(d0, d0);
|
||||
@@ -310,10 +308,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
GETEXSD(q0, 0, 0);
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
FCMPD(v0, q0);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMID(x1, x2, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x38: // SSSE3 opcodes
|
||||
@@ -1728,6 +1723,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1738,6 +1735,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VDUPQD(v1, x5); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -1748,6 +1750,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1758,6 +1762,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VDUPQD(v1, x5); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -1820,6 +1829,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1830,6 +1841,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VDUPQD(v1, x5); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -1851,6 +1867,8 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q1); // save original src1 (Gx)
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(v0, q0, q1); // propagate NAN
|
||||
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -1861,6 +1879,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VDUPQD(v1, x5); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN in saved src1
|
||||
VBIFQ(q1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -2324,13 +2347,23 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
VFMAXPQD(v0, q1, q0); // propagate NAN
|
||||
VFCMEQQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
VUZP1Q_64(d1, q1, q0); // d1 = {q1[0], q0[0]}
|
||||
VFCMEQQD(v0, q1, q1); // per-element non-NaN for Gx
|
||||
VFCMEQQD(d0, q0, q0); // per-element non-NaN for Ex
|
||||
VUZP1Q_64(v1, v0, d0); // first element of each pair
|
||||
VUZP2Q_64(v0, v0, d0); // second element of each pair
|
||||
VANDQ(v0, v1, v0); // both non-NaN per pair
|
||||
}
|
||||
VFADDPQD(q1, q1, q0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(v1, d1, d1); // v1 = src1 non-NaN mask
|
||||
VDUPQD(d0, x5); // d0 = QNaN bit for double
|
||||
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
|
||||
VBIFQ(q1, d0, v1); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQD(v1, q1, q1); // 0 => out is NAN
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
@@ -2342,18 +2375,26 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETEX(q1, 0, 0);
|
||||
GETGX(q0, 1);
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
VUZP1Q_64(v0, q0, q1);
|
||||
VUZP2Q_64(q0, q0, q1);
|
||||
VUZP1Q_64(v0, q0, q1); // v0 = src1 (first of each pair)
|
||||
VUZP2Q_64(q0, q0, q1); // q0 = src2 (second of each pair)
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(v1, v0, q0); // propagate NAN
|
||||
VFCMEQQD(v1, v1, v1); // 0 if NAN, 1 if not NAN
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(d1, v0); // save src1
|
||||
VFCMEQQD(v1, v0, v0); // even elements non-NaN
|
||||
VFCMEQQD(d0, q0, q0); // odd elements non-NaN
|
||||
VANDQ(v1, v1, d0); // v1 = both non-NaN per pair
|
||||
}
|
||||
VFSUBQD(q0, v0, q0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(v0, q0, q0); // 0 => out is NAN
|
||||
VBICQ(v1, v1, v0); // forget it in any input was a NAN alreavy
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(d0, d1, d1); // d0 = src1 non-NaN mask
|
||||
VDUPQD(v0, x5); // v0 = QNaN bit for double
|
||||
VORRQ(v0, d1, v0); // v0 = QNaN(src1)
|
||||
VBIFQ(q0, v0, d0); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQD(v0, q0, q0); // 0 => out is NAN
|
||||
VBICQ(v1, v1, v0); // forget it in any input was a NAN already
|
||||
VSHLQ_64(v1, v1, 63); // only keep the sign bit
|
||||
VORRQ(q0, q0, v1); // NAN -> -NAN
|
||||
}
|
||||
@@ -2877,7 +2918,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
|
||||
case 0xC1:
|
||||
if(rex.w) return dynarec64_00(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
|
||||
INST_NAME("XADD Gw, Ew");
|
||||
INST_NAME("XADD Ew, Gw");
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
nextop = F8;
|
||||
GETGW(x1);
|
||||
@@ -2989,9 +3030,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, q0); // save src1
|
||||
VFCMEQQD(v0, q0, q0);
|
||||
VFCMEQQD(v1, q1, q1);
|
||||
VANDQ(v1, v0, v1); // v1 = both non-NaN
|
||||
}
|
||||
VFSUBQD(v0, q0, q1);
|
||||
VFADDQD(q0, q0, q1);
|
||||
VMOVeD(q0, 0, v0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(v0, q0, q0); // 0 where result is NaN
|
||||
VBICQ(v0, v1, v0); // both non-NaN but result NaN
|
||||
VSHLQ_64(v0, v0, 63); // sign bit only
|
||||
VORRQ(q0, q0, v0); // force -NaN
|
||||
VFCMEQQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
VDUPQD(v1, x5); // QNaN bit
|
||||
VORRQ(v2, v2, v1); // quiet any SNaN
|
||||
VBIFQ(q0, v2, v0); // where src1 NaN: use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
case 0xD1:
|
||||
INST_NAME("PSRLW Gx, Ex");
|
||||
|
||||
@@ -210,11 +210,16 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETGW(x5);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -355,12 +360,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOV32w(x5, (uint16_t)i16);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRH(x1, wback);
|
||||
emit_adc16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
@@ -375,12 +385,17 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?2:1);
|
||||
if(opcode==0x81) i16 = F16S; else i16 = F8S;
|
||||
MOV32w(x5, i16);
|
||||
MOV32w(x5, (uint16_t)i16);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRH(x1, wback);
|
||||
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
|
||||
STLXRH(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
|
||||
@@ -30,6 +30,7 @@ typedef struct arch_flags_s
|
||||
uint8_t vf:1;
|
||||
uint8_t cf:1;
|
||||
uint8_t inv_cf:1;
|
||||
uint8_t pf_v:1;
|
||||
} arch_flags_t;
|
||||
|
||||
#define X87_ST_D 0
|
||||
@@ -96,6 +97,7 @@ static int arch_build(dynarec_arm_t* dyn, int ninst, arch_build_t* arch, int noa
|
||||
arch->flags_.cf = flags&NF_CF;
|
||||
if(arch->flags_.cf)
|
||||
arch->flags_.inv_cf = !dyn->insts[ninst].normal_carry;
|
||||
arch->flags_.pf_v = flags&NF_PF_V;
|
||||
}
|
||||
// opcode can handle unaligned
|
||||
arch->unaligned = dyn->insts[ninst].unaligned;
|
||||
@@ -322,6 +324,9 @@ void adjust_arch(dynablock_t* db, x64emu_t* emu, ucontext_t* p, uintptr_t x64pc)
|
||||
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_C), F_CF);
|
||||
}
|
||||
}
|
||||
if(flags->pf_v) {
|
||||
CONDITIONAL_SET_FLAG(p->uc_mcontext.pstate&(1<<NZCV_V), F_PF);
|
||||
}
|
||||
}
|
||||
struct fpsimd_context *fpsimd = NULL;
|
||||
// find fpsimd struct
|
||||
|
||||
@@ -289,10 +289,7 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
GETEXSS(s0, 0, 0);
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
FCMPS(v0, s0);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMIS(x1, x2, v0, s0);
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
@@ -458,20 +455,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFADDQS(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
@@ -482,20 +485,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFMULQS(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
@@ -531,20 +540,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFSUBQS(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
@@ -569,20 +584,26 @@ uintptr_t dynarec64_AVX_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFDIVQS(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q0, q2, q2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
|
||||
@@ -96,7 +96,13 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i
|
||||
}
|
||||
// UD flags
|
||||
IFX(X_AF) BFCw(xFlags, F_AF, 1);
|
||||
IFX(X_PF) BFCw(xFlags, F_PF, 1);
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
if (BOX64ENV(cputype)) {
|
||||
IFX (X_PF) BFCw(xFlags, F_PF, 1);
|
||||
} else {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
nextop = F8;
|
||||
|
||||
@@ -268,10 +268,7 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
nextop = F8;
|
||||
GETGX(v0, 0);
|
||||
GETEXSD(q0, 0, 0);
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
FCMPD(v0, q0);
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMID(x1, x2, v0, q0);
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
@@ -362,23 +359,30 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFADDQD(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
|
||||
VDUPQD(q1, x5); // QNaN bit
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
if (!vex.l) YMM0(gd);
|
||||
break;
|
||||
case 0x59:
|
||||
INST_NAME("VMULPD Gx, Vx, Ex");
|
||||
@@ -386,10 +390,12 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
@@ -400,6 +406,11 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VDUPQD(q1, x5); // QNaN bit
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd)
|
||||
@@ -474,20 +485,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(q0, v1, v2); // propagate NAN
|
||||
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFSUBQD(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
|
||||
VDUPQD(q1, x5); // QNaN bit
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -512,20 +530,27 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
// check if any input value was NAN
|
||||
VFMAXQD(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
}
|
||||
VFDIVQD(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
|
||||
VDUPQD(q1, x5); // QNaN bit
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN, use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -1161,20 +1186,30 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
// check if any input value was NAN
|
||||
VFMAXPQD(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQD(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
VUZP1Q_64(d1, v2, v1); // d1 = src1 (even elements)
|
||||
VFCMEQQD(q0, v2, v2); // per-element non-NaN for Vx
|
||||
VFCMEQQD(d0, v1, v1); // per-element non-NaN for Ex
|
||||
VUZP1Q_64(q1, q0, d0); // first element of each pair
|
||||
VUZP2Q_64(q0, q0, d0); // second element of each pair
|
||||
VANDQ(q0, q1, q0); // both non-NaN per pair
|
||||
}
|
||||
VFADDPQD(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(q1, d1, d1); // q1 = src1 non-NaN mask
|
||||
VDUPQD(d0, x5); // d0 = QNaN bit for double
|
||||
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
|
||||
VBIFQ(v0, d0, q1); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQD(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -1183,24 +1218,32 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
INST_NAME("VHSUBPD Gx, Vx, Ex");
|
||||
nextop = F8;
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
if(!BOX64ENV(dynarec_fastnan))
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
VUZP1Q_64(q0, v2, v1);
|
||||
VUZP2Q_64(v0, v2, v1);
|
||||
VUZP1Q_64(q0, v2, v1); // q0 = src1 (first of each pair)
|
||||
VUZP2Q_64(v0, v2, v1); // v0 = src2 (second of each pair)
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
// check if any input value was NAN
|
||||
// but need to mix low/high part
|
||||
VFMAXQD(q1, v0, q0); // propagate NAN
|
||||
VFCMEQQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
VMOVQ(d1, q0); // save src1
|
||||
VFCMEQQD(q1, q0, q0); // even elements non-NaN
|
||||
VFCMEQQD(d0, v0, v0); // odd elements non-NaN
|
||||
VANDQ(q1, q1, d0); // both non-NaN per pair
|
||||
}
|
||||
VFSUBQD(v0, q0, v0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQD(q0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(d0, d1, d1); // d0 = src1 non-NaN mask
|
||||
VDUPQD(q0, x5); // q0 = QNaN bit for double
|
||||
VORRQ(q0, d1, q0); // q0 = QNaN(src1)
|
||||
VBIFQ(v0, q0, d0); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQD(q0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
|
||||
VSHLQ_64(q1, q1, 63); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -1349,11 +1392,32 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
INST_NAME("VADDSUBPD Gx, Vx, Ex");
|
||||
nextop = F8;
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
VFCMEQQD(q0, v2, v2);
|
||||
VFCMEQQD(q1, v1, v1);
|
||||
VANDQ(q1, q0, q1); // q1 = both non-NaN
|
||||
}
|
||||
FSUBD(q0, v2, v1);
|
||||
VFADDQD(v0, v2, v1);
|
||||
VMOVeD(v0, 0, q0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VFCMEQQD(q0, v0, v0); // 0 where result is NaN
|
||||
VBICQ(q0, q1, q0); // both non-NaN but result NaN
|
||||
VSHLQ_64(q0, q0, 63); // sign bit only
|
||||
VORRQ(v0, v0, q0); // force -NaN
|
||||
VFCMEQQD(q0, q2, q2); // 0 if src1 was NaN
|
||||
VDUPQD(q1, x5); // QNaN bit
|
||||
VORRQ(q2, q2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q0); // where src1 NaN: use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
break;
|
||||
@@ -1670,13 +1734,12 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
case 0xE6:
|
||||
INST_NAME("VCVTTPD2DQ Gx, Ex");
|
||||
nextop = F8;
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) {
|
||||
GETEX_Y(v1, 0, 0);
|
||||
GETGX_empty(v0);
|
||||
} else {
|
||||
if(BOX64ENV(dynarec_fastround))
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
GETEY(v1);
|
||||
}
|
||||
if(BOX64ENV(dynarec_fastround)) {
|
||||
@@ -1697,7 +1760,6 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!l) {
|
||||
MRS_fpsr(x5);
|
||||
ORRw_mask(x4, xZR, 1, 0); //0x80000000
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int i=0; i<2; ++i) {
|
||||
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
|
||||
|
||||
@@ -818,6 +818,9 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
|
||||
ADDx_U12(ed, ed, 4);
|
||||
TBZ(x4, 3*16, 4+1*4);
|
||||
VST1_32(v0, 3, ed);
|
||||
} else if (vex.l) { // keep avx ymm zero tracking consistent
|
||||
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
|
||||
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
|
||||
}
|
||||
SMWRITE2();
|
||||
break;
|
||||
@@ -860,6 +863,9 @@ uintptr_t dynarec64_AVX_66_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
|
||||
ADDx_U12(ed, ed, 8);
|
||||
TBZ(x4, 1*32, 4+1*4);
|
||||
VST1_64(v0, 1, ed);
|
||||
} else if (vex.l) { // keep avx ymm zero tracking consistent
|
||||
v2 = ymm_get_reg(dyn, ninst, x1, vex.v, 0, gd, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
|
||||
v0 = ymm_get_reg(dyn, ninst, x1, gd, 0, vex.v, (MODREG)?((nextop&7)+(rex.b<<3)):-1, -1);
|
||||
}
|
||||
SMWRITE2();
|
||||
break;
|
||||
|
||||
@@ -240,13 +240,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXD(q1, v0, v1); // propagate NAN
|
||||
FMAXD(q1, v2, v1); // propagate NAN
|
||||
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FADDD(q2, v1, v2); // the high part of the vector is erased...
|
||||
FCMEQD(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FADDD(q2, v1, v2); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -266,13 +271,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXD(q1, v0, v1); // propagate NAN
|
||||
FMAXD(q1, v2, v1); // propagate NAN
|
||||
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FMULD(q2, v1, v2); // the high part of the vector is erased...
|
||||
FCMEQD(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FMULD(q2, v1, v2); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -312,13 +322,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXD(q1, v0, v1); // propagate NAN
|
||||
FMAXD(q1, v2, v1); // propagate NAN
|
||||
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FSUBD(q2, v2, v1); // the high part of the vector is erased...
|
||||
FCMEQD(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FSUBD(q2, v2, v1); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -353,13 +368,18 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXD(q1, v0, v1); // propagate NAN
|
||||
FMAXD(q1, v2, v1); // propagate NAN
|
||||
FCMEQD(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FDIVD(q2, v2, v1); // the high part of the vector is erased...
|
||||
FCMEQD(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQD(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FDIVD(q2, v2, v1); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -424,20 +444,29 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
// check if any input value was NAN
|
||||
VFMAXPQS(q0, v2, v1); // propagate NAN
|
||||
VFCMEQQS(q0, q0, q0); // 0 if NAN, 1 if not NAN
|
||||
VUZP1Q_32(d1, v2, v1); // d1 = src1 (even elements)
|
||||
VFCMEQQS(q0, v2, v2); // per-element non-NaN for Vx
|
||||
VFCMEQQS(d0, v1, v1); // per-element non-NaN for Ex
|
||||
VUZP1Q_32(q1, q0, d0); // even elements of pairs
|
||||
VUZP2Q_32(q0, q0, d0); // odd elements of pairs
|
||||
VANDQ(q0, q1, q0); // both non-NaN per pair
|
||||
}
|
||||
VFADDPQS(v0, v2, v1);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(q1, d1, d1); // q1 = src1 non-NaN mask
|
||||
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 (QNaN bit)
|
||||
VORRQ(d0, d1, d0); // d0 = QNaN(src1)
|
||||
VBIFQ(v0, d0, q1); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQS(q1, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q0, q1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -446,24 +475,31 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
INST_NAME("VHSUBPS Gx, Vx, Ex");
|
||||
nextop = F8;
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
if(!BOX64ENV(dynarec_fastnan))
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
VUZP1Q_32(q0, v2, v1);
|
||||
VUZP2Q_32(v0, v2, v1);
|
||||
VUZP1Q_32(q0, v2, v1); // q0 = src1 (even elements)
|
||||
VUZP2Q_32(v0, v2, v1); // v0 = src2 (odd elements)
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
// check if any input value was NAN
|
||||
// but need to mix low/high part
|
||||
VFMAXQS(q1, v0, q0); // propagate NAN
|
||||
VFCMEQQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
VMOVQ(d1, q0); // save src1
|
||||
VFCMEQQS(q1, q0, q0); // even elements non-NaN
|
||||
VFCMEQQS(d0, v0, v0); // odd elements non-NaN
|
||||
VANDQ(q1, q1, d0); // both non-NaN per pair
|
||||
}
|
||||
VFSUBQS(v0, q0, v0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q1, q0); // forget it in any input was a NAN already
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
VFCMEQQS(d0, d1, d1); // d0 = src1 non-NaN mask
|
||||
MOVIQ_32_lsl(q0, 0x40, 2); // q0 = 0x00400000 (QNaN bit)
|
||||
VORRQ(q0, d1, q0); // q0 = QNaN(src1)
|
||||
VBIFQ(v0, q0, d0); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQS(q0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(q1, q1, q0); // only when both inputs non-NaN but result is NaN
|
||||
VSHLQ_32(q1, q1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, q1); // NAN -> -NAN
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
@@ -509,20 +545,39 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
INST_NAME("VADDSUBPS Gx, Vx, Ex");
|
||||
nextop = F8;
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q2 = fpu_get_scratch(dyn, ninst);
|
||||
}
|
||||
TABLE64C(x2, const_4f_m1_1_m1_1);
|
||||
VLDR128_U12(q0, x2, 0);
|
||||
for(int l=0; l<1+vex.l; ++l) {
|
||||
if(!l) { GETGX_empty_VXEX(v0, v2, v1, 0); } else { GETGY_empty_VYEY(v0, v2, v1); }
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VMOVQ(q2, v2); // save src1
|
||||
VFCMEQQS(q1, v2, v2);
|
||||
VFCMEQQS(d0, v1, v1);
|
||||
VANDQ(q1, q1, d0); // q1 = both non-NaN
|
||||
}
|
||||
if(v0==v1) {
|
||||
//TODO: find a better way
|
||||
if(!l) q1 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(q1, v2);
|
||||
VFMLAQS(q1, v1, q0);
|
||||
VMOVQ(v0, q1);
|
||||
VMOVQ(d0, v2);
|
||||
VFMLAQS(d0, v1, q0);
|
||||
VMOVQ(v0, d0);
|
||||
} else {
|
||||
if(v0!=v2) VMOVQ(v0, v2);
|
||||
VFMLAQS(v0, v1, q0);
|
||||
}
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(d0, v0, v0); // 0 where result is NaN
|
||||
VBICQ(d0, q1, d0); // both non-NaN but result NaN
|
||||
VSHLQ_32(d0, d0, 31); // sign bit only
|
||||
VORRQ(v0, v0, d0); // force -NaN
|
||||
VFCMEQQS(q1, q2, q2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(d0, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(q2, q2, d0); // quiet any SNaN
|
||||
VBIFQ(v0, q2, q1); // where src1 NaN: use QNaN(src1)
|
||||
}
|
||||
}
|
||||
if(!vex.l) YMM0(gd);
|
||||
break;
|
||||
|
||||
@@ -275,13 +275,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXS(q1, v0, v1); // propagate NAN
|
||||
FMAXS(q1, v2, v1); // propagate NAN
|
||||
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FADDS(q2, v1, v2); // the high part of the vector is erased...
|
||||
FCMEQS(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FADDS(q2, v1, v2); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -301,13 +306,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXS(q1, v0, v1); // propagate NAN
|
||||
FMAXS(q1, v2, v1); // propagate NAN
|
||||
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FMULS(q2, v1, v2); // the high part of the vector is erased...
|
||||
FCMEQS(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FMULS(q2, v1, v2); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -375,13 +385,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXS(q1, v0, v1); // propagate NAN
|
||||
FMAXS(q1, v2, v1); // propagate NAN
|
||||
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FSUBS(q2, v2, v1); // the high part of the vector is erased...
|
||||
FCMEQS(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FSUBS(q2, v2, v1); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -415,13 +430,18 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
FMAXS(q1, v0, v1); // propagate NAN
|
||||
FMAXS(q1, v2, v1); // propagate NAN
|
||||
FCMEQS(q1, q1, q1); // 0 if NAN, 1 if not NAN
|
||||
FDIVS(q2, v2, v1); // the high part of the vector is erased...
|
||||
FCMEQS(q0, q2, q2); // 0 => out is NAN
|
||||
VBIC(q0, q1, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(q2, q2, q0); // NAN -> -NAN
|
||||
FCMEQS(q1, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(q0, v2, q0); // QNaN(src1)
|
||||
VBIF(q2, q0, q1); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FDIVS(q2, v2, v1); // the high part of the vector is erased...
|
||||
}
|
||||
|
||||
@@ -84,6 +84,9 @@ uintptr_t getConst(arm64_consts_t which)
|
||||
case const_native_fstp: return (uintptr_t)native_fstp;
|
||||
case const_native_frstor: return (uintptr_t)native_frstor;
|
||||
case const_native_next: return (uintptr_t)native_next;
|
||||
case const_native_next_invalidate: return (uintptr_t)arm64_next_invalid;
|
||||
case const_native_crc32: return (uintptr_t)arm64_crc;
|
||||
case const_native_x31: return (uintptr_t)arm64_x31_hash;
|
||||
case const_int3: return (uintptr_t)EmuInt3;
|
||||
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
|
||||
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
|
||||
|
||||
@@ -47,6 +47,9 @@ typedef enum arm64_consts_s {
|
||||
const_native_fstp,
|
||||
const_native_frstor,
|
||||
const_native_next,
|
||||
const_native_next_invalidate,
|
||||
const_native_crc32,
|
||||
const_native_x31,
|
||||
const_int3,
|
||||
const_x86syscall,
|
||||
const_x64syscall,
|
||||
|
||||
@@ -148,14 +148,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
if(ST_IS_F(0)) {
|
||||
FCMPS(v1, v2);
|
||||
} else {
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMI(x1, x2, ST_IS_F(0), v1, v2);
|
||||
break;
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
@@ -169,14 +162,7 @@ uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
if(ST_IS_F(0)) {
|
||||
FCMPS(v1, v2);
|
||||
} else {
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMI(x1, x2,ST_IS_F(0), v1, v2);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -101,15 +101,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
if(ST_IS_F(0))
|
||||
{
|
||||
FCMPS(v1, v2);
|
||||
} else {
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMI(x1, x2,ST_IS_F(0), v1, v2);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
case 0xF0:
|
||||
@@ -124,15 +116,7 @@ uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET);
|
||||
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
|
||||
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
if(ST_IS_F(0))
|
||||
{
|
||||
FCMPS(v1, v2);
|
||||
} else {
|
||||
FCMPD(v1, v2);
|
||||
}
|
||||
}
|
||||
FCOMI(x1, x2);
|
||||
FCOMI(x1, x2, ST_IS_F(0), v1, v2);
|
||||
X87_POP_OR_FAIL(dyn, ninst, x3);
|
||||
break;
|
||||
|
||||
|
||||
@@ -704,6 +704,9 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ZF, SF_SUBSET);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
if(!ALIGNED_ATOMICxw) {
|
||||
// commit df before branch, CALL_S in GPF path has FORCE_DFNONE
|
||||
if(rex.w && BOX64DRENV(dynarec_safeflags)>1)
|
||||
CHECK_DFNONE(0);
|
||||
if(cpuext.uscat) {
|
||||
if(rex.w) {
|
||||
TSTx_mask(wback, 1, 0, 3);
|
||||
@@ -724,13 +727,14 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
MOVx_REG(x4, xRBX);
|
||||
MOVx_REG(x5, xRCX);
|
||||
CASPALxw(x2, x4, wback);
|
||||
// preserve upper bits of EAX/EDX if equal, per CMPXCHG8B semantics
|
||||
CMPSxw_REG(x2, xRAX);
|
||||
CCMPxw(x3, xRDX, 0, cEQ);
|
||||
CSELx(xRAX, xRAX, x2, cEQ);
|
||||
CSELx(xRDX, xRDX, x3, cEQ);
|
||||
UFLAG_IF {
|
||||
CMPSxw_REG(x2, xRAX);
|
||||
CCMPxw(x3, xRDX, 0, cEQ);
|
||||
IFNATIVE(NF_EQ) {} else {CSETw(x1, cEQ);}
|
||||
}
|
||||
MOVx_REG(xRAX, x2);
|
||||
MOVx_REG(xRDX, x3);
|
||||
if(!ALIGNED_ATOMICxw) {
|
||||
B_MARK3_nocond;
|
||||
}
|
||||
@@ -818,11 +822,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETGB(x2);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRB(x1, wback);
|
||||
emit_adc8(dyn, ninst, x1, x2, x4, x5);
|
||||
STLXRB(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 0x11:
|
||||
@@ -838,11 +847,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING);
|
||||
GETGD;
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRxw(x1, wback);
|
||||
emit_adc32(dyn, ninst, rex, x1, gd, x4, x5);
|
||||
STLXRxw(x4, x1, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 0x20:
|
||||
@@ -1093,11 +1107,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRB(x1, wback);
|
||||
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x3);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
@@ -1113,11 +1132,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x5, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 1);
|
||||
u8 = F8;
|
||||
wb1 = 1;
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRB(x1, wback);
|
||||
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x3);
|
||||
STLXRB(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
@@ -1345,11 +1369,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRxw(x1, wback);
|
||||
emit_adc32(dyn, ninst, rex, x1, x5, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 3: //SBB
|
||||
@@ -1365,11 +1394,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, (opcode==0x81)?4:1);
|
||||
if(opcode==0x81) i64 = F32S; else i64 = F8S;
|
||||
MOV64xw(x5, i64);
|
||||
MOVx_REG(x6, xFlags);
|
||||
MRS_nzcv(x87pc);
|
||||
MARKLOCK;
|
||||
MOVx_REG(xFlags, x6);
|
||||
MSR_nzcv(x87pc);
|
||||
LDAXRxw(x1, wback);
|
||||
emit_sbb32(dyn, ninst, rex, x1, x5, x3, x4);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
NATIVE_RESTORE_X87PC();
|
||||
}
|
||||
break;
|
||||
case 4: //AND
|
||||
@@ -1650,7 +1684,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
|
||||
} else {
|
||||
MARKLOCK;
|
||||
LDAXRxw(x1, wback);
|
||||
MVNw_REG(x1, x1);
|
||||
MVNxw_REG(x1, x1);
|
||||
STLXRxw(x3, x1, wback);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
}
|
||||
|
||||
@@ -31,14 +31,15 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint64_t u64, j64;
|
||||
int32_t i32, i32_;
|
||||
int cacheupd = 0;
|
||||
int v0, v1;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int v0, v1, v2;
|
||||
int q0, q1, q2;
|
||||
int d0, d1, d2;
|
||||
int64_t fixedaddress;
|
||||
int unscaled;
|
||||
|
||||
MAYUSE(d0);
|
||||
MAYUSE(d1);
|
||||
MAYUSE(d2);
|
||||
MAYUSE(q0);
|
||||
MAYUSE(q1);
|
||||
MAYUSE(v0);
|
||||
@@ -261,6 +262,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVD(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -269,6 +272,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FADDD(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -283,6 +291,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVD(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -291,6 +301,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FMULD(v1, d1, d0);
|
||||
}
|
||||
@@ -321,6 +336,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVD(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXD(v0, d0, d1); // propagate NAN
|
||||
FCMEQD(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -329,6 +346,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
FCMEQD(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FSUBD(v1, d1, d0);
|
||||
}
|
||||
@@ -353,6 +375,8 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVD(v2, v0); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXD(d0, v0, v1); // propagate NAN
|
||||
FCMEQD(d0, d0, d0); // 0 if NAN, 1 if not NAN
|
||||
@@ -361,6 +385,11 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, d0, q0); // forget it in any input was a NAN already
|
||||
SHL_64(q0, q0, 63); // only keep the sign bit
|
||||
VORR(d1, d1, q0); // NAN -> -NAN
|
||||
FCMEQD(d0, v2, v2); // 0 if src1 was NaN
|
||||
MOV64x(x5, 0x0008000000000000ULL);
|
||||
VMOVQDfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(d1, v2, d0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FDIVD(d1, v0, v1);
|
||||
}
|
||||
@@ -418,16 +447,25 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
v1 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
VFMAXPQS(v0, q1, q0); // propagate NAN
|
||||
VFCMEQQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
VUZP1Q_32(d1, q1, q0); // d1 = {q1[0], q1[2], q0[0], q0[2]}
|
||||
VFCMEQQS(v0, q1, q1); // per-element non-NaN mask for Gx
|
||||
VFCMEQQS(d0, q0, q0); // per-element non-NaN mask for Ex
|
||||
VUZP1Q_32(v1, v0, d0); // even elements of pairs
|
||||
VUZP2Q_32(v0, v0, d0); // odd elements of pairs
|
||||
VANDQ(v0, v1, v0); // v0 = both non-NaN per pair
|
||||
}
|
||||
VFADDPQS(q1, q1, q0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
VFCMEQQS(v1, d1, d1); // v1 = 0xFFFFFFFF where src1 non-NaN, 0 where NaN
|
||||
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 in all lanes (QNaN bit)
|
||||
VORRQ(d0, d1, d0); // d0 = QNaN(src1) = src1 | 0x00400000
|
||||
VBIFQ(q1, d0, v1); // where src1 was NaN (v1=0): q1 = d0 (QNaN(src1))
|
||||
VFCMEQQS(v1, q1, q1); // 0 => out is NAN
|
||||
VBICQ(v1, v0, v1); // forget it in any input was a NAN already
|
||||
VSHLQ_32(v1, v1, 31); // only keep the sign bit
|
||||
VORRQ(q1, q1, v1); // NAN -> -NAN
|
||||
}
|
||||
break;
|
||||
case 0x7D:
|
||||
@@ -436,20 +474,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
d0 = fpu_get_scratch(dyn, ninst);
|
||||
VUZP1Q_32(d0, v0, v1);
|
||||
VUZP2Q_32(v0, v0, v1);
|
||||
VUZP1Q_32(d0, v0, v1); // d0 = src1 (even elements: first of each pair)
|
||||
VUZP2Q_32(v0, v0, v1); // v0 = src2 (odd elements: second of each pair)
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn, ninst);
|
||||
// check if any input value was NAN
|
||||
VFMAXQS(d1, d0, v0); // propagate NAN
|
||||
VFCMEQQS(d1, d1, d1); // 0 if NAN, 1 if not NAN
|
||||
d2 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(q0, d0); // save src1 for NaN priority
|
||||
VFCMEQQS(d1, d0, d0); // even elements non-NaN
|
||||
VFCMEQQS(d2, v0, v0); // odd elements non-NaN
|
||||
VANDQ(d1, d1, d2); // d1 = both non-NaN per pair
|
||||
}
|
||||
VFSUBQS(v0, d0, v0);
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(d0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(d1, d1, d0); // forget it in any input was a NAN already
|
||||
VSHLQ_32(d1, d1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, d1); // NAN -> -NAN
|
||||
VFCMEQQS(d2, q0, q0); // d2 = src1 non-NaN mask
|
||||
MOVIQ_32_lsl(d0, 0x40, 2); // d0 = 0x00400000 (QNaN bit)
|
||||
VORRQ(d0, q0, d0); // d0 = QNaN(src1)
|
||||
VBIFQ(v0, d0, d2); // where src1 NaN: replace with QNaN(src1)
|
||||
VFCMEQQS(d0, v0, v0); // 0 => out is NAN
|
||||
VBICQ(d1, d1, d0); // forget it in any input was a NAN already
|
||||
VSHLQ_32(d1, d1, 31); // only keep the sign bit
|
||||
VORRQ(v0, v0, d1); // NAN -> -NAN
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -487,6 +532,23 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GOCOND(0x80, "J", "Id");
|
||||
#undef GO
|
||||
|
||||
case 0xA3: // ignore F2 prefix
|
||||
case 0xA4:
|
||||
case 0xA5:
|
||||
case 0xAB:
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
case 0xAF:
|
||||
case 0xB3:
|
||||
case 0xB7:
|
||||
case 0xBA:
|
||||
case 0xBB:
|
||||
case 0xBC: // this one is still BSR, not TZCNT
|
||||
case 0xBD: // and this one is still BSF, not LZCNT
|
||||
case 0xC1:
|
||||
case 0xCD:
|
||||
return dynarec64_0F(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
|
||||
|
||||
case 0xAE:
|
||||
nextop = F8;
|
||||
switch((nextop>>3)&7) {
|
||||
@@ -526,9 +588,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
GETGX(v0, 1);
|
||||
GETEX(v1, 0, 0);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
VMOVQ(v2, v0); // save src1
|
||||
VFCMEQQS(q0, v0, v0);
|
||||
VFCMEQQS(q1, v1, v1);
|
||||
VANDQ(q1, q0, q1); // q1 = both non-NaN
|
||||
}
|
||||
TABLE64C(x2, const_4f_m1_1_m1_1);
|
||||
VLDR128_U12(q0, x2, 0);
|
||||
VFMLAQS(v0, v1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMEQQS(q0, v0, v0); // 0 where result is NaN
|
||||
VBICQ(q0, q1, q0); // both non-NaN but result NaN
|
||||
VSHLQ_32(q0, q0, 31); // sign bit only
|
||||
VORRQ(v0, v0, q0); // force -NaN
|
||||
VFCMEQQS(q0, v2, v2); // 0 if src1 was NaN
|
||||
MOVIQ_32_lsl(q1, 0x40, 2); // QNaN bit 0x00400000
|
||||
VORRQ(v2, v2, q1); // quiet any SNaN
|
||||
VBIFQ(v0, v2, q0); // where src1 NaN: use QNaN(src1)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD6:
|
||||
|
||||
@@ -28,7 +28,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
uint8_t gd, ed;
|
||||
uint8_t wback;
|
||||
uint64_t u64;
|
||||
int v0, v1;
|
||||
int v0, v1, v2;
|
||||
int q0, q1;
|
||||
int d0, d1;
|
||||
int64_t fixedaddress;
|
||||
@@ -288,6 +288,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVS(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXS(v0, d0, d1); // propagate NAN
|
||||
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -296,6 +298,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
// src1 NaN priority
|
||||
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FADDS(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -310,6 +318,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVS(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXS(v0, d0, d1); // propagate NAN
|
||||
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -318,6 +328,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
// src1 NaN priority
|
||||
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FMULS(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -386,6 +402,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVS(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXS(v0, d0, d1); // propagate NAN
|
||||
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -394,6 +412,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
// src1 NaN priority
|
||||
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FSUBS(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -418,6 +442,8 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
if(!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn, ninst);
|
||||
q0 = fpu_get_scratch(dyn, ninst);
|
||||
v2 = fpu_get_scratch(dyn, ninst);
|
||||
FMOVS(v2, d1); // save src1
|
||||
// check if any input value was NAN
|
||||
FMAXS(v0, d0, d1); // propagate NAN
|
||||
FCMEQS(v0, v0, v0); // 0 if NAN, 1 if not NAN
|
||||
@@ -426,6 +452,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
VBIC(q0, v0, q0); // forget it in any input was a NAN already
|
||||
VSHL_32(q0, q0, 31); // only keep the sign bit
|
||||
VORR(v1, v1, q0); // NAN -> -NAN
|
||||
// src1 NaN priority
|
||||
FCMEQS(v0, v2, v2); // 0 if src1 was NaN
|
||||
MOV32w(x5, 0x00400000);
|
||||
VMOVQSfrom(q0, 0, x5);
|
||||
VORR(v2, v2, q0); // quiet any SNaN in src1
|
||||
VBIF(v1, v2, v0); // where src1 was NaN, use QNaN(src1)
|
||||
} else {
|
||||
FDIVS(v1, d1, d0); // the high part of the vector is erased...
|
||||
}
|
||||
@@ -612,6 +644,21 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xA3: // ignore F3 prefix
|
||||
case 0xA4:
|
||||
case 0xA5:
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
case 0xAF:
|
||||
case 0xB3:
|
||||
case 0xB7:
|
||||
case 0xBA:
|
||||
case 0xBB:
|
||||
case 0xBF:
|
||||
case 0xC1:
|
||||
case 0xCD:
|
||||
return dynarec64_0F(dyn, addr-1, ip, ninst, rex, ok, need_epilog);
|
||||
|
||||
case 0xBC:
|
||||
INST_NAME("TZCNT Gd, Ed");
|
||||
if (!BOX64DRENV(dynarec_safeflags)) {
|
||||
|
||||
@@ -786,13 +786,13 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
|
||||
}
|
||||
|
||||
static char buf[4096];
|
||||
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%d, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
|
||||
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s)/%c, set=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d/%d)",
|
||||
dyn->insts[ninst].x64.barrier,
|
||||
dyn->insts[ninst].x64.state_flags,
|
||||
df_status[dyn->f],
|
||||
df_status[dyn->insts[ninst].f_entry],
|
||||
df_status[dyn->insts[ninst].f_exit],
|
||||
dyn->insts[ninst].df_notneeded,
|
||||
dyn->insts[ninst].df_needed?'N':(dyn->insts[ninst].df_notneeded?'U':'-'),
|
||||
dyn->insts[ninst].x64.set_flags,
|
||||
dyn->insts[ninst].x64.gen_flags,
|
||||
dyn->insts[ninst].x64.use_flags,
|
||||
@@ -991,27 +991,23 @@ uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before)
|
||||
return flag;
|
||||
}
|
||||
|
||||
uint8_t flag2native(uint8_t flags)
|
||||
uint8_t flag2native(uint8_t flags, int vf_is_p)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
#ifdef ARM64
|
||||
if(flags&X_ZF) ret|=NF_EQ;
|
||||
if(flags&X_SF) ret|=NF_SF;
|
||||
if(flags&X_OF) ret|=NF_VF;
|
||||
if(!vf_is_p)
|
||||
if(flags&X_OF) ret|=NF_VF;
|
||||
if(flags&X_CF) ret|=NF_CF;
|
||||
if(vf_is_p)
|
||||
if(flags&X_PF) ret|=NF_PF_V; // but no opcode can generate both NF_VF & NF_PF_V at the same time!
|
||||
#else
|
||||
// no native flags on rv64 or la64
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int flagIsNative(uint8_t flags)
|
||||
{
|
||||
if(flags&(X_AF|X_PF)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
|
||||
static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags, int vf_is_p)
|
||||
{
|
||||
// propagate and check wich flags are actually used
|
||||
uint8_t used_flags = 0;
|
||||
@@ -1059,21 +1055,21 @@ static uint8_t getNativeFlagsUsed(dynarec_arm_t* dyn, int start, uint8_t flags)
|
||||
}
|
||||
if(ninst!=start && dyn->insts[ninst].x64.use_flags) {
|
||||
// some flags not compatible with native, partial use not allowed
|
||||
if(flag2native(dyn->insts[ninst].x64.use_flags)!=dyn->insts[ninst].use_nat_flags)
|
||||
if(flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p)!=dyn->insts[ninst].use_nat_flags)
|
||||
return 0;
|
||||
// check if flags are used, but not the natives ones
|
||||
//if(dyn->insts[ninst].use_nat_flags&~used_flags)
|
||||
// return 0;
|
||||
}
|
||||
// check if flags are generated without native option
|
||||
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags)) {
|
||||
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after))
|
||||
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags)) {
|
||||
if(used_flags&~flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p))
|
||||
return 0; // partial covert, not supported for now (TODO: this might be fixable)
|
||||
else
|
||||
return nat_flags_used?used_flags:0; // full covert... End of propagation
|
||||
}
|
||||
// check if flags are still needed
|
||||
if(!(flag2native(dyn->insts[ninst].x64.need_after)&flags))
|
||||
if(!(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&flags))
|
||||
return nat_flags_used?used_flags:0;
|
||||
// check if flags are destroyed, cancel the use then
|
||||
if(dyn->insts[ninst].nat_flags_op && (start!=ninst))
|
||||
@@ -1099,13 +1095,15 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
|
||||
{
|
||||
int ninst = start;
|
||||
// those are the flags generated by the opcode and used later on
|
||||
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after);
|
||||
int vf_is_p = (dyn->insts[ninst].set_nat_flags&NF_PF_V)?1:0;
|
||||
uint8_t flags = dyn->insts[ninst].set_nat_flags&flag2native(dyn->insts[ninst].x64.need_after, vf_is_p);
|
||||
//check if they are actualy used before starting
|
||||
//printf_log(LOG_INFO, "propagateNativeFlags called for start=%d, flags=%x, will need:%x\n", start, flags, flag2native(dyn->insts[ninst].x64.need_after));
|
||||
if(!flags) return;
|
||||
// also check if some native flags are used but not genereated here
|
||||
if(flag2native(dyn->insts[ninst].x64.use_flags)&~flags) return;
|
||||
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags);
|
||||
if(flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p)&~flags) return;
|
||||
if(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&~flags) return;
|
||||
uint8_t used_flags = getNativeFlagsUsed(dyn, start, flags, vf_is_p);
|
||||
//printf_log(LOG_INFO, " will use:%x, carry:%d, generate inverted carry:%d\n", used_flags, used_flags&NF_CF, dyn->insts[ninst].gen_inverted_carry);
|
||||
if(!used_flags) return; // the flags wont be used, so just cancel
|
||||
int nc = dyn->insts[ninst].gen_inverted_carry?0:1;
|
||||
@@ -1122,17 +1120,17 @@ static void propagateNativeFlags(dynarec_arm_t* dyn, int start)
|
||||
return;
|
||||
}
|
||||
// check if flags are generated without native option
|
||||
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after)&used_flags))
|
||||
if((start!=ninst) && dyn->insts[ninst].x64.gen_flags && (flag2native(dyn->insts[ninst].x64.gen_flags&dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags))
|
||||
return;
|
||||
// mark the opcode
|
||||
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after);
|
||||
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags); // should not change anything
|
||||
uint8_t use_flags = flag2native(dyn->insts[ninst].x64.need_before|dyn->insts[ninst].x64.need_after, vf_is_p);
|
||||
if(dyn->insts[ninst].x64.use_flags) use_flags |= flag2native(dyn->insts[ninst].x64.use_flags, vf_is_p); // should not change anything
|
||||
//printf_log(LOG_INFO, " marking ninst=%d with %x | %x&%x => %x\n", ninst, dyn->insts[ninst].need_nat_flags, used_flags, use_flags, dyn->insts[ninst].need_nat_flags | (used_flags&use_flags));
|
||||
dyn->insts[ninst].need_nat_flags |= used_flags&use_flags;
|
||||
if(carry) dyn->insts[ninst].normal_carry = nc;
|
||||
if(carry && dyn->insts[ninst].invert_carry) nc = 0;
|
||||
// check if flags are still needed
|
||||
if(!(flag2native(dyn->insts[ninst].x64.need_after)&used_flags))
|
||||
if(!(flag2native(dyn->insts[ninst].x64.need_after, vf_is_p)&used_flags))
|
||||
return;
|
||||
// go next
|
||||
if(!dyn->insts[ninst].x64.has_next) {
|
||||
@@ -1153,7 +1151,7 @@ void updateNativeFlags(dynarec_native_t* dyn)
|
||||
return;
|
||||
// forward check if native flags are used
|
||||
for(int ninst=0; ninst<dyn->size; ++ninst)
|
||||
if(flag2native(dyn->insts[ninst].x64.gen_flags) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
|
||||
if(flag2native(dyn->insts[ninst].x64.gen_flags,(dyn->insts[ninst].set_nat_flags&NF_PF_V)?1:0) && (dyn->insts[ninst].nat_flags_op==NAT_FLAG_OP_TOUCH)) {
|
||||
propagateNativeFlags(dyn, ninst);
|
||||
}
|
||||
}
|
||||
@@ -1183,7 +1181,7 @@ int nativeFlagsNeedsTransform(dynarec_arm_t* dyn, int ninst)
|
||||
flags_after = dyn->insts[jmp].before_nat_flags;
|
||||
nc_after = dyn->insts[jmp].normal_carry_before;
|
||||
}
|
||||
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
|
||||
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before, (dyn->insts[jmp].before_nat_flags&NF_PF_V)?1:0);
|
||||
flags_x86 &= ~flags_after;
|
||||
if((flags_before&NF_CF) && (flags_after&NF_CF) && (nc_before!=nc_after))
|
||||
return 1;
|
||||
@@ -1282,16 +1280,21 @@ static void propagateXYMMUneeded(dynarec_arm_t* dyn, int ninst, uint16_t mask_x,
|
||||
|
||||
void updateUneeded(dynarec_arm_t* dyn)
|
||||
{
|
||||
propagate_nodf(dyn);
|
||||
|
||||
if(!dyn->use_xmm && !dyn->use_ymm)
|
||||
return;
|
||||
// first propagate the needed regs: those which are used and are not unneeded
|
||||
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
|
||||
uint16_t xmm_needed = dyn->insts[ninst].n.xmm_used&~dyn->insts[ninst].n.xmm_unneeded;
|
||||
uint16_t ymm_needed = dyn->insts[ninst].n.ymm_used&~dyn->insts[ninst].n.ymm_unneeded;
|
||||
if((dyn->insts[ninst].x64.barrier&BARRIER_FLOAT) || (dyn->insts[ninst].x64.jmp && (dyn->insts[ninst].x64.jmp_insts==-1)))
|
||||
{
|
||||
if(dyn->use_xmm) xmm_needed = 0xffff;
|
||||
if(dyn->use_ymm) ymm_needed = 0xffff;
|
||||
}
|
||||
if(xmm_needed || ymm_needed)
|
||||
propagateXYMMNeeded(dyn, ninst, xmm_needed, ymm_needed);
|
||||
if(dyn->insts[ninst].x64.barrier&BARRIER_FLOAT)
|
||||
propagateXYMMNeeded(dyn, ninst, dyn->use_xmm?0xffff:0, dyn->use_ymm?0xffff:0);
|
||||
|
||||
}
|
||||
// then proagate the unneeded one: those which are not needed (not used anymore and will be overwritten)
|
||||
@@ -1300,8 +1303,6 @@ void updateUneeded(dynarec_arm_t* dyn)
|
||||
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
|
||||
propagateXYMMUneeded(dyn, dyn->insts[ninst].pred[i], dyn->insts[ninst].n.xmm_unneeded, dyn->insts[ninst].n.ymm_unneeded);
|
||||
}
|
||||
if(dyn->insts[ninst].df_notneeded)
|
||||
propagate_nodf(dyn, ninst);
|
||||
}
|
||||
// try to add some preload of XYMM on jump were it would make sense
|
||||
for(int ninst=0; ninst<dyn->size; ++ninst)
|
||||
@@ -1468,6 +1469,7 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached)
|
||||
}
|
||||
} else if (can_incr) {
|
||||
// We always have ninst == max_ninst_reached when can_incr == 1
|
||||
dyn->insts[ninst].ymm0_out = dyn->insts[ninst].ymm0_add & ~dyn->insts[ninst].ymm0_sub;
|
||||
++max_ninst_reached;
|
||||
} else {
|
||||
// We didn't update anything, we can leave
|
||||
@@ -1481,6 +1483,7 @@ void updateYmm0s(dynarec_arm_t* dyn, int ninst, int max_ninst_reached)
|
||||
// AVX helpers
|
||||
void avx_mark_zero(dynarec_arm_t* dyn, int ninst, int reg)
|
||||
{
|
||||
dyn->use_ymm = 1;
|
||||
dyn->ymm_zero |= (1<<reg);
|
||||
}
|
||||
|
||||
@@ -1500,6 +1503,7 @@ int is_avx_zero_unset(dynarec_arm_t* dyn, int ninst, int reg)
|
||||
|
||||
void avx_mark_zero_reset(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
dyn->use_ymm = 1;
|
||||
dyn->ymm_zero = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with
|
||||
int neoncache_no_i64(dynarec_arm_t* dyn, int ninst, int st, int a);
|
||||
|
||||
// transform x86 flags to native flags
|
||||
uint8_t flag2native(uint8_t flags);
|
||||
uint8_t flag2native(uint8_t flags, int vf_is_p);
|
||||
// mark a instruction as using/generating flags. return flag
|
||||
uint8_t mark_natflag(dynarec_arm_t* dyn, int ninst, uint8_t flag, int before);
|
||||
// propage the use of nativeflags or not (done between step 0 and step 1)
|
||||
|
||||
@@ -2321,7 +2321,7 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
|
||||
flags_after = dyn->insts[jmp].before_nat_flags;
|
||||
nc_after = dyn->insts[jmp].normal_carry_before;
|
||||
}
|
||||
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before);
|
||||
uint8_t flags_x86 = flag2native(dyn->insts[jmp].x64.need_before, (dyn->insts[jmp].before_nat_flags&NF_PF_V)?1:0);
|
||||
flags_x86 &= ~flags_after;
|
||||
MESSAGE(LOG_DUMP, "\tNative Flags transform ---- ninst=%d -> %d %hhx -> %hhx/%hhx\n", ninst, jmp, flags_before, flags_after, flags_x86);
|
||||
// flags present in before and missing in after
|
||||
@@ -2337,6 +2337,10 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
|
||||
CSETw(s1, cVS);
|
||||
BFIw(xFlags, s1, F_OF, 1);
|
||||
}
|
||||
if((flags_before&NF_PF_V) && (flags_x86&NF_PF_V)) {
|
||||
CSETw(s1, cVS);
|
||||
BFIw(xFlags, s1, F_PF, 1);
|
||||
}
|
||||
if((flags_before&NF_CF) && (flags_x86&NF_CF)) {
|
||||
if(nc_before) // might need to invert carry
|
||||
CSETw(s1, cCS);
|
||||
@@ -2362,6 +2366,11 @@ static void nativeFlagsTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2)
|
||||
UBFXw(s1, xFlags, F_OF, 1);
|
||||
BFIx(s2, s1, NZCV_V, 1);
|
||||
}
|
||||
if(!(flags_before&NF_PF_V) && (flags_after&NF_PF_V)) {
|
||||
GO_MRS(s2);
|
||||
UBFXw(s1, xFlags, F_PF, 1);
|
||||
BFIx(s2, s1, NZCV_V, 1);
|
||||
}
|
||||
if(!(flags_before&NF_CF) && (flags_after&NF_CF)) {
|
||||
GO_MRS(s2);
|
||||
BFIx(s2, xFlags, NZCV_C, 1); // F_CF is bit 0
|
||||
@@ -2393,6 +2402,47 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd) {
|
||||
nativeFlagsTransform(dyn, ninst, x1, x2);
|
||||
}
|
||||
|
||||
void additionnal_checks(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
int s1 = x1;
|
||||
// check if a opcode generate partial flags that may clober existing native flags and see need to be "moved" to xFlags
|
||||
if(dyn->insts[ninst].nat_flags_op || dyn->insts[ninst].nat_flags_op_before) {
|
||||
uint8_t nat_flags = dyn->insts[ninst].need_nat_flags; // that's the native flags that will be generated
|
||||
uint8_t nat_flags_gen = dyn->insts[ninst].set_nat_flags;
|
||||
//TODO: does it need to fetch previous state with getPred?
|
||||
uint8_t nat_flags_before = dyn->insts[ninst].before_nat_flags; //flags before the opcode, but it's only there when opcode also consume natflags
|
||||
uint8_t nat_flags_flush = nat_flags_before&~nat_flags_gen; // flags present before bu not after the operation and so that needs to be spared
|
||||
if(nat_flags_before && nat_flags_flush) {
|
||||
// some flags disapear, and need to be saved
|
||||
MESSAGE(LOG_DUMP, "\tPurging native flags %hhx\n", nat_flags_flush);
|
||||
uint8_t nc_before = dyn->insts[ninst].normal_carry;
|
||||
if(nat_flags_flush&NF_EQ) {
|
||||
CSETw(s1, cEQ);
|
||||
BFIw(xFlags, s1, F_ZF, 1);
|
||||
}
|
||||
if(nat_flags_flush&NF_SF) {
|
||||
CSETw(s1, cMI);
|
||||
BFIw(xFlags, s1, F_SF, 1);
|
||||
}
|
||||
if(nat_flags_flush&NF_VF) {
|
||||
CSETw(s1, cVS);
|
||||
BFIw(xFlags, s1, F_OF, 1);
|
||||
}
|
||||
if(nat_flags_flush&NF_PF_V) {
|
||||
CSETw(s1, cVS);
|
||||
BFIw(xFlags, s1, F_PF, 1);
|
||||
}
|
||||
if(nat_flags_flush&NF_CF) {
|
||||
if(nc_before) // might need to invert carry
|
||||
CSETw(s1, cCS);
|
||||
else
|
||||
CSETw(s1, cCC);
|
||||
BFIw(xFlags, s1, F_CF, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
{
|
||||
x87_reflectcache(dyn, ninst, s1, s2, s3);
|
||||
@@ -2787,3 +2837,97 @@ void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
|
||||
}
|
||||
MESSAGE(LOG_INFO, "-------- doLeave\n");
|
||||
}
|
||||
|
||||
void emit_fcomi(dynarec_arm_t* dyn, int ninst, int s1, int s2, int isfloat, int d1, int d2)
|
||||
{
|
||||
IFX(X_OF|X_AF|X_SF) {
|
||||
MOV32w(s2, 0b100011010101);
|
||||
BICw_REG(xFlags, xFlags, s2);
|
||||
}
|
||||
IFX(X_CF|X_PF|X_ZF) {
|
||||
int nonative = 0;
|
||||
int needCZ = 0;
|
||||
if(isfloat)
|
||||
FCMPS(d1, d2);
|
||||
else
|
||||
FCMPD(d1, d2);
|
||||
IFX(X_ZF) {
|
||||
IFNATIVE(NF_EQ) {
|
||||
// add ZF if VS is set
|
||||
needCZ = 1;
|
||||
} else {
|
||||
nonative = 1;
|
||||
}
|
||||
}
|
||||
IFX(X_CF) {
|
||||
IFNATIVE(NF_CF) {
|
||||
// no need to add CF if VS, because it's a reverse carry (so already "un"set)
|
||||
GEN_INVERTED_CARRY();
|
||||
needCZ = 1;
|
||||
} else {
|
||||
nonative = 1;
|
||||
}
|
||||
}
|
||||
IFX(X_PF) {
|
||||
IFNATIVE(NF_PF_V) {
|
||||
} else {
|
||||
nonative = 1;
|
||||
}
|
||||
}
|
||||
if(needCZ) {
|
||||
#if 1
|
||||
// retest is VF is clear, set NZCV to 0101 if VF is set, to match x86 behaviour (also, inversed Carry)
|
||||
// probably faster like that then the conditionnal jump + reading / reseting the flags
|
||||
if(isfloat)
|
||||
FCCMPS(d1, d2, 0b0101, cVC);
|
||||
else
|
||||
FCCMPD(d1, d2, 0b0101, cVC);
|
||||
#else
|
||||
if(cpuext.flagm) {
|
||||
Bcond(cVC, 4+2*4);
|
||||
MOV32w(s1, 0b0100); //new flags
|
||||
RMIF(s1, 0, 0b0110); // ZC flags only
|
||||
} else {
|
||||
Bcond(cVC, 4+3*4);
|
||||
MRS_nzcv(s1);
|
||||
EORx_mask(s1, s1, 1, 0b100011, 0b000001); // mask = (1<<NZCV_Z)|(1<<NZCV_C) == 0x60000000
|
||||
MSR_nzcv(s1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if(nonative) {
|
||||
MOV32w(s2, 0b01000101);
|
||||
IFX(X_OF|X_AF|X_SF) {} else {BICw_REG(xFlags, xFlags, s2);}
|
||||
CSETw(s1, cMI); /* 1 if less than, 0 else */
|
||||
/*s2 already set */ /* unordered */
|
||||
CSELw(s1, s2, s1, cVS);
|
||||
MOV32w(s2, 0b01000000); /* zero */
|
||||
CSELw(s1, s2, s1, cEQ);
|
||||
/* greater than leave 0 */
|
||||
ORRw_REG(xFlags, xFlags, s1);
|
||||
}
|
||||
}
|
||||
SET_DFNONE();
|
||||
}
|
||||
|
||||
void checkCRC(dynarec_arm_t* dyn, int ninst)
|
||||
{
|
||||
// grab the dynablock address in x5, as this on will not be erased by crc functions
|
||||
int delta = -(dyn->native_size + sizeof(void*));
|
||||
LDRx_literal(x5, delta);
|
||||
// move away xEMU to X6, should be safe there
|
||||
MOVx_REG(x6, xEmu);
|
||||
// prepare and call the crc function
|
||||
TABLE64C(x3, cpuext.crc32?const_native_crc32:const_native_x31);
|
||||
LDRx_U12(xEmu, x5, offsetof(dynablock_t, x64_addr));
|
||||
LDRw_U12(x1, x5, offsetof(dynablock_t, x64_size));
|
||||
BLR(x3);
|
||||
// done, move away result and restore xEmu
|
||||
MOVw_REG(x1, xEmu);
|
||||
MOVx_REG(xEmu, x6);
|
||||
LDRw_U12(x2, x5, offsetof(dynablock_t, hash));
|
||||
SUBw_REG(x1, x1, x2);
|
||||
CBZw(x1, 4+2*4);
|
||||
TABLE64C(x3, const_native_next_invalidate);
|
||||
BLR(x3);
|
||||
}
|
||||
@@ -841,30 +841,10 @@
|
||||
ORRw_REG_LSL(s3, s3, s1, 8); \
|
||||
STRH_U12(s3, xEmu, offsetof(x64emu_t, sw))
|
||||
|
||||
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
|
||||
#define FCOMI(s1, s2) \
|
||||
IFX(X_OF|X_AF|X_SF) { \
|
||||
MOV32w(s2, 0b100011010101); \
|
||||
BICw_REG(xFlags, xFlags, s2); \
|
||||
IFX(X_CF|X_PF|X_ZF) { \
|
||||
MOV32w(s2, 0b01000101); \
|
||||
} \
|
||||
} else { \
|
||||
IFX(X_CF|X_PF|X_ZF) { \
|
||||
MOV32w(s2, 0b01000101); \
|
||||
BICw_REG(xFlags, xFlags, s2); \
|
||||
} \
|
||||
} \
|
||||
IFX(X_CF|X_PF|X_ZF) { \
|
||||
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
|
||||
/*s2 already set */ /* unordered */ \
|
||||
CSELw(s1, s2, s1, cVS); \
|
||||
MOV32w(s2, 0b01000000); /* zero */ \
|
||||
CSELw(s1, s2, s1, cEQ); \
|
||||
/* greater than leave 0 */ \
|
||||
ORRw_REG(xFlags, xFlags, s1); \
|
||||
} \
|
||||
SET_DFNONE(); \
|
||||
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is not done)
|
||||
#define FCOMIS(s1, s2, d1, d2) emit_fcomi(dyn, ninst, s1, s2, 1, d1, d2)
|
||||
#define FCOMID(s1, s2, d1, d2) emit_fcomi(dyn, ninst, s1, s2, 0, d1, d2)
|
||||
#define FCOMI(s1, s2, isfloat, d1, d2) emit_fcomi(dyn, ninst, s1, s2, isfloat, d1, d2)
|
||||
|
||||
#ifndef IF_UNALIGNED
|
||||
#define IF_UNALIGNED(A) if(dyn->insts[ninst].unaligned)
|
||||
@@ -1097,6 +1077,11 @@
|
||||
dyn->doublepop = 0;
|
||||
#define ARCH_RESET()
|
||||
|
||||
#undef PREFLAGSNEEDED
|
||||
#define PREFLAGSNEEDED() \
|
||||
if(dyn->always_test && ninst && (dyn->insts[ninst].sep || (ninst && dyn->insts[ninst-1].x64.has_callret))) \
|
||||
checkCRC(dyn, ninst);
|
||||
|
||||
#if STEP < 2
|
||||
#define GETIP(A) MOV64x(xRIP, A)
|
||||
#define GETIP_(A) MOV64x(xRIP, A)
|
||||
@@ -1307,6 +1292,7 @@
|
||||
#define emit_shld16 STEPNAME(emit_shld16)
|
||||
|
||||
#define emit_pf STEPNAME(emit_pf)
|
||||
#define emit_fcomi STEPNAME(emit_fcomi)
|
||||
|
||||
#define x87_do_push STEPNAME(x87_do_push)
|
||||
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
|
||||
@@ -1339,6 +1325,7 @@
|
||||
#define doPreload STEPNAME(doPreload)
|
||||
#define doEnterBlock STEPNAME(doEnterBlock)
|
||||
#define doLeaveBlock STEPNAME(doLeaveBlock)
|
||||
#define checkCRC STEPNAME(checkCRC)
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
@@ -1354,6 +1341,7 @@
|
||||
#define avx_purge_ymm STEPNAME(avx_purge_ymm)
|
||||
|
||||
#define CacheTransform STEPNAME(CacheTransform)
|
||||
#define additionnal_checks STEPNAME(additionnal_checks)
|
||||
|
||||
#define arm64_move32 STEPNAME(arm64_move32)
|
||||
#define arm64_move64 STEPNAME(arm64_move64)
|
||||
@@ -1479,6 +1467,7 @@ void emit_shld16c(dynarec_arm_t* dyn, int ninst, int s1, int s2, uint32_t c, int
|
||||
void emit_shld16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s5, int s3, int s4);
|
||||
|
||||
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4);
|
||||
void emit_fcomi(dynarec_arm_t* dyn, int ninst, int s1, int s2, int isfloat, int d1, int d2);
|
||||
|
||||
// x87 helper
|
||||
// cache of the local stack counter, to avoid update at every call, return old internal stack counter
|
||||
@@ -1519,6 +1508,7 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
void avx_purge_ymm(dynarec_arm_t* dyn, int ninst, uint16_t mask, int s1);
|
||||
|
||||
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd);
|
||||
void additionnal_checks(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val);
|
||||
void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val);
|
||||
@@ -1611,6 +1601,8 @@ void doPreload(dynarec_arm_t* dyn, int ninst);
|
||||
void doEnterBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// Leave a block (atomic decrement of in_used)
|
||||
void doLeaveBlock(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
|
||||
// in case of allways_test, this insert a check of crc of the dynablock (and exit to ArmNext if wrong)
|
||||
void checkCRC(dynarec_arm_t* dyn, int ninst);
|
||||
|
||||
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
|
||||
@@ -1765,13 +1757,21 @@ uintptr_t dynarec64_AVX_F3_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip
|
||||
break; \
|
||||
case B+0xA: \
|
||||
INST_NAME(T1 "P " T2); \
|
||||
IFNATIVE(NF_PF_V) { \
|
||||
GO( , cVC, cVS, X_PF) \
|
||||
} else { \
|
||||
GO( TSTw_mask(xFlags, 0b011110, 0) \
|
||||
, cEQ, cNE, X_PF) \
|
||||
} \
|
||||
break; \
|
||||
case B+0xB: \
|
||||
INST_NAME(T1 "NP " T2); \
|
||||
IFNATIVE(NF_PF_V) { \
|
||||
GO( , cVS, cVC, X_PF) \
|
||||
} else { \
|
||||
GO( TSTw_mask(xFlags, 0b011110, 0) \
|
||||
, cNE, cEQ, X_PF) \
|
||||
} \
|
||||
break; \
|
||||
case B+0xC: \
|
||||
INST_NAME(T1 "L " T2); \
|
||||
|
||||
@@ -31,8 +31,12 @@
|
||||
Table64(dyn, getConst(V), 2); EMIT(0); \
|
||||
} while(0)
|
||||
#define FTABLE64(A, V) do { mmx87_regs_t v = {.d = V}; Table64(dyn, v.q, 2); EMIT(0); } while(0)
|
||||
#define CALLRET_RET(A) do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); ++dyn->sep_size; } \
|
||||
if(BOX64DRENV(dynarec_callret)>1) {dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP);} \
|
||||
#define CALLRET_RET(A) do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
|
||||
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
|
||||
} \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#define MESSAGE(A, ...) \
|
||||
do { \
|
||||
if (dyn->need_dump) dynarec_log(LOG_NONE, __VA_ARGS__); \
|
||||
if (dyn->need_dump) dynarec_log_prefix(0, LOG_NONE, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#define ENDPREFIX dyn->insts[ninst].size2 = 0
|
||||
#define NEW_INST \
|
||||
@@ -54,7 +54,7 @@
|
||||
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
|
||||
++dyn->sep_size; \
|
||||
} \
|
||||
if(BOX64DRENV(dynarec_callret)>1) { \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; \
|
||||
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
|
||||
EMIT(ARCH_NOP); \
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef struct box64env_s box64env_t;
|
||||
#define NF_SF (1<<1)
|
||||
#define NF_VF (1<<2)
|
||||
#define NF_CF (1<<3)
|
||||
#define NF_PF_V (1<<4)
|
||||
|
||||
// Nothing happens to the native flags
|
||||
#define NAT_FLAG_OP_NONE 0
|
||||
@@ -125,7 +126,8 @@ typedef struct instruction_arm64_s {
|
||||
uint8_t will_read:1; // [strongmem] will read from memory
|
||||
uint8_t last_write:1; // [strongmem] the last write in a SEQ
|
||||
uint8_t lock:1; // [strongmem] lock semantic
|
||||
uint8_t wfe:1; // opcode uses sevl + wfe
|
||||
uint8_t wfe:1; // opcode uses sevl + wfe
|
||||
uint8_t sep:1; // opcode is a secondary entry point
|
||||
uint8_t set_nat_flags; // 0 or combinaison of native flags define
|
||||
uint8_t use_nat_flags; // 0 or combinaison of native flags define
|
||||
uint8_t use_nat_flags_before; // 0 or combinaison of native flags define
|
||||
@@ -137,6 +139,7 @@ typedef struct instruction_arm64_s {
|
||||
unsigned normal_carry:1;
|
||||
unsigned normal_carry_before:1;
|
||||
unsigned invert_carry:1; // this opcode force an inverted carry
|
||||
unsigned df_needed:1;
|
||||
unsigned df_notneeded:1;
|
||||
unsigned unaligned:1; // this opcode can be re-generated for unaligned special case
|
||||
unsigned x87precision:1; // this opcode can handle x87pc
|
||||
|
||||
+63
-2
@@ -213,6 +213,18 @@ void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
MarkDynablock(db);
|
||||
}
|
||||
|
||||
void MarkCRCRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
// Mark will try to find *any* blocks that intersect the range to mark
|
||||
if(!db)
|
||||
return;
|
||||
dynarec_log(LOG_DEBUG, "MarkCRCRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x64_addr, (void*)db->x64_size);
|
||||
if(IntervalIntersects((uintptr_t)db->x64_addr, (uintptr_t)db->x64_addr+db->x64_size-1, addr, addr+size+1)) {
|
||||
MarkDynablock(db); // mark as dirty
|
||||
db->to_delete = 1; // also invalid hash, so it will be deleted and replace
|
||||
}
|
||||
}
|
||||
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
|
||||
{
|
||||
if(!db)
|
||||
@@ -233,6 +245,45 @@ void dynablock_leave_runtime(dynablock_t* db)
|
||||
__atomic_fetch_sub(&db->in_used, 1, __ATOMIC_ACQ_REL);
|
||||
}
|
||||
|
||||
dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits)
|
||||
{
|
||||
#ifndef WIN32
|
||||
static int critical_filled = 0;
|
||||
static sigset_t critical_prot = {0};
|
||||
sigset_t old_sig = {0};
|
||||
if(!critical_filled) {
|
||||
critical_filled = 1;
|
||||
sigfillset(&critical_prot);
|
||||
sigdelset(&critical_prot, SIGSEGV);
|
||||
sigdelset(&critical_prot, SIGILL);
|
||||
sigdelset(&critical_prot, SIGBUS);
|
||||
sigdelset(&critical_prot, SIGINT);
|
||||
sigdelset(&critical_prot, SIGABRT);
|
||||
sigdelset(&critical_prot, SIGFPE);
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &critical_prot, &old_sig);
|
||||
|
||||
if(BOX64ENV(dynarec_wait)) {
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
} else {
|
||||
if(mutex_trylock(&my_context->mutex_dyndump)) { // FillBlock not available for now
|
||||
pthread_sigmask(SIG_SETMASK, &old_sig, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dynarec_log(LOG_DEBUG, "Will call Fillblock64 for Alt %p\n", (void*)addr);
|
||||
dynablock_t* block = FillBlock64(addr, is32bits, MAX_INSTS, 0, 1);
|
||||
|
||||
mutex_unlock(&my_context->mutex_dyndump);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &old_sig, NULL);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/*
|
||||
return NULL if block is not found / cannot be created.
|
||||
Don't create if create==0
|
||||
@@ -243,6 +294,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
|
||||
if(BOX64ENV(nodynarec_delay) && (addr>=BOX64ENV(nodynarec_start)) && (addr<BOX64ENV(nodynarec_end)))
|
||||
return NULL;
|
||||
dynablock_t* block = getDB(addr);
|
||||
if(block && block->to_delete) {
|
||||
// just delete the block then, so we can create a new one right away
|
||||
FreeDynablock(block, 1, 1);
|
||||
block = NULL;
|
||||
}
|
||||
if(block || !create) {
|
||||
if(block && getNeedTest(addr) && (getProtection(block->x64_readaddr)&req_prot)!=req_prot)
|
||||
block = NULL;
|
||||
@@ -276,6 +332,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
|
||||
}
|
||||
}
|
||||
block = getDB(addr); // just in case
|
||||
if(block && block->to_delete) {
|
||||
// just delete the block then, so we can create a new one right away
|
||||
FreeDynablock(block, 0, 1);
|
||||
block = NULL;
|
||||
}
|
||||
if(block) {
|
||||
if(block && getNeedTest(addr) && (getProtection_fast(block->x64_readaddr)&req_prot)!=req_prot)
|
||||
block = NULL;
|
||||
@@ -284,7 +345,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, int create
|
||||
return block;
|
||||
}
|
||||
}
|
||||
block = FillBlock64(addr, is32bits, MAX_INSTS, is_new);
|
||||
block = FillBlock64(addr, is32bits, MAX_INSTS, is_new, 0);
|
||||
if(!block) {
|
||||
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
|
||||
}
|
||||
@@ -330,7 +391,7 @@ dynablock_t* DBSwapInvalid(x64emu_t* emu, dynablock_t* db, uintptr_t addr, int i
|
||||
if(need_lock)
|
||||
mutex_lock(&my_context->mutex_dyndump);
|
||||
db->done = 0; // invalidating the block
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, (void*)addr);
|
||||
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X, gone:%d, autocrc:%d, to_delete:%d) for %p\n", db, db->x64_addr, db->x64_addr+db->x64_size, db->hash, db->gone, db->autocrc, db->to_delete, (void*)addr);
|
||||
// Free db, it's now invalid!
|
||||
dynablock_t* old = InvalidDynablock(db, 0);
|
||||
if(old->previous) {
|
||||
|
||||
@@ -35,6 +35,8 @@ typedef struct dynablock_s {
|
||||
uint8_t dirty; // if need to be tested as soon as it's created
|
||||
uint8_t always_test:2;
|
||||
uint8_t is32bits:1;
|
||||
uint8_t autocrc:1;
|
||||
uint8_t to_delete:1;
|
||||
int callret_size; // size of the array
|
||||
int isize;
|
||||
int arch_size; // size of of arch dependant infos
|
||||
|
||||
+54
-1
@@ -104,6 +104,31 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
//dynablock_t *father = block->father?block->father:block;
|
||||
return jblock;
|
||||
}
|
||||
void* LinkNextInvalid(x64emu_t* emu, uintptr_t addr, void* x2, uintptr_t* x3)
|
||||
{
|
||||
// like LinkNext, but invalid the db found first
|
||||
int is32bits = (R_CS == 0x23);
|
||||
dynablock_t* db = getDB(addr);
|
||||
if(db) {
|
||||
if(db->previous && !db->dirty && X31_hash_code(db->previous->x64_addr, db->previous->x64_size)==db->previous->hash)
|
||||
db = DBSwitchPrevious(emu, db, addr, 1);
|
||||
else
|
||||
db = DBSwapInvalid(emu, db, addr, is32bits, 1);
|
||||
if(db && db->done && db->block) {
|
||||
void* jblock = db->block;
|
||||
if(db->sep_size && (uintptr_t)db->x64_addr!=addr) {
|
||||
jblock = NULL; // not sure how this would happens here, but lets put the case it starts on SEP anyway
|
||||
for(int i=0; i<db->sep_size && !jblock; ++i) {
|
||||
if(addr==(uintptr_t)db->x64_addr + db->sep[i].x64_offs)
|
||||
jblock = db->block + db->sep[i].nat_offs;
|
||||
}
|
||||
}
|
||||
if(jblock)
|
||||
return jblock;
|
||||
}
|
||||
}
|
||||
return LinkNext(emu, addr, x2, x3);
|
||||
}
|
||||
#endif
|
||||
|
||||
void DynaCall(x64emu_t* emu, uintptr_t addr, int no_alt)
|
||||
@@ -162,6 +187,21 @@ static dynablock_t* fastDBGetBlock(x64emu_t* emu, uintptr_t addr, int create, in
|
||||
ret = DBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ALTJUMP
|
||||
static dynablock_t* getDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits)
|
||||
{
|
||||
dynablock_t* ret = getAlternateData((void*)addr);
|
||||
if(ret == (void*)-1LL)
|
||||
return NULL;
|
||||
if(!ret) {
|
||||
ret = CreateDBnoAlt(emu, addr, is32bits);
|
||||
setAlternateData((void*)addr, ret);
|
||||
}
|
||||
dynarec_log(LOG_DEBUG, "Will use No-Alt block %p for Alt %p\n", ret, (void*)addr);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
|
||||
@@ -202,7 +242,14 @@ void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
|
||||
if(emu->flags.need_jmpbuf)
|
||||
emu->flags.need_jmpbuf = 0;
|
||||
if(no_alt)
|
||||
{ no_alt = 0; skip = 1;} // the Dynarec will shadow the Entry Point, so using Intperter to enter the function
|
||||
{
|
||||
// the Dynarec will shadow the Entry Point, so using Intperter to enter the function
|
||||
#if defined(DYNAREC) && defined(HAVE_ALTJUMP)
|
||||
if(!BOX64ENV(dynarec))
|
||||
#endif
|
||||
no_alt = 0;
|
||||
skip = 1;
|
||||
}
|
||||
else
|
||||
R_RIP = (uintptr_t)getAlternate((void*)R_RIP);
|
||||
#ifdef DYNAREC
|
||||
@@ -228,6 +275,12 @@ void EmuRun(x64emu_t* emu, int use_dynarec, int no_alt)
|
||||
}
|
||||
}
|
||||
dynablock_t* block = (skip || ACCESS_FLAG(F_TF))?NULL:fastDBGetBlock(emu, R_RIP, 1, is32bits);
|
||||
#ifdef HAVE_ALTJUMP
|
||||
if(skip && no_alt) {
|
||||
block = getDBnoAlt(emu, R_RIP, is32bits);
|
||||
no_alt = 0;
|
||||
}
|
||||
#endif
|
||||
if(!block || !block->block || !block->done || ACCESS_FLAG(F_TF)) {
|
||||
// no block, or block doesn't have DynaRec content (yet, temp is not null)
|
||||
// Use interpreter (should use single instruction step...)
|
||||
|
||||
@@ -37,6 +37,9 @@ extern uint32_t arm64_x31_hash(void* p, uint32_t len);
|
||||
#define ARCH_CRC(A, B) if(cpuext.crc32) return arm64_crc(A, B); else return arm64_x31_hash(A, B)
|
||||
extern void* create_updateflags();
|
||||
#define ARCH_UPDATEFLAGS() create_updateflags()
|
||||
#define ADDITIONNAL_CHECKS() additionnal_checks(dyn, ninst);
|
||||
#define ARCH_CRC_INLINE
|
||||
extern void arm64_next_invalid();
|
||||
|
||||
#define ARCH_NOP 0b11010101000000110010000000011111
|
||||
#define ARCH_UDF 0xcafe
|
||||
@@ -70,8 +73,16 @@ extern void* create_updateflags();
|
||||
#define STOP_NATIVE_FLAGS(A, B) {}
|
||||
#define ARCH_UNALIGNED(A, B) 0
|
||||
extern uint32_t la64_crc(void* p, uint32_t len);
|
||||
extern void la64_crc_autocrc(); // same as la64_crc, but not using regular ABI
|
||||
#define ARCH_CRC(A, B) return la64_crc(A, B)
|
||||
|
||||
#define ARCH_NOP (0b0000001101<<22)
|
||||
#define ARCH_UDF 0b1010100
|
||||
|
||||
#define JMPNEXT_SIZE (4*sizeof(void*))
|
||||
#define ADDITIONNAL_CHECKS()
|
||||
#define ARCH_CRC_INLINE
|
||||
extern void la64_next_invalid();
|
||||
|
||||
#elif defined(RV64)
|
||||
|
||||
@@ -104,7 +115,12 @@ extern uint32_t la64_crc(void* p, uint32_t len);
|
||||
#define ARCH_ADJUST(A, B, C, D) {}
|
||||
#define STOP_NATIVE_FLAGS(A, B) {}
|
||||
#define ARCH_UNALIGNED(A, B) arch_unaligned(A, B)
|
||||
|
||||
#define ARCH_NOP 0b0010011
|
||||
#define ARCH_UDF 0xc0001073
|
||||
|
||||
#define JMPNEXT_SIZE (4*sizeof(void*))
|
||||
#define ADDITIONNAL_CHECKS()
|
||||
|
||||
#elif defined(PPC64LE)
|
||||
|
||||
@@ -143,6 +159,7 @@ extern uint32_t ppc64le_fast_hash(void* p, uint32_t len);
|
||||
// PPC64LE CreateJmpNext needs 5 instructions (20 bytes) for PC-relative load + branch,
|
||||
// so the jmpnext area needs 5 void* slots (40 bytes) instead of the default 4 (32 bytes).
|
||||
#define JMPNEXT_SIZE (5*sizeof(void*))
|
||||
#define ADDITIONNAL_CHECKS()
|
||||
|
||||
#else
|
||||
#error Unsupported platform
|
||||
|
||||
@@ -207,10 +207,16 @@
|
||||
#define SMDMB() DMB_ISH()
|
||||
#endif
|
||||
|
||||
#ifndef PREFLAGSNEEDED
|
||||
#define PREFLAGSNEEDED()
|
||||
#endif
|
||||
|
||||
#define AREFLAGSNEEDED() \
|
||||
PREFLAGSNEEDED() \
|
||||
if((dyn->insts[ninst].x64.need_before&~X_PEND) && (!ninst || dyn->insts[ninst-1].x64.has_callret)) { \
|
||||
READFLAGS(dyn->insts[ninst].x64.need_before&~X_PEND); \
|
||||
}
|
||||
} \
|
||||
ADDITIONNAL_CHECKS()
|
||||
|
||||
// Insert a Secondary Entry Point if it's asked, but only on block that are from file mapped memory (so some binary file)
|
||||
// and that are not flagged as always_test (as this could slow down a bit, and the block is unsafe), unless SEP level 2 is asked
|
||||
|
||||
@@ -419,7 +419,7 @@ dynablock_t* CreateEmptyBlock(uintptr_t addr, int is32bits, int is_new) {
|
||||
return block;
|
||||
}
|
||||
|
||||
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new) {
|
||||
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt) {
|
||||
/*
|
||||
A Block must have this layout:
|
||||
|
||||
@@ -437,7 +437,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
const uint32_t req_prot = (box64_pagesize==4096)?(PROT_EXEC|PROT_READ):PROT_READ;
|
||||
uintptr_t old_addr = addr;
|
||||
#ifdef HAVE_ALTJUMP
|
||||
uintptr_t altjump = getAlternateJump((void*)addr, is32bits);
|
||||
uintptr_t altjump = noalt?0:getAlternateJump((void*)addr, is32bits);
|
||||
if(altjump) {
|
||||
dynarec_log(LOG_INFO, "Building a Dynablock for %p with an alternate content at %p\n", (void*)addr, (void*)altjump);
|
||||
addr = altjump;
|
||||
@@ -487,6 +487,9 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
helper.next_cap = MAX_INSTS;
|
||||
helper.table64 = NULL;
|
||||
helper.env = GetCurEnvByAddr(addr);
|
||||
if(getProtection(addr)&PROT_NEVERCLEAN) {
|
||||
helper.always_test = 1;
|
||||
}
|
||||
ResetTable64(&helper);
|
||||
helper.table64cap = 0;
|
||||
helper.end = addr + SizeFileMapped(addr);
|
||||
@@ -740,7 +743,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
--imax;
|
||||
if(dyn->need_dump || BOX64ENV(dynarec_log))dynarec_log(LOG_NONE, "Dynablock oversized, with %zu (max=%zd), recomputing cutting at %d from %d\n", native_size, MAXBLOCK_SIZE, imax, helper.size);
|
||||
CancelBlock64(0);
|
||||
return FillBlock64(old_addr, is32bits, imax, is_new);
|
||||
return FillBlock64(old_addr, is32bits, imax, is_new, noalt);
|
||||
}
|
||||
insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
|
||||
insts_rsize = (insts_rsize+7)&~7; // round the size...
|
||||
@@ -789,6 +792,7 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
helper.sep = (sep_t*)seps;
|
||||
block->prefixsize = helper.prefixsize;
|
||||
block->table64 = helper.table64;
|
||||
helper.dynablock = block;
|
||||
if(callret_size)
|
||||
memcpy(helper.callrets, static_callrets, helper.callret_size*sizeof(callret_t));
|
||||
helper.callret_size = 0;
|
||||
@@ -831,7 +835,13 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
block->isize = helper.size;
|
||||
block->block = p;
|
||||
block->jmpnext = next+sizeof(void*);
|
||||
#ifdef ARCH_CRC_INLINE
|
||||
block->always_test = 0;
|
||||
block->autocrc = helper.always_test?1:0;
|
||||
#else
|
||||
block->always_test = helper.always_test;
|
||||
block->autocrc = 0;
|
||||
#endif
|
||||
block->dirty = block->always_test;
|
||||
block->is32bits = is32bits;
|
||||
block->relocsize = helper.reloc_size*sizeof(uint32_t);
|
||||
@@ -908,11 +918,13 @@ dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new)
|
||||
block->dirty = 1;
|
||||
//protectDB(addr, end-addr);
|
||||
}
|
||||
if(getProtection(addr)&PROT_NEVERCLEAN) {
|
||||
block->always_test = 1;
|
||||
}
|
||||
else if(is_inhotpage)
|
||||
#ifdef ARCH_CRC_INLINE
|
||||
if(is_inhotpage && !block->autocrc)
|
||||
block->always_test = 2;
|
||||
#else
|
||||
if(is_inhotpage)
|
||||
block->always_test = 2;
|
||||
#endif
|
||||
if(block->always_test) {
|
||||
dynarec_log(LOG_INFO, "Note: block marked as always dirty %p:%ld\n", block->x64_addr, block->x64_size);
|
||||
#ifdef ARCH_NOP
|
||||
|
||||
@@ -856,22 +856,60 @@ uint8_t geted_ib(dynarec_native_t* dyn, uintptr_t addr, int ninst, uint8_t nexto
|
||||
}
|
||||
#undef F8
|
||||
|
||||
void propagate_nodf(dynarec_native_t* dyn, int ninst)
|
||||
#if defined(ARM64) || defined(LA64) || defined(PPC64LE)
|
||||
static void propagate_dfneeded_internal(dynarec_native_t* dyn, int ninst)
|
||||
{
|
||||
while(ninst>=0) {
|
||||
if(dyn->insts[ninst].df_needed)
|
||||
return; // already flagged
|
||||
dyn->insts[ninst].df_needed = 1;
|
||||
if(dyn->insts[ninst].x64.gen_flags || (dyn->insts[ninst].x64.use_flags&X_PEND) || (dyn->insts[ninst].x64.need_before))
|
||||
return; // flags are use, we can stop propagate there
|
||||
if(!dyn->insts[ninst].pred_sz)
|
||||
return;
|
||||
for(int i=1; i<dyn->insts[ninst].pred_sz; ++i)
|
||||
propagate_dfneeded_internal(dyn, dyn->insts[ninst].pred[i]);
|
||||
ninst = dyn->insts[ninst].pred[0];
|
||||
}
|
||||
}
|
||||
|
||||
static void propagate_nodf_internal(dynarec_native_t* dyn, int ninst)
|
||||
{
|
||||
while(ninst>=0) {
|
||||
if(dyn->insts[ninst].df_needed)
|
||||
return; // flag are needed, stop
|
||||
if(dyn->insts[ninst].df_notneeded)
|
||||
return; // already flagged
|
||||
if(dyn->insts[ninst].x64.gen_flags || dyn->insts[ninst].x64.use_flags)
|
||||
return; // flags are use, so maybe it's needed
|
||||
if(dyn->insts[ninst].x64.has_callret || (dyn->insts[ninst].x64.barrier&BARRIER_FLAGS))
|
||||
return; // stop propagate
|
||||
dyn->insts[ninst].df_notneeded = 1;
|
||||
if(!dyn->insts[ninst].pred_sz)
|
||||
return;
|
||||
for(int i=1; i<dyn->insts[ninst].pred_sz; ++i)
|
||||
propagate_nodf(dyn, dyn->insts[ninst].pred[i]);
|
||||
propagate_nodf_internal(dyn, dyn->insts[ninst].pred[i]);
|
||||
ninst = dyn->insts[ninst].pred[0];
|
||||
}
|
||||
}
|
||||
|
||||
void propagate_nodf(dynarec_native_t* dyn)
|
||||
{
|
||||
// first propagate the df_needed flag
|
||||
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
|
||||
if((dyn->insts[ninst].x64.jmp && dyn->insts[ninst].x64.jmp_insts==-1)
|
||||
|| (dyn->insts[ninst].x64.barrier&BARRIER_FLAGS) || (dyn->insts[ninst].x64.use_flags)
|
||||
|| dyn->insts[ninst].x64.has_callret
|
||||
|| ((dyn->insts[ninst].x64.state_flags&SF_SUB) && dyn->insts[ninst].x64.need_before)
|
||||
)
|
||||
propagate_dfneeded_internal(dyn, ninst);
|
||||
}
|
||||
// and now propagete df_unneeded
|
||||
for(int ninst=dyn->size-1; ninst>=0; --ninst) {
|
||||
if(dyn->insts[ninst].f_exit!=status_unk && dyn->insts[ninst].x64.gen_flags)
|
||||
propagate_nodf_internal(dyn, ninst);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void x64disas_add_register_mapping_annotations(char* buf, const char* disas, const register_mapping_t* mappings, size_t mappings_sz)
|
||||
{
|
||||
static char tmp[32];
|
||||
|
||||
@@ -71,7 +71,7 @@ void native_div0(x64emu_t* emu);
|
||||
// Caches transformation (for loops) // Specific, need to be written par backend
|
||||
int CacheNeedsTransform(dynarec_native_t* dyn, int i1);
|
||||
// propagete defererd to unknow, as state is not needed
|
||||
void propagate_nodf(dynarec_native_t* dyn, int ninst);
|
||||
void propagate_nodf(dynarec_native_t* dyn);
|
||||
|
||||
// predecessor access
|
||||
int isPred(dynarec_native_t* dyn, int ninst, int pred);
|
||||
|
||||
@@ -127,10 +127,17 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
|
||||
if(!ninst) {
|
||||
if(dyn->have_purge)
|
||||
doEnterBlock(dyn, 0, x1, x2, x3);
|
||||
if(dyn->always_test)
|
||||
checkCRC(dyn, 0);
|
||||
if(dyn->insts[0].preload_xmmymm)
|
||||
doPreload(dyn, 0);
|
||||
ENDPREFIX;
|
||||
}
|
||||
#elif defined(LA64)
|
||||
if(!ninst) {
|
||||
if(dyn->always_test)
|
||||
checkCRC(dyn, 0);
|
||||
}
|
||||
#endif
|
||||
fpu_propagate_stack(dyn, ninst);
|
||||
if (reset_n!=-1) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "callback.h"
|
||||
#include "bridge.h"
|
||||
#include "emu/x64run_private.h"
|
||||
#include "../dynablock_private.h"
|
||||
#include "x64trace.h"
|
||||
#include "dynarec_native.h"
|
||||
#include "custommem.h"
|
||||
@@ -787,7 +788,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
GETGD;
|
||||
GETED(4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x4, i64);
|
||||
MOV64x(x4, i64);
|
||||
CLEAR_FLAGS(x3);
|
||||
if (rex.w) {
|
||||
UFLAG_IF {
|
||||
@@ -3381,7 +3382,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
// Push actual return address
|
||||
if (addr < (dyn->start + dyn->isize)) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI_D(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
@@ -3403,6 +3407,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
else
|
||||
j64 = addr + i32;
|
||||
jump_to_next(dyn, j64, 0, ninst, rex.is32bits);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
CALLRET_RET(can_continue);
|
||||
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
|
||||
// jumps out of current dynablock...
|
||||
MARK;
|
||||
@@ -3416,6 +3422,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
LD_D(x4, x4, 0);
|
||||
BR(x4);
|
||||
}
|
||||
CLEARIP();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -4016,7 +4023,10 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
// Push actual return address
|
||||
if (addr < (dyn->start + dyn->isize)) {
|
||||
// there is a next
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI_D(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
@@ -4032,6 +4042,8 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
PUSH1z(xRIP);
|
||||
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
CALLRET_RET(can_continue);
|
||||
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
|
||||
// jumps out of current dynablock...
|
||||
MARK;
|
||||
@@ -4041,6 +4053,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
LD_D(x4, x4, 0);
|
||||
BR(x4);
|
||||
}
|
||||
CLEARIP();
|
||||
break;
|
||||
case 3: // CALL FAR Ed
|
||||
if (MODREG) {
|
||||
@@ -4063,17 +4076,24 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
*ok = 0;
|
||||
}
|
||||
GETIP_(addr, x7);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address. Note that CS will not be tested, but that should be ok?
|
||||
if (addr < (dyn->start + dyn->isize)) {
|
||||
if (can_continue) {
|
||||
// there is a next...
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0;
|
||||
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI_D(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
} else {
|
||||
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
|
||||
PCADDU12I(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI_D(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
@@ -4091,6 +4111,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
ST_H(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
|
||||
CALLRET_RET(can_continue);
|
||||
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
|
||||
// jumps out of current dynablock...
|
||||
MARK;
|
||||
|
||||
@@ -928,7 +928,25 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
nextop = F8;
|
||||
GETEX(q0, 0, 0);
|
||||
GETGX(v0, 1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(v1, q0, v0, cUN);
|
||||
VFCMP_S(d0, v0, v0, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(d1, x5);
|
||||
VOR_V(d1, v0, d1);
|
||||
}
|
||||
VFADD_S(v0, v0, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(v0, v0, d1, d0);
|
||||
VFCMP_S(d0, v0, v0, cUN);
|
||||
VANDN_V(v1, v1, d0);
|
||||
VLDI(d0, 0b011111111100);
|
||||
VSLLI_W(d0, d0, 20);
|
||||
VBITSEL_V(v0, v0, d0, v1);
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
INST_NAME("MULPS Gx, Ex");
|
||||
@@ -938,17 +956,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(v0, q0, q1, cUN);
|
||||
VFCMP_S(d0, q1, q1, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(v1, x5);
|
||||
VOR_V(v1, q1, v1);
|
||||
}
|
||||
VFMUL_S(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, v1, d0);
|
||||
VFCMP_S(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
|
||||
VLDI(v1, 0b011111111100);
|
||||
VSLLI_W(v1, v1, 20);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -973,17 +995,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(v0, q0, q1, cUN);
|
||||
VFCMP_S(d0, q1, q1, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(v1, x5);
|
||||
VOR_V(v1, q1, v1);
|
||||
}
|
||||
VFSUB_S(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, v1, d0);
|
||||
VFCMP_S(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
|
||||
VLDI(v1, 0b011111111100);
|
||||
VSLLI_W(v1, v1, 20);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -1003,17 +1029,21 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(v0, q0, q1, cUN);
|
||||
VFCMP_S(d0, q1, q1, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(v1, x5);
|
||||
VOR_V(v1, q1, v1);
|
||||
}
|
||||
VFDIV_S(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, v1, d0);
|
||||
VFCMP_S(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111100); // broadcast 0xFFFFFFFFFFFFFFFC
|
||||
VLDI(v1, 0b011111111100);
|
||||
VSLLI_W(v1, v1, 20);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -1966,13 +1996,16 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
BNE_MARK(ed, xZR);
|
||||
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
|
||||
}
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
CTZxw(gd, ed);
|
||||
MARK2;
|
||||
IFX (BOX64DRENV(dynarec_safeflags)) {
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
|
||||
}
|
||||
MARK2;
|
||||
SPILL_EFLAGS();
|
||||
break;
|
||||
case 0xBD:
|
||||
@@ -1993,15 +2026,18 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
}
|
||||
BNE_MARK(ed, xZR);
|
||||
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
|
||||
}
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
CLZxw(gd, ed);
|
||||
ADDI_D(x1, xZR, rex.w ? 63 : 31);
|
||||
SUB_D(gd, x1, gd);
|
||||
MARK2;
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
|
||||
}
|
||||
MARK2;
|
||||
SPILL_EFLAGS();
|
||||
break;
|
||||
case 0xBE:
|
||||
@@ -2060,8 +2096,8 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
GETED(0);
|
||||
if (ed != gd) MV(x7, ed);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
|
||||
if (ed != gd) MVxw(gd, x7);
|
||||
WBACK;
|
||||
if (ed != gd) MVxw(gd, x7);
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPS Gx, Ex, Ib");
|
||||
|
||||
@@ -1367,8 +1367,8 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
} else {
|
||||
addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 0, 1);
|
||||
}
|
||||
MV(x2, xRDX);
|
||||
MV(x4, xRAX);
|
||||
SEXT_W(x2, xRDX);
|
||||
SEXT_W(x4, xRAX);
|
||||
u8 = F8;
|
||||
MOV32w(x5, u8);
|
||||
CALL6(const_sse42_compare_string_explicit_len, x1, ed, x2, x3, x4, x5, 0);
|
||||
@@ -1541,17 +1541,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q0, q1, cUN);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q1, q0, cUN);
|
||||
VFCMP_D(d0, q1, q1, cUN);
|
||||
VLDI(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(d1, d1, 48);
|
||||
VOR_V(d1, q1, d1);
|
||||
}
|
||||
VFADD_D(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, d1, d0);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -1562,17 +1567,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q0, q1, cUN);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q1, q0, cUN);
|
||||
VFCMP_D(d0, q1, q1, cUN);
|
||||
VLDI(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(d1, d1, 48);
|
||||
VOR_V(d1, q1, d1);
|
||||
}
|
||||
VFMUL_D(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, d1, d0);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -1621,17 +1631,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q0, q1, cUN);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q1, q0, cUN);
|
||||
VFCMP_D(d0, q1, q1, cUN);
|
||||
VLDI(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(d1, d1, 48);
|
||||
VOR_V(d1, q1, d1);
|
||||
}
|
||||
VFSUB_D(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, d1, d0);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -1654,17 +1669,22 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q0, q1, cUN);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(v0, q1, q0, cUN);
|
||||
VFCMP_D(d0, q1, q1, cUN);
|
||||
VLDI(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(d1, d1, 48);
|
||||
VOR_V(d1, q1, d1);
|
||||
}
|
||||
VFDIV_D(q1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q1, q1, d1, d0);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -2044,13 +2064,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
VFADD_D(q1, d0, q1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(d1, d0, d0, cUN);
|
||||
VLDI(v1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VOR_V(d0, d0, v1);
|
||||
VBITSEL_V(q1, q1, d0, d1);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x7D:
|
||||
@@ -2068,13 +2092,17 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
VFSUB_D(q1, d0, q1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(d1, d0, d0, cUN);
|
||||
VLDI(v1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VOR_V(d0, d0, v1);
|
||||
VBITSEL_V(q1, q1, d0, d1);
|
||||
VFCMP_D(v1, q1, q1, cUN);
|
||||
VANDN_V(v0, v0, v1);
|
||||
VLDI(v1, 0b011111111000); // broadcast 0xFFFFFFFFFFFFFFF8
|
||||
VLDI(v1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(v1, v1, 48);
|
||||
VAND_V(v1, v0, v1);
|
||||
VANDN_V(v0, v0, q1);
|
||||
VOR_V(q1, v0, v1);
|
||||
VBITSEL_V(q1, q1, v1, v0);
|
||||
}
|
||||
break;
|
||||
case 0x7E:
|
||||
@@ -2503,16 +2531,19 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETGWEW(x4, x5, 0);
|
||||
BNE_MARK(ed, xZR);
|
||||
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
|
||||
}
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
|
||||
BSTRINS_D(xFlags, xZR, F_ZF, F_ZF);
|
||||
CTZ_D(gd, ed);
|
||||
GWBACK;
|
||||
MARK2;
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
|
||||
}
|
||||
MARK2;
|
||||
IFX (X_ALL) SPILL_EFLAGS();
|
||||
break;
|
||||
case 0xBD:
|
||||
@@ -2527,6 +2558,9 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETGWEW(x4, x5, 0);
|
||||
BNE_MARK(ed, xZR);
|
||||
IFX (X_ZF) ORI(xFlags, xFlags, 1 << F_ZF);
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) ORI(xFlags, xFlags, 1 << F_PF);
|
||||
}
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
IFXA (X_ZF, !BOX64DRENV(dynarec_safeflags))
|
||||
@@ -2535,10 +2569,10 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
ADDI_D(x1, xZR, 63);
|
||||
SUB_D(gd, x1, gd);
|
||||
GWBACK;
|
||||
MARK2;
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x1, x2);
|
||||
}
|
||||
MARK2;
|
||||
IFX (X_ALL) SPILL_EFLAGS();
|
||||
break;
|
||||
case 0xBE:
|
||||
@@ -2671,10 +2705,28 @@ uintptr_t dynarec64_660F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
d2 = fpu_get_scratch(dyn);
|
||||
VFCMP_D(d0, q0, q1, cUN);
|
||||
VFCMP_D(d1, q0, q0, cUN);
|
||||
VLDI(d2, (0b011 << 10) | 0b0000001000);
|
||||
VSLLI_D(d2, d2, 48);
|
||||
VOR_V(d2, q0, d2);
|
||||
}
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFSUB_D(v0, q0, q1);
|
||||
VFADD_D(q0, q0, q1);
|
||||
VEXTRINS_D(q0, v0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q0, q0, d2, d1);
|
||||
VFCMP_D(d2, q0, q0, cUN);
|
||||
VANDN_V(d0, d0, d2);
|
||||
VLDI(d2, (0b011 << 10) | 0b1111111000);
|
||||
VSLLI_D(d2, d2, 48);
|
||||
VBITSEL_V(q0, q0, d2, d0);
|
||||
}
|
||||
break;
|
||||
case 0xD1:
|
||||
INST_NAME("PSRLW Gx, Ex");
|
||||
|
||||
@@ -381,7 +381,7 @@ uintptr_t dynarec64_66F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
IFXORNAT (X_ALL | X_PEND) {
|
||||
BSTRPICK_D(x6, x1, 15, 0);
|
||||
emit_add16(dyn, ninst, x6, gd, x3, x4, x5);
|
||||
emit_add16(dyn, ninst, x6, x5, x3, x4, x7);
|
||||
}
|
||||
BSTRINS_D(gd, x1, 15, 0);
|
||||
}
|
||||
|
||||
@@ -354,14 +354,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, d0, v1, v2, cUN);
|
||||
VFCMPxy(S, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, q1, q1, 20);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFADDxy(S, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -372,14 +379,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, d0, v1, v2, cUN);
|
||||
VFCMPxy(S, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, q1, q1, 20);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFMULxy(S, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -425,14 +439,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, d0, v1, v2, cUN);
|
||||
VFCMPxy(S, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, q1, q1, 20);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFSUBxy(S, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -452,14 +473,21 @@ uintptr_t dynarec64_AVX_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, in
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, d0, v1, v2, cUN);
|
||||
VFCMPxy(S, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, q1, q1, 20);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFDIVxy(S, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -78,6 +78,9 @@ uintptr_t dynarec64_AVX_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
BNEZ(gd, 8);
|
||||
ORI(xFlags, xFlags, 1 << F_ZF);
|
||||
}
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
IFX (X_PF) emit_pf(dyn, ninst, gd, x2, x5);
|
||||
}
|
||||
SPILL_EFLAGS();
|
||||
break;
|
||||
case 0xF3:
|
||||
@@ -199,7 +202,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
break;
|
||||
|
||||
case 0xF7:
|
||||
INST_NAME("BEXTR Gd, Vd, Ed");
|
||||
INST_NAME("BEXTR Gd, Ed, Vd");
|
||||
nextop = F8;
|
||||
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
|
||||
GETGD;
|
||||
|
||||
@@ -327,14 +327,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, d0, v1, v2, cUN);
|
||||
VFCMPxy(D, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, q1, q1, 48);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFADDxy(D, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -345,14 +352,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, d0, v1, v2, cUN);
|
||||
VFCMPxy(D, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, q1, q1, 48);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFMULxy(D, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -420,14 +434,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, d0, v1, v2, cUN);
|
||||
VFCMPxy(D, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, q1, q1, 48);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFSUBxy(D, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -447,14 +468,21 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, d0, v1, v2, cUN);
|
||||
VFCMPxy(D, q0, v1, v1, cUN);
|
||||
VLDIxy(q1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, q1, q1, 48);
|
||||
VOR_Vxy(q1, v1, q1);
|
||||
}
|
||||
VFDIVxy(D, v0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, q1, q0);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -793,10 +821,16 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
}
|
||||
VFADDxy(D, v0, q0, v0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, q1, q0, q0, cUN);
|
||||
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VOR_Vxy(d1, q0, d1);
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -814,10 +848,16 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
}
|
||||
VFSUBxy(D, v0, q0, v0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, q1, q0, q0, cUN);
|
||||
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VOR_Vxy(d1, q0, d1);
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -945,17 +985,23 @@ uintptr_t dynarec64_AVX_66_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(D, d0, v1, v2, cUN);
|
||||
VFCMPxy(D, q1, v1, v1, cUN);
|
||||
VLDIxy(d1, (0b011 << 10) | 0b0000001000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VOR_Vxy(d1, v1, d1);
|
||||
}
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFSUBxy(D, q0, v1, v2);
|
||||
VFADDxy(D, v0, v1, v2);
|
||||
VEXTRINSxy(D, v0, q0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(D, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b011 << 9) | 0b111111000);
|
||||
VSLLIxy(D, d1, d1, 48); // broadcast 0xfff8000000000000
|
||||
VLDIxy(d1, (0b011 << 10) | 0b1111111000);
|
||||
VSLLIxy(D, d1, d1, 48);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -220,13 +220,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FADD_D(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_D(v0, d0, 0);
|
||||
break;
|
||||
@@ -239,13 +246,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMUL_D(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_D(v0, d0, 0);
|
||||
break;
|
||||
@@ -269,13 +283,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FSUB_D(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_D(v0, d0, 0);
|
||||
break;
|
||||
@@ -304,13 +325,20 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FDIV_D(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_D(v0, d0, 0);
|
||||
break;
|
||||
@@ -358,10 +386,16 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
}
|
||||
VFADDxy(S, v0, q0, v0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, q1, q0, q0, cUN);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VOR_Vxy(d1, q0, d1);
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -379,10 +413,16 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
}
|
||||
VFSUBxy(S, v0, q0, v0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, q1, q0, q0, cUN);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VOR_Vxy(d1, q0, d1);
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -422,7 +462,12 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
VFCMPxy(S, d0, v1, v2, cUN);
|
||||
VFCMPxy(S, q1, v1, v1, cUN);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b0000000100);
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VOR_Vxy(d1, v1, d1);
|
||||
}
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
VFSUBxy(S, q0, v1, v2);
|
||||
@@ -430,10 +475,11 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(0, 0));
|
||||
VEXTRINSxy(W, v0, q0, VEXTRINS_IMM_4_0(2, 2));
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VFCMPxy(S, d1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, d1);
|
||||
VBITSEL_Vxy(v0, v0, d1, q1);
|
||||
VFCMPxy(S, q1, v0, v0, cUN);
|
||||
VANDN_Vxy(d0, d0, q1);
|
||||
VLDIxy(d1, (0b010 << 9) | 0b1111111100);
|
||||
VSLLIxy(W, d1, d1, 20); // broadcast 0xFFC00000
|
||||
VSLLIxy(W, d1, d1, 20);
|
||||
VBITSEL_Vxy(v0, v0, d1, d0);
|
||||
}
|
||||
break;
|
||||
@@ -445,21 +491,23 @@ uintptr_t dynarec64_AVX_F2_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
u8 = sse_setround(dyn, ninst, x1, x2);
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
if (vex.l) {
|
||||
XVXOR_V(d0, d0, d0);
|
||||
XVFTINT_W_D(v0, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
|
||||
if (!BOX64ENV(dynarec_fastround)) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
q1 = fpu_get_scratch(dyn);
|
||||
q2 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
XVFTINT_L_D(q2, v1);
|
||||
XVFCMP_D(d1, v1, v1, cUN); // get NaN mask
|
||||
}
|
||||
XVXOR_V(d0, d0, d0);
|
||||
XVFTINT_W_D(v0, d0, v1); // v0 [lo0, lo1, --, --, hi0, hi1, --, -- ]
|
||||
if (!BOX64ENV(dynarec_fastround)) {
|
||||
XVLDI(q0, 0b1001110000000); // broadcast 0x80000000 to all
|
||||
MOV32w(x5, 0x7FFFFFFF);
|
||||
BSTRPICK_D(x5, x5, 31, 0);
|
||||
XVREPLGR2VR_D(q1, x5);
|
||||
XVFCMP_D(d0, v1, v1, cUN); // get Nan mask
|
||||
XVSLT_D(d1, q1, q2); // get +inf mask
|
||||
XVOR_V(d0, d1, d0);
|
||||
XVSLT_D(d0, q1, q2); // get +inf mask
|
||||
XVOR_V(d0, d0, d1); // combine with NaN mask
|
||||
XVSRLNI_W_D(d0, d0, 0); // [A,B,C,D] => [a,b,--,--,c,d,--,--]
|
||||
XVBITSEL_V(v0, v0, q0, d0);
|
||||
}
|
||||
|
||||
@@ -242,13 +242,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FADD_S(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_S(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_W(v0, d0, 0);
|
||||
break;
|
||||
@@ -266,8 +273,15 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
FCMP_S(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d0, d0);
|
||||
MARK;
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_S(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_W(v0, d0, 0);
|
||||
break;
|
||||
@@ -325,13 +339,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FSUB_S(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_S(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_W(v0, d0, 0);
|
||||
break;
|
||||
@@ -356,13 +377,20 @@ uintptr_t dynarec64_AVX_F3_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FDIV_S(d0, v1, v2);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v1, v2, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v1);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_S(fcc0, v1, v1, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
if (v0 != v1) VOR_V(v0, v1, v1);
|
||||
VEXTRINS_W(v0, d0, 0);
|
||||
break;
|
||||
|
||||
@@ -78,6 +78,8 @@ uintptr_t getConst(la64_consts_t which)
|
||||
case const_native_fstp: return (uintptr_t)native_fstp;
|
||||
case const_native_frstor: return (uintptr_t)native_frstor;
|
||||
case const_native_next: return (uintptr_t)native_next;
|
||||
case const_native_next_invalid: return (uintptr_t)la64_next_invalid;
|
||||
case const_la64_crc_autocrc: return (uintptr_t)la64_crc_autocrc;
|
||||
case const_int3: return (uintptr_t)EmuInt3;
|
||||
case const_x86syscall: return (uintptr_t)EmuX86Syscall;
|
||||
case const_x64syscall: return (uintptr_t)EmuX64Syscall;
|
||||
|
||||
@@ -48,6 +48,8 @@ typedef enum la64_consts_s {
|
||||
const_native_fstp,
|
||||
const_native_frstor,
|
||||
const_native_next,
|
||||
const_native_next_invalid,
|
||||
const_la64_crc_autocrc,
|
||||
const_int3,
|
||||
const_x86syscall,
|
||||
const_x64syscall,
|
||||
|
||||
@@ -1675,7 +1675,7 @@ void emit_dec32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
|
||||
}
|
||||
}
|
||||
IFX (X_SF) {
|
||||
BSTRPICK_D(s5, s1, 31, 31);
|
||||
BSTRPICK_D(s5, s1, rex.w ? 63 : 31, rex.w ? 63 : 31);
|
||||
BSTRINS_D(xFlags, s5, F_SF, F_SF);
|
||||
}
|
||||
if (!rex.w) ZEROUP(s1);
|
||||
|
||||
@@ -58,6 +58,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
if (cpuext.lam_bh) {
|
||||
AMADD_DB_B(x1, gd, wback);
|
||||
ANDI(x1, x1, 0xff);
|
||||
} else {
|
||||
LOCK_8_OP(ADD_D(x4, x1, gd), x1, wback, x3, x4, x5, x6);
|
||||
}
|
||||
@@ -1132,6 +1133,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
INST_NAME("LOCK ADC Ed, Ib");
|
||||
}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
|
||||
if (cpuext.lbt) {
|
||||
@@ -1192,6 +1194,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
} else {
|
||||
INST_NAME("LOCK SBB Ed, Ib");
|
||||
}
|
||||
READFLAGS(X_CF);
|
||||
SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, (opcode == 0x81) ? 4 : 1);
|
||||
if (cpuext.lbt) {
|
||||
@@ -1524,7 +1527,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
if (cpuext.lamcas) {
|
||||
LD_WU(x1, wback, 0);
|
||||
SUB_W(x4, xZR, x1);
|
||||
MV(x6, x1);
|
||||
SEXT_W(x6, x1);
|
||||
AMCAS_DB_W(x1, x4, wback);
|
||||
BNE(x6, x1, -4 * 3);
|
||||
} else {
|
||||
@@ -1573,6 +1576,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
if (cpuext.lam_bh) {
|
||||
AMADD_DB_B(x1, x7, wback);
|
||||
ANDI(x1, x1, 0xff);
|
||||
} else {
|
||||
LOCK_8_OP(ADD_D(x4, x1, x7), x1, wback, x3, x4, x5, x6);
|
||||
}
|
||||
@@ -1594,6 +1598,7 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
|
||||
if (cpuext.lam_bh) {
|
||||
AMADD_DB_B(x1, x7, wback);
|
||||
ANDI(x1, x1, 0xff);
|
||||
} else {
|
||||
LOCK_8_OP(ADD_D(x4, x1, x7), x1, wback, x3, x4, x5, x6);
|
||||
}
|
||||
|
||||
@@ -220,13 +220,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FADD_D(d0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v0, v1, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v0, v0, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -237,13 +244,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FMUL_D(d0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v0, v1, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v0, v0, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -263,13 +277,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FSUB_D(d0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v0, v1, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v0, v0, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -293,13 +314,20 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
FDIV_D(d0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
FCMP_D(fcc0, v0, v1, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_D(fcc1, d0, d0, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_D(d0, d0);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV64x(x5, 0x0008000000000000LL);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(d1, x4);
|
||||
FCMP_D(fcc0, v0, v0, cUN);
|
||||
FSEL(d0, d0, d1, fcc0);
|
||||
}
|
||||
MARK;
|
||||
VEXTRINS_D(v0, d0, 0); // v0[63:0] = d0[63:0]
|
||||
break;
|
||||
case 0x5F:
|
||||
@@ -339,7 +367,24 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VPICKEV_W(v0, q1, q0);
|
||||
VPICKOD_W(v1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(d0, v0, v0, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(d1, x5);
|
||||
VOR_V(d1, v0, d1);
|
||||
}
|
||||
VFADD_S(q0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q0, q0, d1, d0);
|
||||
VFCMP_S(d1, q0, q0, cUN);
|
||||
VFCMP_S(d0, v0, v1, cUN);
|
||||
VANDN_V(d0, d0, d1);
|
||||
VLDI(d1, 0b011111111100);
|
||||
VSLLI_W(d1, d1, 20);
|
||||
VBITSEL_V(q0, q0, d1, d0);
|
||||
}
|
||||
break;
|
||||
case 0x7D:
|
||||
INST_NAME("HSUBPS Gx, Ex");
|
||||
@@ -350,7 +395,24 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VPICKEV_W(v0, q1, q0);
|
||||
VPICKOD_W(v1, q1, q0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(d0, v0, v0, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(d1, x5);
|
||||
VOR_V(d1, v0, d1);
|
||||
}
|
||||
VFSUB_S(q0, v0, v1);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q0, q0, d1, d0);
|
||||
VFCMP_S(d1, q0, q0, cUN);
|
||||
VFCMP_S(d0, v0, v1, cUN);
|
||||
VANDN_V(d0, d0, d1);
|
||||
VLDI(d1, 0b011111111100);
|
||||
VSLLI_W(d1, d1, 20);
|
||||
VBITSEL_V(q0, q0, d1, d0);
|
||||
}
|
||||
break;
|
||||
case 0xAE:
|
||||
nextop = F8;
|
||||
@@ -391,11 +453,29 @@ uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
nextop = F8;
|
||||
GETGX(q0, 1);
|
||||
GETEX(q1, 0, 0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
d0 = fpu_get_scratch(dyn);
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
v1 = fpu_get_scratch(dyn);
|
||||
VFCMP_S(d0, q0, q1, cUN);
|
||||
VFCMP_S(d1, q0, q0, cUN);
|
||||
MOV32w(x5, 0x00400000);
|
||||
VREPLGR2VR_W(v1, x5);
|
||||
VOR_V(v1, q0, v1);
|
||||
}
|
||||
v0 = fpu_get_scratch(dyn);
|
||||
VFSUB_S(v0, q0, q1);
|
||||
VFADD_S(q0, q0, q1);
|
||||
VEXTRINS_W(q0, v0, 0);
|
||||
VEXTRINS_W(q0, v0, 0b00100010);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
VBITSEL_V(q0, q0, v1, d1);
|
||||
VFCMP_S(d1, q0, q0, cUN);
|
||||
VANDN_V(d0, d0, d1);
|
||||
VLDI(d1, 0b011111111100);
|
||||
VSLLI_W(d1, d1, 20);
|
||||
VBITSEL_V(q0, q0, d1, d0);
|
||||
}
|
||||
break;
|
||||
case 0xD6:
|
||||
INST_NAME("MOVDQ2Q Gm, Ex");
|
||||
|
||||
@@ -308,6 +308,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FADD_S(d1, v0, d0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v0, d0, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d1, d1, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d1, d1);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(q0, x4);
|
||||
FCMP_S(fcc0, v0, v0, cUN);
|
||||
FSEL(d1, d1, q0, fcc0);
|
||||
}
|
||||
VEXTRINS_W(v0, d1, 0);
|
||||
break;
|
||||
case 0x59:
|
||||
@@ -317,6 +332,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FMUL_S(d1, v0, d0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v0, d0, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d1, d1, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d1, d1);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(q0, x4);
|
||||
FCMP_S(fcc0, v0, v0, cUN);
|
||||
FSEL(d1, d1, q0, fcc0);
|
||||
}
|
||||
VEXTRINS_W(v0, d1, 0);
|
||||
break;
|
||||
case 0x5A:
|
||||
@@ -360,6 +390,21 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
d1 = fpu_get_scratch(dyn);
|
||||
GETEXSS(d0, 0, 0);
|
||||
FSUB_S(d1, v0, d0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v0, d0, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d1, d1, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d1, d1);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(q0, x4);
|
||||
FCMP_S(fcc0, v0, v0, cUN);
|
||||
FSEL(d1, d1, q0, fcc0);
|
||||
}
|
||||
VEXTRINS_W(v0, d1, 0);
|
||||
break;
|
||||
case 0x5D:
|
||||
@@ -380,13 +425,20 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETEXSS(d0, 0, 0);
|
||||
FDIV_S(d1, v0, d0);
|
||||
if (!BOX64ENV(dynarec_fastnan)) {
|
||||
q0 = fpu_get_scratch(dyn);
|
||||
FCMP_S(fcc0, v0, d0, cUN);
|
||||
BCNEZ_MARK(fcc0);
|
||||
FCMP_S(fcc1, d1, d1, cOR);
|
||||
BCNEZ_MARK(fcc1);
|
||||
FNEG_S(d1, d1);
|
||||
MARK;
|
||||
MOVFR2GR_D(x4, v0);
|
||||
MOV32w(x5, 0x00400000);
|
||||
OR(x4, x4, x5);
|
||||
MOVGR2FR_D(q0, x4);
|
||||
FCMP_S(fcc0, v0, v0, cUN);
|
||||
FSEL(d1, d1, q0, fcc0);
|
||||
}
|
||||
MARK;
|
||||
VEXTRINS_W(v0, d1, 0);
|
||||
break;
|
||||
case 0x5F:
|
||||
|
||||
@@ -2280,3 +2280,24 @@ void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val)
|
||||
}
|
||||
LU52I_D(reg, reg, (val >> 52) & 0xfff);
|
||||
}
|
||||
|
||||
|
||||
void checkCRC(dynarec_la64_t* dyn, int ninst)
|
||||
{
|
||||
// la64_crc_autocrc will use x1-x5 instead of A0-A4 to avoind having to move around the regs
|
||||
// grab the dynablock address in x6, as this on will not be erased by crc functions
|
||||
int delta = -(dyn->native_size + sizeof(void*));
|
||||
PCADDU12I(x6, SPLIT20(delta));
|
||||
LD_D(x6, x6, SPLIT12(delta));
|
||||
// prepare and call the crc function
|
||||
TABLE64C(x3, const_la64_crc_autocrc);
|
||||
LD_D(x1, x6, offsetof(dynablock_t, x64_addr));
|
||||
LD_WU(x2, x6, offsetof(dynablock_t, x64_size));
|
||||
JIRL(xRA, x3, 0x0);
|
||||
// done, result in x1, load the stored hash (sign extended, as the crc will also be sign extended)
|
||||
LD_W(x2, x6, offsetof(dynablock_t, hash));
|
||||
// compare computed crc with stored one, jump to continue is equal
|
||||
BEQ(x1, x2, 4+3*4); // TABLE64C generates 2 opcodes...
|
||||
TABLE64C(x3, const_native_next_invalid);
|
||||
JIRL(xRA, x3, 0x0);
|
||||
}
|
||||
@@ -1028,6 +1028,15 @@
|
||||
#ifndef SET_HASCALLRET
|
||||
#define SET_HASCALLRET()
|
||||
#endif
|
||||
#ifndef CALLRET_RET
|
||||
#define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0)
|
||||
#endif
|
||||
#ifndef CALLRET_GETRET
|
||||
#define CALLRET_GETRET() (dyn->callrets?(dyn->callrets[dyn->callret_size].offs-dyn->native_size):0)
|
||||
#endif
|
||||
#ifndef CALLRET_LOOP
|
||||
#define CALLRET_LOOP() NOP()
|
||||
#endif
|
||||
#define UFLAG_OP1(A) \
|
||||
if (dyn->insts[ninst].x64.gen_flags) { SDxw(A, xEmu, offsetof(x64emu_t, op1)); }
|
||||
#define UFLAG_OP2(A) \
|
||||
@@ -1066,6 +1075,11 @@
|
||||
|
||||
#define ARCH_RESET()
|
||||
|
||||
#undef PREFLAGSNEEDED
|
||||
#define PREFLAGSNEEDED() \
|
||||
if(dyn->always_test && ninst && (dyn->insts[ninst].sep || (ninst && dyn->insts[ninst-1].x64.has_callret))) \
|
||||
checkCRC(dyn, ninst);
|
||||
|
||||
#if STEP < 2
|
||||
#define GETIP(A, scratch)
|
||||
#define GETIP_(A, scratch)
|
||||
@@ -1310,7 +1324,6 @@
|
||||
#define avx_reflect_reg_upper128 STEPNAME(avx_reflect_reg_upper128)
|
||||
#define avx_cleancache STEPNAME(avx_cleancache)
|
||||
|
||||
|
||||
#define fpu_pushcache STEPNAME(fpu_pushcache)
|
||||
#define fpu_popcache STEPNAME(fpu_popcache)
|
||||
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
|
||||
@@ -1320,6 +1333,8 @@
|
||||
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
|
||||
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
|
||||
|
||||
#define checkCRC STEPNAME(checkCRC)
|
||||
|
||||
#define CacheTransform STEPNAME(CacheTransform)
|
||||
#define la64_move64 STEPNAME(la64_move64)
|
||||
#define la64_move32 STEPNAME(la64_move32)
|
||||
@@ -1530,6 +1545,9 @@ void avx_reflect_reg(dynarec_la64_t* dyn, int ninst, int a);
|
||||
void avx_reflect_reg_upper128(dynarec_la64_t* dyn, int ninst, int a, int forwrite);
|
||||
void avx_cleancache(dynarec_la64_t* dyn, int ninst);
|
||||
|
||||
// in case of always_test, this insert a check of crc of the dynablock (and exit to ArmNext if wrong)
|
||||
void checkCRC(dynarec_la64_t* dyn, int ninst);
|
||||
|
||||
void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
|
||||
|
||||
void la64_move64(dynarec_la64_t* dyn, int ninst, int reg, int64_t val);
|
||||
|
||||
@@ -57,3 +57,12 @@
|
||||
EMIT(0); \
|
||||
EMIT(0); \
|
||||
} while (0)
|
||||
#define CALLRET_RET(A) do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
|
||||
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
|
||||
} \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
|
||||
@@ -63,3 +63,21 @@
|
||||
PCADDU12I(A, SPLIT20(val64offset)); \
|
||||
LD_D(A, A, SPLIT12(val64offset)); \
|
||||
} while (0)
|
||||
#define CALLRET_RET(A) \
|
||||
do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
|
||||
MESSAGE(LOG_DUMP, " Dynablock*\n"); \
|
||||
dyn->block += sizeof(void*); \
|
||||
dyn->native_size+=sizeof(void*); \
|
||||
dyn->insts[ninst].size2 += sizeof(void*); \
|
||||
dyn->sep[dyn->sep_size].x64_offs = addr - dyn->start; \
|
||||
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
|
||||
++dyn->sep_size; \
|
||||
} \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; \
|
||||
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
|
||||
EMIT(ARCH_NOP); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
|
||||
@@ -110,7 +110,9 @@ typedef struct instruction_la64_s {
|
||||
uint8_t will_read:1; // [strongmem] will read from memory
|
||||
uint8_t last_write:1; // [strongmem] the last write in a SEQ
|
||||
uint8_t lock:1; // [strongmem] lock semantic
|
||||
uint8_t df_notneeded;
|
||||
uint8_t df_needed:1;
|
||||
uint8_t df_notneeded:1;
|
||||
uint8_t sep:1; // opcode is a secondary entry point
|
||||
uint8_t nat_flags_fusion:1;
|
||||
uint8_t nat_flags_nofusion:1;
|
||||
uint8_t nat_flags_carry:1;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
.global la64_lock_get_d
|
||||
.global la64_lock_get_dd
|
||||
.global la64_crc
|
||||
.global la64_crc_autocrc
|
||||
|
||||
la64_lock_xchg_b:
|
||||
.word 0x385e1486 // amswap_db.b $a2, $a1, $a0
|
||||
@@ -252,5 +253,27 @@ la64_crc:
|
||||
addi.d $a2, $a2, 1
|
||||
addi.w $a1, $a1, -1
|
||||
bnez $a1, 3b
|
||||
4:
|
||||
ret
|
||||
|
||||
la64_crc_autocrc:
|
||||
move $t4, $t2
|
||||
xor $t2, $t2, $t2
|
||||
li.d $t5, 8
|
||||
1:
|
||||
bltu $t3, $t5, 2f
|
||||
ld.d $t6, $t4, 0
|
||||
crc.w.d.w $t2, $t6, $t2
|
||||
addi.d $t4, $t4, 8
|
||||
addi.w $t3, $t3, -8
|
||||
bnez $t3, 1b
|
||||
2:
|
||||
beqz $t3, 4f
|
||||
3:
|
||||
ld.bu $t6, $t4, 0
|
||||
crc.w.b.w $t2, $t6, $t2
|
||||
addi.d $t4, $t4, 1
|
||||
addi.w $t3, $t3, -1
|
||||
bnez $t3, 3b
|
||||
4:
|
||||
ret
|
||||
@@ -11,8 +11,10 @@
|
||||
.align 4
|
||||
|
||||
.extern LinkNext
|
||||
.extern LinkNextInvalid
|
||||
|
||||
.global la64_next
|
||||
.global la64_next_invalid
|
||||
|
||||
.8byte 0 // NULL pointer before la64_next, for getDB
|
||||
la64_next:
|
||||
@@ -54,3 +56,43 @@ la64_next:
|
||||
addi.d $sp, $sp, (8 * 11)
|
||||
// return offset is jump address
|
||||
jr $r16
|
||||
|
||||
la64_next_invalid:
|
||||
// move emu to a0
|
||||
// move IP address to a1
|
||||
addi.d $sp, $sp, -(8 * 11)
|
||||
st.d RDI, $sp, 0
|
||||
st.d RSI, $sp, 8
|
||||
st.d RDX, $sp, 16
|
||||
st.d RCX, $sp, 24
|
||||
st.d R8, $sp, 32
|
||||
st.d R9, $sp, 40
|
||||
st.d RAX, $sp, 48
|
||||
st.d RBX, $sp, 56
|
||||
st.d RSP, $sp, 64
|
||||
st.d RBP, $sp, 72
|
||||
st.d RIP, $sp, 80 // also save r29(rip) to allow change in LinkNext
|
||||
|
||||
move $a0, Emu
|
||||
move $a1, RIP
|
||||
move $a2, $ra // "from" is in ra, so put in a2
|
||||
addi.d $a3, $sp, 80 // a3 is address to change rip
|
||||
// call the function
|
||||
bl LinkNextInvalid
|
||||
// preserve return value
|
||||
move $r16, $a0
|
||||
// pop regs
|
||||
ld.d RDI, $sp, 0
|
||||
ld.d RSI, $sp, 8
|
||||
ld.d RDX, $sp, 16
|
||||
ld.d RCX, $sp, 24
|
||||
ld.d R8, $sp, 32
|
||||
ld.d R9, $sp, 40
|
||||
ld.d RAX, $sp, 48
|
||||
ld.d RBX, $sp, 56
|
||||
ld.d RSP, $sp, 64
|
||||
ld.d RBP, $sp, 72
|
||||
ld.d RIP, $sp, 80
|
||||
addi.d $sp, $sp, (8 * 11)
|
||||
// return offset is jump address
|
||||
jr $r16
|
||||
@@ -539,7 +539,7 @@ uintptr_t dynarec64_00(dynarec_ppc64le_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETGD;
|
||||
GETED(4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x4, i64);
|
||||
MOV64x(x4, i64);
|
||||
CLEAR_FLAGS(x3);
|
||||
if (rex.w) {
|
||||
UFLAG_IF {
|
||||
|
||||
@@ -124,6 +124,7 @@ typedef struct instruction_ppc64le_s {
|
||||
uint8_t will_read:1; // [strongmem] will read from memory
|
||||
uint8_t last_write:1; // [strongmem] the last write in a SEQ
|
||||
uint8_t lock:1; // [strongmem] lock semantic
|
||||
uint8_t df_needed:1;
|
||||
uint8_t df_notneeded:1;
|
||||
uint8_t nat_flags_fusion:1;
|
||||
uint8_t nat_flags_nofusion:1;
|
||||
|
||||
@@ -226,7 +226,7 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETGD;
|
||||
GETED(4);
|
||||
i64 = F32S;
|
||||
MOV64xw(x4, i64);
|
||||
MOV64x(x4, i64);
|
||||
if (rex.w) {
|
||||
// 64bits imul
|
||||
UFLAG_IF {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "box64context.h"
|
||||
#include "box64cpu.h"
|
||||
#include "emu/x64emu_private.h"
|
||||
#include "../dynablock_private.h"
|
||||
#include "x64emu.h"
|
||||
#include "box64stack.h"
|
||||
#include "callback.h"
|
||||
@@ -37,6 +38,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
int64_t i64, j64;
|
||||
uint8_t u8;
|
||||
uint8_t gb1, gb2, eb1, eb2;
|
||||
uint16_t u16;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
uint8_t wback, wb1, wb2, wb;
|
||||
@@ -283,9 +285,16 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
READFLAGS(X_PEND); // lets play safe here too
|
||||
}
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
|
||||
i32 = F16;
|
||||
retn_to_epilog(dyn, ip, ninst, rex, i32);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
u16 = F16;
|
||||
POP1z(xRIP);
|
||||
if (u16 < 0x7ff)
|
||||
ADDIz(xRSP, xRSP, u16);
|
||||
else {
|
||||
MOV32w(x1, u16);
|
||||
ADDz(xRSP, xRSP, x1);
|
||||
}
|
||||
ret_to_next(dyn, ip, ninst, rex);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
@@ -295,8 +304,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
if (BOX64DRENV(dynarec_safeflags)) {
|
||||
READFLAGS(X_PEND); // so instead, force the deferred flags, so it's not too slow, and flags are not lost
|
||||
}
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
|
||||
ret_to_epilog(dyn, ip, ninst, rex);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
POP1z(xRIP);
|
||||
ret_to_next(dyn, ip, ninst, rex);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
@@ -432,7 +442,45 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
MVz(xRSP, xRBP);
|
||||
POP1z(xRBP);
|
||||
break;
|
||||
|
||||
case 0xCA:
|
||||
INST_NAME("FAR RETN");
|
||||
u16 = F16;
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
if (rex.w) {
|
||||
POP1(xRIP);
|
||||
POP1(x3);
|
||||
} else {
|
||||
POP1_32(xRIP);
|
||||
POP1_32(x3);
|
||||
}
|
||||
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
if (u16 < 2048)
|
||||
ADDIz(xRSP, xRSP, u16);
|
||||
else {
|
||||
MOV32w(x1, u16);
|
||||
ADDz(xRSP, xRSP, x1);
|
||||
}
|
||||
ret_to_next(dyn, ip, ninst, rex);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 0xCB:
|
||||
INST_NAME("FAR RET");
|
||||
READFLAGS(X_PEND);
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
if (rex.w) {
|
||||
POP1(xRIP);
|
||||
POP1(x3);
|
||||
} else {
|
||||
POP1_32(xRIP);
|
||||
POP1_32(x3);
|
||||
}
|
||||
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
ret_to_next(dyn, ip, ninst, rex);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
case 0xCC:
|
||||
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack, set all flags (to an unknown state...)
|
||||
SKIPTEST(x1);
|
||||
@@ -559,7 +607,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
INST_NAME("IRET");
|
||||
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
iret_to_epilog(dyn, ip, ninst, rex.w);
|
||||
iret_to_next(dyn, ip, ninst, rex.is32bits, rex.w);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
break;
|
||||
@@ -1093,13 +1141,25 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
}
|
||||
fpu_purgecache(dyn, ninst, 1, x1, x3, x4);
|
||||
PUSH1z(x2);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
|
||||
AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
if(can_continue) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
}
|
||||
ADDI(xSP, xSP, -16);
|
||||
SD(x4, xSP, 0);
|
||||
SD(x2, xSP, 8);
|
||||
@@ -1112,10 +1172,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
else
|
||||
j64 = addr + i32;
|
||||
jump_to_next(dyn, j64, 0, ninst, rex.is32bits);
|
||||
CALLRET_RET(can_continue);
|
||||
MARK;
|
||||
if (BOX64DRENV(dynarec_callret) && dyn->vector_sew != VECTOR_SEWNA)
|
||||
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
|
||||
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
|
||||
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
|
||||
if (BOX64DRENV(dynarec_callret) && !can_continue) {
|
||||
// jumps out of current dynablock...
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
if (dyn->need_reloc) {
|
||||
@@ -1127,6 +1188,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
LD(x4, x4, 0);
|
||||
BR(x4);
|
||||
}
|
||||
CLEARIP();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1649,27 +1711,108 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
|
||||
GETIP_(addr, x7);
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
SET_HASCALLRET();
|
||||
j64 = (dyn->insts) ? (GETMARK - (dyn->native_size)) : 0;
|
||||
AUIPC(x4, ((j64 + 0x800) >> 12) & 0xfffff);
|
||||
ADDI(x4, x4, j64 & 0xfff);
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64 >> 2);
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
}
|
||||
ADDI(xSP, xSP, -16);
|
||||
SD(x4, xSP, 0);
|
||||
SD(xRIP, xSP, 8);
|
||||
}
|
||||
PUSH1z(xRIP);
|
||||
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
CALLRET_RET(can_continue);
|
||||
MARK;
|
||||
if (BOX64DRENV(dynarec_callret) && dyn->vector_sew != VECTOR_SEWNA)
|
||||
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
|
||||
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
|
||||
if (BOX64DRENV(dynarec_callret) && addr >= (dyn->start + dyn->isize)) {
|
||||
if (BOX64DRENV(dynarec_callret) && !can_continue) {
|
||||
// jumps out of current dynablock...
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
if (dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
|
||||
if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
|
||||
TABLE64_(x4, j64);
|
||||
LD(x4, x4, 0);
|
||||
BR(x4);
|
||||
}
|
||||
CLEARIP();
|
||||
break;
|
||||
case 3: // CALL FAR Ed
|
||||
if(MODREG) {
|
||||
DEFAULT;
|
||||
} else {
|
||||
INST_NAME("CALL FAR Ed");
|
||||
PASS2IF ((BOX64DRENV(dynarec_safeflags) > 1) || ((ninst && dyn->insts[ninst - 1].x64.set_flags) || ((ninst > 1) && dyn->insts[ninst - 2].x64.set_flags)), 1) {
|
||||
READFLAGS(X_PEND); // that's suspicious
|
||||
} else {
|
||||
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Hack to put flag in "don't care" state
|
||||
}
|
||||
SMREAD();
|
||||
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0);
|
||||
LDz(x1, wback, 0);
|
||||
ed = x1;
|
||||
LHU(x3, wback, rex.w?8:4);
|
||||
LHU(x5, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
if (BOX64DRENV(dynarec_callret) && BOX64DRENV(dynarec_bigblock) > 1) {
|
||||
BARRIER(BARRIER_FULL);
|
||||
} else {
|
||||
BARRIER(BARRIER_FLOAT);
|
||||
*need_epilog = 0;
|
||||
*ok = 0;
|
||||
}
|
||||
GETIP_(addr, x7);
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
SET_HASCALLRET();
|
||||
// Push actual return address
|
||||
if(addr < (dyn->start+dyn->isize)) {
|
||||
// there is a next...
|
||||
if(BOX64DRENV(dynarec_callret)>1 && !dyn->always_test)
|
||||
j64 = CALLRET_GETRET();
|
||||
else
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
} else {
|
||||
j64 = (dyn->insts)?(GETMARK-(dyn->native_size)):0;
|
||||
AUIPC(x4, SPLIT20(j64));
|
||||
ADDI(x4, x4, SPLIT12(j64));
|
||||
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j64>>2);
|
||||
}
|
||||
ADDI(xSP, xSP, -16);
|
||||
SD(x4, xSP, 0);
|
||||
SD(xRIP, xSP, 8);
|
||||
}
|
||||
PUSH1z(x5);
|
||||
PUSH1z(xRIP);
|
||||
SH(x3, xEmu, offsetof(x64emu_t, segs[_CS]));
|
||||
jump_to_next(dyn, 0, ed, ninst, rex.is32bits);
|
||||
int can_continue = (addr < (dyn->start + dyn->isize));
|
||||
CALLRET_RET(can_continue);
|
||||
MARK;
|
||||
if (BOX64DRENV(dynarec_callret) && can_continue && dyn->vector_sew != VECTOR_SEWNA)
|
||||
vector_vsetvli(dyn, ninst, x3, dyn->vector_sew, VECTOR_LMUL1, 1);
|
||||
if (BOX64DRENV(dynarec_callret) && !can_continue) {
|
||||
// jumps out of current dynablock...
|
||||
j64 = getJumpTableAddress64(addr);
|
||||
if(dyn->need_reloc) AddRelocTable64RetEndBlock(dyn, ninst, addr, STEP);
|
||||
TABLE64_(x4, j64);
|
||||
LD(x4, x4, 0);
|
||||
BR(x4);
|
||||
}
|
||||
CLEARIP();
|
||||
}
|
||||
break;
|
||||
case 4: // JMP Ed
|
||||
INST_NAME("JMP Ed");
|
||||
|
||||
@@ -2460,9 +2460,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
|
||||
if (ed != gd)
|
||||
MV(x7, ed);
|
||||
emit_add32(dyn, ninst, rex, ed, gd, x4, x5, x6);
|
||||
if (ed != gd)
|
||||
MVxw(gd, x7);
|
||||
WBACK;
|
||||
if (ed != gd) MVxw(gd, x7);
|
||||
break;
|
||||
case 0xC2:
|
||||
INST_NAME("CMPPS Gx, Ex, Ib");
|
||||
|
||||
@@ -260,7 +260,11 @@ uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip,
|
||||
case 0x29:
|
||||
INST_NAME("MOVAPS Ex, Gx");
|
||||
nextop = F8;
|
||||
SET_ELEMENT_WIDTH(x1, VECTOR_SEWANY, 1);
|
||||
// on SteamRT3 with Gameoverlay, repear will crash immediatly on a Milk-V Pioneer machine
|
||||
// doing movaps xmmword ptr ss:[rsp+0x10], xmm4 with rsp that seems 4-bytes aligned
|
||||
// so changed VECTOR_SEWANY to VECTOR_SEW32 instead (to also be coherent with PS size)
|
||||
//TODO: check what is really happening here
|
||||
SET_ELEMENT_WIDTH(x1, VECTOR_SEW32, 1);
|
||||
GETGX_vector(v0, 0, dyn->vector_eew);
|
||||
if (MODREG) {
|
||||
ed = (nextop & 7) + (rex.b << 3);
|
||||
|
||||
@@ -487,19 +487,18 @@ void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
|
||||
#endif
|
||||
}
|
||||
|
||||
void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
|
||||
void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
|
||||
{
|
||||
MAYUSE(dyn);
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Ret to epilog\n");
|
||||
POP1z(xRIP);
|
||||
MESSAGE(LOG_DUMP, "Ret to next\n");
|
||||
MVz(x1, xRIP);
|
||||
SMEND();
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
// pop the actual return address from RV64 stack
|
||||
LD(xRA, xSP, 0); // native addr
|
||||
LD(x6, xSP, 8); // x86 addr
|
||||
ADDI(xSP, xSP, 16); // pop
|
||||
// pop the actual return address from LA64 stack
|
||||
LD(xRA, xSP, 0); // native addr
|
||||
LD(x6, xSP, 8); // x86 addr
|
||||
ADDI(xSP, xSP, 16); // pop
|
||||
BNE(x6, xRIP, 2 * 4); // is it the right address?
|
||||
BR(xRA);
|
||||
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
|
||||
@@ -512,43 +511,10 @@ void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
|
||||
CLEARIP();
|
||||
}
|
||||
|
||||
void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n)
|
||||
void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits)
|
||||
{
|
||||
MAYUSE(dyn);
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "Retn to epilog\n");
|
||||
POP1z(xRIP);
|
||||
if (n > 0x7ff) {
|
||||
MOV64x(x1, n);
|
||||
ADDz(xRSP, xRSP, x1);
|
||||
} else {
|
||||
ADDIz(xRSP, xRSP, n);
|
||||
}
|
||||
MVz(x1, xRIP);
|
||||
SMEND();
|
||||
if (BOX64DRENV(dynarec_callret)) {
|
||||
// pop the actual return address from RV64 stack
|
||||
LD(xRA, xSP, 0); // native addr
|
||||
LD(x6, xSP, 8); // x86 addr
|
||||
ADDI(xSP, xSP, 16); // pop
|
||||
BNE(x6, xRIP, 2 * 4); // is it the right address?
|
||||
BR(xRA);
|
||||
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
|
||||
LD(xSP, xEmu, offsetof(x64emu_t, xSPSave));
|
||||
ADDI(xSP, xSP, -16);
|
||||
}
|
||||
NOTEST(x2);
|
||||
int dest = indirect_lookup(dyn, ninst, rex.is32bits, x2, x3);
|
||||
BR(dest);
|
||||
CLEARIP();
|
||||
}
|
||||
|
||||
void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits)
|
||||
{
|
||||
// #warning TODO: is64bits
|
||||
MAYUSE(ninst);
|
||||
MESSAGE(LOG_DUMP, "IRet to epilog\n");
|
||||
NOTEST(x2);
|
||||
MESSAGE(LOG_DUMP, "IRet to next\n");
|
||||
if (is64bits) {
|
||||
POP1(xRIP);
|
||||
POP1(x2);
|
||||
@@ -579,13 +545,10 @@ void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits)
|
||||
// set new RSP
|
||||
MV(xRSP, x3);
|
||||
// Ret....
|
||||
// epilog on purpose, CS might have changed!
|
||||
if (dyn->need_reloc)
|
||||
TABLE64C(x2, const_epilog);
|
||||
else
|
||||
MOV64x(x2, getConst(const_epilog));
|
||||
SMEND();
|
||||
BR(x2);
|
||||
rex_t dummy = { 0 };
|
||||
dummy.is32bits = is32bits;
|
||||
dummy.w = is64bits;
|
||||
ret_to_next(dyn, ip, ninst, dummy);
|
||||
CLEARIP();
|
||||
}
|
||||
|
||||
|
||||
@@ -1096,6 +1096,15 @@
|
||||
#ifndef SET_HASCALLRET
|
||||
#define SET_HASCALLRET()
|
||||
#endif
|
||||
#ifndef CALLRET_RET
|
||||
#define CALLRET_RET(A) do {if(BOX64DRENV(dynarec_callret)>1) {NOP();}} while(0)
|
||||
#endif
|
||||
#ifndef CALLRET_GETRET
|
||||
#define CALLRET_GETRET() (dyn->callrets?(dyn->callrets[dyn->callret_size].offs-dyn->native_size):0)
|
||||
#endif
|
||||
#ifndef CALLRET_LOOP
|
||||
#define CALLRET_LOOP() NOP()
|
||||
#endif
|
||||
#define UFLAG_OP1(A) \
|
||||
if (dyn->insts[ninst].x64.gen_flags) { SDxw(A, xEmu, offsetof(x64emu_t, op1)); }
|
||||
#define UFLAG_OP2(A) \
|
||||
@@ -1253,9 +1262,8 @@
|
||||
#define jump_to_epilog STEPNAME(jump_to_epilog)
|
||||
#define jump_to_epilog_fast STEPNAME(jump_to_epilog_fast)
|
||||
#define jump_to_next STEPNAME(jump_to_next)
|
||||
#define ret_to_epilog STEPNAME(ret_to_epilog)
|
||||
#define retn_to_epilog STEPNAME(retn_to_epilog)
|
||||
#define iret_to_epilog STEPNAME(iret_to_epilog)
|
||||
#define ret_to_next STEPNAME(ret_to_next)
|
||||
#define iret_to_next STEPNAME(iret_to_next)
|
||||
#define call_c STEPNAME(call_c)
|
||||
#define call_n STEPNAME(call_n)
|
||||
#define grab_segdata STEPNAME(grab_segdata)
|
||||
@@ -1420,9 +1428,8 @@ uintptr_t geted16(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop
|
||||
void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
void jump_to_epilog_fast(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst);
|
||||
void jump_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst, int is32bits);
|
||||
void ret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex);
|
||||
void retn_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int n);
|
||||
void iret_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is64bits);
|
||||
void ret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, rex_t rex);
|
||||
void iret_to_next(dynarec_rv64_t* dyn, uintptr_t ip, int ninst, int is32bits, int is64bits);
|
||||
void call_c(dynarec_rv64_t* dyn, int ninst, rv64_consts_t fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
|
||||
void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w);
|
||||
void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
|
||||
|
||||
@@ -55,3 +55,12 @@
|
||||
EMIT(0); \
|
||||
EMIT(0); \
|
||||
} while (0)
|
||||
#define CALLRET_RET(A) do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) { \
|
||||
dyn->insts[ninst].size+=sizeof(void*); dyn->native_size+=sizeof(void*); dyn->insts[ninst+1].sep=1; ++dyn->sep_size; \
|
||||
} \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CALLRET_LOOP() do { dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
|
||||
@@ -78,3 +78,21 @@
|
||||
dynarec_log_prefix(0, LOG_NONE, "\n"); \
|
||||
} \
|
||||
return 0
|
||||
#define CALLRET_RET(A) \
|
||||
do { \
|
||||
if((A) && ISSEP() && BOX64DRENV(dynarec_callret)) {\
|
||||
MESSAGE(LOG_DUMP, " Dynablock*\n"); \
|
||||
dyn->block += sizeof(void*); \
|
||||
dyn->native_size+=sizeof(void*); \
|
||||
dyn->insts[ninst].size2 += sizeof(void*); \
|
||||
dyn->sep[dyn->sep_size].x64_offs = addr - dyn->start; \
|
||||
dyn->sep[dyn->sep_size].nat_offs = dyn->native_size; \
|
||||
++dyn->sep_size; \
|
||||
} \
|
||||
if((A) && (BOX64DRENV(dynarec_callret)>1) && !dyn->always_test) { \
|
||||
dyn->callrets[dyn->callret_size].type = 0; \
|
||||
dyn->callrets[dyn->callret_size++].offs = dyn->native_size; \
|
||||
EMIT(ARCH_NOP); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CALLRET_LOOP() do {dyn->callrets[dyn->callret_size].type = 1; dyn->callrets[dyn->callret_size++].offs = dyn->native_size; EMIT(ARCH_NOP); } while(0)
|
||||
@@ -121,7 +121,9 @@ typedef struct instruction_rv64_s {
|
||||
uint8_t will_read:1; // [strongmem] will read from memory
|
||||
uint8_t last_write:1; // [strongmem] the last write in a SEQ
|
||||
uint8_t lock:1; // [strongmem] lock semantic
|
||||
uint8_t df_notneeded;
|
||||
uint8_t df_needed:1;
|
||||
uint8_t df_notneeded:1;
|
||||
uint8_t sep:1; // opcode is a secondary entry point
|
||||
uint8_t nat_flags_fusion:1;
|
||||
uint8_t nat_flags_nofusion:1;
|
||||
uint8_t nat_flags_carry:1;
|
||||
|
||||
@@ -90,30 +90,6 @@
|
||||
|
||||
#define MODREG ((nextop&0xC0)==0xC0)
|
||||
|
||||
#if defined(__riscv)
|
||||
#define NAN_PROPAGATION(dest, src, break_or_continue) \
|
||||
if (isnan(dest)) { \
|
||||
break_or_continue; \
|
||||
} else if (isnan(src)) { \
|
||||
(dest) = (src); \
|
||||
break_or_continue; \
|
||||
}
|
||||
#else
|
||||
#define NAN_PROPAGATION(dest, src, break_or_continue)
|
||||
#endif
|
||||
|
||||
#define MARK_NAN_VF_2(A, B) for(int idx=0; idx<4; ++idx) mask_nan[idx] = isnanf(A->f[idx]) || isnanf(B->f[idx])
|
||||
#define CHECK_NAN_VF(A) for(int idx=0; idx<4; ++idx) if(!mask_nan[idx] && isnanf(A->f[idx])) A->f[idx] = -NAN
|
||||
|
||||
#define MARK_NAN_VD_2(A, B) for(int idx=0; idx<2; ++idx) mask_nan[idx] = isnan(A->d[idx]) || isnan(B->d[idx])
|
||||
#define CHECK_NAN_VD(A) for(int idx=0; idx<2; ++idx) if(!mask_nan[idx] && isnan(A->d[idx])) A->d[idx] = -NAN
|
||||
|
||||
#define MARK_NAN_F_2(A, B) is_nan = isnanf(A->f[0]) || isnanf(B->f[0])
|
||||
#define CHECK_NAN_F(A) if(!is_nan && isnanf(A->f[0])) A->f[0] = -NAN
|
||||
|
||||
#define MARK_NAN_D_2(A, B) is_nan = isnan(A->d[0]) || isnan(B->d[0])
|
||||
#define CHECK_NAN_D(A) if(!is_nan && isnan(A->d[0])) A->d[0] = -NAN
|
||||
|
||||
#define GOCOND(BASE, PREFIX, COND, NOTCOND, POST)\
|
||||
case BASE+0x0: \
|
||||
PREFIX \
|
||||
|
||||
@@ -53,10 +53,14 @@ uint32_t sse42_compare_string_explicit_len(x64emu_t* emu, sse_regs_t* mem, int l
|
||||
{
|
||||
// get number of packed byte/word
|
||||
int n_packed = (imm8&1)?8:16;
|
||||
if(lreg<0) lreg = -lreg;
|
||||
if(lmem<0) lmem = -lmem;
|
||||
if(lreg>n_packed) lreg = n_packed;
|
||||
if(lmem>n_packed) lmem = n_packed;
|
||||
if (lreg<-n_packed || lreg>n_packed)
|
||||
lreg = n_packed;
|
||||
else if (lreg<0)
|
||||
lreg = -lreg;
|
||||
if (lmem<-n_packed || lmem>n_packed)
|
||||
lmem = n_packed;
|
||||
else if (lmem<0)
|
||||
lmem = -lmem;
|
||||
// aggregate to intres1
|
||||
uint32_t intres1 = 0;
|
||||
switch((imm8>>2)&3) {
|
||||
|
||||
+1
-1
@@ -194,7 +194,7 @@ void x64Int3(x64emu_t* emu, uintptr_t* addr)
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (void*)(R_RSI));
|
||||
perr = 1;
|
||||
} else if (strstr(s, "mkdir")==s) {
|
||||
} else if (!strcmp(s, "mkdir")) {
|
||||
tmp = (char*)(R_RDI);
|
||||
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
|
||||
perr = 1;
|
||||
|
||||
+86
-14
@@ -485,6 +485,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
|
||||
} else if (w == WFpi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI);
|
||||
} else if (w == WFpW) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI);
|
||||
} else if (w == WFpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI);
|
||||
} else if (w == uFEp) {
|
||||
@@ -567,6 +569,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI);
|
||||
} else if (w == fFpu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI);
|
||||
} else if (w == fFpf) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0]);
|
||||
} else if (w == fFpL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI);
|
||||
} else if (w == fFpp) {
|
||||
@@ -687,6 +691,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI);
|
||||
} else if (w == pFuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI);
|
||||
} else if (w == pFud) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, emu->xmm[0].d[0]);
|
||||
} else if (w == pFul) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (intptr_t)R_RSI);
|
||||
} else if (w == pFuL) {
|
||||
@@ -885,8 +891,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, (void*)R_RSI, (void*)R_RDX);
|
||||
} else if (w == vFLup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX);
|
||||
} else if (w == vFLpi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
|
||||
} else if (w == vFLpL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX);
|
||||
} else if (w == vFLpp) {
|
||||
@@ -1157,6 +1161,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX);
|
||||
} else if (w == iFpuU) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint64_t)R_RDX);
|
||||
} else if (w == iFpuf) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].f[0]);
|
||||
} else if (w == iFpul) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX);
|
||||
} else if (w == iFpuL) {
|
||||
@@ -1347,6 +1353,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (int32_t)R_RDX);
|
||||
} else if (w == uFplu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (uint32_t)R_RDX);
|
||||
} else if (w == uFpLi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (int32_t)R_RDX);
|
||||
} else if (w == uFpLu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (uint32_t)R_RDX);
|
||||
} else if (w == uFpLL) {
|
||||
@@ -1365,6 +1373,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX);
|
||||
} else if (w == UFpup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX);
|
||||
} else if (w == UFpUU) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint64_t)R_RSI, (uint64_t)R_RDX);
|
||||
} else if (w == UFppi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
|
||||
} else if (w == fFuii) {
|
||||
@@ -1639,6 +1649,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX);
|
||||
} else if (w == pFpuf) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].f[0]);
|
||||
} else if (w == pFpud) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].d[0]);
|
||||
} else if (w == pFpul) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX);
|
||||
} else if (w == pFpuL) {
|
||||
@@ -2451,6 +2463,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == iFpppU) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX);
|
||||
} else if (w == iFpppd) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, emu->xmm[0].d[0]);
|
||||
} else if (w == iFpppL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
|
||||
} else if (w == iFpppp) {
|
||||
@@ -2495,8 +2509,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
|
||||
} else if (w == uFiiuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == uFiipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == uFifff) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0]);
|
||||
} else if (w == uFippp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == uFuipi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX);
|
||||
} else if (w == uFuuuu) {
|
||||
@@ -2537,8 +2555,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == uFpiii) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
|
||||
} else if (w == uFpiiu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == uFpiip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
|
||||
} else if (w == uFpiup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX);
|
||||
} else if (w == uFpipi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX);
|
||||
} else if (w == uFpipu) {
|
||||
@@ -2633,6 +2655,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
|
||||
} else if (w == UFppuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == dFppdd) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0]);
|
||||
} else if (w == dFpppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == lFEipV) {
|
||||
@@ -2713,6 +2737,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
|
||||
} else if (w == LFpipl) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (intptr_t)R_RCX);
|
||||
} else if (w == LFpipL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
|
||||
} else if (w == LFpCii) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX);
|
||||
} else if (w == LFpupL) {
|
||||
@@ -2777,6 +2803,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)(R_RSP + 8));
|
||||
} else if (w == pFEpCL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (uintptr_t)R_RDX);
|
||||
} else if (w == pFEplp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (void*)R_RDX);
|
||||
} else if (w == pFEppi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX);
|
||||
} else if (w == pFEppu) {
|
||||
@@ -2849,6 +2877,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0]);
|
||||
} else if (w == pFLiip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX);
|
||||
} else if (w == pFLupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == pFLLup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uintptr_t)R_RDI, (uintptr_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX);
|
||||
} else if (w == pFLLLL) {
|
||||
@@ -2883,8 +2913,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == pFpipd) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, emu->xmm[0].d[0]);
|
||||
} else if (w == pFpipL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX);
|
||||
} else if (w == pFpipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX);
|
||||
} else if (w == pFpCip) {
|
||||
@@ -3553,6 +3581,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8);
|
||||
} else if (w == iFpiuLi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uintptr_t)R_RCX, (int32_t)R_R8);
|
||||
} else if (w == iFpiupi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (int32_t)R_R8);
|
||||
} else if (w == iFpiupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == iFpiUpi) {
|
||||
@@ -3653,6 +3683,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], emu->xmm[2].f[0], emu->xmm[3].f[0]);
|
||||
} else if (w == iFpffpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].f[0], emu->xmm[1].f[0], (void*)R_RSI, (void*)R_RDX);
|
||||
} else if (w == iFpdddd) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0]);
|
||||
} else if (w == iFplupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi64 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (intptr_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == iFplluu) {
|
||||
@@ -3833,10 +3865,10 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (int32_t)R_R8);
|
||||
} else if (w == uFipupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFipLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFuiiii) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8);
|
||||
} else if (w == uFupLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFULCLL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu64 ", %" PRIu64 ", %" PRIu8 ", %" PRIu64 ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (uint64_t)R_RDI, (uintptr_t)R_RSI, (uint8_t)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8);
|
||||
} else if (w == uFULWLL) {
|
||||
@@ -3871,6 +3903,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFpupuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8);
|
||||
} else if (w == uFpupLp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFpuppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFpULuU) {
|
||||
@@ -3911,6 +3945,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uintptr_t)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFppLpu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8);
|
||||
} else if (w == uFppLpL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
|
||||
} else if (w == uFppLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (void*)R_R8);
|
||||
} else if (w == uFpppip) {
|
||||
@@ -3939,6 +3975,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
|
||||
} else if (w == dFlplpl) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi64 ", %" PRIp ", %" PRIi64 ", %" PRIp ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (intptr_t)R_RDI, (void*)R_RSI, (intptr_t)R_RDX, (void*)R_RCX, (intptr_t)R_R8);
|
||||
} else if (w == dFppddd) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIf ", %" PRIf ", %" PRIf ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0]);
|
||||
} else if (w == dFppppL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8);
|
||||
} else if (w == lFEippL) {
|
||||
@@ -4719,6 +4757,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
|
||||
} else if (w == iFpiuupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
} else if (w == iFpiupip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (int32_t)R_R8, (void*)R_R9);
|
||||
} else if (w == iFpipipi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (void*)R_R8, (int32_t)R_R9);
|
||||
} else if (w == iFpipipp) {
|
||||
@@ -5027,10 +5067,14 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
} else if (w == uFpuUppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint64_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
} else if (w == uFpupuup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
|
||||
} else if (w == uFpupupu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9);
|
||||
} else if (w == uFpupupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
} else if (w == uFpupppu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9);
|
||||
} else if (w == uFpupppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
|
||||
} else if (w == uFppiiii) {
|
||||
@@ -5223,6 +5267,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9);
|
||||
} else if (w == pFpupuui) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (int32_t)R_R9);
|
||||
} else if (w == pFpupuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9);
|
||||
} else if (w == pFpupuup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9);
|
||||
} else if (w == pFpuppip) {
|
||||
@@ -5687,12 +5733,14 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu16 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(uint16_t*)(R_RSP + 8));
|
||||
} else if (w == iFpWppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpuiiuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8));
|
||||
} else if (w == iFpuiCuCp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIu8 ", %" PRIu32 ", %" PRIu8 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (uint8_t)R_RCX, (uint32_t)R_R8, (uint8_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpuiuupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpuuuuup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpuuuupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpupuupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFpupuLpL) {
|
||||
@@ -5733,8 +5781,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8));
|
||||
} else if (w == iFppiiiip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFppiiuup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == iFppiiLll) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIi64 ", %" PRIi64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (uintptr_t)R_R8, (intptr_t)R_R9, *(intptr_t*)(R_RSP + 8));
|
||||
} else if (w == iFppiipii) {
|
||||
@@ -5915,6 +5961,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == pFuupupup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == pFudddduu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0], (uint32_t)R_RSI, (uint32_t)R_RDX);
|
||||
} else if (w == pFfiiiiid) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIf ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, emu->xmm[0].f[0], (int32_t)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, emu->xmm[1].d[0]);
|
||||
} else if (w == pFduuulul) {
|
||||
@@ -5979,6 +6027,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8));
|
||||
} else if (w == pFppuippp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8));
|
||||
} else if (w == pFppuuuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8));
|
||||
} else if (w == pFppuuupu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8));
|
||||
} else if (w == pFppuuupp) {
|
||||
@@ -6263,6 +6313,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu8 ", %" PRIu8 ", %" PRIu16 ", %" PRIu16 ", %" PRIp ", %" PRIu16 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint8_t)R_RSI, (uint8_t)R_RDX, (uint16_t)R_RCX, (uint16_t)R_R8, (void*)R_R9, *(uint16_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
|
||||
} else if (w == iFpWCuWCuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu16 ", %" PRIu8 ", %" PRIu32 ", %" PRIu16 ", %" PRIu8 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint16_t)R_RSI, (uint8_t)R_RDX, (uint32_t)R_RCX, (uint16_t)R_R8, (uint8_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
|
||||
} else if (w == iFpuiiipip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFpuiipppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFpuippLpp) {
|
||||
@@ -6277,6 +6329,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16));
|
||||
} else if (w == iFpuuuuuup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFpuuuuppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFpuuupupu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
|
||||
} else if (w == iFpuupuupp) {
|
||||
@@ -6315,8 +6369,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
|
||||
} else if (w == iFpLpppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFppiiipip) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFppillppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi64 ", %" PRIi64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (intptr_t)R_RCX, (intptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFppipiipi) {
|
||||
@@ -6455,8 +6507,12 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == pFpuuuupup) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == pFpudddduu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIf ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, emu->xmm[0].d[0], emu->xmm[1].d[0], emu->xmm[2].d[0], emu->xmm[3].d[0], (uint32_t)R_RDX, (uint32_t)R_RCX);
|
||||
} else if (w == pFpuLdiiLi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu64 ", %" PRIf ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uintptr_t)R_RDX, emu->xmm[0].d[0], (int32_t)R_RCX, (int32_t)R_R8, (uintptr_t)R_R9, *(int32_t*)(R_RSP + 8));
|
||||
} else if (w == pFpupupuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16));
|
||||
} else if (w == pFpupLLLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == pFpupppppp) {
|
||||
@@ -6621,6 +6677,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
|
||||
} else if (w == vFpppiiiipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == vFpppuuuuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
|
||||
} else if (w == vFpppUupppU) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint64_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(uint64_t*)(R_RSP + 24));
|
||||
} else if (w == vFpppffffff) {
|
||||
@@ -6647,6 +6705,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFEppplPPPP) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (intptr_t)R_RCX, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32));
|
||||
} else if (w == iFEpppLpLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFEppppLppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16));
|
||||
} else if (w == iFEpppppupp) {
|
||||
@@ -6753,6 +6813,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIu32 ", %" PRIu32 ", %" PRIi64 ", %" PRIp ", %" PRIi32 ", %" PRIu32 ", %" PRIi32 ", %" PRIu32 ", %" PRIf ")", tid, *(void**)(R_RSP), func, (uint32_t)R_RDI, (uint32_t)R_RSI, (intptr_t)R_RDX, (void*)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(int32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), emu->xmm[0].f[0]);
|
||||
} else if (w == uFpuupuppuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
|
||||
} else if (w == uFpLiipLLLp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(uintptr_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == uFppLpLuppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (uint32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == uFppppppppp) {
|
||||
@@ -6799,6 +6861,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
|
||||
} else if (w == pFpLppLLiLi) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIu64 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (uintptr_t)R_R9, *(int32_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24));
|
||||
} else if (w == pFppupupuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24));
|
||||
} else if (w == pFppupppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == pFpppiiiiii) {
|
||||
@@ -6929,6 +6993,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (int32_t)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == iFEppLuppupp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == iFEppppLpppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (uintptr_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == iFEppppppipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(int32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24));
|
||||
} else if (w == iFEpppppppip) {
|
||||
@@ -7113,6 +7179,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIu64 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIi32 ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uintptr_t)R_RCX, (uintptr_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(void**)(R_RSP + 24), *(int32_t*)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFpippupppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFpuuiiuuiiuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
|
||||
} else if (w == iFpuppppppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFpLipiiiippp) {
|
||||
@@ -7127,8 +7195,6 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (void*)R_RCX, (void*)R_R8, (uintptr_t)R_R9, *(uintptr_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(uint32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFppLLupppLpp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uintptr_t)R_RDX, (uintptr_t)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(uintptr_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFpppiiuuiiuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
|
||||
} else if (w == iFpppippppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == iFpppppiiuupp) {
|
||||
@@ -7159,6 +7225,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (uint32_t)R_RDX, (int32_t)R_RCX, (int32_t)R_R8, (void*)R_R9, *(uint32_t*)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(int32_t*)(R_RSP + 32));
|
||||
} else if (w == pFEpppppppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32));
|
||||
} else if (w == pFpupppppuuuu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(uint32_t*)(R_RSP + 24), *(uint32_t*)(R_RSP + 32), *(uint32_t*)(R_RSP + 40));
|
||||
} else if (w == pFpppppppuipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(uint32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40));
|
||||
} else if (w == pFppppppppppp) {
|
||||
@@ -7309,6 +7377,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (uint32_t)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == iFpippuuuiipppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(int32_t*)(R_RSP + 16), *(int32_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == iFpupiwwWWwwWWu) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIi32 ", %" PRIi16 ", %" PRIi16 ", %" PRIu16 ", %" PRIu16 ", %" PRIi16 ", %" PRIi16 ", %" PRIu16 ", %" PRIu16 ", %" PRIu32 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uint32_t)R_RSI, (void*)R_RDX, (int32_t)R_RCX, (int16_t)R_R8, (int16_t)R_R9, *(uint16_t*)(R_RSP + 8), *(uint16_t*)(R_RSP + 16), *(int16_t*)(R_RSP + 24), *(int16_t*)(R_RSP + 32), *(uint16_t*)(R_RSP + 40), *(uint16_t*)(R_RSP + 48), *(uint32_t*)(R_RSP + 56));
|
||||
} else if (w == iFpLLlliiLppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIu64 ", %" PRIu64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi32 ", %" PRIi32 ", %" PRIu64 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (uintptr_t)R_RSI, (uintptr_t)R_RDX, (intptr_t)R_RCX, (intptr_t)R_R8, (int32_t)R_R9, *(int32_t*)(R_RSP + 8), *(uintptr_t*)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == iFppppppLLLLupp) {
|
||||
@@ -7317,6 +7387,8 @@ void x64Print(x64emu_t* emu, char* buff, size_t buffsz, const char* func, int ti
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == uFippuuuulllipp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIi32 ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi32 ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (uint32_t)R_RCX, (uint32_t)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(intptr_t*)(R_RSP + 16), *(intptr_t*)(R_RSP + 24), *(intptr_t*)(R_RSP + 32), *(int32_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == uFpiipupLpLpLpL) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIi32 ", %" PRIi32 ", %" PRIp ", %" PRIu32 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ", %" PRIp ", %" PRIu64 ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (int32_t)R_RSI, (int32_t)R_RDX, (void*)R_RCX, (uint32_t)R_R8, (void*)R_R9, *(uintptr_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(uintptr_t*)(R_RSP + 24), *(void**)(R_RSP + 32), *(uintptr_t*)(R_RSP + 40), *(void**)(R_RSP + 48), *(uintptr_t*)(R_RSP + 56));
|
||||
} else if (w == uFpppppuupppppp) {
|
||||
snprintf(buff, buffsz, "%04d|%p: Calling %s(%" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIu32 ", %" PRIu32 ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ", %" PRIp ")", tid, *(void**)(R_RSP), func, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (uint32_t)R_R9, *(uint32_t*)(R_RSP + 8), *(void**)(R_RSP + 16), *(void**)(R_RSP + 24), *(void**)(R_RSP + 32), *(void**)(R_RSP + 40), *(void**)(R_RSP + 48), *(void**)(R_RSP + 56));
|
||||
} else if (w == LFEpLiiuuuiupLp) {
|
||||
|
||||
+34
-14
@@ -770,7 +770,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i)
|
||||
if (isnan(EX->f[i]))
|
||||
GX->f[i] = EX->f[i];
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
else
|
||||
GX->f[i] = (EX->f[i] < 0) ? (-NAN) : sqrtf(EX->f[i]);
|
||||
break;
|
||||
@@ -784,7 +784,7 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
else if (EX->f[i]<0)
|
||||
GX->f[i] = -NAN;
|
||||
else if (isnan(EX->f[i]))
|
||||
GX->f[i] = EX->f[i];
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
else if (isinf(EX->f[i]))
|
||||
GX->f[i] = 0.0;
|
||||
else
|
||||
@@ -832,9 +832,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i) {
|
||||
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
|
||||
GX->f[i] += EX->f[i];
|
||||
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
|
||||
if(isnanf(GX->f[i])) {
|
||||
GX->ud[i] |= 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] += EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x59: /* MULPS Gx, Ex */
|
||||
@@ -842,9 +847,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i) {
|
||||
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
|
||||
GX->f[i] *= EX->f[i];
|
||||
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
|
||||
if(isnanf(GX->f[i])) {
|
||||
GX->ud[i] |= 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] *= EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x5A: /* CVTPS2PD Gx, Ex */
|
||||
@@ -868,9 +878,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i) {
|
||||
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
|
||||
GX->f[i] -= EX->f[i];
|
||||
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
|
||||
if(isnanf(GX->f[i])) {
|
||||
GX->ud[i] |= 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] -= EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x5D: /* MINPS Gx, Ex */
|
||||
@@ -887,9 +902,14 @@ uintptr_t Run0F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for(int i=0; i<4; ++i) {
|
||||
maskps[i] = isnanf(GX->f[i]) || isnanf(EX->f[i]);
|
||||
GX->f[i] /= EX->f[i];
|
||||
if(isnanf(GX->f[i]) && !maskps[i]) GX->ud[i] |= 0x80000000;
|
||||
if(isnanf(GX->f[i])) {
|
||||
GX->ud[i] |= 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] /= EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x5F: /* MAXPS Gx, Ex */
|
||||
|
||||
+79
-43
@@ -1292,10 +1292,10 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(EX->d[i]<0.0) // on x86, default nan are negative
|
||||
GX->d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
|
||||
if(EX->d[i]<0.0)
|
||||
GX->d[i] = -NAN;
|
||||
else if(isnan(EX->d[i]))
|
||||
GX->d[i] = EX->d[i];
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
else
|
||||
GX->d[i] = sqrt(EX->d[i]);
|
||||
}
|
||||
@@ -1333,21 +1333,31 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_VD_2(GX, EX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GX->d[i] += EX->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(GX->d[i])) {
|
||||
GX->q[i] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] += EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
break;
|
||||
case 0x59: /* MULPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_VD_2(GX, EX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GX->d[i] *= EX->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(GX->d[i])) {
|
||||
GX->q[i] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] *= EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
break;
|
||||
case 0x5A: /* CVTPD2PS Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -1394,11 +1404,16 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_VD_2(GX, EX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GX->d[i] -= EX->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(GX->d[i])) {
|
||||
GX->q[i] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] -= EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
break;
|
||||
case 0x5D: /* MINPD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -1414,10 +1429,14 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
for (int i=0; i<2; ++i) {
|
||||
is_nan = isnan(GX->d[i]) || isnan(EX->d[i]);
|
||||
GX->d[i] /= EX->d[i];
|
||||
if(!is_nan && isnan(GX->d[i]))
|
||||
GX->d[i] = -NAN;
|
||||
if(isnan(GX->d[i])) {
|
||||
GX->q[i] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] /= EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x5F: /* MAXPD Gx, Ex */
|
||||
@@ -1738,34 +1757,50 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
|
||||
GX->d[0] += GX->d[1];
|
||||
if(!is_nan && isnan(GX->d[0]))
|
||||
GX->d[0] = -NAN;
|
||||
if(EX==GX) {
|
||||
GX->d[1] = GX->d[0];
|
||||
if(isnan(GX->d[0])) {
|
||||
GX->q[0] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(GX->d[1])) {
|
||||
GX->q[0] = GX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
|
||||
GX->d[1] = EX->d[0] + EX->d[1];
|
||||
if(!is_nan && isnan(GX->d[1]))
|
||||
GX->d[1] = -NAN;
|
||||
GX->d[0] += GX->d[1];
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EX==GX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
if(isnan(EX->d[0])) {
|
||||
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[1])) {
|
||||
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[1] = EX->d[0] + EX->d[1];
|
||||
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x7D: /* HSUBPD Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
|
||||
GX->d[0] -= GX->d[1];
|
||||
if(!is_nan && isnan(GX->d[0]))
|
||||
GX->d[0] = -NAN;
|
||||
if(EX==GX) {
|
||||
GX->d[1] = GX->d[0];
|
||||
if(isnan(GX->d[0])) {
|
||||
GX->q[0] |= 0x0008000000000000ULL;
|
||||
} else if(isnan(GX->d[1])) {
|
||||
GX->q[0] = GX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
|
||||
GX->d[1] = EX->d[0] - EX->d[1];
|
||||
if(!is_nan && isnan(GX->d[1]))
|
||||
GX->d[1] = -NAN;
|
||||
GX->d[0] -= GX->d[1];
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EX==GX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
if(isnan(EX->d[0])) {
|
||||
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[1])) {
|
||||
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[1] = EX->d[0] - EX->d[1];
|
||||
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x7E: /* MOVD Ed, Gx */
|
||||
@@ -2284,10 +2319,11 @@ uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_VD_2(GX, EX);
|
||||
GX->d[0] -= EX->d[0];
|
||||
GX->d[1] += EX->d[1];
|
||||
CHECK_NAN_VD(GX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[i])) GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
else { if(i==0) GX->d[0] -= EX->d[0]; else GX->d[1] += EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; }
|
||||
}
|
||||
break;
|
||||
case 0xD1: /* PSRLW Gx, Ex */
|
||||
nextop = F8;
|
||||
|
||||
+14
-11
@@ -39,6 +39,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
uint32_t tmp32u, tmp32u2;
|
||||
int64_t tmp64s;
|
||||
uint64_t tmp64u, tmp64u2;
|
||||
x64flags_t eflags;
|
||||
reg64_t *oped, *opgd;
|
||||
#ifdef USE_CAS
|
||||
uint64_t tmpcas;
|
||||
@@ -280,7 +281,7 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
break;
|
||||
|
||||
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
|
||||
#define GO(B, OP) \
|
||||
#define GO(B, OP, F) \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
if(MODREG) { \
|
||||
@@ -289,13 +290,15 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
} \
|
||||
GETEW(0); \
|
||||
GETGW; \
|
||||
if(F) {CHECK_FLAGS(emu); eflags=emu->eflags;} \
|
||||
do { \
|
||||
if(F) emu->eflags = eflags; \
|
||||
tmp16u = native_lock_read_h(ED); \
|
||||
tmp16u = OP##16(emu, tmp16u, GW->word[0]); \
|
||||
} while (native_lock_write_h(ED, tmp16u)); \
|
||||
break;
|
||||
#else
|
||||
#define GO(B, OP) \
|
||||
#define GO(B, OP, F) \
|
||||
case B+1: \
|
||||
nextop = F8; \
|
||||
if(MODREG) { \
|
||||
@@ -309,13 +312,13 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
pthread_mutex_unlock(&my_context->mutex_lock); \
|
||||
break;
|
||||
#endif
|
||||
GO(0x00, add) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or) /* OR 0x08 -> 0x0D */
|
||||
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
|
||||
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
|
||||
GO(0x20, and) /* AND 0x20 -> 0x25 */
|
||||
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
|
||||
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
|
||||
GO(0x00, add, 0) /* ADD 0x00 -> 0x05 */
|
||||
GO(0x08, or, 0) /* OR 0x08 -> 0x0D */
|
||||
GO(0x10, adc, 1) /* ADC 0x10 -> 0x15 */
|
||||
GO(0x18, sbb, 1) /* SBB 0x18 -> 0x1D */
|
||||
GO(0x20, and, 0) /* AND 0x20 -> 0x25 */
|
||||
GO(0x28, sub, 0) /* SUB 0x28 -> 0x2D */
|
||||
GO(0x30, xor, 0) /* XOR 0x30 -> 0x35 */
|
||||
#undef GO
|
||||
|
||||
case 0x81: /* GRP Ew,Iw */
|
||||
@@ -332,8 +335,8 @@ uintptr_t Run66F0(x64emu_t *emu, rex_t rex, uintptr_t addr)
|
||||
switch((nextop>>3)&7) {
|
||||
case 0: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = add16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 1: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = or16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 2: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 3: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 2: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp16u2 = native_lock_read_h(EW); tmp16u2 = adc16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 3: CHECK_FLAGS(emu); eflags=emu->eflags; do { emu->eflags=eflags; tmp16u2 = native_lock_read_h(EW); tmp16u2 = sbb16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 4: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = and16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 5: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = sub16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
case 6: do { tmp16u2 = native_lock_read_h(EW); tmp16u2 = xor16(emu, tmp16u2, tmp16u);} while(native_lock_write_h(ED, tmp16u2)); break;
|
||||
|
||||
+60
-72
@@ -262,14 +262,14 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX; GETGY;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (isnan(EX->f[i]))
|
||||
GX->f[i] = EX->f[i];
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
else
|
||||
GX->f[i] = (EX->f[i] < 0) ? (-NAN) : sqrtf(EX->f[i]);
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (isnan(EY->f[i]))
|
||||
GY->f[i] = EY->f[i];
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
else
|
||||
GY->f[i] = (EY->f[i] < 0) ? (-NAN) : sqrtf(EY->f[i]);
|
||||
} else
|
||||
@@ -282,13 +282,11 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(EX->f[i]))
|
||||
GX->f[i] = EX->f[i];
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
else if (EX->f[i] == 0)
|
||||
GX->f[i] = 1.0f/EX->f[i];
|
||||
else if (EX->f[i]<0)
|
||||
GX->f[i] = -NAN;
|
||||
else if (isnan(EX->f[i]))
|
||||
GX->f[i] = EX->f[i];
|
||||
else if (isinf(EX->f[i]))
|
||||
GX->f[i] = 0.0;
|
||||
else
|
||||
@@ -298,13 +296,11 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETEY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(EY->f[i]))
|
||||
GY->f[i] = EY->f[i];
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
else if (EY->f[i] == 0)
|
||||
GY->f[i] = 1.0f/EY->f[i];
|
||||
else if (EY->f[i]<0)
|
||||
GY->f[i] = -NAN;
|
||||
else if (isnan(EY->f[i]))
|
||||
GY->f[i] = EY->f[i];
|
||||
else if (isinf(EY->f[i]))
|
||||
GY->f[i] = 0.0;
|
||||
else
|
||||
@@ -398,29 +394,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETVX;
|
||||
GETGY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
|
||||
if (isnan(VX->f[i]))
|
||||
GX->f[i] = VX->f[i];
|
||||
else
|
||||
GX->f[i] = EX->f[i];
|
||||
continue;
|
||||
if(isnanf(VX->f[i])) {
|
||||
GX->ud[i] = VX->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] = VX->f[i] + EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
GX->f[i] = VX->f[i] + EX->f[i];
|
||||
if(isnan(GX->f[i])) GX->f[i] = -NAN;
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
|
||||
if (isnan(VY->f[i]))
|
||||
GY->f[i] = VY->f[i];
|
||||
else
|
||||
GY->f[i] = EY->f[i];
|
||||
continue;
|
||||
if(isnanf(VY->f[i])) {
|
||||
GY->ud[i] = VY->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EY->f[i])) {
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GY->f[i] = VY->f[i] + EY->f[i];
|
||||
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
GY->f[i] = VY->f[i] + EY->f[i];
|
||||
if(isnan(GY->f[i])) GY->f[i] = -NAN;
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
@@ -432,29 +426,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETVX;
|
||||
GETGY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
|
||||
if (isnan(VX->f[i]))
|
||||
GX->f[i] = VX->f[i];
|
||||
else
|
||||
GX->f[i] = EX->f[i];
|
||||
continue;
|
||||
if(isnanf(VX->f[i])) {
|
||||
GX->ud[i] = VX->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] = VX->f[i] * EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
GX->f[i] = VX->f[i] * EX->f[i];
|
||||
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
|
||||
if (isnan(VY->f[i]))
|
||||
GY->f[i] = VY->f[i];
|
||||
else
|
||||
GY->f[i] = EY->f[i];
|
||||
continue;
|
||||
if(isnanf(VY->f[i])) {
|
||||
GY->ud[i] = VY->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EY->f[i])) {
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GY->f[i] = VY->f[i] * EY->f[i];
|
||||
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
GY->f[i] = VY->f[i] * EY->f[i];
|
||||
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
@@ -497,29 +489,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETVX;
|
||||
GETGY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
|
||||
if (isnan(VX->f[i]))
|
||||
GX->f[i] = VX->f[i];
|
||||
else
|
||||
GX->f[i] = EX->f[i];
|
||||
continue;
|
||||
if(isnanf(VX->f[i])) {
|
||||
GX->ud[i] = VX->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] = VX->f[i] - EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
GX->f[i] = VX->f[i] - EX->f[i];
|
||||
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
|
||||
if (isnan(VY->f[i]))
|
||||
GY->f[i] = VY->f[i];
|
||||
else
|
||||
GY->f[i] = EY->f[i];
|
||||
continue;
|
||||
if(isnanf(VY->f[i])) {
|
||||
GY->ud[i] = VY->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EY->f[i])) {
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GY->f[i] = VY->f[i] - EY->f[i];
|
||||
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
GY->f[i] = VY->f[i] - EY->f[i];
|
||||
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
@@ -553,29 +543,27 @@ uintptr_t RunAVX_0F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETVX;
|
||||
GETGY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VX->f[i]) || isnan(EX->f[i])) {
|
||||
if (isnan(VX->f[i]))
|
||||
GX->f[i] = VX->f[i];
|
||||
else
|
||||
GX->f[i] = EX->f[i];
|
||||
continue;
|
||||
if(isnanf(VX->f[i])) {
|
||||
GX->ud[i] = VX->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EX->f[i])) {
|
||||
GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GX->f[i] = VX->f[i] / EX->f[i];
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
GX->f[i] = VX->f[i] / EX->f[i];
|
||||
if (isnan(GX->f[i])) GX->ud[i] |= 0x80000000;
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
for(int i=0; i<4; ++i) {
|
||||
if (isnan(VY->f[i]) || isnan(EY->f[i])) {
|
||||
if (isnan(VY->f[i]))
|
||||
GY->f[i] = VY->f[i];
|
||||
else
|
||||
GY->f[i] = EY->f[i];
|
||||
continue;
|
||||
if(isnanf(VY->f[i])) {
|
||||
GY->ud[i] = VY->ud[i] | 0x00400000;
|
||||
} else if(isnanf(EY->f[i])) {
|
||||
GY->ud[i] = EY->ud[i] | 0x00400000;
|
||||
} else {
|
||||
GY->f[i] = VY->f[i] / EY->f[i];
|
||||
if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
GY->f[i] = VY->f[i] / EY->f[i];
|
||||
if (isnan(GY->f[i])) GY->ud[i] |= 0x80000000;
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
|
||||
@@ -75,7 +75,11 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
CLEAR_FLAG(F_CF);
|
||||
CLEAR_FLAG(F_OF);
|
||||
CLEAR_FLAG(F_AF); // Undef
|
||||
CLEAR_FLAG(F_PF); // Undef
|
||||
if (BOX64ENV(cputype)) {
|
||||
CLEAR_FLAG(F_PF);
|
||||
} else {
|
||||
CONDITIONAL_SET_FLAG(PARITY(GD->byte[0] & 0xff), F_PF);
|
||||
}
|
||||
break;
|
||||
case 0xF3:
|
||||
nextop = F8;
|
||||
@@ -152,6 +156,7 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
case 0xF5: /* BZHI Gd, Ed, Vd */
|
||||
nextop = F8;
|
||||
if(vex.l) EmitSignal(emu, X64_SIGILL, (void*)R_RIP, 0);
|
||||
ResetFlags(emu);
|
||||
GETGD;
|
||||
GETED(0);
|
||||
GETVD;
|
||||
@@ -200,8 +205,7 @@ uintptr_t RunAVX_0F38(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GD->dword[0] = (ED->dword[0]>>tmp32u)&tmp64u;
|
||||
else
|
||||
GD->dword[0] = 0;
|
||||
if(MODREG)
|
||||
GD->dword[1] = 0;
|
||||
GD->dword[1] = 0;
|
||||
}
|
||||
ResetFlags(emu);
|
||||
CONDITIONAL_SET_FLAG(rex.w?(GD->q[0]==0):(GD->dword[0]==0), F_ZF);
|
||||
|
||||
+160
-80
@@ -237,8 +237,10 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX; GETGY;
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(EX->d[i]<0.0) // on x86, default nan are negative
|
||||
GX->d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
|
||||
if(EX->d[i]<0.0)
|
||||
GX->d[i] = -NAN;
|
||||
else if(isnan(EX->d[i]))
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
else
|
||||
GX->d[i] = sqrt(EX->d[i]);
|
||||
}
|
||||
@@ -247,6 +249,8 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(EY->d[i]<0.0)
|
||||
GY->d[i] = -NAN;
|
||||
else if(isnan(EY->d[i]))
|
||||
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
|
||||
else
|
||||
GY->d[i] = sqrt(EY->d[i]);
|
||||
}
|
||||
@@ -319,20 +323,30 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GETVX;
|
||||
MARK_NAN_VD_2(VX, EX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GX->d[i] = VX->d[i] + EX->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VX->d[i])) {
|
||||
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] = VX->d[i] + EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
GETGY;
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VD_2(VY, EY);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GY->d[i] = VY->d[i] + EY->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VY->d[i])) {
|
||||
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[i])) {
|
||||
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[i] = VY->d[i] + EY->d[i];
|
||||
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GY);
|
||||
} else {
|
||||
GY->u128 = 0;
|
||||
}
|
||||
@@ -343,19 +357,29 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_VD_2(VX, EX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GX->d[i] = VX->d[i] * EX->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VX->d[i])) {
|
||||
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] = VX->d[i] * EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VD_2(VY, EY);
|
||||
for(int i=0; i<2; ++i) {
|
||||
GY->d[i] = VY->d[i] * EY->d[i];
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VY->d[i])) {
|
||||
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[i])) {
|
||||
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[i] = VY->d[i] * EY->d[i];
|
||||
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GY);
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -445,18 +469,30 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
GETVX;
|
||||
MARK_NAN_VD_2(VX, EX);
|
||||
GX->d[0] = VX->d[0] - EX->d[0];
|
||||
GX->d[1] = VX->d[1] - EX->d[1];
|
||||
CHECK_NAN_VD(GX);
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VX->d[i])) {
|
||||
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] = VX->d[i] - EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
GETGY;
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VD_2(VY, EY);
|
||||
GY->d[0] = VY->d[0] - EY->d[0];
|
||||
GY->d[1] = VY->d[1] - EY->d[1];
|
||||
CHECK_NAN_VD(GY);
|
||||
for (int i=0; i<2; ++i) {
|
||||
if(isnan(VY->d[i])) {
|
||||
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[i])) {
|
||||
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[i] = VY->d[i] - EY->d[i];
|
||||
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GY->u128 = 0;
|
||||
}
|
||||
@@ -489,19 +525,29 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_VD_2(VX, EX);
|
||||
for (int i=0; i<2; ++i) {
|
||||
GX->d[i] = VX->d[i] / EX->d[i];
|
||||
if(isnan(VX->d[i])) {
|
||||
GX->q[i] = VX->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[i])) {
|
||||
GX->q[i] = EX->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[i] = VX->d[i] / EX->d[i];
|
||||
if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GX);
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VD_2(VY, EY);
|
||||
for (int i=0; i<2; ++i) {
|
||||
GY->d[i] = VY->d[i] / EY->d[i];
|
||||
if(isnan(VY->d[i])) {
|
||||
GY->q[i] = VY->q[i] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[i])) {
|
||||
GY->q[i] = EY->q[i] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[i] = VY->d[i] / EY->d[i];
|
||||
if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VD(GY);
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -1086,17 +1132,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
eax1 = *EX;
|
||||
EX = &eax1;
|
||||
}
|
||||
is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
|
||||
GX->d[0] = VX->d[0] + VX->d[1];
|
||||
if(!is_nan && isnan(GX->d[0]))
|
||||
GX->d[0] = -NAN;
|
||||
if(EX==VX) {
|
||||
GX->d[1] = GX->d[0];
|
||||
if(isnan(VX->d[0])) {
|
||||
GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(VX->d[1])) {
|
||||
GX->q[0] = VX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
|
||||
GX->d[1] = EX->d[0] + EX->d[1];
|
||||
if(!is_nan && isnan(GX->d[1]))
|
||||
GX->d[1] = -NAN;
|
||||
GX->d[0] = VX->d[0] + VX->d[1];
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EX==VX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
if(isnan(EX->d[0])) {
|
||||
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[1])) {
|
||||
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[1] = EX->d[0] + EX->d[1];
|
||||
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
if(vex.l) {
|
||||
if(GY==EY) {
|
||||
@@ -1104,17 +1158,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
EY = &eay1;
|
||||
}
|
||||
GETVY;
|
||||
is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
|
||||
GY->d[0] = VY->d[0] + VY->d[1];
|
||||
if(!is_nan && isnan(GY->d[0]))
|
||||
GY->d[0] = -NAN;
|
||||
if(EY==VY) {
|
||||
GY->d[1] = GY->d[0];
|
||||
if(isnan(VY->d[0])) {
|
||||
GY->q[0] = VY->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(VY->d[1])) {
|
||||
GY->q[0] = VY->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
|
||||
GY->d[1] = EY->d[0] + EY->d[1];
|
||||
if(!is_nan && isnan(GY->d[1]))
|
||||
GY->d[1] = -NAN;
|
||||
GY->d[0] = VY->d[0] + VY->d[1];
|
||||
if(isnan(GY->d[0])) GY->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EY==VY) {
|
||||
GY->q[1] = GY->q[0];
|
||||
} else {
|
||||
if(isnan(EY->d[0])) {
|
||||
GY->q[1] = EY->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[1])) {
|
||||
GY->q[1] = EY->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[1] = EY->d[0] + EY->d[1];
|
||||
if(isnan(GY->d[1])) GY->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
@@ -1130,17 +1192,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
eax1 = *EX;
|
||||
EX = &eax1;
|
||||
}
|
||||
is_nan = isnan(VX->d[0]) || isnan(VX->d[1]);
|
||||
GX->d[0] = VX->d[0] - VX->d[1];
|
||||
if(!is_nan && isnan(GX->d[0]))
|
||||
GX->d[0] = -NAN;
|
||||
if(EX==VX) {
|
||||
GX->d[1] = GX->d[0];
|
||||
if(isnan(VX->d[0])) {
|
||||
GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(VX->d[1])) {
|
||||
GX->q[0] = VX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
|
||||
GX->d[1] = EX->d[0] - EX->d[1];
|
||||
if(!is_nan && isnan(GX->d[1]))
|
||||
GX->d[1] = -NAN;
|
||||
GX->d[0] = VX->d[0] - VX->d[1];
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EX==VX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
} else {
|
||||
if(isnan(EX->d[0])) {
|
||||
GX->q[1] = EX->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EX->d[1])) {
|
||||
GX->q[1] = EX->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GX->d[1] = EX->d[0] - EX->d[1];
|
||||
if(isnan(GX->d[1])) GX->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
if(vex.l) {
|
||||
if(GY==EY) {
|
||||
@@ -1148,17 +1218,25 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
EY = &eay1;
|
||||
}
|
||||
GETVY;
|
||||
is_nan = isnan(VY->d[0]) || isnan(VY->d[1]);
|
||||
GY->d[0] = VY->d[0] - VY->d[1];
|
||||
if(!is_nan && isnan(GY->d[0]))
|
||||
GY->d[0] = -NAN;
|
||||
if(EY==VY) {
|
||||
GY->d[1] = GY->d[0];
|
||||
if(isnan(VY->d[0])) {
|
||||
GY->q[0] = VY->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(VY->d[1])) {
|
||||
GY->q[0] = VY->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
is_nan = isnan(EY->d[0]) || isnan(EY->d[1]);
|
||||
GY->d[1] = EY->d[0] - EY->d[1];
|
||||
if(!is_nan && isnan(GY->d[1]))
|
||||
GY->d[1] = -NAN;
|
||||
GY->d[0] = VY->d[0] - VY->d[1];
|
||||
if(isnan(GY->d[0])) GY->q[0] |= 0x8000000000000000ULL;
|
||||
}
|
||||
if(EY==VY) {
|
||||
GY->q[1] = GY->q[0];
|
||||
} else {
|
||||
if(isnan(EY->d[0])) {
|
||||
GY->q[1] = EY->q[0] | 0x0008000000000000ULL;
|
||||
} else if(isnan(EY->d[1])) {
|
||||
GY->q[1] = EY->q[1] | 0x0008000000000000ULL;
|
||||
} else {
|
||||
GY->d[1] = EY->d[0] - EY->d[1];
|
||||
if(isnan(GY->d[1])) GY->q[1] |= 0x8000000000000000ULL;
|
||||
}
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
@@ -1297,17 +1375,19 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_VD_2(VX, EX);
|
||||
GX->d[0] = VX->d[0] - EX->d[0];
|
||||
GX->d[1] = VX->d[1] + EX->d[1];
|
||||
CHECK_NAN_VD(GX);
|
||||
for(int i=0; i<2; ++i) {
|
||||
if(isnan(VX->d[i])) { GX->q[i] = VX->q[i] | 0x0008000000000000ULL; }
|
||||
else if(isnan(EX->d[i])) { GX->q[i] = EX->q[i] | 0x0008000000000000ULL; }
|
||||
else { if(i==0) GX->d[0] = VX->d[0] - EX->d[0]; else GX->d[1] = VX->d[1] + EX->d[1]; if(isnan(GX->d[i])) GX->q[i] |= 0x8000000000000000ULL; }
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VD_2(VY, EY);
|
||||
GY->d[0] = VY->d[0] - EY->d[0];
|
||||
GY->d[1] = VY->d[1] + EY->d[1];
|
||||
CHECK_NAN_VD(GY);
|
||||
for(int i=0; i<2; ++i) {
|
||||
if(isnan(VY->d[i])) { GY->q[i] = VY->q[i] | 0x0008000000000000ULL; }
|
||||
else if(isnan(EY->d[i])) { GY->q[i] = EY->q[i] | 0x0008000000000000ULL; }
|
||||
else { if(i==0) GY->d[0] = VY->d[0] - EY->d[0]; else GY->d[1] = VY->d[1] + EY->d[1]; if(isnan(GY->d[i])) GY->q[i] |= 0x8000000000000000ULL; }
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
|
||||
+79
-80
@@ -189,7 +189,7 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
if(EX->d[0]<0.0 )
|
||||
GX->d[0] = -NAN;
|
||||
else if(isnan(EX->d[0]))
|
||||
GX->d[0] = EX->d[0];
|
||||
GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else
|
||||
GX->d[0] = sqrt(EX->d[0]);
|
||||
GX->q[1] = VX->q[1];
|
||||
@@ -202,9 +202,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_D_2(VX, EX);
|
||||
GX->d[0] = VX->d[0] + EX->d[0];
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] = VX->d[0] + EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
GX->q[1] = VX->q[1];
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -214,9 +214,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_D_2(VX, EX);
|
||||
GX->d[0] = VX->d[0] * EX->d[0];
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] = VX->d[0] * EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
if(GX!=VX) {
|
||||
GX->q[1] = VX->q[1];
|
||||
}
|
||||
@@ -240,7 +240,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
GX->d[0] = VX->d[0] - EX->d[0];
|
||||
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] = VX->d[0] - EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
GX->q[1] = VX->q[1];
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -263,14 +265,9 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
#ifndef NOALIGN
|
||||
is_nan = isnan(VX->d[0]) || isnan(EX->d[0]);
|
||||
#endif
|
||||
GX->d[0] = VX->d[0] / EX->d[0];
|
||||
#ifndef NOALIGN
|
||||
if(!is_nan && isnan(GX->d[0]))
|
||||
GX->d[0] = -NAN;
|
||||
#endif
|
||||
if(isnan(VX->d[0])) GX->q[0] = VX->q[0] | 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] = VX->d[0] / EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
GX->q[1] = VX->q[1];
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -328,44 +325,46 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
eax1 = *EX;
|
||||
EX = &eax1;
|
||||
}
|
||||
mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
|
||||
mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
|
||||
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] + VX->f[1]));
|
||||
GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] + VX->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000;
|
||||
else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000;
|
||||
else { GX->f[i] = VX->f[j] + VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
|
||||
}
|
||||
if(EX==VX) {
|
||||
GX->f[2] = GX->f[0];
|
||||
GX->f[3] = GX->f[1];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
GX->ud[2] = GX->ud[0];
|
||||
GX->ud[3] = GX->ud[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
|
||||
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
|
||||
GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] + EX->f[1]));
|
||||
GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] + EX->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000;
|
||||
else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000;
|
||||
else { GX->f[i+2] = EX->f[j] + EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; }
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GX);
|
||||
if(vex.l) {
|
||||
if(GY==EY) {
|
||||
eay1 = *EY;
|
||||
EY = &eay1;
|
||||
}
|
||||
GETVY;
|
||||
mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
|
||||
mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
|
||||
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] + VY->f[1]));
|
||||
GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] + VY->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000;
|
||||
else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000;
|
||||
else { GY->f[i] = VY->f[j] + VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
|
||||
}
|
||||
if(EY==VY) {
|
||||
GY->f[2] = GY->f[0];
|
||||
GY->f[3] = GY->f[1];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
GY->ud[2] = GY->ud[0];
|
||||
GY->ud[3] = GY->ud[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
|
||||
mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
|
||||
GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] + EY->f[1]));
|
||||
GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] + EY->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000;
|
||||
else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000;
|
||||
else { GY->f[i+2] = EY->f[j] + EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; }
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GY);
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -380,44 +379,46 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
eax1 = *EX;
|
||||
EX = &eax1;
|
||||
}
|
||||
mask_nan[0] = isnanf(VX->f[0]) || isnanf(VX->f[1]);
|
||||
mask_nan[1] = isnanf(VX->f[2]) || isnanf(VX->f[3]);
|
||||
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(VX->f[1]) ? VX->f[1] : (VX->f[0] - VX->f[1]));
|
||||
GX->f[1] = isnan(VX->f[2]) ? VX->f[2] : (isnan(VX->f[3]) ? VX->f[3] : (VX->f[2] - VX->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(VX->f[j])) GX->ud[i] = VX->ud[j] | 0x00400000;
|
||||
else if(isnanf(VX->f[j+1])) GX->ud[i] = VX->ud[j+1] | 0x00400000;
|
||||
else { GX->f[i] = VX->f[j] - VX->f[j+1]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
|
||||
}
|
||||
if (EX == VX) {
|
||||
GX->f[2] = GX->f[0];
|
||||
GX->f[3] = GX->f[1];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
GX->ud[2] = GX->ud[0];
|
||||
GX->ud[3] = GX->ud[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
|
||||
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
|
||||
GX->f[2] = isnan(EX->f[0]) ? EX->f[0] : (isnan(EX->f[1]) ? EX->f[1] : (EX->f[0] - EX->f[1]));
|
||||
GX->f[3] = isnan(EX->f[2]) ? EX->f[2] : (isnan(EX->f[3]) ? EX->f[3] : (EX->f[2] - EX->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(EX->f[j])) GX->ud[i+2] = EX->ud[j] | 0x00400000;
|
||||
else if(isnanf(EX->f[j+1])) GX->ud[i+2] = EX->ud[j+1] | 0x00400000;
|
||||
else { GX->f[i+2] = EX->f[j] - EX->f[j+1]; if(isnanf(GX->f[i+2])) GX->ud[i+2] |= 0x80000000; }
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GX);
|
||||
if (vex.l) {
|
||||
if (GY == EY) {
|
||||
eay1 = *EY;
|
||||
EY = &eay1;
|
||||
}
|
||||
GETVY;
|
||||
mask_nan[0] = isnanf(VY->f[0]) || isnanf(VY->f[1]);
|
||||
mask_nan[1] = isnanf(VY->f[2]) || isnanf(VY->f[3]);
|
||||
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(VY->f[1]) ? VY->f[1] : (VY->f[0] - VY->f[1]));
|
||||
GY->f[1] = isnan(VY->f[2]) ? VY->f[2] : (isnan(VY->f[3]) ? VY->f[3] : (VY->f[2] - VY->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(VY->f[j])) GY->ud[i] = VY->ud[j] | 0x00400000;
|
||||
else if(isnanf(VY->f[j+1])) GY->ud[i] = VY->ud[j+1] | 0x00400000;
|
||||
else { GY->f[i] = VY->f[j] - VY->f[j+1]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
|
||||
}
|
||||
if (EY == VY) {
|
||||
GY->f[2] = GY->f[0];
|
||||
GY->f[3] = GY->f[1];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
GY->ud[2] = GY->ud[0];
|
||||
GY->ud[3] = GY->ud[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EY->f[0]) || isnanf(EY->f[1]);
|
||||
mask_nan[3] = isnanf(EY->f[2]) || isnanf(EY->f[3]);
|
||||
GY->f[2] = isnan(EY->f[0]) ? EY->f[0] : (isnan(EY->f[1]) ? EY->f[1] : (EY->f[0] - EY->f[1]));
|
||||
GY->f[3] = isnan(EY->f[2]) ? EY->f[2] : (isnan(EY->f[3]) ? EY->f[3] : (EY->f[2] - EY->f[3]));
|
||||
for(int i=0; i<2; ++i) {
|
||||
int j = i*2;
|
||||
if(isnanf(EY->f[j])) GY->ud[i+2] = EY->ud[j] | 0x00400000;
|
||||
else if(isnanf(EY->f[j+1])) GY->ud[i+2] = EY->ud[j+1] | 0x00400000;
|
||||
else { GY->f[i+2] = EY->f[j] - EY->f[j+1]; if(isnanf(GY->f[i+2])) GY->ud[i+2] |= 0x80000000; }
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GY);
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
@@ -460,21 +461,19 @@ uintptr_t RunAVX_F20F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_VF_2(VX, EX);
|
||||
GX->f[0] = isnan(VX->f[0]) ? VX->f[0] : (isnan(EX->f[0]) ? EX->f[0] : (VX->f[0] - EX->f[0]));
|
||||
GX->f[1] = isnan(VX->f[1]) ? VX->f[1] : (isnan(EX->f[1]) ? EX->f[1] : (VX->f[1] + EX->f[1]));
|
||||
GX->f[2] = isnan(VX->f[2]) ? VX->f[2] : (isnan(EX->f[2]) ? EX->f[2] : (VX->f[2] - EX->f[2]));
|
||||
GX->f[3] = isnan(VX->f[3]) ? VX->f[3] : (isnan(EX->f[3]) ? EX->f[3] : (VX->f[3] + EX->f[3]));
|
||||
CHECK_NAN_VF(GX);
|
||||
for(int i=0; i<4; ++i) {
|
||||
if(isnanf(VX->f[i])) { GX->ud[i] = VX->ud[i] | 0x00400000; }
|
||||
else if(isnanf(EX->f[i])) { GX->ud[i] = EX->ud[i] | 0x00400000; }
|
||||
else { if(i&1) GX->f[i] = VX->f[i] + EX->f[i]; else GX->f[i] = VX->f[i] - EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
|
||||
}
|
||||
if(vex.l) {
|
||||
GETEY;
|
||||
GETVY;
|
||||
MARK_NAN_VF_2(VY, EY);
|
||||
GY->f[0] = isnan(VY->f[0]) ? VY->f[0] : (isnan(EY->f[0]) ? EY->f[0] : (VY->f[0] - EY->f[0]));
|
||||
GY->f[1] = isnan(VY->f[1]) ? VY->f[1] : (isnan(EY->f[1]) ? EY->f[1] : (VY->f[1] + EY->f[1]));
|
||||
GY->f[2] = isnan(VY->f[2]) ? VY->f[2] : (isnan(EY->f[2]) ? EY->f[2] : (VY->f[2] - EY->f[2]));
|
||||
GY->f[3] = isnan(VY->f[3]) ? VY->f[3] : (isnan(EY->f[3]) ? EY->f[3] : (VY->f[3] + EY->f[3]));
|
||||
CHECK_NAN_VF(GY);
|
||||
for(int i=0; i<4; ++i) {
|
||||
if(isnanf(VY->f[i])) { GY->ud[i] = VY->ud[i] | 0x00400000; }
|
||||
else if(isnanf(EY->f[i])) { GY->ud[i] = EY->ud[i] | 0x00400000; }
|
||||
else { if(i&1) GY->f[i] = VY->f[i] + EY->f[i]; else GY->f[i] = VY->f[i] - EY->f[i]; if(isnanf(GY->f[i])) GY->ud[i] |= 0x80000000; }
|
||||
}
|
||||
} else
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
|
||||
+14
-12
@@ -211,7 +211,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
if(EX->f[0]<0.0 )
|
||||
GX->f[0] = -NAN;
|
||||
else if(isnanf(EX->f[0]))
|
||||
GX->f[0] = EX->f[0];
|
||||
GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else
|
||||
GX->f[0] = sqrt(EX->f[0]);
|
||||
if(GX!=VX) {
|
||||
@@ -229,7 +229,7 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
else if (EX->f[0]<0)
|
||||
GX->f[0] = -NAN;
|
||||
else if (isnan(EX->f[0]))
|
||||
GX->f[0] = EX->f[0];
|
||||
GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else if (isinf(EX->f[0]))
|
||||
GX->f[0] = 0.0;
|
||||
else
|
||||
@@ -258,9 +258,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_F_2(VX, EX);
|
||||
GX->f[0] = VX->f[0] + EX->f[0];
|
||||
CHECK_NAN_F(GX);
|
||||
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] = VX->f[0] + EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
if(GX!=VX) {
|
||||
GX->ud[1] = VX->ud[1];
|
||||
GX->q[1] = VX->q[1];
|
||||
@@ -273,9 +273,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_F_2(VX, EX);
|
||||
GX->f[0] = VX->f[0] * EX->f[0];
|
||||
CHECK_NAN_F(GX);
|
||||
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] = VX->f[0] * EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
if(GX!=VX) {
|
||||
GX->ud[1] = VX->ud[1];
|
||||
GX->q[1] = VX->q[1];
|
||||
@@ -330,7 +330,9 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
GX->f[0] = VX->f[0] - EX->f[0];
|
||||
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] = VX->f[0] - EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
if(GX!=VX) {
|
||||
GX->ud[1] = VX->ud[1];
|
||||
GX->q[1] = VX->q[1];
|
||||
@@ -360,13 +362,13 @@ uintptr_t RunAVX_F30F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step)
|
||||
GETGX;
|
||||
GETVX;
|
||||
GETGY;
|
||||
MARK_NAN_F_2(VX, EX);
|
||||
GX->f[0] = VX->f[0] / EX->f[0];
|
||||
if(isnanf(VX->f[0])) GX->ud[0] = VX->ud[0] | 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] = VX->f[0] / EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
if(GX!=VX) {
|
||||
GX->ud[1] = VX->ud[1];
|
||||
GX->q[1] = VX->q[1];
|
||||
}
|
||||
CHECK_NAN_F(GX);
|
||||
GY->u128 = 0;
|
||||
break;
|
||||
case 0x5F: /* VMAXSS Gx, Vx, Ex */
|
||||
|
||||
+92
-54
@@ -187,7 +187,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETED(0);
|
||||
GETGD;
|
||||
tmp64u = ED->q[0];
|
||||
tmp64u = rex.w ? ED->q[0] : ED->dword[0];
|
||||
for(int j=0; j<4*(rex.w+1); ++j) {
|
||||
GD->dword[0] ^= (tmp64u >> (j * 8)) & 0xff;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@@ -212,7 +212,7 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
if(EX->d[0]<0.0 )
|
||||
GX->d[0] = -NAN;
|
||||
else if(isnan(EX->d[0]))
|
||||
GX->d[0] = EX->d[0];
|
||||
GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else
|
||||
GX->d[0] = sqrt(EX->d[0]);
|
||||
break;
|
||||
@@ -221,24 +221,17 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_D_2(GX, EX);
|
||||
{
|
||||
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
|
||||
GX->d[0] += EX->d[0];
|
||||
}
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] += EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
break;
|
||||
case 0x59: /* MULSD Gx, Ex */
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
|
||||
MARK_NAN_D_2(GX, EX);
|
||||
{
|
||||
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
|
||||
GX->d[0] *= EX->d[0];
|
||||
}
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] *= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
break;
|
||||
case 0x5A: /* CVTSD2SS Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -251,12 +244,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_D_2(GX, EX);
|
||||
{
|
||||
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
|
||||
GX->d[0] -= EX->d[0];
|
||||
}
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] -= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
break;
|
||||
case 0x5D: /* MINSD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -269,10 +259,9 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_D_2(GX, EX);
|
||||
NAN_PROPAGATION(GX->d[0], EX->d[0], break);
|
||||
GX->d[0] /= EX->d[0];
|
||||
CHECK_NAN_D(GX);
|
||||
if(isnan(GX->d[0])) GX->q[0] |= 0x0008000000000000ULL;
|
||||
else if(isnan(EX->d[0])) GX->q[0] = EX->q[0] | 0x0008000000000000ULL;
|
||||
else { GX->d[0] /= EX->d[0]; if(isnan(GX->d[0])) GX->q[0] |= 0x8000000000000000ULL; }
|
||||
break;
|
||||
case 0x5F: /* MAXSD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -339,41 +328,85 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);
|
||||
mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);
|
||||
GX->f[0] += GX->f[1];
|
||||
GX->f[1] = GX->f[2] + GX->f[3];
|
||||
eax1 = *GX;
|
||||
if(isnanf(eax1.f[0])) {
|
||||
GX->ud[0] = eax1.ud[0] | 0x00400000;
|
||||
} else if(isnanf(eax1.f[1])) {
|
||||
GX->ud[0] = eax1.ud[1] | 0x00400000;
|
||||
} else {
|
||||
GX->f[0] = eax1.f[0] + eax1.f[1];
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000;
|
||||
}
|
||||
if(isnanf(eax1.f[2])) {
|
||||
GX->ud[1] = eax1.ud[2] | 0x00400000;
|
||||
} else if(isnanf(eax1.f[3])) {
|
||||
GX->ud[1] = eax1.ud[3] | 0x00400000;
|
||||
} else {
|
||||
GX->f[1] = eax1.f[2] + eax1.f[3];
|
||||
if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000;
|
||||
}
|
||||
if(EX==GX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
|
||||
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
|
||||
GX->f[2] = EX->f[0] + EX->f[1];
|
||||
GX->f[3] = EX->f[2] + EX->f[3];
|
||||
if(isnanf(EX->f[0])) {
|
||||
GX->ud[2] = EX->ud[0] | 0x00400000;
|
||||
} else if(isnanf(EX->f[1])) {
|
||||
GX->ud[2] = EX->ud[1] | 0x00400000;
|
||||
} else {
|
||||
GX->f[2] = EX->f[0] + EX->f[1];
|
||||
if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000;
|
||||
}
|
||||
if(isnanf(EX->f[2])) {
|
||||
GX->ud[3] = EX->ud[2] | 0x00400000;
|
||||
} else if(isnanf(EX->f[3])) {
|
||||
GX->ud[3] = EX->ud[3] | 0x00400000;
|
||||
} else {
|
||||
GX->f[3] = EX->f[2] + EX->f[3];
|
||||
if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GX);
|
||||
break;
|
||||
case 0x7D: /* HSUBPS Gx, Ex */
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
mask_nan[0] = isnanf(GX->f[0]) || isnanf(GX->f[1]);
|
||||
mask_nan[1] = isnanf(GX->f[2]) || isnanf(GX->f[3]);
|
||||
GX->f[0] -= GX->f[1];
|
||||
GX->f[1] = GX->f[2] - GX->f[3];
|
||||
eax1 = *GX;
|
||||
if(isnanf(eax1.f[0])) {
|
||||
GX->ud[0] = eax1.ud[0] | 0x00400000;
|
||||
} else if(isnanf(eax1.f[1])) {
|
||||
GX->ud[0] = eax1.ud[1] | 0x00400000;
|
||||
} else {
|
||||
GX->f[0] = eax1.f[0] - eax1.f[1];
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000;
|
||||
}
|
||||
if(isnanf(eax1.f[2])) {
|
||||
GX->ud[1] = eax1.ud[2] | 0x00400000;
|
||||
} else if(isnanf(eax1.f[3])) {
|
||||
GX->ud[1] = eax1.ud[3] | 0x00400000;
|
||||
} else {
|
||||
GX->f[1] = eax1.f[2] - eax1.f[3];
|
||||
if(isnanf(GX->f[1])) GX->ud[1] |= 0x80000000;
|
||||
}
|
||||
if(EX==GX) {
|
||||
GX->q[1] = GX->q[0];
|
||||
mask_nan[2] = mask_nan[0];
|
||||
mask_nan[3] = mask_nan[1];
|
||||
} else {
|
||||
mask_nan[2] = isnanf(EX->f[0]) || isnanf(EX->f[1]);
|
||||
mask_nan[3] = isnanf(EX->f[2]) || isnanf(EX->f[3]);
|
||||
GX->f[2] = EX->f[0] - EX->f[1];
|
||||
GX->f[3] = EX->f[2] - EX->f[3];
|
||||
if(isnanf(EX->f[0])) {
|
||||
GX->ud[2] = EX->ud[0] | 0x00400000;
|
||||
} else if(isnanf(EX->f[1])) {
|
||||
GX->ud[2] = EX->ud[1] | 0x00400000;
|
||||
} else {
|
||||
GX->f[2] = EX->f[0] - EX->f[1];
|
||||
if(isnanf(GX->f[2])) GX->ud[2] |= 0x80000000;
|
||||
}
|
||||
if(isnanf(EX->f[2])) {
|
||||
GX->ud[3] = EX->ud[2] | 0x00400000;
|
||||
} else if(isnanf(EX->f[3])) {
|
||||
GX->ud[3] = EX->ud[3] | 0x00400000;
|
||||
} else {
|
||||
GX->f[3] = EX->f[2] - EX->f[3];
|
||||
if(isnanf(GX->f[3])) GX->ud[3] |= 0x80000000;
|
||||
}
|
||||
}
|
||||
CHECK_NAN_VF(GX);
|
||||
break;
|
||||
|
||||
GOCOND(0x80
|
||||
@@ -382,15 +415,21 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
,,STEP3
|
||||
) /* 0x80 -> 0x8F Jxx */
|
||||
|
||||
case 0xA4: // ignore F2 prefix
|
||||
case 0xA3: // ignore F2 prefix
|
||||
case 0xA4:
|
||||
case 0xA5:
|
||||
case 0xAB:
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
case 0xAF:
|
||||
case 0xB3:
|
||||
case 0xB7:
|
||||
case 0xBA:
|
||||
case 0xBB:
|
||||
case 0xBC: // this one is still BSR, not TZCNT
|
||||
case 0xBD: // and this one is still BSF, not LZCNT
|
||||
case 0xC1:
|
||||
case 0xCD:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test0F(test, rex, addr-1, step);
|
||||
#else
|
||||
@@ -420,12 +459,11 @@ uintptr_t RunF20F(x64emu_t *emu, rex_t rex, uintptr_t addr, int *step)
|
||||
nextop = F8;
|
||||
_GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_VF_2(GX, EX);
|
||||
GX->f[0] -= EX->f[0];
|
||||
GX->f[1] += EX->f[1];
|
||||
GX->f[2] -= EX->f[2];
|
||||
GX->f[3] += EX->f[3];
|
||||
CHECK_NAN_VF(GX);
|
||||
for(int i=0; i<4; ++i) {
|
||||
if(isnanf(GX->f[i])) GX->ud[i] |= 0x00400000;
|
||||
else if(isnanf(EX->f[i])) GX->ud[i] = EX->ud[i] | 0x00400000;
|
||||
else { if(i&1) GX->f[i] += EX->f[i]; else GX->f[i] -= EX->f[i]; if(isnanf(GX->f[i])) GX->ud[i] |= 0x80000000; }
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xD6: /* MOVDQ2Q Gm, Ex */
|
||||
|
||||
+28
-24
@@ -228,7 +228,7 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
|
||||
if (EX->f[0]<0)
|
||||
GX->f[0] = -NAN;
|
||||
else if (isnanf(EX->f[0]))
|
||||
GX->f[0] = EX->f[0];
|
||||
GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else
|
||||
GX->f[0] = sqrtf(EX->f[0]);
|
||||
break;
|
||||
@@ -241,37 +241,35 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
|
||||
else if (EX->f[0]<0)
|
||||
GX->f[0] = -NAN;
|
||||
else if (isnan(EX->f[0]))
|
||||
GX->f[0] = EX->f[0];
|
||||
GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else if (isinf(EX->f[0]))
|
||||
GX->f[0] = 0.0;
|
||||
else
|
||||
GX->f[0] = 1.0f/sqrtf(EX->f[0]);
|
||||
break;
|
||||
case 0x53: /* RCPSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
|
||||
GX->f[0] = 1.0f/EX->f[0];
|
||||
break;
|
||||
case 0x53: /* RCPSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] = 1.0f/EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
break;
|
||||
|
||||
case 0x58: /* ADDSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_F_2(GX, EX);
|
||||
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
|
||||
GX->f[0] += EX->f[0];
|
||||
CHECK_NAN_F(GX);
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] += EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
break;
|
||||
case 0x59: /* MULSS Gx, Ex */
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_F_2(GX, EX);
|
||||
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
|
||||
GX->f[0] *= EX->f[0];
|
||||
CHECK_NAN_F(GX);
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] *= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
break;
|
||||
case 0x5A: /* CVTSS2SD Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -299,8 +297,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
|
||||
GX->f[0] -= EX->f[0];
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] -= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
break;
|
||||
case 0x5D: /* MINSS Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -313,10 +312,9 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
|
||||
nextop = F8;
|
||||
GETEX(0);
|
||||
GETGX;
|
||||
MARK_NAN_F_2(GX, EX);
|
||||
NAN_PROPAGATION(GX->f[0], EX->f[0], break);
|
||||
GX->f[0] /= EX->f[0];
|
||||
CHECK_NAN_F(GX);
|
||||
if(isnanf(GX->f[0])) GX->ud[0] |= 0x00400000;
|
||||
else if(isnanf(EX->f[0])) GX->ud[0] = EX->ud[0] | 0x00400000;
|
||||
else { GX->f[0] /= EX->f[0]; if(isnanf(GX->f[0])) GX->ud[0] |= 0x80000000; }
|
||||
break;
|
||||
case 0x5F: /* MAXSS Gx, Ex */
|
||||
nextop = F8;
|
||||
@@ -362,13 +360,19 @@ uintptr_t RunF30F(x64emu_t *emu, rex_t rex, uintptr_t addr, int* step)
|
||||
memcpy(EX, GX, 16); // unaligned...
|
||||
break;
|
||||
|
||||
case 0xA4: // ignore F3 prefix
|
||||
case 0xA3: // ignore F3 prefix
|
||||
case 0xA4:
|
||||
case 0xA5:
|
||||
case 0xAC:
|
||||
case 0xAD:
|
||||
case 0xAF:
|
||||
case 0xB3:
|
||||
case 0xB7:
|
||||
case 0xBA:
|
||||
case 0xBB:
|
||||
case 0xBF:
|
||||
case 0xC1:
|
||||
case 0xCD:
|
||||
#ifdef TEST_INTERPRETER
|
||||
return Test0F(test, rex, addr-1, step);
|
||||
#else
|
||||
|
||||
+79
-51
@@ -581,9 +581,11 @@ uint32_t cvtf16_32(uint16_t v)
|
||||
ret.exponant = 126 - s;
|
||||
ret.fraction = in.fraction << s;
|
||||
}
|
||||
} else if(in.exponant==0b11111)
|
||||
} else if(in.exponant==0b11111) {
|
||||
ret.exponant = 0b11111111;
|
||||
else {
|
||||
if(in.fraction)
|
||||
ret.fraction |= (1 << 22); // SNaN -> QNaN
|
||||
} else {
|
||||
int e = in.exponant - 15;
|
||||
ret.exponant = e + 127;
|
||||
}
|
||||
@@ -607,61 +609,87 @@ uint16_t cvtf32_16(uint32_t v, uint8_t rounding)
|
||||
// nan and infinites
|
||||
ret.exponant = 0b11111;
|
||||
ret.fraction = in.fraction >> 13;
|
||||
if(in.fraction && !ret.fraction)
|
||||
ret.fraction = 0b1000000000;
|
||||
if(in.fraction)
|
||||
ret.fraction |= 0b1000000000; // SNaN -> QNaN
|
||||
return ret.u16;
|
||||
} else {
|
||||
// regular numbers
|
||||
int e = in.exponant - 127;
|
||||
uint16_t f = (in.fraction>>13)|0b10000000000; // add back implicit msb
|
||||
uint16_t r = in.fraction&0b1111111111111;
|
||||
switch(rounding) {
|
||||
case 0: // nearest even
|
||||
if(r>=0b1000000000000)
|
||||
++f;
|
||||
break;
|
||||
case 1: // round down
|
||||
f += r?ret.sign:0;
|
||||
break;
|
||||
case 2: // round up
|
||||
f += r?(1-ret.sign):0;
|
||||
break;
|
||||
case 3: // truncate
|
||||
break;
|
||||
}
|
||||
if(f>0b11111111111) { // implicit msb included
|
||||
++e;
|
||||
f>>=1;
|
||||
}
|
||||
// remove implicit msb
|
||||
if(f) {
|
||||
while(!(f&0b10000000000)) {
|
||||
f<<=1;
|
||||
--e;
|
||||
}
|
||||
}
|
||||
// there is no msb to remove, as it's implicit and was not added back before
|
||||
if(!f) e = -15;
|
||||
else if(e<-14) {
|
||||
// flush to zero
|
||||
f >>= (-15-e);
|
||||
e = -15;
|
||||
if((rounding==1 && ret.sign) || ((rounding==2) && !ret.sign))
|
||||
f = 1; // rounding artifact
|
||||
}
|
||||
else if(e>15) {
|
||||
if((rounding==1 && !in.sign) || (rounding==2 && in.sign) || (rounding==3)) {
|
||||
// Clamp to max
|
||||
f=0b1111111111;
|
||||
e = 15;
|
||||
if(e < -14) {
|
||||
// result is a half-precision denormal (or zero)
|
||||
int shift = -14 - e;
|
||||
uint32_t mantissa = (1u << 23) | in.fraction;
|
||||
// total right shift to align 24-bit mantissa into 10-bit fraction
|
||||
int total_shift = 13 + shift;
|
||||
uint16_t fraction;
|
||||
int guard, sticky;
|
||||
if(total_shift >= 25) {
|
||||
fraction = 0;
|
||||
guard = 0;
|
||||
sticky = 1; // mantissa always nonzero (has implicit bit)
|
||||
} else {
|
||||
// overflow to inifity
|
||||
f=0;
|
||||
e = 16;
|
||||
fraction = (mantissa >> total_shift) & 0x3FF;
|
||||
guard = (mantissa >> (total_shift - 1)) & 1;
|
||||
sticky = (total_shift >= 2) ? ((mantissa & ((1u << (total_shift - 1)) - 1)) ? 1 : 0) : 0;
|
||||
}
|
||||
} else f&=0b1111111111; // remove implicit msb (bit 11)
|
||||
ret.fraction = f;
|
||||
ret.exponant = e+15;
|
||||
switch(rounding) {
|
||||
case 0: // nearest even
|
||||
if(guard && (sticky || (fraction & 1)))
|
||||
++fraction;
|
||||
break;
|
||||
case 1: // round down
|
||||
if((guard || sticky) && ret.sign)
|
||||
++fraction;
|
||||
break;
|
||||
case 2: // round up
|
||||
if((guard || sticky) && !ret.sign)
|
||||
++fraction;
|
||||
break;
|
||||
case 3: // truncate
|
||||
break;
|
||||
}
|
||||
if(fraction >= 0x400) {
|
||||
// rounding promoted denormal to smallest normal
|
||||
ret.fraction = 0;
|
||||
ret.exponant = 1;
|
||||
} else {
|
||||
ret.fraction = fraction;
|
||||
ret.exponant = 0;
|
||||
}
|
||||
} else {
|
||||
// normal result (e >= -14)
|
||||
uint16_t f = (in.fraction>>13)|0b10000000000;
|
||||
uint16_t r = in.fraction&0b1111111111111;
|
||||
switch(rounding) {
|
||||
case 0: // nearest even
|
||||
if(r > 0b1000000000000 || (r == 0b1000000000000 && (f & 1)))
|
||||
++f;
|
||||
break;
|
||||
case 1: // round down
|
||||
f += r?ret.sign:0;
|
||||
break;
|
||||
case 2: // round up
|
||||
f += r?(1-ret.sign):0;
|
||||
break;
|
||||
case 3: // truncate
|
||||
break;
|
||||
}
|
||||
if(f>0b11111111111) {
|
||||
++e;
|
||||
f>>=1;
|
||||
}
|
||||
if(e>15) {
|
||||
if((rounding==1 && !in.sign) || (rounding==2 && in.sign) || (rounding==3)) {
|
||||
f=0b1111111111;
|
||||
e = 15;
|
||||
} else {
|
||||
f=0;
|
||||
e = 16;
|
||||
}
|
||||
} else f&=0b1111111111;
|
||||
ret.fraction = f;
|
||||
ret.exponant = e+15;
|
||||
}
|
||||
}
|
||||
|
||||
return ret.u16;
|
||||
|
||||
@@ -13,5 +13,8 @@ void addCheckAlternate(void* addr, void* alt);
|
||||
void cleanAlternate(void);
|
||||
#ifdef HAVE_ALTJUMP
|
||||
uintptr_t getAlternateJump(void* addr, int is32bits);
|
||||
// will return MAP_FAIL (void*)-1LL if there no alternate at addr
|
||||
void* getAlternateData(void* addr);
|
||||
void setAlternateData(void* addr, void* data);
|
||||
#endif
|
||||
#endif //__ALTERNATE_H__
|
||||
@@ -8,6 +8,7 @@ uint32_t X31_hash_code(void* addr, int len);
|
||||
void FreeDynablock(dynablock_t* db, int need_lock, int need_remove);
|
||||
void MarkDynablock(dynablock_t* db);
|
||||
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
void MarkCRCRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
|
||||
void FreeInvalidDynablock(dynablock_t* db, int need_lock);
|
||||
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock);
|
||||
@@ -30,5 +31,6 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t native_addr);
|
||||
int getX64AddressInst(dynablock_t* db, uintptr_t x64pc);
|
||||
uintptr_t getX64InstAddress(dynablock_t* db, int inst);
|
||||
|
||||
dynablock_t* CreateDBnoAlt(x64emu_t* emu, uintptr_t addr, int is32bits);
|
||||
|
||||
#endif //__DYNABLOCK_H_
|
||||
@@ -10,6 +10,6 @@ typedef struct instsize_s instsize_t;
|
||||
void addInst(instsize_t* insts, size_t* size, int x64_size, int native_size);
|
||||
|
||||
void CancelBlock64(int need_lock);
|
||||
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new);
|
||||
dynablock_t* FillBlock64(uintptr_t addr, int is32bits, int inst_max, int is_new, int noalt);
|
||||
|
||||
#endif //__DYNAREC_ARM_H_
|
||||
@@ -55,7 +55,6 @@ extern char* ftrace_name;
|
||||
INTEGER(BOX64_DYNAREC_SEP, dynarec_sep, 1, 0, 2, 1) \
|
||||
BOOLEAN(BOX64_DYNAREC_DF, dynarec_df, 1, 1) \
|
||||
INTEGER(BOX64_DYNAREC_DIRTY, dynarec_dirty, 0, 0, 2, 0) \
|
||||
BOOLEAN(BOX64_DYNAREC_HOTPAGE_ALT, dynarec_hotpage_alt, 1, 0) \
|
||||
BOOLEAN(BOX64_DYNAREC_NOHOTPAGE, dynarec_nohotpage, 0, 0) \
|
||||
BOOLEAN(BOX64_DYNAREC_DIV0, dynarec_div0, 0, 1) \
|
||||
INTEGER(BOX64_DYNAREC_DUMP, dynarec_dump, 0, 0, 2, 1) \
|
||||
|
||||
@@ -227,6 +227,7 @@ GO("libselinux.so.1", selinux)
|
||||
GO("libsecret-1.so.0", secret1)
|
||||
GO("libpci.so.3", libpci)
|
||||
GO("libgmp.so.10", gmp)
|
||||
GO("libgmp.so", gmp)
|
||||
GO("libFAudio.so.0", faudio)
|
||||
GO("libgstallocators-1.0.so.0", gstallocators)
|
||||
GO("libgstapp-1.0.so.0", gstapp)
|
||||
|
||||
@@ -621,6 +621,13 @@ int my_sigactionhandler_oldcode_32(x64emu_t* emu, int32_t sig, int simple, sigin
|
||||
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14;
|
||||
if(!mmapped) info2->si_code = 1;
|
||||
info2->si_errno = 0;
|
||||
} else if (info->si_errno==0xb09d) {
|
||||
// bound exception
|
||||
sigcontext->uc_mcontext.gregs[I386_ERR] = 0;
|
||||
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 5;
|
||||
info2->si_errno = 0;
|
||||
info2->si_code = 128;
|
||||
info2->_sifields._sigfault.__si_addr = 0;
|
||||
}else {
|
||||
sigcontext->uc_mcontext.gregs[I386_ERR] = 0x14|((sysmapped && !(real_prot&PROT_READ))?0:1);
|
||||
sigcontext->uc_mcontext.gregs[I386_TRAPNO] = 14;
|
||||
|
||||
@@ -800,8 +800,8 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
|
||||
// check if block is still valid
|
||||
int is_hotpage = checkInHotPage(x64pc);
|
||||
uint32_t hash = (db->gone || is_hotpage)?0:X31_hash_code(db->x64_addr, db->x64_size);
|
||||
if(!db->gone && !is_hotpage && hash==db->hash) {
|
||||
dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, always_test=%d) is clean, %s continuing at %p (%p)!\n", db, db->x64_addr, db->always_test, type_callret?"self-loop":"ret from callret", (void*)x64pc, (void*)addr);
|
||||
if(!db->gone && (!is_hotpage || db->autocrc) && hash==db->hash) {
|
||||
dynarec_log(LOG_INFO, "Dynablock (%p, x64addr=%p, always_test=%d, autocrc=%d) is clean, %s continuing at %p (%p)!\n", db, db->x64_addr, db->always_test, db->autocrc, type_callret?"self-loop":"ret from callret", (void*)x64pc, (void*)addr);
|
||||
// it's good! go next opcode
|
||||
CONTEXT_PC(p)+=4;
|
||||
if(db->always_test)
|
||||
|
||||
@@ -89,8 +89,8 @@ void getUnalignedRange(uintptr_t start, size_t size, uintptr_t addrs[])
|
||||
int mark_db_unaligned(dynablock_t* db, uintptr_t x64pc)
|
||||
{
|
||||
add_unaligned_address(x64pc);
|
||||
db->hash++; // dirty the block
|
||||
MarkDynablock(db); // and mark it
|
||||
db->to_delete = 1; // mark block for deletion
|
||||
MarkDynablock(db); // and mark it as dirty
|
||||
if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as needing unaligned handling\n", db, (void*)x64pc);
|
||||
return 2; // marked, exit handling...
|
||||
}
|
||||
@@ -98,8 +98,8 @@ if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address
|
||||
int mark_db_autosmc(dynablock_t* db, uintptr_t x64pc)
|
||||
{
|
||||
add_autosmc_address(x64pc);
|
||||
db->hash++; // dirty the block
|
||||
MarkDynablock(db); // and mark it
|
||||
db->to_delete = 1; // mark block for deletion
|
||||
MarkDynablock(db); // and mark it as dirty
|
||||
if(BOX64ENV(showsegv)) printf_log(LOG_INFO, "Marked db %p as dirty, and address %p as creating internal SMC\n", db, (void*)x64pc);
|
||||
return 2; // marked, exit handling...
|
||||
}
|
||||
|
||||
@@ -298,6 +298,7 @@ void freeVulkanOverlay(my_vulkanoverlay_t* v)
|
||||
#define GO_uFpubp(A, B, N) static uint32_t my_##A##_##N(void* a, uint32_t b, void* c, void* d) {return (uint32_t)F4(A, #B +2, N);}
|
||||
#define GO_UFpp(A, B, N) static uint64_t my_##A##_##N(void* a, void* b) {return (uint64_t)F2(A, #B +2, N);}
|
||||
#define GO_UFpu(A, B, N) static uint64_t my_##A##_##N(void* a, uint32_t b) {return (uint64_t)F2(A, #B +2, N);}
|
||||
#define GO_UFpUU(A, B, N) static uint64_t my_##A##_##N(void* a, uint64_t b, uint64_t c) {return (uint64_t)F3(A, #B +2, N);}
|
||||
#define GO_UFppuu(A, B, N) static uint64_t my_##A##_##N(void* a, void* b, uint32_t c, uint32_t d) {return (uint64_t)F4(A, #B +2, N);}
|
||||
#define GO_UFpUui(A, B, N) static uint64_t my_##A##_##N(void* a, uint64_t b, uint32_t c, int d) {return (uint64_t)F4(A, #B +2, N);}
|
||||
|
||||
@@ -628,6 +629,7 @@ CREATE(vkCreateDebugReportCallbackEXT) // needs better wrapping because of Debu
|
||||
CREATE(vkCreateDebugUtilsMessengerEXT) // Needs better wrapping?
|
||||
CREATE(vkRegisterDeviceEventEXT)
|
||||
CREATE(vkCreateWin32SurfaceKHR)
|
||||
CREATE(vkCreateShaderInstrumentationARM)
|
||||
#undef CREATE
|
||||
#undef GO
|
||||
// DESTROY64
|
||||
@@ -699,6 +701,7 @@ DESTROY(vkDestroyPipelineBinaryKHR)
|
||||
DESTROY(vkDestroyTensorARM)
|
||||
DESTROY(vkDestroyTensorViewARM)
|
||||
DESTROY(vkDestroyDataGraphPipelineSessionARM)
|
||||
DESTROY(vkDestroyShaderInstrumentationARM)
|
||||
|
||||
#undef DESTROY
|
||||
#undef GO
|
||||
|
||||
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user