32 Commits
Author SHA1 Message Date
JWWTSL bb716a2a65 Fix typos in comments and documentation (#1072)
Correct "adressing", "constains", "informations", "Aleady" and
"interpretor".
2026-10-20 15:45:11 +02:00
ptitSeb 7dec0819b5 [WRAPPER] Added 1 wrapped function to libxml2 (for #1061) 2026-09-27 08:26:24 +02:00
SpongeBob b05cb3ab54 Fix LOCK 16-bit INC/DEC using 32-bit primop in interpreter path (#1070)
RunF066 handles F0 66 FF /0,/1 (LOCK INC/DEC Ew). The non-DYNAREC path applied inc32/dec32 to ED->dword[0], corrupting the upper 16 bits and computing OF/SF/ZF/AF/PF at the wrong operand width. The DYNAREC path just above correctly uses inc16/dec16, as does the non-LOCK Grp5 Ew handler in x86run66.c (EW->word[0] = inc16/dec16). Narrow the interpreter LOCK path to ED->word[0] with inc16/dec16.
2026-09-11 09:45:03 +02:00
SpongeBob dea645b38d Fix aligned_realloc returning freed pointer (use-after-free) (#1069)
my_safer_scalable_aligned_realloc and my_scalable_aligned_realloc grew the allocation via box_memalign+memcpy+box_free(p), then returned p instead of new_p. Callers received a dangling pointer while the live copy leaked, causing double-ownership, heap corruption, and crashes on TBB aligned growth. Return new_p.
2026-09-11 09:44:05 +02:00
SpongeBob 707a141e0d Fix CVTTPS2PI low lane using high lane for lower-bound check (#1068)
Case 0x2C (CVTTPS2PI Gm,Ex) validated GM.sd[0] against EX->f[1] for the negative-overflow test instead of EX->f[0]. The high lane just above correctly tests f[1] twice, and CVTPS2PI just below loops per-lane with f[i]. A low lane in range paired with an out-of-range high lane (e.g. f0=1.0, f1=-3e9) wrongly produced the 0x80000000 indefinite value, and a truly underflowing low lane could slip through. Test the low lane against itself.
2026-09-11 09:42:51 +02:00
SpongeBob 14181b503b Fix atfork parent/child loop decrement causing infinite loop and OOB (#1067)
x86emu_fork ran parent/child atfork handlers with 'for (i=0; i<sz; --i)'. With sz>0, i goes 0,-1,-2... staying <sz forever: infinite loop plus out-of-bounds atforks[i] access. The prepare loop just above correctly iterates reverse with '--i' from sz-1. Change parent/child loops to '++i' for forward iteration.
2026-09-10 09:18:54 +02:00
SpongeBob 9a67cb9355 Fix 16-bit disp16 precedence bug in getecommon16o (#1066)
In C, == binds tighter than &, so 'm&7==6' parsed as 'm&(7==6)' = 'm&0' = always false. Disp16 was never fetched for mod==00,rm==110 16-bit addressing (GET_EW16_OFFS), leaving a wrong effective address and unadvanced EIP. Parenthesize as '(m&7)==6' to match getecommon16.
2026-09-10 08:54:49 +02:00
ptitSeb 39d3ed2033 [INTPER] Added 64 66 8D opcode (for #1064) 2026-08-12 22:27:32 +02:00
ptitSeb 646fc2d3a8 [INTERP] Added 66 8D opcode (for #1064) 2026-08-12 19:35:09 +02:00
ptitSeb 0579f8b9c4 [PANDORA] Fix build 2026-01-07 18:00:58 +01:00
docgalaxyblock 50a2603027 Fix typo 'Snapragon' in CMakeLists.txt (#1057) 2025-11-22 15:21:33 +01:00
ptitSeb 10224524df [ELFLOADER] Fixed regression from previous commit (for #1055) 2025-11-11 13:29:51 +01:00
ptitSeb 0886bb79c4 [ELFLOADER] Added support for IFUNC in PltResolver 2025-11-06 16:26:48 +01:00
Loyalburrito fa14e0ab14 Add comments to systemd-binfmt restart script (#1050)
This script checks for the presence of systemd and restarts the binfmt_misc service
2025-09-20 18:37:35 +02:00
ptitSeb ac48800fbb Added 64/65 F7 opcode (for #1048) 2025-07-28 13:58:03 +02:00
ptitSeb b197194e2d [CI] Changed TAGRA build to use ubunt 22.04 as 20.04 has been removed 2025-06-22 13:41:26 +02:00
ptitSeb 2796d6ef92 [WRAPPER] Added 1 more wrapped function to libgobject2 (used by steam) 2025-06-22 13:23:14 +02:00
ptitSeb d60937b1ac [WRAPPER] Added wrapped libGLX (backported from box64) 2025-04-28 12:02:52 +02:00
ptitSeb d0aad67ba0 [WRAPPER] Add libm to the libc collection of libs 2025-03-07 16:59:22 +01:00
ptitSeb 66fc843ae8 [WRAPPER] Fixed ld-linux.so.2 being an essential (not emulated) lib 2025-03-07 16:21:08 +01:00
ptitSeb 7e56375859 [WRAPPER] Some fixes to bsd wrapper and essential libs handling 2025-03-07 15:54:03 +01:00
Hugh Cole-Baker c13b3cc9cd [DEBIAN] exclude x86 libunwind from shlibdeps (#1032) 2025-02-22 22:22:32 +01:00
ptitSeb ba5b9e9954 Fixed a potential issue with findBlockHinted (for #1031) 2025-02-21 15:10:56 +01:00
ptitSeb fa59e748f9 [DYNAREC] Added a test for optimized REP MOVSB to avoid optim on overlapping addresses move 2025-02-12 12:49:37 +01:00
ptitSeb c467c05112 [CI] Update to upload-artifact v4 2025-02-10 09:18:51 +01:00
ptitSeb bb164a299f [DYNAREC] Optimized REP MOVSB opcode 2025-02-10 09:05:52 +01:00
ptitSeb eaf2e84e19 [INTERPRETER] Removed some useless tests on x87 comp 2025-01-08 15:54:50 +01:00
ptitSeb 7dcba89c71 [DYNAREC] Removed some bloated x87 code, improved test19 (backported from box64) 2025-01-08 15:31:14 +01:00
ptitSeb 5c5639be09 Trace program break to not allocate memory over there (backported from box64) 2025-01-07 15:39:44 +01:00
ValdikSS ee0c949bc2 Document BOX86_ARG0 argv[0] rewriting variable (#1021) 2025-01-04 17:00:37 +01:00
ValdikSS d9402213f6 Fix crash with incorrect argv[0]: rewrite it only if "box86" is present (#1020) 2025-01-04 16:58:17 +01:00
ValdikSS efe8bb4e6c Bumped version to v0.3.8 (#1019) 2025-01-04 13:27:06 +01:00
53 changed files with 1380 additions and 489 deletions

No files matched your search

+5 -5
View File
@@ -34,16 +34,16 @@ jobs:
include:
- platform: TEGRAX1
type: Release
os: ubuntu-20.04
os: ubuntu-22.04
- platform: TEGRAX1
type: Trace
os: ubuntu-20.04
os: ubuntu-22.04
- platform: TEGRAX1ARM32
type: Release
os: ubuntu-20.04
os: ubuntu-22.04
- platform: TEGRAX1ARM32
type: Trace
os: ubuntu-20.04
os: ubuntu-22.04
runs-on: ${{ matrix.os }}
steps:
@@ -111,7 +111,7 @@ jobs:
ctest -j$(nproc)
- name: "Upload Artifact"
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box86
+4 -3
View File
@@ -20,9 +20,9 @@ option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based devi
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROIDXU4 "Set to ON if targeting an ODROID-XU4 device" ${ODROIDXU4})
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(SD845 "Set to ON if targeting a Snapdragon 845 based device" ${SD845})
option(SD865 "Set to ON if targeting a Snapdragon 865 based device" ${SD865})
option(SD888 "Set to ON if targeting a Snapdragon 888 based device" ${SD888})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
@@ -413,6 +413,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibbsd.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibglx.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibdl.c"
+15
View File
@@ -1,3 +1,18 @@
box86 (0.3.8) unstable; urgency=low
* Some optimisation of x86 P flags handling
* Some x87 fixes and improvments
* Added some of the tim64 wrapped functions to libc and friends
* Changed the installation folder of x86 libs to avoid conflict with linux distro
* Some fixes to internal memory tracking
* Some more Vulkan extensions wrapped
* Better handling of BOX86_MAXCPU
* Some changes and improvments on Signal handling
* More wrapped functions, and fix to some existing ones
* A few more syscall, and fix to some existing ones
* New build profile for SD865
-- Sebastien Chevalier <[email protected]> Fri, 06 Dec 2024 14:06:00 -0100
box86 (0.3.6) unstable; urgency=low
* Wrapping: More libs and and function wrapping (gtk3, vulkan...)
* Reworked X11 Callback handling, for better stability
+6 -1
View File
@@ -10,4 +10,9 @@ override_dh_auto_configure:
-DNOGIT=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
dh_shlibdeps \
--exclude=libgcc_s.so.1 \
--exclude=libpng12.so.0 \
--exclude=libstdc++.so.5 \
--exclude=libstdc++.so.6 \
--exclude=libunwind.so.8
+6 -1
View File
@@ -293,6 +293,11 @@ Use of the new fuext_waitc syscall
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX86_ARG0
Define argv[0] of the executable.
* yyyy
Will rewrite argv[0] instead of using program path.
#### BOX86_FIX_64BIT_INODES *
Fix/Don't fix 64bit inodes
* 0 : Don't fix 64bit inodes. (Default.)
@@ -316,7 +321,7 @@ Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a va
#### BOX86_BOX64
Define where to find box64 binary
* yyyy
Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
Will use yyyy as x86_64 interpreter, to launch x64_64 binaries
#### BOX86_JITGDB *
+2
View File
@@ -1,4 +1,6 @@
#!/bin/sh
# Restart the systemd-binfmt service to load new binary format rules.
# This ensures the system is immediately ready to run programs with Box86.
if [ -d '/run/systemd/system' ]; then
systemctl restart systemd-binfmt || :
fi
+1 -1
View File
@@ -729,7 +729,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
variables["u"] = -1 # Unsigned shift
variables["w"] = -1 # wback (used in adressing)
variables["w"] = -1 # wback (used in addressing)
variables["shift"] = False # Shift already detected?
+4 -3
View File
@@ -74,7 +74,7 @@ For each of them:
NOTE: Those structure letters are "fake types" that are accepted in the macros.
`gbl` contains the first list, `redirects` the second and
`filespec` constains file specific informations (eg, structures, typedefs required...).
`filespec` contains file specific information (eg, structures, typedefs required...).
After sorting the data, it generates:
@@ -631,7 +631,7 @@ class Clauses:
combinable[len(last_combined) - 1] = True
add = (i | attempt[0], m | (i ^ attempt[0]))
if add in combined:
continue # Aleady added
continue # Already added
combined.append(add)
last_combined.pop()
last_combined = combined
@@ -753,6 +753,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("appindicator","appindicator3")\
or match("appindicator","ayatanaappindicator3")\
or match("appindicator3","ayatanaappindicator3")\
or match("libgl", "libglx") \
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
@@ -1150,7 +1151,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
for fhdr in files_header:
files_guard[fhdr] = trim(files_guard[fhdr])
# TODO: put the informations below in a structure (like in box64, where
# TODO: put the information below in a structure (like in box64, where
# typedefs & co. are stored in an ABI-specific structure)
return_x87: str = "DKdf"
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 3
#define BOX86_REVISION 8
#define BOX86_REVISION 9
#endif //__BOX86_VERSION_H_
+17 -1
View File
@@ -999,6 +999,9 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
// don't need to add precise tracking probably
}
uintptr_t pbrk = 0;
uintptr_t old_brk = 0;
uintptr_t* cur_brk = NULL;
void loadProtectionFromMap()
{
if(box86_mapclean)
@@ -1015,8 +1018,14 @@ void loadProtectionFromMap()
if(sscanf(buf, "%x-%x %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
if(!pbrk && strstr(buf, "[heap]"))
pbrk = s;
}
}
if(!pbrk) {
printf_log(LOG_INFO, "BOX86: Warning, program break not found\n");
if(cur_brk) pbrk = *cur_brk; // approximate is better than nothing
}
fclose(f);
box86_mapclean = 1;
}
@@ -1051,12 +1060,18 @@ int getMmapped(uintptr_t addr)
#define MEDIAN (void*)0x40000000
static void* findBlockHinted(void* hint, size_t size, uintptr_t mask)
{
// first, check if program break as changed
if(pbrk && cur_brk && *cur_brk!=old_brk) {
old_brk = *cur_brk;
setProtection(pbrk, old_brk-pbrk, PROT_READ|PROT_WRITE);
}
int prot;
if(hint<LOWEST) hint = LOWEST;
uintptr_t bend = 0;
uintptr_t cur = (uintptr_t)hint;
if(!mask) mask = 0xffff;
while(bend!=0xffffffffLL) {
uintptr_t end_mem = 0xffffffffLL - mask;
while(bend<end_mem) {
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
if(bend-cur>=size)
return (void*)cur;
@@ -1165,6 +1180,7 @@ void init_custommem_helper(box86context_t* ctx)
if(inited) // already initialized
return;
inited = 1;
cur_brk = dlsym(RTLD_NEXT, "__curbrk");
memprot = init_rbtree();
init_mutexes();
#ifdef DYNAREC
+13 -1
View File
@@ -2520,13 +2520,25 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("REP MOVSB");
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,1);
SMREAD();
GETDIR(x3, 1);
SUBS_REG_LSL_IMM5(x2, xEDI, xESI, 0);
SUBS_IMM8(x2, x2, 4);
B_MARK(cCC);
MARK2;
SUBS_IMM8(x2, xECX, 4);
B_MARK(cCC);
LDRAI_REG_LSL_IMM5(x1, xESI, x3, 2);
STRAI_REG_LSL_IMM5(x1, xEDI, x3, 2);
MOV_REG(xECX, x2);
B_MARK2(cNE);
B_MARK3(c__);
MARK;
LDRBAI_REG_LSL_IMM5(x1, xESI, x3, 0);
STRBAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
MARK3;
SMWRITE();
// done
break;
+1 -1
View File
@@ -475,7 +475,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVD(d1, v0);
}
VCMP_F32(d1*2, s0);
FCOMI(x1, x2, 0, 0, d1*2, s0, 1);
FCOMI(x1, x2);
break;
case 0x31:
+1 -1
View File
@@ -282,7 +282,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
GETEX(q0, 0);
VCMP_F64(v0, q0);
FCOMI(x1, x2, 0, 0, v0, q0, 0);
FCOMI(x1, x2);
break;
case 0x38: // SSSE3 opcodes
+4 -4
View File
@@ -100,7 +100,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
break;
case 0xD8:
case 0xD9:
@@ -118,7 +118,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -275,7 +275,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
}
FCOM(x1, x2, x3, x14, v1, ST_IS_F(0)?s0:d1, ST_IS_F(0));
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
@@ -296,7 +296,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
}
FCOM(x1, x2, x3, x14, v1, ST_IS_F(0)?s0:d1, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
+1 -1
View File
@@ -126,7 +126,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64_0(v1);
}
FCOM(x1, x2, 0, 0, v1, 0, ST_IS_F(0)); // same flags...
FCOM(x1, x2); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
+3 -3
View File
@@ -128,7 +128,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -185,7 +185,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VCMP_F64(v1, d0);
FCOM(x1, x2, x3, x14, v1, d0, 0);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FICOMP ST0, Ed");
@@ -196,7 +196,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
VCMP_F64(v1, d0);
FCOM(x1, x2, x3, x14, v1, d0, 0);
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
+2 -2
View File
@@ -149,7 +149,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
break;
case 0xF0:
case 0xF1:
@@ -168,7 +168,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
break;
case 0xE0:
+4 -4
View File
@@ -96,7 +96,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
break;
case 0xD8:
case 0xD9:
@@ -114,7 +114,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -258,7 +258,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2, x3, x14, v1, d1, 0);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
@@ -275,7 +275,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2, x3, x14, v1, d1, 0);
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
+49 -5
View File
@@ -32,6 +32,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uint8_t ed;
int v1, v2;
int i1, i2, i3;
int j32;
MAYUSE(v2);
MAYUSE(v1);
@@ -111,7 +112,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
break;
case 0xE8:
case 0xE9:
@@ -129,7 +130,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -178,10 +179,53 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("FISTTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
parity = getedparity(dyn, ninst, addr, nextop, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistt64, -1, 0);
if(ninst
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)dyn->insts[ninst-1].x86.addr==0xDF
&& (((*(uint8_t*)(dyn->insts[ninst-1].x86.addr+1))>>3)&7)==5)
{
if(parity) {
STRD_IMM8(x2, ed, 0); // x2/x3 is 64bits
} else {
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
}
} else {
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
fpu_get_scratch_double(dyn); // to alocate v0
v2 = fpu_get_scratch_double(dyn);
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
} else if(a>0) {
ADD_IMM8(x14, x14, a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x14, xEmu, x14, 4); // each fpu_ll is 2 int64: ref than ll
MOVW(x2, offsetof(x86emu_t, fpu_ll)); //can be optimized?
ADD_REG_LSL_IMM5(x14, x14, x2, offsetof(fpu_ll_t, sref));
VLDR_64(v2, x14, 0);
VCEQ_32(v2, v2, v1); // compare
VMOVfrV_D(x2, x3, v2);
ANDS_REG_LSL_IMM5(x2, x2, x3, 0); // if NE then values are the same!
B_MARK(cEQ); // do the i64 conversion
// memcpy(ed, &STll(0).ll, sizeof(int64_t));
LDRD_IMM8(x2, x14, offsetof(fpu_ll_t, sq)); // load ll
B_MARK3(c__);
MARK;
MOV32(x2, arm_fist64_3);
VMOV_64(0, v1); // prepare call to log2
CALL_1DR_U64(x2, x2, x3, x14, (1<<x1));
MARK3;
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
+2 -2
View File
@@ -94,7 +94,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -107,7 +107,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOM(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOM(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
+4 -74
View File
@@ -90,7 +90,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
@@ -111,7 +111,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VCMP_F64(v1, v2);
}
FCOMI(x1, x2, x3, x14, v1, v2, ST_IS_F(0));
FCOMI(x1, x2);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
@@ -186,9 +186,9 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
VCVT_S32_F32(s0, v1);
} else {
VCVTR_S32_F64(s0, v1);
VCVT_S32_F64(s0, v1);
}
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
@@ -337,12 +337,10 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x3, ed, 4);
}
} else {
#if 1
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
fpu_get_scratch_double(dyn); // to alocate v0
v2 = fpu_get_scratch_double(dyn);
#if 1
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
@@ -375,74 +373,6 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK3;
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
#else
v0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
// check STll(0).ref==ST(0).q so emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top]
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
} else if(a>0) {
ADD_IMM8(x14, x14, a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x14, xEmu, x14, 4); // each fpu_ll is 2 int64: ref than ll
MOVW(x2, offsetof(x86emu_t, fpu_ll)); //can be optimized?
ADD_REG_LSL_IMM5(x14, x14, x2, 0);
VLDR_64(v2, x14, 0);
VCEQ_32(v2, v2, v1); // compare
VMOVfrV_D(x2, x3, v2);
ANDS_REG_LSL_IMM5(x2, x2, x3, 0); // if NE then values are the same!
B_MARK(cEQ); // do the i64 conversion
// memcpy(ed, &STll(0).ll, sizeof(int64_t));
LDRD_IMM8(x2, x14, 8); // load ll
B_MARK3(c__);
MARK;
VEOR(v0, v0, v0);
MOVW(x2, 0x41F0);
VMOVtoDx_16(v0, 3, x2); // V0 = (1<<32) as double
VMOVfrDx_32(x14, v1, 1); // get high part to extract sign
VABS_F64(v1 ,v1); //ST0 will be poped, so lost...
VDIV_F64(v2, v1, v0); // v2 = abs(ST0)/(1<<32) : so 32 bits high part
MSR_nzcvq_0();
VMRS(x2); // get fpscr
ORR_IMM8(x3, x2, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_U32_F64(s0, v2); // convert high part to U32
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMSR(x2); // put back fpscr
TSTS_IMM8_ROR(x3, 0b00000001, 0);
B_MARK2(cEQ); // not overflow...
MARKLOCK;
MOV_IMM(x3, 0b10, 1); // 0x80000000
MOVW(x2, 0);
B_MARK3(c__);
MARK2; // continue conversion, it fits an int64!
VCVT_F64_U32(v2, s0); // int part now
VMLS_F64(v1, v2, v0); // compute low part
VMOVfrV(x3, s0); // transfert high path
TSTS_IMM8_ROR(x14, 0b10, 1); // test high part with 0x800000000
B_MARKLOCK(cNE); // int overflow...
VCVT_U32_F64(s0, v1); // convert low part
VMOVfrV(x2, s0); // transfert low part
TSTS_IMM8_ROR(x14, 0b10, 1); // 0x800000000
B_MARK3(cEQ);
RSBS_IMM8(x2, x2, 0); // NEG(i64)
RSC_IMM8(x3, x3, 0);
MARK3;
STR_IMM9(x2, x1, 0);
STR_IMM9(x3, x1, 4);
#endif
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x2, x3, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistp64, -1, 0);
#endif
}
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
-22
View File
@@ -126,21 +126,6 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
fpu_fbst(emu, ed);
}
void arm_fistp64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).sref==ST(0).sq) {
memcpy(ed, &STll(0).sq, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
int64_t arm_fist64_0(double d)
{
int64_t tmp;
@@ -178,13 +163,6 @@ int64_t arm_fist64_3(double d)
return tmp;
}
void arm_fistt64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
int64_t tmp = ST0.d;
memcpy(ed, &tmp, sizeof(tmp));
}
void arm_fld(x86emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
-2
View File
@@ -16,8 +16,6 @@ void arm_fscale(x86emu_t* emu);
void arm_fbld(x86emu_t* emu, uint8_t* ed);
void arm_fild64(x86emu_t* emu, int64_t* ed);
void arm_fbst(x86emu_t* emu, uint8_t* ed);
void arm_fistp64(x86emu_t* emu, int64_t* ed);
void arm_fistt64(x86emu_t* emu, int64_t* ed);
void arm_fld(x86emu_t* emu, uint8_t* ed);
void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
+3 -57
View File
@@ -316,7 +316,7 @@
#define IFXN(A, B) if((dyn->insts[ninst].x86.gen_flags&(A) && !(dyn->insts[ninst].x86.gen_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3, s4, v1, v2, is_f) \
#define FCOM(s1, s2) \
VMRS_APSR(); /* 0b0100011100000000 */ \
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, sw)); /*offset is 8bits right?*/ \
BIC_IMM8(s1, s1, 0b01000111, 12); \
@@ -324,36 +324,10 @@
ORR_IMM8_COND(cEQ, s1, s1, 0b01000000, 12); /* equal */ \
ORR_IMM8_COND(cMI, s1, s1, 0b00000001, 12); /* less than */ \
/* greater than leave 0 */ \
if(s4) { \
Bcond(cVS, (is_f?11:13)*4-8); \
if(is_f) { \
MOVW(s4, 0); \
MOVT(s4, 0x7ff0); /* +inf */ \
VMOVfrV(s2, v1); \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
Bcond(cEQ, 5*4-8); /* same */ \
VMOVfrV(s2, v2); \
ORR_IMM8(s4, s4, 0b10, 1); /* -inf */ \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
} else { \
MOVW(s4, 0); \
MOVT(s4, 0x7ff0); /* +inf */ \
VMOVfrV_D(s2, s3, v1); \
ORR_REG_LSL_IMM5(s2, s2, s3, 0); \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
Bcond(cEQ, 6*4-8); /* same */ \
VMOVfrV_D(s2, s3, v2); \
ORR_REG_LSL_IMM5(s2, s2, s3, 0); \
ORR_IMM8(s4, s4, 0b10, 1); /* -inf */ \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
} \
Bcond(cNE, 4+4-8); /* same */ \
MOVW(s1, 0); \
} \
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2, s3, s4, v1, v2, is_f) \
#define FCOMI(s1, s2) \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
VMRS_APSR(); /* 0b111 */ \
BIC_IMM8(xFlags, xFlags, 0b1000101, 0); \
@@ -361,38 +335,10 @@
ORR_IMM8_COND(cEQ, xFlags, xFlags, 0b01000000, 0); /* zero */ \
ORR_IMM8_COND(cMI, xFlags, xFlags, 0b00000001, 0); /* less than */ \
/* greater than leave 0 */ \
if(s4) { \
Bcond(cVS, (is_f?11:13)*4-8); \
if(is_f) { \
MOVW(s4, 0); \
MOVT(s4, 0x7ff0); /* +inf */ \
VMOVfrV(s2, v1); \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
Bcond(cEQ, 5*4-8); /* same */ \
VMOVfrV(s2, v2); \
ORR_IMM8(s4, s4, 0b10, 1); /* -inf */ \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
} else { \
MOVW(s4, 0); \
MOVT(s4, 0x7ff0); /* +inf */ \
VMOVfrV_D(s2, s3, v1); \
ORR_REG_LSL_IMM5(s2, s2, s3, 0); \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
Bcond(cEQ, 6*4-8); /* same */ \
VMOVfrV_D(s2, s3, v2); \
ORR_REG_LSL_IMM5(s2, s2, s3, 0); \
ORR_IMM8(s4, s4, 0b10, 1); /* -inf */ \
CMPS_REG_LSL_IMM5(s2, s4, 0); \
} \
Bcond(cNE, 4+4-8); /* same */ \
BIC_IMM8(xFlags, xFlags, 0b1000101, 0); \
} \
} \
SET_DFNONE(s1); \
IFX(X_OF|X_AF|X_SF|X_PEND) { \
/* clear 0b100010010000 */ \
BIC_IMM8(xFlags, xFlags, 0b10001001, 14); \
} \
SET_DFNONE(s1); \
#if STEP == 0
+9 -1
View File
@@ -1808,7 +1808,7 @@ static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
if(!a->dlpi_name[0]) /*don't send information about box86 itself*/ \
return 0; \
return RunFunctionFmt(my_dl_iterate_phdr_fct_##A, "pLp", a, b, c); \
}
@@ -2033,6 +2033,9 @@ kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h)
return h?h->weakdefver:NULL;
}
#ifndef STT_GNU_IFUNC
#define STT_GNU_IFUNC 10
#endif
uintptr_t pltResolver = ~(uintptr_t)0;
EXPORT void PltResolver(x86emu_t* emu)
@@ -2076,6 +2079,11 @@ EXPORT void PltResolver(x86emu_t* emu)
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
RunElfInitPltResolver(sym_elf, emu);
}
if(sym_elf && sym && ((sym->st_info&0xf)==STT_GNU_IFUNC)) {
// this is an IFUNC, needs to evaluate the function first!
printf_dump(LOG_DEBUG, " Indirect function, will call the resolver now at %p\n", (void*)offs);
offs = RunFunction(offs, 0);
}
offs = (uintptr_t)getAlternate((void*)offs);
if(p) {
+1 -1
View File
@@ -108,7 +108,7 @@
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m&7==6) base = F16S; break; \
case 0: if((m&7)==6) base = F16S; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
+2 -2
View File
@@ -53,12 +53,12 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
// error...
} else if(v!=0) {
// execute atforks parent functions
for (int i=0; i<my_context->atfork_sz; --i)
for (int i=0; i<my_context->atfork_sz; ++i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<my_context->atfork_sz; --i)
for (int i=0; i<my_context->atfork_sz; ++i)
if(my_context->atforks[i].child)
EmuCall(emu, my_context->atforks[i].child);
}
+1 -1
View File
@@ -270,7 +270,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
GM.sd[1] = 0x80000000;
else
GM.sd[1] = EX->f[1];
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[1]<-(float)0x80000000U)
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[0]<-(float)0x80000000U)
GM.sd[0] = 0x80000000;
else
GM.sd[0] = EX->f[0];
+35
View File
@@ -12,6 +12,7 @@
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
@@ -416,6 +417,40 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
return addr-1; // ignore FS: to execute regular opcode
break;
case 0xF7: /* GRP3 Ed(,Id) */
nextop = F8;
GET_ED_OFFS(tlsdata);
switch((nextop>>3)&7) {
case 0:
case 1: /* TEST Ed,Id */
tmp32u = F32;
test32(emu, ED->dword[0], tmp32u);
break;
case 2: /* NOT Ed */
ED->dword[0] = not32(emu, ED->dword[0]);
break;
case 3: /* NEG Ed */
ED->dword[0] = neg32(emu, ED->dword[0]);
break;
case 4: /* MUL EAX,Ed */
mul32_eax(emu, ED->dword[0]);
break;
case 5: /* IMUL EAX,Ed */
imul32_eax(emu, ED->dword[0]);
break;
case 6: /* DIV Ed */
if(!ED->dword[0])
emit_div0(emu, (void*)R_EIP, 0);
div32(emu, ED->dword[0]);
break;
case 7: /* IDIV Ed */
if(!ED->dword[0])
emit_div0(emu, (void*)R_EIP, 0);
idiv32(emu, ED->dword[0]);
break;
}
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
+6
View File
@@ -48,6 +48,12 @@ uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
GW.word[0] = EW->word[0];
break;
case 0x8D: /* LEA Gw,M */
nextop = F8;
GET_ED_; // segment doesn't enter in the computation
GW.word[0] = (uint16_t)(uint32_t)ED;
break;
default:
return 0;
}
+6 -2
View File
@@ -284,7 +284,11 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
GET_EW;
EW->word[0] = emu->segs[(nextop&0x38)>>3];
break;
case 0x8D: /* LEA Gw,M */
nextop = F8;
GET_ED_;
GW.word[0] = (uint16_t)(uint32_t)ED;
break;
case 0x8E: /* MOV Seg,Ew */
nextop = F8;
GET_EW;
@@ -584,4 +588,4 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
return 0;
}
return addr;
}
}
+2 -2
View File
@@ -147,7 +147,7 @@ uintptr_t RunF066(x86emu_t *emu, uintptr_t addr)
} while(arm_lock_write_h(ED, inc16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = inc32(emu, ED->dword[0]);
ED->word[0] = inc16(emu, ED->word[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
@@ -168,7 +168,7 @@ uintptr_t RunF066(x86emu_t *emu, uintptr_t addr)
} while(arm_lock_write_h(ED, dec16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = dec32(emu, ED->dword[0]);
ED->word[0] = dec16(emu, ED->word[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
-8
View File
@@ -84,10 +84,6 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
emu->sw.f.F87_C0 = 1;
emu->sw.f.F87_C2 = 1;
emu->sw.f.F87_C3 = 1;
} else if ((b==-INFINITY) || (ST0.d==INFINITY)) {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C3 = 0;
} else if (isgreater(ST0.d, b)) {
emu->sw.f.F87_C0 = 0;
emu->sw.f.F87_C2 = 0;
@@ -115,10 +111,6 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
SET_FLAG(F_CF);
SET_FLAG(F_PF);
SET_FLAG(F_ZF);
} else if ((b==-INFINITY) || (ST0.d==INFINITY)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
} else if (isgreater(ST0.d, b)) {
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
+2 -2
View File
@@ -380,14 +380,14 @@ static void initDummyLib(library_t *lib)
static const char* essential_libs[] = {
"libc.so.6", "libpthread.so.0", "librt.so.1", "libGL.so.1", "libGL.so", "libX11.so.6",
"libasound.so.2", "libdl.so.2", "libm.so.6",
"libasound.so.2", "libdl.so.2", "libm.so.6", "libbsd.so.0", "libbsd.so", "ld-linux.so.2",
"libXxf86vm.so.1", "libXinerama.so.1", "libXrandr.so.2", "libXext.so.6", "libXfixes.so.3", "libXcursor.so.1",
"libXrender.so.1", "libXft.so.2", "libXi.so.6", "libXss.so.1", "libXpm.so.4", "libXau.so.6", "libXdmcp.so.6",
"libX11-xcb.so.1", "libxcb.so.1", "libxcb-xfixes.so.0", "libxcb-shape.so.0", "libxcb-shm.so.0", "libxcb-randr.so.0",
"libxcb-image.so.0", "libxcb-keysyms.so.1", "libxcb-xtest.so.0", "libxcb-glx.so.0", "libxcb-dri2.so.0", "libxcb-dri3.so.0",
"libXtst.so.6", "libXt.so.6", "libXcomposite.so.1", "libXdamage.so.1", "libXmu.so.6", "libxkbcommon.so.0",
"libxkbcommon-x11.so.0", "libpulse-simple.so.0", "libpulse.so.0", "libvulkan.so.1", "libvulkan.so",
"ld-linux-x86-64.so.2", "crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4"
"crashhandler.so", "libtcmalloc_minimal.so.0", "libtcmalloc_minimal.so.4"
};
static int isEssentialLib(const char* name) {
for (int i=0; i<sizeof(essential_libs)/sizeof(essential_libs[0]); ++i)
+3 -1
View File
@@ -5,9 +5,12 @@
GO("libpthread.so.0", libpthread)
GO("librt.so.1", librt)
GO("libbsd.so.0", libbsd)
GO("libbsd.so", libbsd)
GO("libGL.so.1", libgl)
GO("libGL.so", libgl)
GO("libGLU.so.1", libglu)
GO("libGLX.so.0", libglx)
GO("libGLX.so", libglx)
GO("libX11.so.6", libx11)
GO("libasound.so.2", libasound)
GO("libSDL2-2.0.so.0", sdl2)
@@ -183,7 +186,6 @@ GO("libpcre.so.3", libpcre)
#ifdef ANDROID
GO("libc.so", libc)
GO("libm.so", libm)
GO("libbsd.so", libbsd)
GO("libdl.so", libdl)
GO("libcups.so", libcups)
GO("liblber-2.4.so", lber)
+3 -1
View File
@@ -1,6 +1,8 @@
#define _TIME_BITS 64
#define _FILE_OFFSET_BITS 64
#ifdef PANDORA
#define _ATFILE_SOURCE
#endif
#include <string.h>
#include <sys/stat.h>
+4 -2
View File
@@ -1459,8 +1459,10 @@ int main(int argc, const char **argv, char **env)
my_context->box64path = getenv("BOX86_BOX64");
if(!my_context->box64path) {
my_context->box64path = box_strdup(my_context->box86path);
char* p = strrchr(my_context->box64path, '8'); // get the 8 of box86
p[0] = '6'; p[1] = '4'; // change 86 to 64
if (strstr(my_context->box64path, "box86")) {
char* p = strrchr(my_context->box64path, '8'); // get the 8 of box86
p[0] = '6'; p[1] = '4'; // change 86 to 64
}
}
if(!FileExist(my_context->box64path, IS_FILE)) {
box_free(my_context->box64path);
+2 -2
View File
@@ -692,7 +692,7 @@ EXPORT void* my_safer_scalable_aligned_realloc(void* p, size_t size, size_t alig
void* new_p = box_memalign(align, size);
memcpy(new_p, p, (old_size<size)?old_size:size);
box_free(p);
return p;
return new_p;
}
EXPORT void my_safer_scalable_free(void*p , void* old)
@@ -740,7 +740,7 @@ EXPORT void* my_scalable_aligned_realloc(void* p, size_t size, size_t align)
void* new_p = box_memalign(align, size);
memcpy(new_p, p, (old_size<size)?old_size:size);
box_free(p);
return p;
return new_p;
}
EXPORT size_t my_scalable_msize(void* p)
+5
View File
@@ -187,6 +187,7 @@
#() iFuu
#() iFup
#() iFli
#() iFLL
#() iFLp
#() iFpw
#() iFpi
@@ -3381,6 +3382,10 @@ wrappedlibglu:
- gluNurbsCallback
- gluQuadricCallback
- gluTessCallback
wrappedlibglx:
- pFp:
- glXGetProcAddress
- glXGetProcAddressARB
wrappedlibharfbuzz:
wrappedlibibus:
- vFpippp:
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
*******************************************************************/
#ifndef __wrappedlibglxDEFS_H_
#define __wrappedlibglxDEFS_H_
#endif // __wrappedlibglxDEFS_H_
@@ -0,0 +1,20 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
*******************************************************************/
#ifndef __wrappedlibglxTYPES_H_
#define __wrappedlibglxTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void* (*pFp_t)(void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(glXGetProcAddress, pFp_t) \
GO(glXGetProcAddressARB, pFp_t)
#endif // __wrappedlibglxTYPES_H_
@@ -0,0 +1,8 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v2.0.0.11) *
*******************************************************************/
#ifndef __wrappedlibglxUNDEFS_H_
#define __wrappedlibglxUNDEFS_H_
#endif // __wrappedlibglxUNDEFS_H_
+2
View File
@@ -259,6 +259,7 @@ typedef int32_t (*iFui_t)(uint32_t, int32_t);
typedef int32_t (*iFuu_t)(uint32_t, uint32_t);
typedef int32_t (*iFup_t)(uint32_t, void*);
typedef int32_t (*iFli_t)(intptr_t, int32_t);
typedef int32_t (*iFLL_t)(uintptr_t, uintptr_t);
typedef int32_t (*iFLp_t)(uintptr_t, void*);
typedef int32_t (*iFpw_t)(void*, int16_t);
typedef int32_t (*iFpi_t)(void*, int32_t);
@@ -2715,6 +2716,7 @@ void iFui(x86emu_t *emu, uintptr_t fcn) { iFui_t fn = (iFui_t)fcn; R_EAX=fn(*(ui
void iFuu(x86emu_t *emu, uintptr_t fcn) { iFuu_t fn = (iFuu_t)fcn; R_EAX=fn(*(uint32_t*)(R_ESP + 4), *(uint32_t*)(R_ESP + 8)); }
void iFup(x86emu_t *emu, uintptr_t fcn) { iFup_t fn = (iFup_t)fcn; R_EAX=fn(*(uint32_t*)(R_ESP + 4), *(void**)(R_ESP + 8)); }
void iFli(x86emu_t *emu, uintptr_t fcn) { iFli_t fn = (iFli_t)fcn; R_EAX=fn(*(intptr_t*)(R_ESP + 4), *(int32_t*)(R_ESP + 8)); }
void iFLL(x86emu_t *emu, uintptr_t fcn) { iFLL_t fn = (iFLL_t)fcn; R_EAX=fn(*(uintptr_t*)(R_ESP + 4), *(uintptr_t*)(R_ESP + 8)); }
void iFLp(x86emu_t *emu, uintptr_t fcn) { iFLp_t fn = (iFLp_t)fcn; R_EAX=fn(*(uintptr_t*)(R_ESP + 4), *(void**)(R_ESP + 8)); }
void iFpw(x86emu_t *emu, uintptr_t fcn) { iFpw_t fn = (iFpw_t)fcn; R_EAX=fn(*(void**)(R_ESP + 4), *(int16_t*)(R_ESP + 8)); }
void iFpi(x86emu_t *emu, uintptr_t fcn) { iFpi_t fn = (iFpi_t)fcn; R_EAX=fn(*(void**)(R_ESP + 4), *(int32_t*)(R_ESP + 8)); }
+1
View File
@@ -219,6 +219,7 @@ void iFui(x86emu_t *emu, uintptr_t fnc);
void iFuu(x86emu_t *emu, uintptr_t fnc);
void iFup(x86emu_t *emu, uintptr_t fnc);
void iFli(x86emu_t *emu, uintptr_t fnc);
void iFLL(x86emu_t *emu, uintptr_t fnc);
void iFLp(x86emu_t *emu, uintptr_t fnc);
void iFpw(x86emu_t *emu, uintptr_t fnc);
void iFpi(x86emu_t *emu, uintptr_t fnc);
+1 -1
View File
@@ -266,7 +266,7 @@ GO(g_thread_get_type, iFv)
GO(g_time_zone_get_type, iFv)
//GOM(g_type_add_class_cache_func, vFEpB)
GO(g_type_add_class_private, vFpiu)
//GO(g_type_add_instance_private,
GO(g_type_add_instance_private, iFLL)
//GOM(g_type_add_interface_check, vFEpB)
//GOM(g_type_add_interface_dynamic, vFEiip)
GOM(g_type_add_interface_static, vFEiip)
+2 -4
View File
@@ -19,11 +19,9 @@
#include "callback.h"
#ifdef ANDROID
const char* libbsdName = "libbsd.so";
#else
const char* libbsdName = "libbsd.so.0";
#endif
#define ALTNAME "libbsd.so"
#define LIBNAME libbsd
#define PRE_INIT\
+16 -3
View File
@@ -2572,7 +2572,6 @@ EXPORT int32_t my_execvp(x86emu_t* emu, const char* path, char* const argv[])
// fullpath is gone, so the search will only be on PATH, not on BOX86_PATH (is that an issue?)
return execvp(path, argv);
}
// execvpe should use PATH to search for the program first
EXPORT int32_t my_execvpe(x86emu_t* emu, const char* path, char* const argv[], char* const envv[])
{
@@ -2599,22 +2598,35 @@ EXPORT int32_t my_execvpe(x86emu_t* emu, const char* path, char* const argv[], c
if(self) newargv[1] = emu->context->fullpath;
if(script) newargv[2] = emu->context->bashpath;
printf_log(LOG_DEBUG, " => execvp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
#ifdef PANDORA
int ret = execve(newargv[0], newargv, envv);
#else
int ret = execvpe(newargv[0], newargv, envv);
#endif
box_free(fullpath);
return ret;
}
#ifndef PANDORA
box_free(fullpath);
#endif
if((!strcmp(path + strlen(path) - strlen("/uname"), "/uname") || !strcmp(path, "uname"))
&& argv[1] && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "-p") || !strcmp(argv[1], "-i"))
&& !argv[2]) {
// uname -m is redirected to box86 -m
path = my_context->box86path;
char *argv2[3] = { my_context->box86path, argv[1], NULL };
#ifdef PANDORA
return execve(fullpath, argv2, envv);
#else
return execvpe(path, argv2, envv);
#endif
}
#ifdef PANDORA
return execve(fullpath, argv, envv);
#else
// fullpath is gone, so the search will only be on PATH, not on BOX86_PATH (is that an issue?)
return execvpe(path, argv, envv);
#endif
}
// execvp should use PATH to search for the program first
@@ -3683,10 +3695,11 @@ EXPORT char my___libc_single_threaded = 0;
"libm.so", \
"libbsd.so"
#else
#define NEEDED_LIBS 4,\
#define NEEDED_LIBS 5,\
"ld-linux.so.2", \
"libpthread.so.0", \
"librt.so.1", \
"libm.so.6", \
"libbsd.so.0"
#define NEEDED_LIBS_234 6, \
"ld-linux.so.2", \
+53
View File
@@ -0,0 +1,53 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
#include "wrappedlibs.h"
#include "debug.h"
#include "wrapper.h"
#include "bridge.h"
#include "librarian/library_private.h"
#include "x86emu.h"
#include "emu/x86emu_private.h"
#include "callback.h"
#include "librarian.h"
#include "box86context.h"
#include "myalign.h"
#include "gltools.h"
const char* libglxName = "libGLX.so.0";
#define LIBNAME libglx
#include "generated/wrappedlibglxtypes.h"
#include "wrappercallback.h"
#define SUPER() \
GO(0) \
GO(1) \
GO(2) \
GO(3) \
#undef SUPER
EXPORT void* myx_glXGetProcAddress(x86emu_t* emu, void* name)
{
khint_t k;
const char* rname = (const char*)name;
return getGLProcAddress(emu, (glprocaddress_t)my->glXGetProcAddress, rname);
}
EXPORT void* myx_glXGetProcAddressARB(x86emu_t* emu, void* name)
{
khint_t k;
const char* rname = (const char*)name;
return getGLProcAddress(emu, (glprocaddress_t)my->glXGetProcAddressARB, rname);
}
#define ALTMY myx_
#include "wrappedlib_init.h"
+45
View File
@@ -0,0 +1,45 @@
#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))
#error meh!
#endif
// __glXGLLoadGLXFunction
GO(glXChooseFBConfig, pFpipp)
GO(glXChooseVisual, pFpip)
GO(glXCopyContext,vFppp)
GO(glXCreateContext,pFpppi)
GO(glXCreateGLXPixmap,pFppp)
GO(glXCreateNewContext,pFppipi)
GO(glXCreatePbuffer,pFppp)
GO(glXCreatePixmap,pFppp)
GO(glXCreateWindow,pFpppp)
GO(glXDestroyContext,vFpp)
GO(glXDestroyGLXPixmap,vFpp)
GO(glXDestroyPbuffer,vFpp)
GO(glXDestroyPixmap,vFpp)
GO(glXDestroyWindow,vFpp)
GO(glXGetClientString, pFpi)
GO(glXGetConfig, iFppip)
GO(glXGetCurrentContext, pFv)
GO(glXGetCurrentDisplay, pFv)
GO(glXGetCurrentDrawable, pFv)
GO(glXGetCurrentReadDrawable, pFv)
GO(glXGetFBConfigAttrib, iFppip)
GO(glXGetFBConfigs,pFpip)
GOM(glXGetProcAddress, pFEp)
GOM(glXGetProcAddressARB, pFEp)
GO(glXGetSelectedEvent, vFppp)
GO(glXGetVisualFromFBConfig, pFpp)
GO(glXIsDirect,iFpp)
GO(glXMakeContextCurrent,iFpppp)
GO(glXMakeCurrent,iFppp)
GO(glXQueryContext,iFppip)
GO(glXQueryDrawable, iFppip)
GO(glXQueryExtension, iFppp)
GO(glXQueryExtensionsString,pFpi)
GO(glXQueryServerString,pFpii)
GO(glXQueryVersion,iFppp)
GO(glXSelectEvent, vFppu)
GO(glXSwapBuffers,vFpp)
GO(glXUseXFont,vFpiii)
GO(glXWaitGL,vFv)
GO(glXWaitX,vFv)
+1 -1
View File
@@ -203,7 +203,7 @@ GO(xmlCheckFilename, iFp)
GO(xmlCheckHTTPInput, pFpp)
GO(xmlCheckLanguageID, iFp)
GO(xmlCheckUTF8, iFp)
//GO(xmlCheckVersion,
GO(xmlCheckVersion, vFi)
GO(xmlChildElementCount, LFp)
GO(xmlCleanupCharEncodingHandlers, vFv)
GO(xmlCleanupEncodingAliases, vFv)
+886 -210
View File
File diff suppressed because it is too large. Load diff
BIN
View File
Binary file not shown.
+108 -50
View File
@@ -32,7 +32,7 @@ uint64_t _fucompp_(double a, double b)
:"=a" (ret):"m"(a), "m"(b):"cc");
return ret;
}
uint64_t _fistpw_(double a)
uint64_t _fistpw_(double a, uint8_t rd)
{
uint16_t ret;
uint16_t t1, t2;
@@ -40,15 +40,31 @@ uint64_t _fistpw_(double a)
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov $0x0c, %%ah\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fistp %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _fistpl_(double a)
uint64_t _fisttpw_(double a, uint8_t rd)
{
uint16_t ret;
uint16_t t1, t2;
asm volatile (
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fisttp %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _fistpl_(double a, uint8_t rd)
{
uint32_t ret;
uint16_t t1, t2;
@@ -56,15 +72,31 @@ uint64_t _fistpl_(double a)
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov $0x0c, %%ah\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fistpl %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _fistpq_(double a)
uint64_t _fisttpl_(double a, uint8_t rd)
{
uint32_t ret;
uint16_t t1, t2;
asm volatile (
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fisttpl %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _fistpq_(double a, uint8_t rd)
{
uint64_t ret;
uint16_t t1, t2;
@@ -72,15 +104,15 @@ uint64_t _fistpq_(double a)
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov $0x0c, %%ah\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fistpq %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _frndint_(double a)
uint64_t _fisttpq_(double a, uint8_t rd)
{
uint64_t ret;
uint16_t t1, t2;
@@ -88,13 +120,29 @@ uint64_t _frndint_(double a)
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov $0x0c, %%ah\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"fisttpq %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
uint64_t _frndint_(double a, uint8_t rd)
{
uint64_t ret;
uint16_t t1, t2;
asm volatile (
"fldl %1\n"
"fstcw %2\n"
"mov %2, %%ax\n"
"mov %4, %%ah\n"
"mov %%ax, %3\n"
"fldcw %3\n"
"frndint\n"
"fstpl %0\n"
"fldcw %2\n"
:"=m" (ret):"m"(a), "m"(t1), "m"(t2):"cc");
:"=m" (ret):"m"(a), "m"(t1), "m"(t2), "m"(rd):"cc");
return ret;
}
#endif
@@ -105,44 +153,54 @@ int main(int argc, const char** argv)
char pf, cf, zf;
char pa, ca, za;
uint64_t flags;
uint64_t tests[][2] = {
{0x0, 0x4082c00000000000LL},
{0x8000000000000000LL, 0x4082c00000000000LL},
{0x8000000000000000LL, 0x0},
{0x8000000000000000LL, 0x3ff0000000000000LL},
{0x3ff0000000000000LL, 0x3fe89d9000000000LL},
{0x3ff0000000000000LL, 0x7ff0000000000000LL},
{0xfff0000000000000LL, 0x7ff0000000000000LL},
{0x3ff0002ca0000000LL, 0xaeff000025000000LL},
{0x3ff0000050000000LL, 0xc082c00000000000LL},
{0x0, 0x7ff8000000000001LL},
{0x7ff8000000000001LL, 0x7ff8000000000001LL},
};
int n = sizeof(tests)/sizeof(tests[0]);
for(int i=0; i<n; ++i)
for(int j=0; j<2; ++j) {
*(uint64_t*)&a = tests[i][0+j];
*(uint64_t*)&b = tests[i][1-j];
printf("FUCOMI 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
flags = _fucomip_(a, b);
ca = (flags>>0)&1?'C':'-';
za = (flags>>(0+6))&1?'Z':'-';
pa = (flags>>(0+2))&1?'P':'-';
printf("%c%c%c\n", za, pa, ca);
printf("FUCOMPP 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
flags = _fucompp_(a, b);
ca = (flags>>8)&1?'C':'-';
za = (flags>>(8+6))&1?'Z':'-';
pa = (flags>>(8+2))&1?'P':'-';
printf("%c%c%c\n", za, pa, ca);
printf("FRNDINT 0x%llx => 0x%llx\n", *(uint64_t*)&a, _frndint_(a));
printf("FRNDINT 0x%llx => 0x%llx\n", *(uint64_t*)&b, _frndint_(b));
printf("FISTP 0x%llx => word: %x\n", *(uint64_t*)&a, _fistpw_(a));
printf("FISTP 0x%llx => word: %x\n", *(uint64_t*)&b, _fistpw_(b));
printf("FISTP 0x%llx => long: %x\n", *(uint64_t*)&a, _fistpl_(a));
printf("FISTP 0x%llx => long: %x\n", *(uint64_t*)&b, _fistpl_(b));
printf("FISTP 0x%llx => quad: %llx\n", *(uint64_t*)&a, _fistpq_(a));
printf("FISTP 0x%llx => quad: %llx\n", *(uint64_t*)&b, _fistpq_(b));
uint64_t tests[] = {
0x0,
0x4082c00000000000LL,
0x8000000000000000LL,
0x40dfffc000000000LL,
0x40e0002000000000LL, // 0x7fff and 0x8001 as double
0xc0e0002000000000LL,
0xc0dfffc000000000LL, // -0x8001 and -0x7fff as double
0x3ff0000000000000LL,
0x3fe89d9000000000LL,
0x7ff0000000000000LL,
0xfff0000000000000LL,
0x3ff0002ca0000000LL,
0xaeff000025000000LL,
0x3ff0000050000000LL,
0xc082c00000000000LL,
0x7ff8000000000001LL,
};
int n = sizeof(tests)/sizeof(tests[0]);
for(int i=0; i<n; ++i)
for(int j=0; j<n; ++j) {
*(uint64_t*)&a = tests[i];
*(uint64_t*)&b = tests[j];
printf("FUCOMI 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
flags = _fucomip_(a, b);
ca = (flags>>0)&1?'C':'-';
za = (flags>>(0+6))&1?'Z':'-';
pa = (flags>>(0+2))&1?'P':'-';
printf("%c%c%c\n", za, pa, ca);
printf("FUCOMPP 0x%llx 0x%llx ", *(uint64_t*)&a, *(uint64_t*)&b);
flags = _fucompp_(a, b);
ca = (flags>>8)&1?'C':'-';
za = (flags>>(8+6))&1?'Z':'-';
pa = (flags>>(8+2))&1?'P':'-';
printf("%c%c%c\n", za, pa, ca);
}
for(int i=0; i<n; ++i) {
*(uint64_t*)&a = tests[i];
for(int rd=0; rd<3; ++rd) {
printf("Rounding %d\n", rd);
printf(" FRNDINT 0x%llx => 0x%llx\n", *(uint64_t*)&a, _frndint_(a, rd<<2));
printf(" FISTP 0x%llx => word: %x\n", *(uint64_t*)&a, _fistpw_(a, rd<<2));
printf(" FISTP 0x%llx => long: %x\n", *(uint64_t*)&a, _fistpl_(a, rd<<2));
printf(" FISTP 0x%llx => quad: %llx\n", *(uint64_t*)&a, _fistpq_(a, rd<<2));
printf(" FISTTP 0x%llx => word: %x\n", *(uint64_t*)&a, _fisttpw_(a, rd<<2));
printf(" FISTTP 0x%llx => long: %x\n", *(uint64_t*)&a, _fisttpl_(a, rd<<2));
printf(" FISTTP 0x%llx => quad: %llx\n", *(uint64_t*)&a, _fisttpq_(a, rd<<2));
}
}
printf("\nDone\n");
}