186 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
ptitSeb ec278bd784 Bumped version to v0.3.8 2024-12-06 15:04:39 +01:00
ptitSeb f1559b066c [DYNAREC] Improved x87 comparison (backporteed from Box64) 2024-12-04 11:13:17 +01:00
ptitSeb c9d20f60c8 [TRACE] Improved x87 trace (backported from Box64) 2024-12-04 11:12:45 +01:00
ptitSeb 512f0a6c92 [INTERPRETER] Improve x87 comparison (backported from Box64) 2024-12-04 10:25:46 +01:00
ptitSeb 1c280bd8a0 [INTERPRETER] Fixed x87 long double store that would loose sign on negative 0.0 2024-12-04 10:09:56 +01:00
ptitSeb 20432122de [INTERPRETER] Fixed D9 F4 opcode ([DYNAREC] too) (backported from box64) 2024-12-03 14:36:23 +01:00
ptitSeb e754df0fb1 [INTERPRETER] Fixes some longdoub / double conversion cases (on nan/infinites/0.0) (backported from Box64)" 2024-12-03 14:26:46 +01:00
ptitSeb b9d565f444 [INTERPRETER] Added 0F 20..23 opcodes 2024-11-23 14:32:29 +01:00
theofficialgman 58f1b5d1e3 [X86LIBS] Changed x86 libs install directory to prevent conflicts (#1014) 2024-11-20 17:52:53 +01:00
ptitSeb f921c0cdbe [WRAPPER] Added 1 wrapped function to fontconfig (for hl2) 2024-11-16 14:02:22 +01:00
ptitSeb 1e749beb2e Added BOX86_NOCRASHHANDLER to ignore crashhandler.so (for #1012) 2024-11-09 09:53:48 +01:00
ptitSeb 4caece4c0c Improved syscall 120 and added syscal 26 (for #1012) 2024-11-08 17:54:27 +01:00
ptitSeb d6b76922e7 Yet another adjustment to getcontext / setcontext wrapped functons 2024-11-08 16:46:12 +01:00
ptitSeb 69a021454a Adjusted getcontext / setcontext wrapped functons (should help #1012) 2024-11-08 16:19:58 +01:00
ptitSeb 336dc5b676 [VULKAN] Added 1 more extention 2024-11-07 16:50:08 +01:00
Mike Wang 450347f099 Fixed some typos: BOX64 -> BOX86 (#1011) 2024-11-06 17:12:55 +01:00
ptitSeb 30c72e23bd Added some new functions and a few fixes (for Steam) 2024-11-06 16:06:13 +01:00
ptitSeb ce0b4d1884 [CMAKE] Fixed SD865 profile, as a77.a55 is not supported in current build chain 2024-11-06 11:52:31 +01:00
ptitSeb 72d934b34c Added SD865 profile (for the new Retroid Pocket mini 5) 2024-11-05 15:43:49 +01:00
ptitSeb 4e8d4a2bff Added SD865 profile (for the new Retroid Pocket mini 5) 2024-11-05 15:41:26 +01:00
Mike Wang c993aacd04 [CMAKE] Check CMAKE_SYSTEM_PROCESSOR after project() (#1008) 2024-10-29 16:56:37 +01:00
ptitSeb a7855d3bcb Fixed a warning 2024-10-09 20:24:08 +02:00
ptitSeb 7b8a6aa91d Changed hack for sem_timedwait to avoid changing const timespec 2024-10-09 10:09:52 +02:00
ptitSeb c65c514882 Added a fix for old game that use sem_timewait in an incorrect way 2024-10-08 19:10:09 +02:00
ptitSeb 62bc6bb1f3 [VULKAN] Added one vulkan extension 2024-10-04 15:13:41 +02:00
ptitSeb 0504c042f4 [TRACE] Improved some freetype function trace 2024-10-04 15:13:18 +02:00
ptitSeb 54c806c576 Another attempt to fix the __st_ino build issue (for #983) 2024-09-17 15:25:22 +02:00
ptitSeb 55e08ab0be Try to fix some build issue (might help #983) 2024-09-17 13:35:53 +02:00
ptitSeb e717b959c6 [TRACE] A bit more traces details 2024-09-16 15:27:03 +02:00
ptitSeb f97763cacd [PANDORA] Fixed OpenPandora build 2024-09-13 17:59:35 +02:00
ptitSeb fc43e4c22b [WRAPPER] Fixed some warning on wrapped libpulse 2024-09-13 17:59:11 +02:00
ptitSeb b01829b7d6 [RCFILE] Fixed a typo in a profile 2024-09-12 10:34:54 +02:00
ptitSeb d1fcdee8a8 Simplified old pthread cond functions 2024-09-12 10:26:16 +02:00
ptitSeb 56b23e0668 Fixed a libc syscall fallback 2024-09-12 10:25:50 +02:00
ptitSeb d927dae7e7 [WRAPPER] Fixed a few libc functions signatures 2024-09-12 10:25:01 +02:00
ptitSeb a49c286214 Better wrapping of legacy stat/fstat/lstat using stat64 this time 2024-08-27 10:41:33 +02:00
ptitSeb 80e092ae44 re-wrapped legacy stat/fstat/lstat using 32bits stat and not 64bits ones 2024-08-26 10:13:53 +02:00
ptitSeb 05017f46d2 Added 1 wrapped function to libX11 2024-08-25 16:34:55 +02:00
ptitSeb 0caa80f9f1 Fixed a potential issue with glibc TLS block building 2024-08-25 16:34:35 +02:00
Raezroth 66a91b8580 Fix missing space in PKGBUILD-rk3xxx causing syntax error (#994) 2024-08-15 08:56:08 +02:00
ptitSeb bcd36a3152 [WRAPPER] Added 1 wrapped symbol to libc (for #985) 2024-08-11 15:35:24 +02:00
ptitSeb 6aba6364c4 [WRAPPER] Added 1 wrapped function to libxcb (for #986) 2024-08-11 15:30:35 +02:00
ptitSeb 0cf5179d7f [ANDROID] Try to fix this f***** android build 2024-08-11 15:22:13 +02:00
ptitSeb 3c9823198c [WRAPPER] Added 1 wrapped function to libgnutls (for #988) 2024-08-11 15:10:24 +02:00
ptitSeb 664956aaa0 Fixed some issue when build OS is _time64 aware (should help #987 #983 #976 #975, maybe some other) 2024-08-11 14:51:26 +02:00
ptitSeb 9811f140ce Fixed some copy/pasta issues with some not offten used libdl capabilities 2024-08-06 14:21:11 +02:00
Ilya114 26ddd6e9ef Update README_UK.md (#984) 2024-07-28 09:44:48 +02:00
ptitSeb c5bccdf300 Added 3 more wrapped function, not exclusive to android after all 2024-07-17 18:22:35 +02:00
ptitSeb 4b20581753 Fixed another typo 2024-07-16 20:45:32 +02:00
ptitSeb a4f38779eb Fixed some typos 2024-07-16 18:55:34 +02:00
ptitSeb 27c21f6979 Changed how TRAPNO 12 is triggered 2024-07-16 17:24:36 +02:00
rajdakin e14d8abb61 [MAXCPU] Added support for maxcpu (backport from box64) (#982)
* [MAXCPU] Added support for maxcpu (backport from box64)

* [MAXCPU] Added documentation for maxcpu

* [ARM PRINTER] Fixed ADR decoder

* [WRAPPED] Fixed wrapped libc
2024-07-16 11:15:33 +02:00
ptitSeb 54ed80f68a [VULKAN] Added 1 more extension (for #980) 2024-07-16 10:23:19 +02:00
ptitSeb a187c7ccd3 Added 2 new time64 wrapped libc functions 2024-07-16 10:12:41 +02:00
Panda f6a5322cf3 chore: check if arm-linux-gnueabihf-gcc exists else user defined value (#981)
closes #978
2024-07-16 10:00:03 +02:00
Panda 5da8235b18 build: fix PKGBUILD-rk3xxx, _rkmodel was never set (#979)
Code was taken from box64's PKGBUILD-rk3xxx
2024-07-16 08:11:18 +02:00
ptitSeb 21e9a43d21 [TRACE] Fixed some issue with function name printing 2024-07-13 10:11:04 +02:00
ptitSeb dcc0355113 Fixed some issue on tracking when protecting memory with PROT=0 2024-07-13 10:07:51 +02:00
ptitSeb 666b5a6ce6 Fixed a nasty bug on memory permission tracking 2024-07-11 12:16:16 +02:00
ptitSeb fcbebfa8c8 [RCFILE] Added 1 new profile 2024-07-05 10:04:32 +02:00
ptitSeb 9354744f68 [DOCS] Change organisation of COMPILE.md 2024-07-03 09:56:52 +02:00
ptitSeb fc0b51f3b8 Added a few more wrapped function (for steam) 2024-06-19 21:15:36 +02:00
theofficialgman cd88702516 switch to maintained Pi-Apps-Coders apt repo (#971) 2024-06-19 18:40:26 +02:00
MichaIng 223fa8ea17 Update ODROID-XU4 target (#970)
The ODROID target was meant for the ODROID-XU4, hence it is renamed accordingly, to better indicate that.

Furthermore, gcc 4.9 added support for `-mcpu=cortex-a15.cortex-a7` to optimise support for this ARM big.LITTLE chip: https://www.gnu.org/software/gcc/gcc-4.9/changes.html#arm
`-mcpu=cortex-a9` was used as compatible option, while the Samsung Exynos 5422 SoC of the ODROID-XU4 actually has 4x Cortex-A15 and 4x Cortex-A7 CPUs: https://wiki.odroid.com/odroid-xu4/odroid-xu4

Signed-off-by: MichaIng <[email protected]>
2024-06-17 22:56:11 +02:00
Krzysztof Aleksander PyrkoszandKrzysztof Aleksander Pyrkosz d3d971d449 Wrapped a handful of time64 functions (#969)
Co-authored-by: Krzysztof Aleksander Pyrkosz <[email protected]>
2024-06-15 22:59:26 +02:00
Kaze 2e589f42fe Update install_steam.sh (#963)
Fixes :
$@ was not escaped so it was not included in the steam launch script.

Added libibus-1.0-5 package that is required by newer versions of steam.
I didn't had to specify armhf on Pi 5 so I don't know if it's required for other platforms?
2024-05-23 19:50:52 +02:00
ptitSeb 96a34a2a40 Fixed a typo in x87 stack restauration 2024-05-22 23:48:08 +02:00
ptitSeb 69f0c979d4 More x87 fixes ([DYNAREC] too) 2024-05-22 23:34:47 +02:00
ptitSeb ff702c0318 [DYNAREC] Fixed a regression with the improved emit_pf helper 2024-05-22 21:58:50 +02:00
ptitSeb 968fc3fcfe [DYNAREC] Fixes to Cosim and to some x87 utility functions 2024-05-22 20:25:59 +02:00
ptitSeb 4abaa3d835 [DYNAREC] Simplified emit_pf helper 2024-05-22 11:08:24 +02:00
ptitSeb 121c67655b Start of a new dev. cycle 2024-05-22 10:38:48 +02:00
ptitSeb 9f8b96b749 Bumped version to v0.3.6 2024-05-21 17:31:57 +02:00
ptitSeb a9c50ef238 [DYNAREC] More fixes to CALLRET=1 2024-05-19 23:22:19 +02:00
ptitSeb 984da28f40 [DYNAREC] Handling of memfd_create backed mmap on dynarec (backported from box64) 2024-05-19 19:13:40 +02:00
ptitSeb a8babcba8d [DYNAREC] More fixes on dynarec and bigblock backported from box64 2024-05-19 18:53:48 +02:00
ptitSeb 13c7029de5 Added some virtual files (if missing) to allow wine to compute cachesize and coherency (backported from box64) 2024-05-19 18:50:33 +02:00
ptitSeb 148722dac4 [DYNAREC] Re-introduce a simple HotPage handling, to speedup heavily obfuscated program loading (backported from box64) 2024-05-19 18:39:38 +02:00
ptitSeb dd5bba2aac Allocate Dynarec memory by 2Mb batch, and advise for hugepage if available 2024-05-19 18:07:21 +02:00
ptitSeb b044c19329 [DYNAREC] Small change on flags to 66 0F 63 opcode 2024-05-19 18:02:18 +02:00
ptitSeb fb1dbb3821 Some fixes to PCMP[E/I]STRM opcodes 2024-05-19 17:57:35 +02:00
ptitSeb 4f21d83e62 [DYNAREC] Some more x87 handling improvments backported from box64 2024-05-19 17:56:59 +02:00
ptitSeb b145080d37 [DYNAREC] Fixed CALLRET and backported many BIBLOCK improvments from box64 2024-05-19 17:22:58 +02:00
ptitSeb 0829c14a73 Backported new FFREE and x87 tags handling from box64 ([DYNAREC] too) 2024-05-19 14:39:01 +02:00
ptitSeb 4141748f9a [DYNAREC] Fixed previous commit 2024-05-19 14:15:30 +02:00
ptitSeb 25e1d8bae8 [DYNAREC] Backported some Flags optimisation fixes from box64 2024-05-19 09:29:30 +02:00
ptitSeb 79e622a839 Setup stack nicely for pthread_once (might help wine) 2024-05-17 10:02:26 +02:00
ptitSeb 932045054f Removed the export WINEFSYNC=0 at start, use BOX86_FUTEX_WAITV=0 to disable instead 2024-05-14 16:15:55 +02:00
shenmo f5f1e1413d feat: add BOX86_RCFILE support (#960)
* feat: try add BOX86_RCFILE support

Make box86 support _RCFILE env like box64
https://github.com/ptitSeb/box64/blob/main/src/core.c#L1595

* adjust: comment rcfile loading to avoid crash
2024-04-30 14:30:38 +02:00
ptitSeb 24f2c68805 Added 2 wrapped functions to sdl2 2024-04-18 10:09:35 +02:00
澪 7748d10246 update X86WINE, libxxf86vm1:armhf (#955)
It should be armhf
2024-04-18 08:14:57 +02:00
Hagb (Junyu Guo 郭俊余) 22ee4685a1 Set rounding mode for some rounding functions of libm (#953)
This commit rewrites fesetround and fegetround to set and get the
rounding mode in x86emu, and applies the rounding mode on rounding
functions (`{,l,ll}rint{,f,l}` and `nearbyint{,f,l}`).
2024-04-15 08:00:33 +02:00
Hagb (Junyu Guo 郭俊余) 35ea6fd109 Fix rounding of some x87 instructions (#951)
* Fix rounding of some x87 instructions

* Add missing tests/roundtest.h

* Fix build error of dynarec_arm_helper.c

* set rounding mode only when BOX86_DYNAREC_FASTROUND = 0

* Fix build error

* Set rounding mode for trigonometric instructions

They should work in Android build

* Add missing conditions

* Apply BOX86_DYNAREC_FASTROUND=0 on fpu_rounding test

* Avoid two-step rounding

* Keep consistent with dynarec

* Fix naming conflict

* Move setround to fpu_setround

* Move setround to fpu_setround
2024-04-14 20:37:17 +02:00
ptitSeb 3744603bcc Don't load libGL in SDL_GL_GetProcAddress for GOA_CLONES config (for #950) 2024-04-14 19:38:25 +02:00
ptitSeb 4861b78dc4 Load custom GL lib after SDL2 loads its instead of before shoudl help #950 2024-04-14 11:51:06 +02:00
ptitSeb ba017657ad [ELFLOAER] Improved elfloader a bit (in sync with box64) 2024-03-29 23:21:04 +01:00
ptitSeb 811c4fccd8 [DYNAREC] Fixed some issue with x87 stack managment 2024-03-29 15:06:11 +01:00
ptitSeb 3992ab5931 Added some __isoc23_ symbols as synonym on wrapped libc (for #947) 2024-03-27 15:38:10 +01:00
ptitSeb 266392e315 [DYNAREC] More fixes on 16bits shift opcodes 2024-03-21 04:15:23 +01:00
ChenhoyogandHaoyang Chen 83e550b122 [DYNAREC] Fixed 66 C1 /5 SHR opcode. (#946)
Co-authored-by: Haoyang Chen <[email protected]>
2024-03-21 04:12:55 +01:00
ptitSeb b5f2b9c936 Added F0 FE /0 /1 opcodes ([DYNAREC] too) (for #944) 2024-03-14 10:09:02 +01:00
xctan 82f610faee [WRAPPER] Fixed a typo in the signature of my___libc_start_main (#941) 2024-03-04 15:38:49 +01:00
ptitSeb ec77755952 [STEAM] Removed the -cef-disable-gpu workaround, it's not needed anymore 2024-03-02 17:42:32 +01:00
ptitSeb 14c9cb148d Add -cef-disable-gpu to steam installer, as it's needed on many config now 2024-03-01 18:52:14 +01:00
ptitSeb f48aeaac60 This helps linux steam too 2024-02-28 11:22:42 +01:00
ptitSeb 74eb4ed9d5 Added CA opcode 2024-02-25 14:34:27 +01:00
ptitSeb 68503a37cf Try to detect steam wine and enforce parameter for an easier to emulate version 2024-02-25 12:13:34 +01:00
ptitSeb 49e6609182 Updated generated files 2024-02-25 12:13:04 +01:00
ptitSeb 966bb72e9e Added some hack to rename wine binary process too (help mesa pick up the correct binary being run) 2024-02-24 14:15:00 +01:00
ValdikSS 14b978a568 Add forgotten GOM definition for _dl_find_object wrapper in libdl (#938) 2024-02-21 15:02:42 +01:00
ptitSeb 8378f9b307 Added 0F 01 E0..E7 opcodes ([DYNAREC] too) 2024-02-10 13:13:35 +01:00
ptitSeb 9dc0f8243a [DYNAREC] DD /6 opcode also reset FPU 2024-02-07 10:20:12 +01:00
ValdikSS eaeacc6706 Update getopts @GLIBC_2.0 variables (optarg, ...) (#933) 2024-02-02 10:21:57 +01:00
leonpano2006 031dba2904 again quick fix(i alreadey made meny mistakes) (#932)
* Fix for xavier and orin no ARM_DYNAREC

* fix arm64 error

* Update CMakeLists.txt
2024-01-26 22:23:43 +01:00
leonpano2006 f8229ea561 fix if(_aarch64 for TEGRA_194 and TEGRA_234 (#931)
* Fix for xavier and orin no ARM_DYNAREC

* fix arm64 error
2024-01-26 21:08:53 +01:00
ptitSeb e5bfe84394 Improved 0F 01 opcode handling ([DYNAREC] too) 2024-01-26 15:22:08 +01:00
ptitSeb 5e926a266f Merge branch 'master' of https://github.com/ptitSeb/box86 2024-01-26 15:21:17 +01:00
ptitSeb 29e97a88a2 Improved 0F 01 opcode handling ([DYNAREC] too) 2024-01-26 15:21:09 +01:00
leonpano2006 a94e8ed659 Fix for xavier and orin no ARM_DYNAREC (#930) 2024-01-26 11:23:06 +01:00
KreitinnSoftware b013c86338 [CI] Update NDK to 25b for Android Builds (#929) 2024-01-26 08:21:40 +01:00
leonpano2006 29926438a8 Added build flags for Jetson Orin and xavier (#928)
* Update CMakeLists.txt

* Update CMakeLists.txt
2024-01-26 08:21:20 +01:00
ptitSeb 87097f437b [DYNAREC] Added 66 0F 38 40 opcode 2024-01-25 13:51:12 +01:00
ptitSeb 35f266ea94 [DYNAREC] Added 66 0F 3A 0E opcode 2024-01-25 13:35:58 +01:00
ptitSeb 88fd555ef0 [DYNAREC] Added 66 0F 38 2B opcode 2024-01-25 11:09:03 +01:00
ptitSeb 107d792ab1 [DYNAREC] Added 66 0F 38 38/39/3B/3C/3D/3E/3F opcodes 2024-01-25 10:34:59 +01:00
ptitSeb 30f364f166 [DYNAREC] Added 66 0F 38 3A opcode 2024-01-25 10:29:36 +01:00
ValdikSS e259ffcf66 More wrappers (#926)
* Add XML_SetDoctypeDeclHandler wrapper for expat library

* More wrappers for fontconfig and freetype:

* FT_Get_MM_WeightVector
* FT_Set_MM_WeightVector
* FT_Get_CMap_Format
* FcInitLoadConfigAndFonts
* FcConfigDestroy

* More wrappers for libpng16:

* png_get_mem_ptr
* png_set_invert_mono
* png_set_invert_alpha
2024-01-22 08:17:23 +01:00
ValdikSS 027605e4d5 Wrap png_set_flush for libpng16 (#925) 2024-01-21 22:19:02 +01:00
ptitSeb 2c58b45d8e [ELFLOADER] Zero'd memory when using mmap and filesize smaller than memsize 2024-01-21 12:20:30 +01:00
ptitSeb 159351fc3c [TRACE] Improved trace for __libc_start_main init handling 2024-01-21 12:19:09 +01:00
ptitSeb d4cf4ee521 [ARM] Improved some of the lock operation (seems to helps Anomaly linux version) 2024-01-21 11:37:13 +01:00
ptitSeb 7d90fff7cd Reworked exit, unloading libs and running Fini as it should (plus a workaround for hanging exit, might help Anomaly series gmaes linux version) 2024-01-21 11:32:42 +01:00
ptitSeb 68dcf9d0bf Reworked wrapping of callback in X11 Va args (backported from box64) 2024-01-21 11:02:31 +01:00
ptitSeb d89c10415a [ELFLOADER] Call elf init if libc_start_main init is NULL (backported from box64) (for #924) 2024-01-21 10:47:35 +01:00
ptitSeb 99310cc9c6 Change memory tracking to use rbtree (backported from box64) 2024-01-21 10:26:10 +01:00
ptitSeb 57d126cddc [DYNAREC] Test when changing page on building a dynablock if it's safe (backported from box64) 2024-01-21 10:02:33 +01:00
ptitSeb 2b35400dc5 [RCFILE] Updated steam profile with disabled cllret (for #920, maybe #915 too) 2024-01-17 16:07:25 +01:00
ptitSeb d1d899babd [INTERPRETER] Fixed VM Detection (TF trick) for interpreter 2024-01-15 17:49:33 +01:00
ptitSeb fe112fece8 [ELFLOADER] Fixed some issue with COPY/GLOB_DAT relocations 2024-01-15 13:33:42 +01:00
airidosas252 74a338df94 box86rc: additional compatibility flags for games (#921)
Since these games are very very finnicky when it comes to running on box86, they need quite a few additional env variables to fix, but with them, these games perform and run just fine.

- STRONGMEM is crucial since otherwise the game will crash right after it launches, unless you force only one thread for it.
- FASTNAN fixes broken audio, otherwise the game has half broken audio.
- X87DOUBLE is only specific to Mass Effect, because otherwise the game crashes when it starts loading up data.
- FORWARD wouldn't be needed if you had box86 compiled before december. I guess it's some sorta regression that gotten introduced with dynarec optimizations. (I bisected the exact commit which break these games. Posted on Termux Discord)

Otherwise, with these exact flags the games are completely playable, albeit a bit stuttery.
2024-01-14 20:24:35 +01:00
mocsy f2496984d5 Update COMPILE.md (#917)
apt install neon-support
2024-01-11 19:04:22 +01:00
ptitSeb 3ebcc84d52 [VULKAN] Added VK_KHR_maintenance5 extension 2024-01-11 10:38:51 +01:00
ptitSeb c878264ede Rollback that small global hack, it can breaks getopts use 2024-01-06 10:31:44 +01:00
ptitSeb fbf3e1b1cc [PANDORA] Don't use lscpu that doesn't exist there 2024-01-04 18:44:49 +01:00
ptitSeb e23d2167b4 [DYNAREC] Try to reduce penalty when there is multiple stack miss on CALLRET=1 2024-01-04 18:30:20 +01:00
ptitSeb 3d485c6159 [RCFILE] Added some callret to a few profiles 2024-01-04 15:31:03 +01:00
ptitSeb 9af5916104 [DYNAREC] Added support for BOX86_DYNAREC_CALLRET env. var. (back ported from box64) 2024-01-04 14:56:10 +01:00
ptitSeb 80e93dcee4 [DYNAREC] Added Faked 0F 01 opcode to help build bigger dynablocks 2024-01-04 14:52:49 +01:00
ptitSeb 90f21fb710 [DYNAREC] Fixed 16bits math opcodes (fixed ZSnes, maybe some other) 2024-01-03 15:54:10 +01:00
ptitSeb 41a8bc0da9 [DYNAREC] Re-enabled that small D9 F2 optim, but working good now 2023-12-22 20:38:09 +01:00
ptitSeb 06e40a2379 [DYNAREC] Disabled that small optim on D9 F2, it break things (Flatout 2 at least probably many other) 2023-12-22 20:20:02 +01:00
ptitSeb 78104d1b5f Expose max of 32 cpus core when Wine is launched (avoid buch of warning on machine with many cores) 2023-12-20 17:52:46 +01:00
ptitSeb 9626291470 [RCFILE] Fixed a file leak 2023-12-20 10:29:52 +01:00
ptitSeb 6f4a8fbd5d Start of a new dev. cycle 2023-12-20 10:29:32 +01:00
163 changed files with 7941 additions and 2105 deletions

No files matched your search

+1 -1
View File
@@ -14,7 +14,7 @@ on:
- GENERIC_ARM
- A64
- GAMESHELL
- ODROID
- ODROIDXU4
- PANDORA
- PHYTIUM
- PYRA
+10 -10
View File
@@ -27,23 +27,23 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, SD888, ADLINK, PHYTIUM, ANDROID]
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROIDXU4, RK3399, RK3288, A64, SD845, SD888, ADLINK, PHYTIUM, ANDROID]
type: [Release, Trace]
os: [ubuntu-latest]
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:
@@ -57,10 +57,10 @@ jobs:
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
sudo apt-get -y install git cmake make python3
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DNOLOADADDR=1" >> $GITHUB_ENV
wget https://dl.google.com/android/repository/android-ndk-r25b-linux.zip
unzip android-ndk-r25b-linux.zip
echo "BOX86_COMPILER=$PWD/android-ndk-r25b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DBAD_SIGNAL=1" >> $GITHUB_ENV
else
sudo apt-get -y install gcc-arm-linux-gnueabihf
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
@@ -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
+73 -33
View File
@@ -11,15 +11,18 @@ option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gamef
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(RK3588 "Set to ON if targeting an Rockchip RK3588 / RK3588S based device" ${RK3588})
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
option(ODROIDN2 "Set to ON if targeting an ODROID-N2 device" ${ODROIDN2})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 (ARM64) based device" ${TEGRAX1})
option(TEGRAX1ARM32 "Set to ON if targeting an Tegra X1 (ARM32) based device" ${TEGRAX1ARM32})
option(TEGRA_T194 "Set to ON if targeting an Tegra Xavier based device" ${TEGRA_T194})
option(TEGRA_T234 "Set to ON if targeting an Tegra Orin based device" ${TEGRA_T234})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
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(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})
@@ -35,7 +38,7 @@ option(NOGIT "Set to ON if not building from a git clone repo (like when buildin
option(NO_LIB_INSTALL "Set ON to not install a few x86 libs that are used by many program" ${NO_LIB_INSTALL})
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROIDXU4 OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR TEGRA_T194 OR TEGRA_T234 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD865 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -74,23 +77,29 @@ else()
endif()
cmake_host_system_information(RESULT CMAKE_HOST_SYSTEM_PROCESSOR QUERY OS_PLATFORM)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "arm" _arm)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armv8l" _armv8l)
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "aarch64" AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRA_T194 OR TEGRA_T234 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
set(COMPILER_TRIPLE arm-linux-gnueabihf-gcc)
find_program(COMPILER_FOUND ${COMPILER_TRIPLE})
if(COMPILER_FOUND)
set(CMAKE_C_COMPILER ${COMPILER_FOUND})
else()
message(STATUS "Cross compiler ${COMPILER_TRIPLE} not found, using CC or -DCMAKE_C_COMPILER")
endif()
endif()
project(box86 C ASM)
enable_testing()
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "armhf" _armhf)
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "arm" _arm)
string(COMPARE EQUAL "${CMAKE_SYSTEM_PROCESSOR}" "armv8l" _armv8l)
set(default_build_type "RelwithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
@@ -135,10 +144,10 @@ elseif(RPI4ARM64)
add_definitions(-DRPI4ARM64)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ODROID)
add_definitions(-DODROID)
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
elseif(ODROIDXU4)
add_definitions(-DODROIDXU4)
add_definitions(-marm -mcpu=cortex-a15.cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15.cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
elseif(RK3288)
add_definitions(-DRK3288)
add_definitions(-mcpu=cortex-a17 -mfpu=neon -mfloat-abi=hard -marm)
@@ -147,6 +156,11 @@ elseif(SD845)
add_definitions(-DSD845)
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(SD865)
add_definitions(-DSD865)
#note that cortex-a77.cortex-a55 is not supported, so fall back to a76 instead
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a76.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(SD888)
add_definitions(-DSD888)
add_definitions(-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
@@ -188,6 +202,14 @@ elseif(TEGRAX1ARM32)
add_definitions(-DTEGRAX1ARM32)
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(TEGRA_T194)
add_definitions(-DTEGRA_T194)
add_definitions(-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a76+crypto -mtune=cortex-a76 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a76+crypto -mtune=cortex-a76 -mfloat-abi=hard")
elseif(TEGRA_T234)
add_definitions(-DTEGRA_T234)
add_definitions(-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8.2-a+fp16+simd+crypto+predres -mfpu=crypto-neon-fp-armv8 -mcpu=cortex-a78ae+crypto -mtune=cortex-a78ae -mfloat-abi=hard")
elseif(PHYTIUM)
add_definitions(-DPHYTIUM)
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
@@ -228,6 +250,12 @@ else()
set(BOX86 box86)
endif()
try_compile(HAVE_ST_INO ${CMAKE_BINARY_DIR}/compile_tests ${CMAKE_SOURCE_DIR}/tests/test_st_ino.c)
if(HAVE_ST_INO)
message("stat64 has __st_info field")
add_definitions(-DHAVE_ST_INO)
endif()
set(BOX86_ELF_ADDRESS "0x62800000")
@@ -313,6 +341,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/tools/my_cpuid.c"
"${BOX86_ROOT}/src/tools/gtkclass.c"
"${BOX86_ROOT}/src/tools/rcfile.c"
"${BOX86_ROOT}/src/tools/rbtree.c"
"${BOX86_ROOT}/src/tools/wine_tools.c"
"${BOX86_ROOT}/src/elfs/elfloader.c"
"${BOX86_ROOT}/src/elfs/elfparser.c"
@@ -334,6 +363,8 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/libtools/auxval.c"
"${BOX86_ROOT}/src/libtools/myalign.c"
"${BOX86_ROOT}/src/libtools/myalign64.c"
"${BOX86_ROOT}/src/libtools/myalignsys64.c"
"${BOX86_ROOT}/src/libtools/stat64_helper.c"
"${BOX86_ROOT}/src/libtools/myfts.c"
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
@@ -382,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"
@@ -777,20 +809,21 @@ if(NOT _x86 AND NOT _x86_64)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION ${TERMUX_PATH}/usr/etc/)
endif()
endif()
set(INSTALL_PATH "/usr/lib/box86-i386-linux-gnu/")
if(NOT NO_LIB_INSTALL)
if(NOT TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${INSTALL_PATH})
else()
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}${INSTALL_PATH})
endif()
endif()
endif()
@@ -987,14 +1020,21 @@ add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(fpu_rounding ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test26 -D TEST_OUTPUT=tmpfile26.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref26.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(fpu_rounding PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTROUND=0")
endif(BOX86LIB)
+31
View File
@@ -1,3 +1,34 @@
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
* Reworked exit and the load/unload of libs
* Some more profiles in box86rc
* More SSE3+ opcodes in dynarec
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
* => should improve games stability
* Better handling of large block in the dynarec
* => should speedup dynarec, and allow use of BIGBLOCK 2 or 3 on more software
* Added suport for BOX86_DYNAREC_CALLRET optimisation.
* => backported from box64, can give 10% or more speed increase (but can also decrease speed in some cases). Still a bit crashy so use with care.
-- Sebastien Chevalier <[email protected]> Thu, 31 May 2024 17:30:33 -0100
box86 (0.3.4) unstable; urgency=low
* X86Libs: Updated libstdc++ & libgcc_s
+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
+33
View File
@@ -1,3 +1,36 @@
v0.3.8
======
* 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
v0.3.6
======
* Wrapping: More libs and function wrapping (gtk3, vulkan...)
* Reworked X11 Callback handling, for better stability
* Reworked exit and the load/unload of libs
* Some more profiles in box86rc
* More SSE3+ opcodes in dynarec
* Better way to rename executable (including wine ones) so driver like mesa can apply the correct profile
* Better handling of the Hardware Counter and TSC emulation
* Reworked memory managment in the Dynarec, limiting amount of dynamic allocation
* PageSize detection and handling dynamic. Larger than 4K pagesize will be handled automaticaly. Note that box64 does not emulate 4K page size, so some program might still refuse to work on larger page (like Wine for example)
=> Linux Games can now load even on a 16K pagesize machine like a mac M1, and games (including Unity3D ones) can be played with no issues.
* Lots of improvments in x87 handling (virtual stack, rounding, ffree, etc.)
=> should improve games stability
* Better handling of large block in the dynarec
=> should speedup dynarec, and allow use of BIGBLOCK 2 or 3 on more software
* Added suport for BOX86_DYNAREC_CALLRET optimisation.
=> backported from box64, can give 10% or more speed increase (but can also decrease speed in some cases). Still a bit crashy so use with care.
v0.3.4
======
* X86Libs: Updated libstdc++ & libgcc_s
+58 -15
View File
@@ -1,18 +1,21 @@
Compiling/Installing
----
#### Debian-based Linux
You can use [@Itai-Nelken](https://github.com/Itai-Nelken)'s apt repository to install precompiled box86 debs, updated weekly.
If you don't want to compile box86 yourself and prefer to use third-party pre-build version, go to the [end of the document](#pre-build-packages) for alternatives.
```
sudo wget https://itai-nelken.github.io/weekly-box86-debs/debian/box86.list -O /etc/apt/sources.list.d/box86.list
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box86-debs-archive-keyring.gpg
sudo apt update && sudo apt install box86 -y
You can also generate your own debian package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
Important note, if you are using a 64bits OS, you need to have multi-arch enabled, with armhf support, for box86 to works. On Debian/Ubuntu/Armbian OS, you need to do:
```bash
sudo dpkg --add-architecture armhf && sudo apt-get update
sudo apt-get install libc6:armhf -y
```
**Note:** On a 64bit OS, install the `box86:armhf` package.
And of course you will need to install much more library to be able to run software and games (like X11, mesa, SDL, pulseaudio...)
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
## Per-platform compiling instructions
----
#### for Pandora
@@ -60,9 +63,9 @@ sudo make install
sudo systemctl restart systemd-binfmt
```
#### for ODROID
#### for ODROID-XU3/XU4/MC1/HC1/HC2
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
`mkdir build; cd build; cmake .. -DODROIDXU4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### for RK3399
@@ -80,11 +83,11 @@ As most RK3588 devices run an AARCH64 OS, you'll need an `armhf` multiarch envir
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for ODROID N2/N2+
#### for ODROID-N2/N2+
`mkdir build; cd build; cmake .. -DODROIDN2=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most ODROID N2/N2+ devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most ODROID-N2/N2+ devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
@@ -164,6 +167,7 @@ To have a trace enabled build (***the interpreter will be slightly slower***), a
#### to have ARM Dynarec
###### *Note: VFPv3 and NEON are required for Dynarec.*
###### You might need to `sudo apt install neon-support` package for CMAKE to correctly detect them.
###### *Note: Compiling with `ARM_DYNAREC` without selecting a hardware profile is not advised.*
@@ -171,7 +175,7 @@ Dynarec is only available on the ARM architecture (for the meantime anyways). Ac
You will most likely need `-marm` in compilation flags (Many compilers default to the Thumb instruction set and Dynarec does not support this).
###### *Note: If you get error building that "target CPU does not support ARM mode", then try to pick a hardware profile (like ODROID for armv7 or PI4 for armv8).*
###### *Note: If you get error building that "target CPU does not support ARM mode", then try to pick a hardware profile (like ODROIDXU4 for armv7 or PI4 for armv8).*
##### 64bit OS with Dynarec
@@ -184,7 +188,7 @@ If you are not building from a git clone (for example, downloading a release sou
----
Testing
## Testing
----
A few tests are included with box86.
@@ -200,7 +204,46 @@ NVIDIA doesn't provide armhf libraries for their GPU drivers at this time. There
----
Debian Packaging
## Debian Packaging
----
Box86 can also be packaged into a .deb file ***using the source code zip from the releases page*** with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`. Configure any additional cmake options you might want in `debian/rules`.
## Pre-build packages
----
#### Debian-based Linux
You can use the [Pi-Apps-Coders apt repository](https://github.com/Pi-Apps-Coders/box86-debs) to install precompiled box86 debs, updated every 24 hours.
```
# check if .list file already exists
if [ -f /etc/apt/sources.list.d/box86.list ]; then
sudo rm -f /etc/apt/sources.list.d/box86.list || exit 1
fi
# check if .sources file already exists
if [ -f /etc/apt/sources.list.d/box86.sources ]; then
sudo rm -f /etc/apt/sources.list.d/box86.sources || exit 1
fi
# download gpg key from specified url
if [ -f /usr/share/keyrings/box86-archive-keyring.gpg ]; then
sudo rm -f /usr/share/keyrings/box86-archive-keyring.gpg
fi
sudo mkdir -p /usr/share/keyrings
wget -qO- "https://pi-apps-coders.github.io/box86-debs/KEY.gpg" | sudo gpg --dearmor -o /usr/share/keyrings/box86-archive-keyring.gpg
# create .sources file
echo "Types: deb
URIs: https://Pi-Apps-Coders.github.io/box86-debs/debian
Suites: ./
Signed-By: /usr/share/keyrings/box86-archive-keyring.gpg" | sudo tee /etc/apt/sources.list.d/box86.sources >/dev/null
```
On a 32bit OS, run the following additional commands
```
sudo apt update
sudo apt install box86-generic-arm -y
```
On a 64bit OS, run the following additional commands
```
sudo dpkg --add-architecture armhf
sudo apt update
sudo apt install box86-generic-arm:armhf -y
```
+1 -6
View File
@@ -104,12 +104,7 @@ Final note: the Steam BigPicture will work, but also need steamwebhelper (and so
- If you have trouble installing Steam, you can find `install_steam.sh` in the root folder of the box86 repo. This simple script will download and install steam in your home folder, and then create a shortcut to steam in `/usr/local/bin` (and for this it will ask for sudo permission). Simply use `steam` to launch once it's installed. Note that the installation, being in the Home folder, will only work for a single user. Don't use this script if you need a multi-user installation.
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables (it's automatically there if you used the `install_steam.sh` script)
to disable `steamwebhelper` when box64 installed and running, create (or edit) `~/.box64rc` and add:
```
[steamwebhelper]
BOX64_EXIT=1
```
in it and it will be disable. Comment with a `#` those 2 lines to enable it again
If you have issue with steam starting, with `steamwebhelper` not starting, you'll need to start steam with `-cef-disable-gpu` or `-cef-disable-gpu-compositor`.
----
+2 -7
View File
@@ -2,7 +2,7 @@
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box86/issues/new)
[Дивитись журнал змін](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [Повідомити про помилку](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
@@ -104,12 +104,7 @@ Linux версія Steam тепер може працювати з Box86, але
- Якщо у вас виникли проблеми зі встановленням Steam, ви можете знайти `install_steam.sh` у кореневій папці сховища box86. Цей простий скрипт завантажить і встановить Steam у вашу домашню папку, а потім створить ярлик steam у `/usr/local/bin` (для цього він запитає дозвіл sudo). Просто використовуйте `steam` для запуску після встановлення. Зауважте, що інсталяція, яка знаходиться в папці Home, працюватиме лише для одного користувача. Не використовуйте цей скрипт, якщо вам потрібна багатокористувацька інсталяція.
- Щоб уникнути повідомлення «libc.so.6 відсутній», ви можете використовувати `STEAMOS=1` і `STEAM_RUNTIME=1` як змінні середовища (воно автоматично з’являється, якщо ви використовували сценарій `install_steam.sh`)
Щоб вимкнути `steamwebhelper`, коли Box64 встановлений і працює, створіть (або відредагуйте) `~/.box64rc` і додайте у ньому:
```
[steamwebhelper]
BOX64_EXIT=1
```
І тоді `steamwebhelper` буде вимкнено. Прокоментуйте `#` ці 2 рядки, щоб увімкнути його знову.
Якщо у вас виникла проблема із запуском Steam (не запускається `steamwebhelper`), вам потрібно запустити Steam за допомогою `-cef-disable-gpu` або `-cef-disable-gpu-compositor`.
----
+23 -13
View File
@@ -30,7 +30,7 @@ Disables Box86 printing its version and build
#### BOX86_LD_LIBRARY_PATH *
Path to look for x86 libraries. Default is current folder and `lib` in current folder.
Also, `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exist.
Also, `/usr/lib/i386-linux-gnu`, `/lib/i386-linux-gnu`, and `/usr/lib/box86-i386-linux-gnu` are added if they exist.
#### BOX86_PATH *
Path to look for x86 executable. Default is current folder and `bin` in current folder.
@@ -162,8 +162,8 @@ Enable/Disable generation of -NAN
#### BOX86_DYNAREC_FASTROUND *
Enable/Disable generation of precise x86 rounding
* 0 : Generate float/double -> int rounding like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (faster, Default)
* 0 : Generate float/double -> int rounding and use current rounding mode for float/double compution like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion, and no set rounding mode) (faster, Default)
#### BOX86_DYNAREC_SAFEFLAGS *
Handling of flags on CALL/RET opcodes
@@ -171,15 +171,10 @@ Handling of flags on CALL/RET opcodes
* 1 : most of RET will need flags, most of CALLS will not (Default)
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
#### BOX86_DYNAREC_HOTPAGE *
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
#### BOX86_DYNAREC_FASTPAGE *
Will use a faster handling of HotPage (Page being both executed and written)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
#### BOX86_DYNAREC_CALLRET *
Optimisation of CALL/RET opcodes (not compatible with jit/dynarec/smc)
* 0 : Don't optimize CALL/RET, use Jump Table for boths (Default)
* 1 : Try to optimized CALL/RET, skipping the use of the JumpTable when possible
#### BOX86_DYNAREC_BLEEDING_EDGE *
Detect MonoBleedingEdge and apply conservative settings
@@ -211,6 +206,11 @@ Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX86_MAXCPU
Maximum CPU Core exposed
* 0 : Don't cap the number of cpu core exposed (Default)
* XXX : Cap the maximum CPU Core exposed to XXX (usefull with wine64 or GridAutosport for example)
#### BOX86_LIBCEF *
Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
@@ -275,6 +275,11 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX86_NOCRASHHANDLER *
Diables crashhandler.so
* 0 : Regular process for crashhandler.so (Default)
* 1 : Do not load crashhandler.so, even if present
#### BOX86_FUTEX_WAITV *
Use of the new fuext_waitc syscall
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
@@ -288,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.)
@@ -311,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 *
+1 -1
View File
@@ -112,7 +112,7 @@ if [ "$karch" = "aarch64" ] || [ "$karch" = "aarch64-linux-gnu" ] || [ "$karch"
libdbus-1-3:armhf libfontconfig1:armhf libfreetype6:armhf libglu1-mesa:armhf libglu1:armhf libgnutls30:armhf \
libgssapi-krb5-2:armhf libkrb5-3:armhf libodbc1:armhf libosmesa6:armhf libsdl2-2.0-0:armhf libv4l-0:armhf \
libxcomposite1:armhf libxcursor1:armhf libxfixes3:armhf libxi6:armhf libxinerama1:armhf libxrandr2:armhf \
libxrender1:armhf libxxf86vm1 libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
libxrender1:armhf libxxf86vm1:armhf libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
# This list found by downloading...
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel-i386_7.1~bullseye-1_i386.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/winehq-devel_7.1~bullseye-1_i386.deb
+3 -3
View File
@@ -18,11 +18,11 @@ mv ./usr/* ../
cd ../ && rm -rf ./tmp/
# create run script
echo "#!/bin/bash
echo '#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam $@" > steam
~/steam/bin/steam $@' > steam
# make script executable and move
chmod +x steam
@@ -35,7 +35,7 @@ if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
sudo apt update # update package lists with the newly added arch
# install the libraries that Steam requires
sudo apt install libc6:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf
sudo apt install libc6:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf libibus-1.0-5
# this one is not there all the time, so just try it...
sudo apt install libncurses5:armhf
+2 -1
View File
@@ -13,6 +13,7 @@ provides=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}
conflicts=("${pkgname%-git}" "${pkgname%-rk3xxx-git}-git" "${pkgname%-rk3xxx-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
_rkmodel=`tr -d '\0' < /proc/device-tree/compatible`
pkgver() {
cd "$srcdir/${pkgname%-rk3xxx-git}"
@@ -22,7 +23,7 @@ pkgver() {
prepare() {
cd "${srcdir}/${pkgname%-rk3xxx-git}"
# Check for RockChip version number
if [[ ${_rkmodel} =~ "rk3288"]]; then
if [[ ${_rkmodel} =~ "rk3288" ]]; then
_rksuffix=3288
elif [[ ${_rkmodel} =~ "rk3399" ]]; then
_rksuffix=3399
+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
+2 -2
View File
@@ -72,7 +72,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
# Get all actual instructions
# Ignore white lines and lines beginning with either !, ; or #
insts = list(filter(lambda l: not re.match("^\s*$", l) and not re.match("^([!;#])", l), insts.split('\n')))
insts = list(filter(lambda l: not re.match("^\\s*$", l) and not re.match("^([!;#])", l), insts.split('\n')))
try:
# Do not open with `with` to be able to open it in writing mode
@@ -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 4
#define BOX86_REVISION 9
#endif //__BOX86_VERSION_H_
+180 -264
View File
@@ -23,7 +23,7 @@
#include <sys/mman.h>
#include "custommem.h"
#include "threads.h"
//#define TRACE_MEMSTAT
#include "rbtree.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/dynablock_private.h"
@@ -54,23 +54,12 @@ static pthread_mutex_t mutex_blocks;
#endif
#define MEMPROT_SHIFT 12
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
#ifdef DYNAREC
static uint8_t hotpages[MEMPROT_SIZE] = {0};
#endif
#ifdef TRACE_MEMSTAT
static uint32_t memprot_allocated = 0, memprot_max_allocated = 0;
#endif
//#define TRACE_MEMSTAT
rbtree* memprot = NULL;
static int inited = 0;
typedef struct mapmem_s {
uintptr_t begin, end;
struct mapmem_s *next;
} mapmem_t;
static mapmem_t *mapallmem = NULL;
static mapmem_t *mmapmem = NULL;
static rbtree* mapallmem = NULL;
static rbtree* mmapmem = NULL;
typedef struct blocklist_s {
void* block;
@@ -80,6 +69,7 @@ typedef struct blocklist_s {
} blocklist_t;
#define MMAPSIZE (64*1024) // allocate 64kb sized blocks
#define DYNMMAPSZ (2*1024*1024) // allocate 2Mb block for dynarec
static int n_blocks = 0; // number of blocks for custom malloc
static int c_blocks = 0; // capacity of blocks for custom malloc
@@ -402,6 +392,8 @@ void* customMalloc(size_t size)
void* ret = allocBlock(p_blocks[i].block, p, size, &p_blocks[i].first);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
mutex_unlock(&mutex_blocks);
if(mapallmem)
setProtection((uintptr_t)p, allocsize, PROT_READ | PROT_WRITE);
return ret;
}
void* customCalloc(size_t n, size_t size)
@@ -539,7 +531,7 @@ uintptr_t AllocDynarecMap(size_t size)
// check if new
if(!list->chunks[i].size) {
// alloc a new block, aversized or not, we are at the end of the list
size_t allocsize = (sz>MMAPSIZE)?sz:MMAPSIZE;
size_t allocsize = (sz>DYNMMAPSZ)?sz:DYNMMAPSZ;
// allign sz with pagesize
allocsize = (allocsize+(box86_pagesize-1))&~(box86_pagesize-1);
#ifndef USE_MMAP
@@ -551,10 +543,13 @@ uintptr_t AllocDynarecMap(size_t size)
mprotect(p, allocsize, PROT_READ | PROT_WRITE | PROT_EXEC);
#else
void* p = mmap(NULL, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(p==(void*)-1) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", allocsize);
if(p==MAP_FAILED) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes (%s)\n", allocsize, strerror(errno));
return 0;
}
#ifdef MADV_HUGEPAGE
madvise(p, allocsize, MADV_HUGEPAGE);
#endif
#endif
#ifdef TRACE_MEMSTAT
dynarec_allocated += allocsize;
@@ -794,22 +789,33 @@ uintptr_t getJumpAddress64(uintptr_t addr)
void protectDB(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
uintptr_t cur = addr&~(box86_pagesize-1);
uintptr_t end = ALIGN(addr+size);
mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
while(cur!=end) {
uint32_t prot = 0, oprot;
uintptr_t bend = 0;
rb_get_end(memprot, cur, &prot, &bend);
if(bend>end)
bend = end;
oprot = prot;
uint32_t dyn = prot&PROT_DYN;
if(!prot)
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
prot&=~PROT_CUSTOM;
if(!(dyn&PROT_NOPROT)) {
prot = PROT_READ | PROT_WRITE | PROT_EXEC;
if(!(dyn&PROT_NEVERPROT)) {
prot&=~PROT_CUSTOM;
if(prot&PROT_WRITE) {
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i] = prot|PROT_DYNAREC; // need to use atomic exchange?
} else
memprot[i] = prot|PROT_DYNAREC_R;
if(!dyn)
mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
prot |= PROT_DYNAREC;
} else
prot |= PROT_DYNAREC_R;
}
if (prot != oprot) // If the node doesn't exist, then prot != 0
rb_set(memprot, cur, bend, prot);
cur = bend;
}
mutex_unlock(&mutex_prot);
}
@@ -819,21 +825,36 @@ void protectDB(uintptr_t addr, uintptr_t size)
void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
{
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p (mark=%d)\n", (void*)addr, (void*)(addr+size-1), mark);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
uintptr_t cur = addr&~(box86_pagesize-1);
uintptr_t end = ALIGN(addr+size);
mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
if(!(prot&PROT_NOPROT)) {
while(cur!=end) {
uint32_t prot = 0, oprot;
uintptr_t bend = 0;
if (!rb_get_end(memprot, cur, &prot, &bend)) {
if(bend>=end) break;
else {
cur = bend;
continue;
}
}
oprot = prot;
if(bend>end)
bend = end;
if(!(prot&PROT_NEVERPROT)) {
if(prot&PROT_DYNAREC) {
prot&=~PROT_DYN;
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i] = prot; // need to use atomic exchange?
cleanDBFromAddressRange(cur, bend-cur, 0);
mprotect((void*)cur, bend-cur, prot);
} else if(prot&PROT_DYNAREC_R)
memprot[i] = prot&~PROT_CUSTOM;
prot &= ~PROT_CUSTOM;
}
if (prot != oprot)
rb_set(memprot, cur, bend, prot);
cur = bend;
}
mutex_unlock(&mutex_prot);
}
@@ -841,138 +862,71 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
int isprotectedDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "isprotectedDB %p -> %p => ", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
if(!(prot&PROT_DYN)) {
uintptr_t end = ALIGN(addr+size);
addr &=~(box86_pagesize-1);
mutex_lock(&mutex_prot);
while (addr < end) {
uint32_t prot;
uintptr_t bend;
if (!rb_get_end(memprot, addr, &prot, &bend) || !(prot&PROT_DYN)) {
dynarec_log(LOG_DEBUG, "0\n");
mutex_unlock(&mutex_prot);
return 0;
} else {
addr = bend;
}
}
mutex_unlock(&mutex_prot);
dynarec_log(LOG_DEBUG, "1\n");
return 1;
}
uintptr_t hotpage = 0;
int hotpage_cnt = 0;
#define HOTPAGE_MARK 64
void SetHotPage(uintptr_t addr)
{
hotpage = addr&~(box86_pagesize-1);
hotpage_cnt = HOTPAGE_MARK;
}
int isInHotPage(uintptr_t addr)
{
if(!hotpage_cnt)
return 0;
--hotpage_cnt;
return (addr>=hotpage) && (addr<hotpage+box86_pagesize);
}
int checkInHotPage(uintptr_t addr)
{
return hotpage_cnt && (addr>=hotpage) && (addr<hotpage+box86_pagesize);
}
#endif
void printMapMem(mapmem_t* mapmem)
{
mapmem_t* m = mapmem;
while(m) {
printf_log(LOG_NONE, " %p-%p\n", (void*)m->begin, (void*)m->end);
m = m->next;
}
}
void addMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
if(begin<box86_pagesize)
begin = box86_pagesize;
begin &=~(box86_pagesize-1);
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
// find attach point (cannot be the 1st one by construction)
mapmem_t* m = mapmem;
while(m->next && begin>m->next->begin) {
m = m->next;
}
// attach at the end of m
mapmem_t* newm;
if(m->end>=begin-1) {
if(end<=m->end)
return; // zone completly inside current block, nothing to do
m->end = end; // enlarge block
newm = m;
} else {
// create a new block
newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
newm->next = m->next;
newm->begin = begin;
newm->end = end;
m->next = newm;
}
while(newm && newm->next && (newm->next->begin-1)<=newm->end) {
// fuse with next
if(newm->next->end>newm->end)
newm->end = newm->next->end;
mapmem_t* tmp = newm->next;
newm->next = tmp->next;
box_free(tmp);
}
// all done!
}
void removeMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
if(begin<box86_pagesize)
begin = box86_pagesize;
begin &=~(box86_pagesize-1);
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
mapmem_t* m = mapmem, *prev = NULL;
while(m) {
// check if block is beyond the zone to free
if(m->begin > end)
return;
// check if the block is completly inside the zone to free
if(m->begin>=begin && m->end<=end) {
// just free the block
mapmem_t *tmp = m;
if(prev) {
prev->next = m->next;
m = prev;
} else {
mapmem = m->next; // change attach, but should never happens
m = mapmem;
prev = NULL;
}
box_free(tmp);
} else if(begin>m->begin && end<m->end) { // the zone is totaly inside the block => split it!
mapmem_t* newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t)); // create a new "next"
newm->end = m->end;
m->end = begin - 1;
newm->begin = end + 1;
newm->next = m->next;
m->next = newm;
// nothing more to free
return;
} else if(begin>m->begin && begin<m->end) { // free the tail of the block
m->end = begin - 1;
} else if(end>m->begin && end<m->end) { // free the head of the block
m->begin = end + 1;
}
prev = m;
m = m->next;
}
}
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t old_prot = memprot[i];
uint32_t dyn=(old_prot&PROT_DYN);
if(!(dyn&PROT_NOPROT)) {
uintptr_t cur = addr & ~(box86_pagesize-1);
uintptr_t end = ALIGN(cur+size);
rb_set(mapallmem, cur, cur+size, 1);
while (cur < end) {
uintptr_t bend;
uint32_t oprot;
rb_get_end(memprot, cur, &oprot, &bend);
if(bend>end) bend = end;
uint32_t dyn=(oprot&PROT_DYN);
if(!(dyn&PROT_NEVERPROT)) {
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
mprotect((void*)cur, bend-cur, prot&~PROT_WRITE);
} else if(dyn && !(prot&PROT_WRITE)) {
dyn = PROT_DYNAREC_R;
}
}
memprot[i] = prot|dyn;
if ((prot|dyn) != oprot)
rb_set(memprot, cur, bend, prot|dyn);
cur = bend;
}
mutex_unlock(&mutex_prot);
}
@@ -980,13 +934,12 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
size = ALIGN(size);
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i] = prot;
}
uintptr_t cur = addr & ~(box86_pagesize-1);
uintptr_t end = ALIGN(cur+size);
rb_set(mapallmem, cur, end, 1);
rb_set(memprot, cur, end, prot);
mutex_unlock(&mutex_prot);
}
@@ -994,26 +947,31 @@ void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
{
if(!size)
return;
size = (size+box86_pagesize-1)&~(box86_pagesize-1); // round size
addr &= ~(box86_pagesize-1);
size = ALIGN(size);
mutex_lock(&mutex_prot);
addMapMem(mmapmem, addr, addr+size-1);
rb_set(mmapmem, addr, addr+size, 1);
mutex_unlock(&mutex_prot);
if(prot)
setProtection(addr, size, prot);
else {
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
rb_set(mapallmem, addr, addr+size, 1);
rb_unset(memprot, addr, addr+size);
mutex_unlock(&mutex_prot);
}
}
void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
{
size = ALIGN(size);
addr &= ~(box86_pagesize-1);
if(prot)
setProtection(addr, size, prot);
else {
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
rb_set(mapallmem, addr, addr+size, 1);
rb_unset(memprot, addr, addr+size);
mutex_unlock(&mutex_prot);
}
}
@@ -1021,11 +979,11 @@ void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
void refreshProtection(uintptr_t addr)
{
mutex_lock(&mutex_prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
int prot = memprot[idx];
if(!(prot&PROT_DYNAREC)) {
int ret = mprotect((void*)(idx<<MEMPROT_SHIFT), box86_pagesize, prot&~PROT_CUSTOM);
printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(idx<<MEMPROT_SHIFT), prot, ret, ret?strerror(errno):"ok");
uint32_t prot;
uintptr_t bend;
if (rb_get_end(memprot, addr, &prot, &bend)) {
int ret = mprotect((void*)(addr&~(box86_pagesize-1)), box86_pagesize, prot&~PROT_CUSTOM);
dynarec_log(LOG_DEBUG, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr, (void*)(addr&~(box86_pagesize-1)), prot, ret, ret?strerror(errno):"ok");
}
mutex_unlock(&mutex_prot);
}
@@ -1033,47 +991,17 @@ printf_log(LOG_INFO, "refreshProtection(%p): %p/0x%x (ret=%d/%s)\n", (void*)addr
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
size = ALIGN(size);
addr &= ~(box86_pagesize-1);
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
rb_set(mapallmem, addr, addr+size, 1);
mutex_unlock(&mutex_prot);
// don't need to add precise tracking probably
}
#ifdef DYNAREC
int IsInHotPage(uintptr_t addr) {
int idx = (addr>>MEMPROT_SHIFT);
if(!hotpages[idx])
return 0;
// decrement hot
arm_lock_decifnot0b(&hotpages[idx]);
return 1;
}
int AreaInHotPage(uintptr_t start, uintptr_t end_) {
uintptr_t idx = (start>>MEMPROT_SHIFT);
uintptr_t end = (end_>>MEMPROT_SHIFT);
int ret = 0;
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t hot = hotpages[i];
if(hot) {
// decrement hot
arm_lock_decifnot0b(&hotpages[i]);
ret = 1;
}
}
if(ret && box86_dynarec_log>LOG_INFO)
dynarec_log(LOG_DEBUG, "BOX64: AreaInHotPage %p-%p\n", (void*)start, (void*)end_);
return ret;
}
void AddHotPage(uintptr_t addr) {
int idx = (addr>>MEMPROT_SHIFT);
arm_lock_storeb(&hotpages[idx], box86_dynarec_hotpage);
}
#endif
uintptr_t pbrk = 0;
uintptr_t old_brk = 0;
uintptr_t* cur_brk = NULL;
void loadProtectionFromMap()
{
if(box86_mapclean)
@@ -1090,48 +1018,41 @@ 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;
}
void freeProtection(uintptr_t addr, uintptr_t size)
{
size = ALIGN(size);
addr &= ~(box86_pagesize-1);
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
mutex_lock(&mutex_prot);
removeMapMem(mmapmem, addr, addr+size-1);
removeMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i] = 0;
}
rb_unset(mapallmem, addr, addr+size);
rb_unset(mmapmem, addr, addr+size);
rb_unset(memprot, addr, addr+size);
mutex_unlock(&mutex_prot);
}
uint32_t getProtection(uintptr_t addr)
{
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
mutex_lock(&mutex_prot);
uint32_t ret = memprot[idx];
uint32_t ret = rb_get(memprot, addr);
mutex_unlock(&mutex_prot);
return ret;
}
int getMmapped(uintptr_t addr)
{
mapmem_t* m = mmapmem;
if(addr<box86_pagesize) return 0;
while(m) {
uintptr_t begin = m->begin;
uintptr_t end = m->end;
if(addr>=begin && addr<=end)
return 1;
if(addr<begin)
return 0;
m = m->next;
}
return 0;
return rb_get(mmapmem, addr);
}
@@ -1139,22 +1060,26 @@ int getMmapped(uintptr_t addr)
#define MEDIAN (void*)0x40000000
static void* findBlockHinted(void* hint, size_t size, uintptr_t mask)
{
mapmem_t* m = mapallmem;
uintptr_t h = (uintptr_t)hint;
// 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(m) {
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;
if(bend>=0xc0000000 && (uintptr_t)hint<0xc0000000)
return NULL;
}
// granularity 0x10000
uintptr_t addr = m->end+1;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
// check hint and available size
if(addr<=h && end>=h && end-h+1>=size)
return hint;
uintptr_t aaddr = (addr+mask)&~mask;
if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
return (void*)aaddr;
if(end>=0xc0000000 && h<0xc0000000)
return NULL;
m = m->next;
cur = (bend+mask)&~mask;
}
return NULL;
}
@@ -1182,16 +1107,12 @@ void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask)
int isBlockFree(void* hint, size_t size)
{
mapmem_t* m = mapallmem;
uintptr_t h = (uintptr_t)hint;
while(m) {
uintptr_t addr = m->end+1;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
if(addr<=h && end>=h && end-h+1>=size)
int prot;
uintptr_t bend = 0;
uintptr_t cur = (uintptr_t)hint;
if(!rb_get_end(mapallmem, cur, &prot, &bend)) {
if(bend-cur>=size)
return 1;
if(addr>h)
return 0;
m = m->next;
}
return 0;
}
@@ -1259,6 +1180,8 @@ 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
#ifdef ARM
@@ -1273,13 +1196,9 @@ void init_custommem_helper(box86context_t* ctx)
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
// init mapallmem list
mapallmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mapallmem->begin = 0x0;
mapallmem->end = (uintptr_t)LOWEST - 1;
mapallmem = init_rbtree();
// init mmapmem list
mmapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mmapmem->begin = 0x0;
mmapmem->end = (uintptr_t)box86_pagesize - 1;
mmapmem = init_rbtree();
loadProtectionFromMap();
}
@@ -1298,7 +1217,7 @@ void fini_custommem_helper(box86context_t *ctx)
}
if (njmps_in_cur_lv1 > njmps_in_lv1_max) njmps_in_lv1_max = njmps_in_cur_lv1;
}
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lu kio\n- customMalloc: %zu kio\n- memprot: %lu kio (peak at %ld kio)\n- jump table: %zu kio (%zu level 1 table allocated, for %zu jumps, with at most %zu per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, memprot_allocated / 1024, memprot_max_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lu kio\n- customMalloc: %zu kio\n- jump table: %zu kio (%zu level 1 table allocated, for %zu jumps, with at most %zu per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#endif
if(!inited)
return;
@@ -1333,6 +1252,13 @@ void fini_custommem_helper(box86context_t *ctx)
kh_destroy(lockaddress, lockaddress);
lockaddress = NULL;
#endif
delete_rbtree(memprot);
memprot = NULL;
delete_rbtree(mmapmem);
mmapmem = NULL;
delete_rbtree(mapallmem);
mapallmem = NULL;
for(int i=0; i<n_blocks; ++i)
#ifdef USE_MMAP
munmap(p_blocks[i].block, p_blocks[i].size);
@@ -1344,16 +1270,6 @@ void fini_custommem_helper(box86context_t *ctx)
pthread_mutex_destroy(&mutex_blocks);
pthread_mutex_destroy(&mutex_prot);
#endif
while(mapallmem) {
mapmem_t *tmp = mapallmem;
mapallmem = mapallmem->next;
box_free(tmp);
}
while(mmapmem) {
mapmem_t *tmp = mmapmem;
mmapmem = mmapmem->next;
box_free(tmp);
}
}
#ifdef DYNAREC
+11
View File
@@ -192,6 +192,9 @@ Op is 20-27
// and dst, src1, #imm ror rot*2
#define AND_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2000000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// and.c dst, src, #(imm8)
#define AND_IMM8_COND(cond, dst, src, imm8) \
EMIT((cond) | 0x02000000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and.s dst, src, #(imm8)
#define ANDS_IMM8(dst, src, imm8) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -427,6 +430,8 @@ Op is 20-27
// blx reg
#define BLX(reg) EMIT(0xe12fff30 | (reg) )
// blx cond reg
#define BLXcond(C, reg) EMIT(C | 0x012fff30 | (reg) )
// b cond offset
#define Bcond(C, O) EMIT(C | (0b101<<25) | (0<<24) | (((O)>>2)&0xffffff))
@@ -434,6 +439,10 @@ Op is 20-27
// bl cond offset
#define BLcond(C, O) EMIT(C | (0b101<<25) | (1<<24) | (((O)>>2)&0xffffff))
// adr
#define ADR_gen(cond, P, Rd, Imm12) (cond | (1<<25) | (((P)?0b0100:0b0010)<<21) | (0b1111<<16) | ((Rd)<<12) | (Imm12))
#define ADR(cond, Rd, Imm) EMIT(ADR_gen(cond, (Imm>=0), Rd, ((Imm>=0)?Imm:-Imm)&0b111111111111))
// push reg!, {list}
// all | const |pre-index| subs | no PSR |writeback| store | base |reg list
#define PUSH(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (1<<21) | (0<<20) | ((reg)<<16) | (list))
@@ -909,6 +918,8 @@ Op is 20-27
#define VMOV_igen(i, D, imm3, Vd, cmode, Q, op, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | (op)<<5 | 1<<4 | (imm4))
#define VMOV_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 0, (imm)&15))
#define VMOVQ_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 1, 0, (imm)&15))
// Dd <= imm8 6bits duplicated 1bit -> 1byte
#define VMOV_D64(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 1, (imm)&15))
// Dd <= imm8 in high bits
#define VMOV_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 0, 0, (imm8)&15))
// Dd <= imm8 in high bits
+8 -1
View File
@@ -9,8 +9,11 @@
.global arm_epilog
arm_epilog:
//update register -> emu
//pop {r0}
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be Flags now)
// restore stack pointer
ldr sp, [r0, #(8*4+2*4)]
pop {r4, r5}
str r4, [r0, #(8*4+2*4)] // put back old value
//restore all used register
vpop {d8-d15}
pop {r4-r12, pc}
@@ -20,6 +23,10 @@ arm_epilog:
.global arm_epilog_fast
arm_epilog_fast:
// restore stack pointer
ldr sp, [r0, #(8*4+2*4)]
pop {r4, r5}
str r4, [r0, #(8*4+2*4)] // put back old value
//restore all used register
vpop {d8-d15}
pop {r4-r12, pc}
+2
View File
@@ -471,8 +471,10 @@ ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>,
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 0 1 1 1 1 Rd imm12 ADR<c> <Rd>, #-<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 0 1 1 1 1 Rd imm12 ADR<c> <Rd>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
+4
View File
@@ -101,6 +101,7 @@ arm_lock_storeifnull:
beq arm_lock_storeifnull
arm_lock_storeifnull_exit:
mov r0, r2
dmb ish
bx lr
arm_lock_storeifref2:
@@ -116,6 +117,7 @@ arm_lock_storeifref2_loop:
beq arm_lock_storeifref_loop
mov r0, r2
arm_lock_storeifref2_exit:
dmb ish
bx lr
arm_lock_storeifref:
@@ -175,11 +177,13 @@ arm_lock_incif0b_0:
bx lr
arm_lock_stored:
dmb ish
str r1, [r0]
dmb ish
bx lr
arm_lock_storeb:
dmb ish
strb r1, [r0]
dmb ish
bx lr
+12
View File
@@ -4197,6 +4197,12 @@ const char* arm_print(uint32_t opcode) {
uint16_t imm12 = ((opcode >> 0) & 0xFFF);
sprintf(ret, "EOR%s%s %s, %s, #0x%x", (s ? "S" : ""), cond, regname[rd], regname[rn], print_modified_imm_ARM(imm12));
} else if ((opcode & 0x0FFF0000) == 0x024F0000) {
const char* cond = conds[(opcode >> 28) & 0xF];
int rd = (opcode >> 12) & 0xF;
uint16_t imm12 = ((opcode >> 0) & 0xFFF);
sprintf(ret, "ADR%s %s, #-0x%x", cond, regname[rd], print_modified_imm_ARM(imm12));
} else if ((opcode & 0x0FE00000) == 0x02400000) {
int s = (opcode >> 20) & 1;
const char* cond = conds[(opcode >> 28) & 0xF];
@@ -4213,6 +4219,12 @@ const char* arm_print(uint32_t opcode) {
uint16_t imm12 = ((opcode >> 0) & 0xFFF);
sprintf(ret, "RSB%s%s %s, %s, #0x%x", (s ? "S" : ""), cond, regname[rd], regname[rn], print_modified_imm_ARM(imm12));
} else if ((opcode & 0x0FFF0000) == 0x028F0000) {
const char* cond = conds[(opcode >> 28) & 0xF];
int rd = (opcode >> 12) & 0xF;
uint16_t imm12 = ((opcode >> 0) & 0xFFF);
sprintf(ret, "ADR%s %s, #0x%x", cond, regname[rd], print_modified_imm_ARM(imm12));
} else if ((opcode & 0x0FE00000) == 0x02800000) {
int s = (opcode >> 20) & 1;
const char* cond = conds[(opcode >> 28) & 0xF];
+5 -2
View File
@@ -11,9 +11,12 @@ arm_prolog:
//save all used register
push {r4-r12, lr}
vpush {d8-d15}
// save Sp and setup stack for optionnal callret
ldr r4, [r0, #(8*4+2*4)] // grab old value of xSPSave
mov r5, #0
push {r4-r5}
str sp, [r0, #(8*4+2*4)]
//setup emu -> register
//push {r0}
ldm r0, {r4-r12} // all 8 register in direct access, plus flags, no EIP (so r14 can be used as scratch)
//TODO
//jump to function
bx r1
+4 -20
View File
@@ -262,33 +262,17 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
{
if(isInHotPage(addr))
return NULL;
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
if(db && db->done && db->block && getNeedTest(addr)) {
if(db->always_test)
sched_yield(); // just calm down...
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
emu->test.test = 0;
if(box86_dynarec_fastpage) {
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
if(hash==db->hash) { // seems ok, run it without reprotecting it
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
return db;
}
db->done = 0; // invalidating the block, it's already not good
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 1);
return NULL; // not building a new one, it's still a hotpage
} else {
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
return NULL;
}
}
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, db->always_test, (void*)addr);
// Free db, it's now invalid!
dynablock_t* old = InvalidDynablock(db, need_lock);
// start again... (will create a new block)
@@ -300,7 +284,7 @@ dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
} else
FreeInvalidDynablock(old, need_lock);
} else {
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X, always_test:%d) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, db->always_test, (void*)addr);
protectDB((uintptr_t)db->x86_addr, db->x86_size);
// fill back jumptable
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
+11 -3
View File
@@ -20,6 +20,7 @@
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#include "custommem.h"
void x86test_check(x86emu_t* ref, uintptr_t ip);
#endif
@@ -59,9 +60,13 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
// no block, let link table as is...
#ifdef HAVE_TRACE
if(LOG_INFO<=box86_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
if(checkInHotPage(addr)) {
dynarec_log(LOG_INFO, "Not trying to run a block from a Hotpage at %p\n", (void*)addr);
} else {
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2-4);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p(elf=%s))\n", (void*)addr, x2-4, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
}
}
#endif
//tableupdate(arm_epilog, addr, table);
@@ -137,11 +142,13 @@ int DynaRun(x86emu_t* emu)
JUMPBUFF jmpbuf[1] = {0};
int skip = 0;
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
uintptr_t old_savesp = emu->xSPSave;
emu->flags.jmpbuf_ready = 0;
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
emu->old_savedsp = emu->xSPSave;
emu->flags.jmpbuf_ready = 1;
#ifdef ANDROID
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
@@ -199,4 +206,5 @@ int DynaRun(x86emu_t* emu)
}
// clear the setjmp
emu->jmpbuf = old_jmpbuf;
emu->xSPSave = old_savesp;
}
+90 -46
View File
@@ -73,8 +73,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
}
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 64;
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
printf_log(LOG_NONE, "Warning, overallocating next\n");
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -98,15 +97,14 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
void add_jump(dynarec_arm_t *dyn, int ninst) {
// add slots
if(dyn->jmp_sz == dyn->jmp_cap) {
dyn->jmp_cap += 64;
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
printf_log(LOG_NONE, "Warning, overallocating jmps\n");
}
dyn->jmps[dyn->jmp_sz++] = ninst;
}
int get_first_jump(dynarec_arm_t *dyn, int next) {
for(int i=0; i<dyn->jmp_sz; ++i)
if(dyn->insts[dyn->jmps[i]].x86.jmp == next)
return i;
return dyn->jmps[i];
return -2;
}
@@ -282,33 +280,47 @@ void addInst(instsize_t* insts, size_t* size, int x86_size, int native_size)
}
}
static void recurse_mark_alive(dynarec_arm_t* dyn, int i)
{
if(dyn->insts[i].x86.alive)
return;
dyn->insts[i].x86.alive = 1;
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
recurse_mark_alive(dyn, dyn->insts[i].x86.jmp_insts);
if(i<dyn->size-1 && dyn->insts[i].x86.has_next)
recurse_mark_alive(dyn, i+1);
}
static void fillPredecessors(dynarec_arm_t* dyn)
static int sizePredecessors(dynarec_arm_t* dyn)
{
int pred_sz = 1; // to be safe
// compute total size of predecessor to alocate the array
// compute total size of predecessor to allocate the array
// mark alive...
recurse_mark_alive(dyn, 0);
// first compute the jumps
int jmpto;
for(int i=0; i<dyn->size; ++i) {
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1) {
++pred_sz;
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
if(dyn->insts[i].x86.alive && dyn->insts[i].x86.jmp && ((jmpto=dyn->insts[i].x86.jmp_insts)!=-1)) {
pred_sz++;
dyn->insts[jmpto].pred_sz++;
}
}
// remove "has_next" from orphean branch
// remove "has_next" from orphan branch
for(int i=0; i<dyn->size-1; ++i) {
if(!dyn->insts[i].x86.has_next) {
if(dyn->insts[i+1].x86.has_next && !dyn->insts[i+1].pred_sz)
dyn->insts[i+1].x86.has_next = 0;
}
if(dyn->insts[i].x86.has_next && !dyn->insts[i+1].x86.alive)
dyn->insts[i].x86.has_next = 0;
}
// second the "has_next"
for(int i=0; i<dyn->size-1; ++i) {
if(dyn->insts[i].x86.has_next) {
++pred_sz;
++dyn->insts[i+1].pred_sz;
pred_sz++;
dyn->insts[i+1].pred_sz++;
}
}
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
return pred_sz;
}
static void fillPredecessors(dynarec_arm_t* dyn)
{
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -317,7 +329,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
// fill pred
for(int i=0; i<dyn->size; ++i) {
for(int i=0; i<dyn->size; ++i) if(dyn->insts[i].x86.alive) {
if((i!=dyn->size-1) && dyn->insts[i].x86.has_next)
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && (dyn->insts[i].x86.jmp_insts!=-1)) {
@@ -332,14 +344,10 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
need |= dyn->insts[ninst].x86.need_after;
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET || dyn->insts[ninst].x86.state_flags==SF_SET || dyn->insts[ninst].x86.state_flags==SF_SET_NODF)) {
need &=~X_PEND;
need |= X_ALL;
}
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SET)) {
need &=~X_PEND;
need |= dyn->insts[ninst].x86.set_flags; // SF_SET will compute all flags, it's not SUBSET!
}
if((need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET_PENDING) {
need |= X_ALL&~(dyn->insts[ninst].x86.set_flags);
}
@@ -348,10 +356,11 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
dyn->insts[ninst].x86.gen_flags |= X_PEND;
dyn->insts[ninst].x86.need_after = need;
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
if(dyn->insts[ninst].x86.may_set)
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
else if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
need &=~X_PEND; // Consume X_PEND if relevant
need &=~X_PEND; // Consume X_PEND if relevant
need |= dyn->insts[ninst].x86.use_flags;
if(dyn->insts[ninst].x86.need_before == need)
return ninst - 1;
@@ -374,22 +383,23 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
}
void* current_helper = NULL;
static int static_jmps[MAX_INSTS+2];
static uintptr_t static_next[MAX_INSTS+2];
static instruction_arm_t static_insts[MAX_INSTS+2] = {0};
// TODO: ninst could be a uint16_t instead of an int, that could same some temp. memory
void CancelBlock(int need_lock)
{
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(helper) {
dynaFree(helper->next);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = NULL;
}
}
current_helper = NULL;
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
@@ -438,10 +448,6 @@ void* FillBlock(dynablock_t* block, uintptr_t addr) {
*/
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
return CreateEmptyBlock(block, addr);
@@ -458,10 +464,19 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm_t*)dynaCalloc(helper.cap, sizeof(instruction_arm_t));
helper.cap = MAX_INSTS;
helper.insts = static_insts;
helper.jmps = static_jmps;
helper.jmp_cap = MAX_INSTS;
helper.next = static_next;
helper.next_cap = MAX_INSTS;
// pass 0, addresses, x86 jump addresses, overall size of the block
uintptr_t end = arm_pass0(&helper, addr);
if(helper.abort) {
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
CancelBlock(0);
return NULL;
}
// basic checks
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
@@ -470,7 +485,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
AddHotPage(addr);
CancelBlock(0);
return NULL;
}
@@ -483,10 +497,10 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
for(int ii=0; ii<helper.jmp_sz; ++ii) {
int i = helper.jmps[ii];
uintptr_t j = helper.insts[i].x86.jmp;
helper.insts[i].x86.jmp_insts = -1;
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
@@ -519,30 +533,50 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(helper.insts[i2].x86.addr==j)
k=i2;
}*/
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
if(k!=-1) {
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
}
}
}
// no need for next and jmps anymore
dynaFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
dynaFree(helper.jmps);
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// fill predecessors with the jump address
int alloc_size = sizePredecessors(&helper);
helper.predecessor = (int*)alloca(alloc_size*sizeof(int));
fillPredecessors(&helper);
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// remove fpu stuff on non-executed code
for(int i=1; i<helper.size-1; ++i)
if(!helper.insts[i].pred_sz) {
int ii = i;
while(ii<helper.size && !helper.insts[ii].pred_sz)
fpu_reset_ninst(&helper, ii++);
i = ii;
}
// pass 1, float optimisations, first pass for flags
arm_pass1(&helper, addr);
if(helper.abort) {
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
CancelBlock(0);
return NULL;
}
// pass 2, instruction size
arm_pass2(&helper, addr);
if(helper.abort) {
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
CancelBlock(0);
return NULL;
}
// ok, now allocate mapped memory, with executable flag on
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
@@ -576,13 +610,16 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
helper.arm_size = 0;
helper.insts_size = 0; // reset
arm_pass3(&helper, addr);
if(helper.abort) {
if(box86_dynarec_dump || box86_dynarec_log)dynarec_log(LOG_NONE, "Abort dynablock on pass0\n");
CancelBlock(0);
return NULL;
}
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
dynaFree(helper.insts);
helper.insts = NULL;
helper.instsize = NULL;
dynaFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
@@ -601,7 +638,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
// Check if something changed, to abbort if it as
if((block->hash != hash)) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%zu)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
AddHotPage(addr);
CancelBlock(0);
return NULL;
}
@@ -619,15 +655,23 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
CancelBlock(0);
return NULL;
}
// ok, free the helper now
helper.insts = NULL;
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "BOX86: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
}
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%zu, marking as need_test\n", block->x86_addr, block->x86_size);
AddHotPage(addr);
block->dirty = 1;
//protectDB(addr, end-addr);
}
if(getProtection(addr)&PROT_NEVERCLEAN) {
block->dirty = 1;
block->always_test = 1;
}
if(block->always_test) {
dynarec_log(LOG_DEBUG, "Note: block marked as always dirty %p:%ld\n", block->x86_addr, block->x86_size);
}
current_helper = NULL;
//block->done = 1;
return (void*)block;
+103 -62
View File
@@ -352,7 +352,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("DAA");
MESSAGE(LOG_DUMP, "Need Optimization DAA\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UXTB(x1, xEAX, 0);
CALL_(daa8, x1, 0);
BFI(xEAX, x1, 0, 8);
@@ -414,7 +414,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("DAS");
MESSAGE(LOG_DUMP, "Need Optimization DAS\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UXTB(x1, xEAX, 0);
CALL_(das8, x1, 0);
BFI(xEAX, x1, 0, 8);
@@ -476,7 +476,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("AAA");
MESSAGE(LOG_DUMP, "Need Optimization AAA\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UXTH(x1, xEAX, 0);
CALL_(aaa16, x1, 0);
BFI(xEAX, x1, 0, 16);
@@ -544,7 +544,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("AAS");
MESSAGE(LOG_DUMP, "Need Optimization AAS\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UXTH(x1, xEAX, 0);
CALL_(aas16, x1, 0);
BFI(xEAX, x1, 0, 16);
@@ -1239,7 +1239,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x9D:
INST_NAME("POPF");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
POP1(xFlags);
MOV32(x1, 0x3F7FD7);
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
@@ -1441,7 +1441,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
GETEB(x1);
u8 = F8;
MOVW(x2, u8);
@@ -1452,7 +1452,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
GETEB(x1);
u8 = F8;
MOVW(x2, u8);
@@ -1524,7 +1524,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
GETEDW(x14, x1);
u8 = F8;
MOVW(x2, u8);
@@ -1563,7 +1563,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
WBACK;
} else if(u8>1) {
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, u8);
CALL_(rcr32, ed, (1<<x14));
WBACK;
@@ -1602,11 +1602,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC2:
INST_NAME("RETN");
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
//SETFLAGS(X_ALL,_NODF SF_SET_NODF); // Hack, set all flags (to an unknown state...)
if(box86_dynarec_safeflags) {
READFLAGS(X_PEND); // lets play safe here too
}
BARRIER(BARRIER_FLOAT);
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
*need_epilog = 0;
@@ -1614,12 +1614,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC3:
INST_NAME("RET");
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
// SETFLAGS(X_ALL,_NODF SF_SET_NODF); // Hack, set all flags (to an unknown state...)
// ^^^ that hack break PlantsVsZombies and GOG Setup under wine....
if(box86_dynarec_safeflags) {
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
}
BARRIER(BARRIER_FLOAT);
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); // using next, even if there no next
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -1666,7 +1666,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xCC:
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
SETFLAGS(X_ALL, SF_SET_NODF); // Hack, set all flags (to an unknown state...)
NOTEST(x1, x14);
if(PK(0)=='S' && PK(1)=='C') {
addr+=2;
BARRIER(BARRIER_FLOAT);
@@ -1674,7 +1675,6 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
{
addr+=4;
SKIPTEST(x14);
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
MOV32(x14, ip+1+2);
SMEND();
@@ -1685,7 +1685,6 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*need_epilog = 1;
} else {
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
SKIPTEST(x14);
SMEND();
x87_forget(dyn, ninst, x3, x14, 0);
if((box86_log<2) && !cycle_log) { // call the wrapper directly
@@ -1734,8 +1733,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xCD:
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
SKIPTEST(x14);
SETFLAGS(X_ALL, SF_SET_NODF); // Hack, set all flags (to an unknown state...)
SKIPTEST(x1, x14);
SMEND();
u8 = F8;
if(u8==0x80) {
@@ -1765,7 +1764,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("IRET");
SETFLAGS(X_ALL, SF_SET); // Not a hack, EFLAGS are restored
SETFLAGS(X_ALL, SF_SET_NODF); // Not a hack, EFLAGS are restored
BARRIER(BARRIER_FLOAT);
iret_to_epilog(dyn, ninst);
*need_epilog = 0;
@@ -1793,7 +1792,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Eb, 1");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEB(x1);
CALL_(rcl8, x1, (1<<x3));
@@ -1803,7 +1802,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Eb, 1");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEB(x1);
CALL_(rcr8, x1, (1<<x3));
@@ -1855,7 +1854,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
@@ -1864,16 +1863,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("RCR Ed, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETED;
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
MOVW(x3, 1);
STR_IMM9(x3, xEmu, offsetof(x86emu_t, op2));
SET_DF(x3, d_rcr32);
} else IFX(X_ALL) {
SET_DFNONE(x3);
}
IFX(X_OF) {
XOR_REG_LSR_IMM8(x3, xFlags, ed, 31);
BFI(xFlags, x3, F_OF, 1);
@@ -1969,7 +1960,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Eb, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEB(x1);
CALL_(rcl8, x1, (1<<x3));
@@ -1979,7 +1970,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Eb, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEB(x1);
CALL_(rcr8, x1, (1<<x3));
@@ -2084,7 +2075,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
@@ -2094,7 +2085,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcr32, ed, (1<<x14));
@@ -2132,7 +2123,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD4:
INST_NAME("AAM Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UBFX(x1, xEAX, 0, 8); // load AL
u8 = F8;
MOVW(x2, u8);
@@ -2141,7 +2132,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD5:
INST_NAME("AAD Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
UBFX(x1, xEAX, 0, 16); // load AX
u8 = F8;
MOVW(x2, u8);
@@ -2264,28 +2255,28 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#endif
switch(tmp) {
case 1:
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
//SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call 0\n");
SKIPTEST(x14);
SKIPTEST(x1, x14);
MOV32(xEIP, addr);
PUSH1(xEIP);
break;
case 2:
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
//SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
SKIPTEST(x14);
SKIPTEST(x1, x14);
u8 = PK(i32+1);
gd = xEAX+((u8&0x38)>>3);
MOV32(gd, addr);
break;
case 3:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
SKIPTEST(x1, x14);
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
MOV32(x2, addr);
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
SKIPTEST(x14);
// calling a native function
if(isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
// return value will be on the stack, so the stack depth needs to be updated
@@ -2326,21 +2317,39 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
}
// regular call
//BARRIER_NEXT(BARRIER_FULL);
if(/*box86_dynarec_callret &&*/ box86_dynarec_bigblock>1) {
/*if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
*need_epilog = 0;
*ok = 0;
}*/
MOV32(x2, addr);
fpu_purgecache(dyn, ninst, 1, x1, x3, x14);
PUSH1(x2);
if(box86_dynarec_callret) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x14, j32);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j32 = getJumpTableAddress(addr);
MOV32(x14, j32);
LDR_IMM9(x14, x14, 0);
}
PUSH(xSP, (1<<x2)|(1<<x14));
} else {
*need_epilog = 0;
*ok = 0;
}
if(u32==0) { // self modifying code maybe? so use indirect address fetching
MOV32(x14, addr-4);
LDR_IMM9(x14, x14, 0);
@@ -2384,7 +2393,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, EAX */
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
MOV32(xEIP, ip);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
@@ -2500,7 +2509,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(box86_dynarec_safeflags>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags to "dont'care" state
}
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
@@ -2511,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;
@@ -2744,7 +2765,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 6:
INST_NAME("DIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization DIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEB(x1);
STM(xEmu, (1<<xEAX));
CALL(div8, -1, 0);
@@ -2753,7 +2774,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7:
INST_NAME("IDIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization IDIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEB(x1);
STM(xEmu, (1<<xEAX));
CALL(idiv8, -1, 0);
@@ -2806,7 +2827,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
if(ninst && dyn->insts && (nextop==0xF0)
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0xB8
@@ -2854,7 +2875,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("IDIV Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
if(arm_div && ninst && dyn->insts
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x99) {
@@ -2908,7 +2929,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFA:
case 0xFB:
INST_NAME(opcode==0xFA?"STI":"CLI");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
MOV32(xEIP, ip);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
@@ -2975,14 +2996,34 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
}
GETEDH(xEIP);
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
MOV32(x2, addr);
if(box86_dynarec_callret) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x3, j32);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j32 = getJumpTableAddress(addr);
MOV32(x3, j32);
LDR_IMM9(x3, x3, 0);
}
PUSH(xSP, (1<<x2)|(1<<x3));
}
PUSH1(x2);
jump_to_next(dyn, 0, ed, ninst);
break;
+70 -11
View File
@@ -86,11 +86,70 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch(opcode) {
case 0x01:
nextop = F8;
if(MODREG)
switch(nextop) {
case 0xD0:
INST_NAME("FAKE xgetbv");
addr = fakeed(dyn, addr, ninst, nextop);
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
//CALL(arm_ud, -1, 0);
SKIPTEST(x1, x14);
UDF(0);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("SMSW Ed");
ed = xEAX+(nextop&7);
MOV32(ed, (1<<0) | (1<<4)); // only PE and ET set...
break;
default:
DEFAULT;
}
else
switch((nextop>>3)&7) {
case 0:
INST_NAME("SGDT Ed");
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
MOVW(x1, 0x7f);
STRH_IMM8(x1, wback, 0);
MOVW(x1, 0x000c);
STRH_IMM8(x1, wback, 2);
MOVW(x1, 0xd000);
STRH_IMM8(x1, wback, 4);
break;
case 1:
INST_NAME("SIDT Ed");
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
MOVW(x1, 0xfff);
STRH_IMM8(x1, wback, 0);
MOVW(x1, 0);
STR_IMM9(x1, wback, 2);
break;
case 4:
INST_NAME("SMSW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
// dummy for now... Do I need to track CR0 state?
MOVW(x1, (1<<0) | (1<<4)); // only PE and ET set...
STRH_IMM8(x1, wback, 0);
break;
default:
DEFAULT;
}
break;
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
//CALL(arm_ud, -1, 0);
SKIPTEST(x14);
SKIPTEST(x1, x14);
UDF(0);
break;
@@ -385,7 +444,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
nextop = F8;
GETGX(v0, 0);
if(MODREG) {
@@ -422,7 +481,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x31:
INST_NAME("RDTSC");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x14);
SKIPTEST(x1, x14);
CALL(ReadTSC, xEAX, 0); // will return the u64 in x1:xEAX
MOV_REG(xEDX, x1);
break;
@@ -658,7 +717,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x51:
INST_NAME("SQRTPS Gx, Ex");
SKIPTEST(x1);
SKIPTEST(x1, x14);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -727,7 +786,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
SKIPTEST(x1);
SKIPTEST(x1, x14);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -750,7 +809,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
SKIPTEST(x1);
SKIPTEST(x1, x14);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -1585,7 +1644,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
AND_IMM8(x3, xECX, 0x1f);
GETED;
GETGD;
@@ -1643,7 +1702,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED;
GETGD;
u8 = F8;
@@ -1653,7 +1712,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xAD:
nextop = F8;
INST_NAME("SHRD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
AND_IMM8(x3, xECX, 0x1f);
GETED;
GETGD;
@@ -1726,7 +1785,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5:
INST_NAME("XRSTOR Ed (not implemented");
FAKEED;
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_ud, -1, 0);
+26 -4
View File
@@ -18,6 +18,7 @@
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "custommem.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
@@ -364,7 +365,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
SETFLAGS(X_ALL, SF_SET_NODF); //Hack to put flag in "don't care" state
}
if(MODREG) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
@@ -372,10 +373,31 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
}
BARRIER(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
if(box86_dynarec_callret && box86_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
MOV32(x2, addr);
if(box86_dynarec_callret) {
SET_HASCALLRET();
// Push actual return address
if(addr < (dyn->start+dyn->isize)) {
// there is a next...
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)-8):0;
MESSAGE(LOG_NONE, "\tCALLRET set return to +%di\n", j32>>2);
ADR(c__, x3, j32);
} else {
MESSAGE(LOG_NONE, "\tCALLRET set return to Jmptable(%p)\n", (void*)addr);
j32 = getJumpTableAddress(addr);
MOV32(x3, j32);
LDR_IMM9(x3, x3, 0);
}
PUSH(xSP, (1<<x2)|(1<<x3));
}
PUSH1(x2);
jump_to_next(dyn, 0, xEIP, ninst);
break;
+4 -4
View File
@@ -508,7 +508,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEDO2(x14);
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
@@ -519,7 +519,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x2));
@@ -601,7 +601,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x2));
@@ -611,7 +611,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
+37 -36
View File
@@ -48,8 +48,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x2);
GETSEW(x1);
GETGW(x2);
GETEW(x1);
emit_add16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -57,16 +57,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x1);
GETSEW(x2);
GETGW(x1);
GETEW(x2);
emit_add16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16S;
SXTH(x1, xEAX, 0);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_add16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -124,8 +124,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x2);
GETSEW(x1);
GETGW(x2);
GETEW(x1);
emit_adc16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -134,8 +134,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x1);
GETSEW(x2);
GETGW(x1);
GETEW(x2);
emit_adc16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
@@ -143,8 +143,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16S;
SXTH(x1, xEAX, 0);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -154,8 +154,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x2);
GETSEW(x1);
GETGW(x2);
GETEW(x1);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -165,7 +165,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETSEW(x2);
GETEW(x2);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
@@ -173,8 +173,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16S;
SXTH(x1, xEAX, 0);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -220,8 +220,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x2);
GETSEW(x1);
GETGW(x2);
GETEW(x1);
emit_sub16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -229,16 +229,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETSGW(x1);
GETSEW(x2);
GETGW(x1);
GETEW(x2);
emit_sub16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16S;
SXTH(x1, xEAX, 0);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -637,7 +637,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x9D:
INST_NAME("POPF (16b)");
SETFLAGS(X_ALL, SF_SET); // lower 16bits is all flags handled in dynarec
SETFLAGS(X_ALL, SF_SET_NODF); // lower 16bits is all flags handled in dynarec
LDRHA_IMM8(x2, xESP, 2);
MOV32(x1, 0x7FD7);
AND_REG_LSL_IMM5(x2, x2, x1, 0);
@@ -753,7 +753,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
INST_NAME("RCL Ew, Ib");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
@@ -763,7 +763,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("RCR Ew, Ib");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
@@ -774,7 +774,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 6:
INST_NAME("SHL Ew, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
emit_shl16c(dyn, ninst, x1, u8&31, x2, x14);
@@ -787,7 +787,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5:
INST_NAME("SHR Ed, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
emit_shr16c(dyn, ninst, x1, u8&31, x2, x14);
@@ -800,7 +800,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7:
INST_NAME("SAR Ed, Ib");
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1);
u8 = F8;
emit_sar16c(dyn, ninst, x1, u8&31, x2, x14);
@@ -849,7 +849,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
INST_NAME("RCL Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
@@ -858,7 +858,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("RCR Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
@@ -942,7 +942,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
INST_NAME("RCL Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
@@ -951,7 +951,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("RCR Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
@@ -1161,7 +1161,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("DIV Ew");
if(arm_div) {
GETEW(x1);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
SET_DFNONE(x2);
UXTH(x2, xEAX, 0);
ORR_REG_LSL_IMM5(x2, x2, xEDX, 16);
UDIV(x3, x2, ed);
@@ -1170,7 +1171,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(xEDX, x14, 0, 16);
} else {
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(div16, -1, 0);
@@ -1180,7 +1181,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7:
INST_NAME("IDIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEW(x1);
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(idiv16, -1, 0);
+122 -4
View File
@@ -276,7 +276,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
// no special check...
case 0x2F:
if(opcode==0x2F) {INST_NAME("COMISD Gx, Ex");} else {INST_NAME("UCOMISD Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
@@ -468,6 +468,96 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VABSQ_S32(q0, q1);
break;
case 0x2B:
INST_NAME("PACKUSDW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn);
v1 = fpu_get_scratch_quad(dyn);
VEORQ(v0, v0, v0);
VMAXQ_S32(v1, v0, q0); // values < 0 => 0
VQMOVN_U32(q0, v1);
if(q0==q1) {
VMOV_64(q0+1, q0);
} else {
VMAXQ_S32(v0, v0, q1);
VQMOVN_U32(q0+1, v0);
}
break;
case 0x38:
INST_NAME("PMINSB Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMINQ_S8(q0, q0, q1);
break;
case 0x39:
INST_NAME("PMINSD Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMINQ_S32(q0, q0, q1);
break;
case 0x3A:
INST_NAME("PMINUW Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMINQ_U16(q0, q0, q1);
break;
case 0x3B:
INST_NAME("PMINUD Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMINQ_U32(q0, q0, q1);
break;
case 0x3C:
INST_NAME("PMAXSB Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMAXQ_S8(q0, q0, q1);
break;
case 0x3D:
INST_NAME("PMAXSD Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMAXQ_S32(q0, q0, q1);
break;
case 0x3E:
INST_NAME("PMAXUW Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMAXQ_U16(q0, q0, q1);
break;
case 0x3F:
INST_NAME("PMAXUD Gx,Ex");
nextop = F8;
GETEX(q1, 0);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMINQ_U32(q0, q0, q1);
break;
case 0x40:
INST_NAME("PMULLD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX(q0, 1);
VMULQ_32(q0, q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
@@ -577,6 +667,34 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x3A: // these are some more SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0E:
INST_NAME("PBLENDW Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_double(dyn);
u8 = F8;
i32 = 0;
for(int i=0; i<4; ++i)
if((u8&(1<<i)))
i32|=(0b11<<(i*2));
if(i32 && (q0!=q1)) {
VMOV_D64(v0, i32);
VBICD(q0, q0, v0);
VANDD(v0, q1, v0);
VORRD(q0, q0, v0);
}
i32 = 0;
for(int i=0; i<4; ++i)
if((u8&(1<<(i+4))))
i32|=(0b11<<(i*2));
if(i32 && (q0!=q1)) {
VMOV_D64(v0, i32);
VBICD(q0+1, q0+1, v0);
VANDD(v0, q1+1, v0);
VORRD(q0+1, q0+1, v0);
}
break;
case 0x0F:
INST_NAME("PALIGNR Gx, Ex, Ib");
nextop = F8;
@@ -686,7 +804,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x63:
INST_NAME("PCMPISTRI Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
nextop = F8;
GETG;
if(!sse_reflect_reg(dyn, ninst, gd, x2)) {
@@ -1718,7 +1836,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("SHLD Ew, Gw, CL");
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEWW(x14, x1);
GETGW(x2);
if(opcode==0xA4) {
@@ -1770,7 +1888,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("SHRD Ew, Gw, CL");
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_DF);
GETEWW(x14, x1);
GETGW(x2);
if(opcode==0xAC) {
+51 -2
View File
@@ -33,6 +33,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int d1;
int fixedaddress;
int parity;
uint8_t u8;
MAYUSE(d1);
MAYUSE(s0);
@@ -52,11 +53,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, v2);
} else {
VADD_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xC8:
case 0xC9:
@@ -69,11 +74,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, v2);
} else {
VMUL_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xD0:
case 0xD1:
@@ -110,7 +119,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -123,11 +132,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, v2);
} else {
VSUB_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xE8:
case 0xE9:
@@ -140,11 +153,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v2, v1);
} else {
VSUB_F64(v1, v2, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
case 0xF1:
@@ -157,11 +174,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, v2);
} else {
VDIV_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xF8:
case 0xF9:
@@ -174,11 +195,15 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v2, v1);
} else {
VDIV_F64(v1, v2, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
default:
@@ -196,12 +221,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
@@ -216,12 +245,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
@@ -264,7 +297,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, d1);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
@@ -279,12 +312,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
@@ -299,12 +336,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
@@ -319,12 +360,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, s0);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
@@ -339,12 +384,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETED;
VMOVtoV(s0, ed);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, s0, v1);
} else {
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
+130 -62
View File
@@ -67,7 +67,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v2 = x87_do_push(dyn, ninst, x3, X87_ST(nextop&7));
X87_PUSH_OR_FAIL(v2, dyn, ninst, x3, X87_ST(nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, (nextop&7)+1, X87_COMBINE(0, (nextop&7)+1));
if(ST_IS_F(0)) {
VMOV_32(v2, v1);
@@ -134,25 +134,49 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i1 = x87_get_current_cache(dyn, ninst, 0, NEON_CACHE_ST_D);
// value put in x14
if(i1==-1) {
// not in cache, so check Empty status and load it
// x14 will be the actual top
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
i2 = -dyn->n.x87stack;
if(i2) {
if(i2<0) {
SUB_IMM8(x14, x14, -i2);
} else {
ADD_IMM8(x14, x14, i2);
if(fpu_is_st_freed(dyn, ninst, 0)) {
MOV32(x14, 0b100000100000000);
B_MARK3(c__);
} else { // not in cache, so check Empty status and load it
// load tag
LDRH_IMM8(x3, xEmu, offsetof(x86emu_t, fpu_tags));
if(i2) {
if(i2<0) {
MOV_REG_LSL_IMM5(x3, x3, -i2*2);
} else {
MOV32(x14, 0xffff);
ORR_REG_LSL_IMM5(x3, x3, x14, 16);
MOV_REG_LSR_IMM5(x3, x3, i2*2);
}
}
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
TSTS_IMM8(x3, 0b11);
MOVW(x14, 0b100000100000000); // empty
B_MARK3(cNE);
// check stack TODO: this test should not be needed, something is wrong with tag handling
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, fpu_stack));
if(i2) {
if(i2<0) {
ADD_IMM8(x3, x3, -i2);
} else {
SUB_IMM8(x3, x3, i2);
}
}
CMPS_IMM8(x3, 0);
B_MARK3(cLE);
// x14 will be the actual top
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
i2 = -dyn->n.x87stack;
if(i2) {
if(i2<0) {
SUB_IMM8(x14, x14, -i2);
} else {
ADD_IMM8(x14, x14, i2);
}
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
}
ADD_REG_LSL_IMM5(x1, xEmu, x14, 3);
LDRD_IMM8(x2, x1, offsetof(x86emu_t, x87)); // load r2/r3 with ST0 anyway, for sign extraction
ADD_REG_LSL_IMM5(x1, xEmu, x14, 2);
LDR_IMM9(x1, x1, offsetof(x86emu_t, p_regs));
CMPS_IMM8(x1, 0b11);
MOVW_COND(cEQ, x14, 0b100000100000000); // empty: C3,C2,C0 = 101
B_MARK3(cEQ);
} else {
// simply move from cache reg to r2/r3
v1 = dyn->n.x87reg[i1];
@@ -194,7 +218,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
VMOV_i_32(v1, 0b01110000);
} else {
@@ -204,7 +228,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_l2t));
VLDR_32(v1, x2, 0);
@@ -216,7 +240,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_l2e));
VLDR_32(v1, x2, 0);
@@ -228,7 +252,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_pi));
VLDR_32(v1, x2, 0);
@@ -240,7 +264,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_lg2));
VLDR_32(v1, x2, 0);
@@ -252,7 +276,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
MOV32(x2, (&f_ln2));
VLDR_32(v1, x2, 0);
@@ -264,7 +288,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0)) {
VMOV_8(v1/2, 0); // float is *2...
} else {
@@ -281,18 +305,20 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL(arm_f2xm1, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
//if(ST0.d!=0.0)
// ST0.d = exp2(ST0.d)-1.0;
VMOV_64(0, v1);
CALL_1D(exp2, 0); // return is d0
if((PK(0)==0xD9 && PK(1)==0xE8) && // next inst is FLD1
(PK(2)==0xDE && PK(3)==0xC1)) {
MESSAGE(LOG_DUMP, "Hack for fld1 / faddp st1, st0\n");
VMOV_64(0, v1);
CALL_1D(exp2, 0); // return is d0
VMOV_64(v1, 0);
addr+=4;
} else {
VMOV_i_64(v1, 0b01110000); // 1.0
VSUB_F64(v1, 0, v1);
//ST0.d = expm1(LN2 * ST0.d);
MOV32(x2, (&d_ln2));
VLDR_64(0, x2, 0);
VMUL_F64(0, 0, v1);
CALL_1D(expm1, 0); // return is d0
VMOV_64(v1, 0);
}
#endif
// should set C1 to 0
@@ -301,19 +327,25 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FYL2X");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_64(0, v1); // prepare call to log2
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d)*ST(1).d
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF2:
INST_NAME("FPTAN");
v2 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v2, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
// seems that tan of glib doesn't follow the rounding direction mode
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMOV_64(0, v1); // prepare call to tan
CALL_1D(tan, 0);
CALL_1D(tan, box86_dynarec_fastround ? 0 : (1 << u8));
VMOV_64(v1, 0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C1 = 0;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
@@ -321,8 +353,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
u8 = F8;
u8 = F8;
} else {
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
@@ -340,11 +370,15 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FPATAN");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMOV_64(0, v2); // prepare call to atan2
VMOV_64(1, v1);
CALL_2D(atan2, 0);
CALL_2D(atan2, box86_dynarec_fastround ? 0 : (1 << u8));
VMOV_64(v2, 0); //ST(1).d = atan2(ST1.d, ST0.d);
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF4:
@@ -352,7 +386,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
s0 = x87_stackcount(dyn, ninst, x3);
CALL(arm_fxtract, -1, 0);
x87_unstackcount(dyn, ninst, x3, s0);
// C1 set only if stack under/overflow occurs
break;
case 0xF5:
@@ -451,32 +487,45 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FYL2XP1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_i_64(0, 0b01110000); // D0 = 1.0
VADD_F64(0, 0, v1); // prepare call to log2
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
x87_do_pop(dyn, ninst, x3);
//ST(1).d = (ST(1).d * log1p(ST0.d)) / M_LN2;
VMOV_64(0, v1); // prepare call to log1p
CALL_1D(log1p, 0);
VMUL_F64(v2, v2, 0);
MOV32(x2, (&d_ln2));
VLDR_64(0, x2, 0);
VDIV_F64(v2, v2, 0);
X87_POP_OR_FAIL(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSQRT_F32(v1, v1);
} else {
VSQRT_F64(v1, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
// should set C1 to 0
break;
case 0xFB:
INST_NAME("FSINCOS");
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v2, dyn, ninst, x3, NEON_CACHE_ST_D);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
// seems that sin and cos function of glibc don't follow the rounding mode
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMOV_64(0, v1);
CALL_1D(sin, 0);
CALL_1D(sin, box86_dynarec_fastround ? 0 : (1 << u8));
VSWP(v1, 0);
CALL_1D(cos, 0); // would it be faster to do sqrt(1-sin()²) ???
CALL_1D(cos, box86_dynarec_fastround ? 0 : (1 << u8)); // would it be faster to do sqrt(1-sin()²) ???
VMOV_64(v2, 0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C2 C1 = 0 0
@@ -511,26 +560,32 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
//if(ST0.d!=0.0)
// ST0.d *= exp2(trunc(ST1.d));
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cEQ);
if(!arm_v8) {
VMOV_64(0, v2);
CALL_1DD(trunc, exp2, 0);
} else {
VRINTZ_F64(0, v2);
CALL_1D(exp2, 0);
}
VMUL_F64(v1, v1, 0);
// ST0.d = ldexp(ST0.d, trunc(ST1.d));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
s0 = fpu_get_scratch_single(dyn);
// value of s0 =
// 2^31-1 (ST1 >= 2^31), -2^31 (ST1 < -2^31) or int(ST1) (other situations)
VCVT_S32_F64(s0 , v2);
VMOVfrV(x2, s0);
VMOV_64(0, v1);
CALL_1DDR(ldexp, x2, x3, box86_dynarec_fastround ? 0 : (1 << u8));
VMOV_64(v1, 0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
// should set C1 to 0
break;
case 0xFE:
INST_NAME("FSIN");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
// seems that sin of glib doesn't follow the rounding direction mode
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMOV_64(0, v1); // prepare call to sin
CALL_1D(sin, 0);
CALL_1D(sin, box86_dynarec_fastround ? 0 : (1 << u8));
VMOV_64(v1, 0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C2 C1 = 0 0
@@ -539,9 +594,14 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
INST_NAME("FCOS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
// seems that cos of glib doesn't follow the rounding direction mode
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMOV_64(0, v1); // prepare call to cos
CALL_1D(cos, 0);
CALL_1D(cos, box86_dynarec_fastround ? 0 : (1 << u8));
VMOV_64(v1, 0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C2 C1 = 0 0
@@ -574,7 +634,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else
@@ -600,7 +660,11 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = v1;
else {
s0 = fpu_get_scratch_single(dyn);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VCVT_F32_F64(s0, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
@@ -619,7 +683,11 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = v1;
else {
s0 = fpu_get_scratch_single(dyn);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VCVT_F32_F64(s0, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
@@ -630,7 +698,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FLDENV Ed");
+28 -3
View File
@@ -33,6 +33,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int d0;
int s0;
int fixedaddress;
uint8_t u8;
MAYUSE(s0);
MAYUSE(d0);
@@ -128,8 +129,8 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE4:
@@ -155,7 +156,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VADD_F64(v1, v1, d0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FIMUL ST0, Ed");
@@ -165,7 +170,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMUL_F64(v1, v1, d0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FICOM ST0, Ed");
@@ -188,7 +197,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCVT_F64_S32(d0, s0);
VCMP_F64(v1, d0);
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FISUB ST0, Ed");
@@ -198,7 +207,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VSUB_F64(v1, v1, d0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FISUBR ST0, Ed");
@@ -208,7 +221,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VSUB_F64(v1, d0, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FIDIV ST0, Ed");
@@ -218,7 +235,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VDIV_F64(v1, v1, d0);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FIDIVR ST0, Ed");
@@ -228,7 +249,11 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
VCVT_F64_S32(d0, s0);
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VDIV_F64(v1, d0, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
}
}
+11 -13
View File
@@ -141,7 +141,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
@@ -160,7 +160,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0)) {
@@ -183,7 +183,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
@@ -218,7 +218,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
VMSR(x14); // put back values
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 2:
INST_NAME("FIST Ed, ST0");
@@ -260,7 +260,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
break;
case 5:
@@ -268,20 +268,18 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
// the FLD is immediatly followed by an FSTP
LDR_IMM9(x2, ed, 0);
LDR_IMM9(x3, ed, 4);
LDM(ed, (1<<x2)|(1<<x3));
LDRH_IMM8(x14, ed, 8);
// no persistant scratch register, so unrool both instruction here...
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; //0xDB
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
STM(ed, (1<<x2)|(1<<x3));
STRH_IMM8(x14, ed, 8);
} else {
if(box86_x87_no80bits) {
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
@@ -298,10 +296,10 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
X87_PUSH_OR_FAIL_empty( , dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
@@ -407,7 +405,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK2;
#endif
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+51 -2
View File
@@ -31,6 +31,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int d1;
int fixedaddress;
int parity;
uint8_t u8;
MAYUSE(d1);
MAYUSE(v2);
@@ -48,11 +49,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FADD STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v1, v1, v2);
} else {
VADD_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xC8:
case 0xC9:
@@ -65,11 +70,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FMUL STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v1, v1, v2);
} else {
VMUL_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xD0:
case 0xD1:
@@ -106,7 +115,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -119,11 +128,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUBR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v2, v1);
} else {
VSUB_F64(v1, v2, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xE8:
case 0xE9:
@@ -136,11 +149,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUB STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v1, v1, v2);
} else {
VSUB_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xF0:
case 0xF1:
@@ -153,11 +170,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVR STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v2, v1);
} else {
VDIV_F64(v1, v2, v1);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 0xF8:
case 0xF9:
@@ -170,11 +191,15 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIV STx, ST0");
v2 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v1, v1, v2);
} else {
VDIV_F64(v1, v1, v2);
}
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
default:
switch((nextop>>3)&7) {
@@ -192,7 +217,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VADD_F64(v1, v1, d1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
@@ -208,7 +237,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VMUL_F64(v1, v1, d1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
@@ -243,7 +276,7 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
VCMP_F64(v1, d1);
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FSUB ST0, double[ED]");
@@ -259,7 +292,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VSUB_F64(v1, v1, d1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
@@ -275,7 +312,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VSUB_F64(v1, d1, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
@@ -291,7 +332,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VDIV_F64(v1, v1, d1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
@@ -307,7 +352,11 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VDIV_F64(v1, d1, v1);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
break;
}
}
+65 -9
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);
@@ -45,10 +46,21 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
#if 1
if((nextop&7)==0 && PK(0)==0xD9 && PK(1)==0xF7) {
MESSAGE(LOG_DUMP, "Hack for FFREE ST0 / FINCSTP\n");
X87_POP_OR_FAIL(dyn, ninst, x1);
addr+=2;
SKIPTEST(x1, x14);
} else
x87_free(dyn, ninst, x1, x2, x3, nextop&7);
#else
INST_NAME("FFREE STx");
x87_purgecache(dyn, ninst, 0, x1, x2, x3);
MOVW(x1, nextop&7);
CALL(fpu_do_free, -1, 0);
#endif
break;
case 0xD0:
case 0xD1:
@@ -69,7 +81,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
case 0xDA:
@@ -81,7 +93,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSTP ST0, STx");
// copy the cache value for st0 to stx
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -119,7 +131,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
@@ -153,7 +165,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
@@ -167,11 +179,54 @@ 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);
x87_do_pop(dyn, ninst, x3);
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:
INST_NAME("FST double");
@@ -200,7 +255,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 4:
INST_NAME("FRSTOR m108byte");
@@ -215,6 +270,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
CALL(reset_fpu, -1, 0);
break;
case 7:
INST_NAME("FNSTSW m2byte");
+47 -14
View File
@@ -7,6 +7,7 @@
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "dynarec/arm_emitter.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
@@ -27,6 +28,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t nextop = F8;
int v1, v2;
uint8_t u8;
MAYUSE(v2);
MAYUSE(v1);
@@ -43,12 +45,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FADDP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VADD_F32(v2, v2, v1);
} else {
VADD_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
case 0xC9:
@@ -61,12 +67,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FMULP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VMUL_F32(v2, v2, v1);
} else {
VMUL_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD0:
case 0xD1:
@@ -85,7 +95,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD9:
@@ -98,8 +108,8 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOM(x1, x2);
x87_do_pop(dyn, ninst, x3);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
case 0xE1:
@@ -112,12 +122,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUBRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v2, v1, v2);
} else {
VSUB_F64(v2, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE8:
case 0xE9:
@@ -130,12 +144,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FSUBP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VSUB_F32(v2, v2, v1);
} else {
VSUB_F64(v2, v2, v1);
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
@@ -148,12 +166,16 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVRP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastround)
u8 = x87_setround(dyn, ninst, x1, x2, x14);
if(ST_IS_F(0)) {
VDIV_F32(v2, v1, v2);
} else {
VDIV_F64(v2, v1, v2);
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround)
x87_restoreround(dyn, ninst, u8);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF8:
case 0xF9:
@@ -166,11 +188,21 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastnan) {
if(!box86_dynarec_fastround || !box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(!box86_dynarec_fastnan) {
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
} else if(!box86_dynarec_fastround)
MOV_REG(x3, x14);
if(!box86_dynarec_fastround){
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x1, x1, 10, 2); // extract round...
UBFX(x2, x1, 1, 1); // swap bits 0 and 1
BFI(x2, x1, 1, 1);
BFI(x3, x2, 22, 2); // inject new round
}
VMSR(x3); // put new fpscr
}
if(ST_IS_F(0)) {
VDIV_F32(v2, v2, v1);
@@ -185,9 +217,10 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VNEG_F64_cond(cNE, v2, v2);
}
VMSR(x14); // restore fpscr
}
x87_do_pop(dyn, ninst, x3);
if(!box86_dynarec_fastround || !box86_dynarec_fastnan)
VMSR(x14); // restore fpscr
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xD8:
+18 -84
View File
@@ -53,7 +53,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("FFREEP STx");
// not handling Tag...
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xE0:
@@ -81,7 +81,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FUCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0))
@@ -91,7 +91,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xF0:
case 0xF1:
@@ -102,7 +102,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_NODF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(ST_IS_F(0))
@@ -112,7 +112,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64(v1, v2);
}
FCOMI(x1, x2);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 0xC8:
@@ -161,7 +161,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRSH_IMM8(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
@@ -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);
@@ -197,7 +197,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
VMSR(x14);
break;
case 2:
@@ -242,20 +242,22 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, x1);
X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
s0 = x87_stackcount(dyn, ninst, x3);
CALL(fpu_fbld, -1, 0);
x87_unstackcount(dyn, ninst, x3, s0);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
X87_PUSH_OR_FAIL(v1, dyn, ninst, x1, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
@@ -314,8 +316,10 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
s0 = x87_stackcount(dyn, ninst, x3);
CALL(fpu_fbst, -1, 0);
x87_do_pop(dyn, ninst, x3);
x87_unstackcount(dyn, ninst, x3, s0);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
case 7: // could be inlined for most thing, but is it usefull?
INST_NAME("FISTP i64, ST0");
@@ -333,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;
@@ -371,76 +373,8 @@ 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_do_pop(dyn, ninst, x3);
X87_POP_OR_FAIL(dyn, ninst, x3);
break;
default:
DEFAULT;
+18 -18
View File
@@ -53,7 +53,7 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -96,7 +96,7 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -130,7 +130,7 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -173,7 +173,7 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -207,7 +207,7 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -258,7 +258,7 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -292,7 +292,7 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -326,7 +326,7 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -360,7 +360,7 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -394,7 +394,7 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -428,7 +428,7 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -462,7 +462,7 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -497,7 +497,7 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -540,7 +540,7 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -574,7 +574,7 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -617,7 +617,7 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -651,7 +651,7 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -694,6 +694,6 @@ void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+33 -33
View File
@@ -69,7 +69,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -151,7 +151,7 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -203,7 +203,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -288,7 +288,7 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -338,7 +338,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -390,7 +390,7 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -442,7 +442,7 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_CF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -495,7 +495,7 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -547,7 +547,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -615,7 +615,7 @@ void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -668,7 +668,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_CF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -734,7 +734,7 @@ void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -778,7 +778,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -823,7 +823,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -870,7 +870,7 @@ void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -915,7 +915,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -960,7 +960,7 @@ void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1006,7 +1006,7 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1057,7 +1057,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1127,7 +1127,7 @@ void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1179,7 +1179,7 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -1232,7 +1232,7 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1285,7 +1285,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -1353,7 +1353,7 @@ void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1407,7 +1407,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1479,7 +1479,7 @@ void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1533,7 +1533,7 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_CF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -1587,7 +1587,7 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1642,7 +1642,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
IFX(X_AF|X_OF|X_CF|X_PF){if(save_s4) {POP(xSP, 1<<s4);}}
}
@@ -1710,7 +1710,7 @@ void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1758,7 +1758,7 @@ void emit_neg32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1807,7 +1807,7 @@ void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1855,6 +1855,6 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+21 -21
View File
@@ -76,7 +76,7 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFC_COND(cNE, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -130,7 +130,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -181,7 +181,7 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -233,7 +233,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -280,7 +280,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -323,7 +323,7 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -371,7 +371,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
@@ -433,7 +433,7 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -479,7 +479,7 @@ void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -517,7 +517,7 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -557,7 +557,7 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -597,7 +597,7 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -645,7 +645,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
@@ -707,7 +707,7 @@ void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -753,7 +753,7 @@ void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -792,7 +792,7 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -835,7 +835,7 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -968,7 +968,7 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1035,7 +1035,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1096,7 +1096,7 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -1160,7 +1160,7 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
+16 -68
View File
@@ -55,7 +55,10 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
// and now the tricky ones (and mostly unused), PF and AF
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4);
}
// and now the tricky ones (and mostly unused), AF
IFX(X_AF) {
// bc = (res & (~d | s)) | (~d & s)
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
@@ -68,19 +71,6 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_CF|X_AF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
@@ -112,7 +102,7 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -140,6 +130,9 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
@@ -161,18 +154,6 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
@@ -204,7 +185,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
@@ -230,6 +211,9 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s3, s4);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
@@ -251,18 +235,6 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
@@ -292,7 +264,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -321,19 +293,8 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
if(s1==s2) {
AND_IMM8(s3, s1, 31);
} else {
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
}
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
emit_pf(dyn, ninst, s3, s4);
}
}
@@ -362,15 +323,8 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
emit_pf(dyn, ninst, s3, s4);
}
}
@@ -399,13 +353,7 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s2, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s2, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
emit_pf(dyn, ninst, s3, s4);
}
}
+46
View File
@@ -986,6 +986,52 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xFE:
nextop = F8;
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Eb
INST_NAME("INC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if(MODREG) {
GETEB(x1);
emit_inc8(dyn, ninst, x1, x2, x14);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_inc8(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
break;
case 1: //DEC Ed
INST_NAME("DEC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if(MODREG) {
GETEB(x1);
emit_dec8(dyn, ninst, x1, x2, x14);
EBBACK;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_dec8(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
break;
default:
DEFAULT;
}
SMDMB();
break;
case 0xFF:
nextop = F8;
SMDMB();
+91 -32
View File
@@ -62,10 +62,20 @@ void arm_fpatan(x86emu_t* emu)
}
void arm_fxtract(x86emu_t* emu)
{
int32_t tmp32s = (ST1.q&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST1.d /= exp2(tmp32s);
ST0.d = tmp32s;
int tmp32s;
if(isnan(ST1.d)) {
ST0.d = ST1.d;
} else if(isinf(ST1.d)) {
ST0.d = ST1.d;
ST1.d = INFINITY;
} else if(ST1.d==0.0) {
ST0.d = ST1.d;
ST1.d = -INFINITY;
} else {
// LD80bits doesn't have implicit "1" bit, so need to adjust for that
ST0.d = frexp(ST1.d, &tmp32s)*2;
ST1.d = tmp32s-1;
}
}
void arm_fprem(x86emu_t* emu)
{
@@ -116,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;
@@ -168,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);
@@ -487,13 +475,18 @@ void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
dyn->n.neoncache[i+1].v = 0;
}
// Reset fpu regs counter
static void fpu_reset_reg_neoncache(neoncache_t* n)
{
n->fpu_reg = 0;
for (int i=0; i<24; ++i) {
n->fpuused[i]=0;
n->neoncache[i].v = 0;
}
}
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->n.fpu_reg = 0;
for (int i=0; i<24; ++i) {
dyn->n.fpuused[i]=0;
dyn->n.neoncache[i].v = 0;
}
fpu_reset_reg_neoncache(&dyn->n);
}
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
@@ -740,6 +733,7 @@ void neoncacheUnwind(neoncache_t* cache)
// unswap
int a = -1;
int b = -1;
// in neoncache
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if(cache->neoncache[j].n == cache->combined1)
@@ -756,7 +750,7 @@ void neoncacheUnwind(neoncache_t* cache)
cache->combined1 = cache->combined2 = 0;
}
if(cache->news) {
// reove the newly created neoncache
// remove the newly created neoncache
for(int i=0; i<24; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
@@ -773,11 +767,23 @@ void neoncacheUnwind(neoncache_t* cache)
}
}
cache->x87stack-=cache->stack_push;
cache->tags>>=(cache->stack_push*2);
cache->stack-=cache->stack_push;
if(cache->pushed>=cache->stack_push)
cache->pushed-=cache->stack_push;
else
cache->pushed = 0;
cache->stack_push = 0;
}
cache->x87stack+=cache->stack_pop;
cache->stack_next = cache->stack;
if(cache->stack_pop) {
if(cache->poped>=cache->stack_pop)
cache->poped-=cache->stack_pop;
else
cache->poped = 0;
cache->tags<<=(cache->stack_pop*2);
}
cache->stack_pop = 0;
cache->barrier = 0;
// And now, rebuild the x87cache info with neoncache
@@ -1028,3 +1034,56 @@ void print_opcode(dynarec_arm_t* dyn, int ninst, uint32_t opcode)
{
dynarec_log(LOG_NONE, "\t%08x\t%s\n", opcode, arm_print(opcode));
}
static void x87_reset(neoncache_t* n)
{
for (int i=0; i<8; ++i)
n->x87cache[i] = -1;
n->x87stack = 0;
n->stack = 0;
n->stack_next = 0;
n->stack_pop = 0;
n->stack_push = 0;
n->combined1 = n->combined2 = 0;
n->swapped = 0;
n->barrier = 0;
n->pushed = 0;
n->poped = 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].t == NEON_CACHE_ST_F || n->neoncache[i].t == NEON_CACHE_ST_D)
n->neoncache[i].v = 0;
}
static void mmx_reset(neoncache_t* n)
{
n->mmxcount = 0;
for (int i=0; i<8; ++i)
n->mmxcache[i] = -1;
}
static void sse_reset(neoncache_t* n)
{
for (int i=0; i<8; ++i)
n->ssecache[i].v = -1;
}
void fpu_reset(dynarec_arm_t* dyn)
{
x87_reset(&dyn->n);
mmx_reset(&dyn->n);
sse_reset(&dyn->n);
fpu_reset_reg(dyn);
}
void fpu_reset_ninst(dynarec_arm_t* dyn, int ninst)
{
x87_reset(&dyn->insts[ninst].n);
mmx_reset(&dyn->insts[ninst].n);
sse_reset(&dyn->insts[ninst].n);
fpu_reset_reg_neoncache(&dyn->insts[ninst].n);
}
int fpu_is_st_freed(dynarec_arm_t* dyn, int ninst, int st)
{
return (dyn->n.tags&(0b11<<(st*2)))?1:0;
}
+6 -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);
@@ -101,4 +99,10 @@ const char* getCacheName(int t, int n);
void inst_name_pass3(dynarec_arm_t* dyn, int ninst, const char* name);
void print_opcode(dynarec_arm_t* dyn, int ninst, uint32_t opcode);
// reset the cache
void fpu_reset(dynarec_arm_t* dyn);
void fpu_reset_ninst(dynarec_arm_t* dyn, int ninst);
// is st freed
int fpu_is_st_freed(dynarec_arm_t* dyn, int ninst, int st);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+343 -197
View File
@@ -288,47 +288,68 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
MESSAGE(LOG_DUMP, "Ret next\n");
POP1(xEIP);
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
MOV_REG(x1, xEIP);
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
MESSAGE(LOG_DUMP, "Ret next\n");
POP1(xEIP);
SMEND();
if(box86_dynarec_callret) {
// pop the actual return address for ARM stack
POP(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
BXcond(cEQ, x3);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
CMPS_IMM8(x3, 0); // that was already the top of the stack...
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave)); // load pointer only if not already on top
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
}
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
MOV_REG(x1, xEIP);
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
BX(x3);
}
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
{
MESSAGE(LOG_DUMP, "Retn epilog\n");
POP1(xEIP);
if(n>0xff) {
MOVW(x1, n);
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
} else {
ADD_IMM8(xESP, xESP, n);
}
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
MOV_REG(x1, xEIP);
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
MESSAGE(LOG_DUMP, "Retn epilog\n");
POP1(xEIP);
if(n>0xff) {
MOVW(x1, n);
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
} else {
ADD_IMM8(xESP, xESP, n);
}
SMEND();
if(box86_dynarec_callret) {
// pop the actual return address for ARM stack
POP(xSP, (1<<x2)|(1<<x3));
CMPS_REG_LSL_IMM5(x2, xEIP, 0); // is it the right address?
BXcond(cEQ, x3);
// not the correct return address, regular jump, but purge the stack first, it's unsync now...
CMPS_IMM8(x3, 0); // that was already the top of the stack...
LDR_IMM9_COND(cNE, xSP, xEmu, offsetof(x86emu_t, xSPSave));
SUB_COND_IMM8(cEQ, xSP, xSP, 8); // unpop
}
MOV32(x2, getJumpTable());
MOV_REG_LSR_IMM5(x3, xEIP, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x2, x2, x3, 2); // shiftsizeof(uintptr_t)
UBFX(x3, xEIP, 0, JMPTABL_SHIFT);
LDR_REG_LSL_IMM5(x3, x2, x3, 2); // shiftsizeof(uintptr_t)
MOV_REG(x1, xEIP);
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
BX(x3);
}
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
MESSAGE(LOG_DUMP, "IRet epilog\n");
SET_DFNONE(x1);
// POP IP
POP1(xEIP);
// POP CS
@@ -375,7 +396,6 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
SET_NODF();
}
#if defined(__ARM_PCS) && !defined(__ARM_PCS_VFP)
@@ -427,7 +447,6 @@ void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
SET_NODF();
}
// call a function with n double args (taking care of the SOFTFP / HARD call) that return a double too
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags)
@@ -476,8 +495,53 @@ void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
SET_NODF();
}
// call a function with 1 double arg (taking care of the SOFTFP / HARD call) and 1 non-float arg that return a double
void call_ddr(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int arg, int reg, int ret, uint32_t mask, int saveflags)
{
if(ret!=-2 && !mask) {
// ARM ABI require the stack to be 8-bytes aligned!
// so, if no mask asked, add one to stay 8-bytes aligned
if(ret!=xFlags) mask=1<<xFlags; else mask=1<<x3;
}
if(ret!=-2) {
PUSH(xSP, (1<<xEmu) | mask);
}
fpu_pushcache(dyn, ninst, reg);
if(saveflags) {
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
#ifdef ARM_SOFTFP
VMOVfrV_64(0, 1, 0);// D0 -> r0:r1
MOV_REG(2, arg);
#else
MOV_REG(0, arg);
#endif
MOV32(reg, (uintptr_t)fnc);
BLX(reg);
if(fnc2) {
#ifdef ARM_SOFTFP
// result are already in r0:r1 for next call
#endif
MOV32(reg, (uintptr_t)fnc2);
BLX(reg);
}
#ifdef ARM_SOFTFP
POP(xSP, (1<<2) | (1<<3));
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
#endif
fpu_popcache(dyn, ninst, reg);
if(ret>=0) {
MOV_REG(ret, 0);
}
if(ret!=-2) {
POP(xSP, (1<<xEmu) | mask);
}
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
}
// call a function with 1 arg, (taking care of the SOFTFP / HARD call) that return a double, using s1 as scratch
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags)
{
@@ -539,27 +603,10 @@ void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
}
// x87 stuffs
static void x87_reset(dynarec_arm_t* dyn)
{
for (int i=0; i<8; ++i)
dyn->n.x87cache[i] = -1;
dyn->n.x87stack = 0;
dyn->n.stack = 0;
dyn->n.stack_next = 0;
dyn->n.stack_pop = 0;
dyn->n.stack_push = 0;
dyn->n.combined1 = dyn->n.combined2 = 0;
dyn->n.swapped = 0;
dyn->n.barrier = 0;
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].t == NEON_CACHE_ST_F || dyn->n.neoncache[i].t == NEON_CACHE_ST_D)
dyn->n.neoncache[i].v = 0;
}
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
{
if(!dyn->n.x87stack)
return;
return 0;
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, scratch);
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->n.x87stack);
@@ -586,6 +633,39 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
dyn->n.stack_next -= dyn->n.stack;
dyn->n.stack = 0;
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
return a;
}
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count)
{
if(!count)
return;
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, scratch);
MESSAGE(LOG_DUMP, "\tSynch x87 Unstackcount (%d)\n", dyn->n.x87stack);
int a = -count;
// Add x87stack to emu fpu_stack
LDR_IMM9(scratch, xEmu, offsetof(x86emu_t, fpu_stack));
if(a>0) {
ADD_IMM8(scratch, scratch, a);
} else {
SUB_IMM8(scratch, scratch, -a);
}
STR_IMM9(scratch, xEmu, offsetof(x86emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDR_IMM9(scratch, xEmu, offsetof(x86emu_t, top));
if(a>0) {
SUB_IMM8(scratch, scratch, a);
} else {
ADD_IMM8(scratch, scratch, -a);
}
AND_IMM8(scratch, scratch, 7);
STR_IMM9(scratch, xEmu, offsetof(x86emu_t, top));
// reset x87stack, but not the stack count of neoncache
dyn->n.x87stack = count;
dyn->n.stack = count;
dyn->n.stack_next += dyn->n.stack;
MESSAGE(LOG_DUMP, "\t------x87 Unstackcount\n");
}
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b)
@@ -610,11 +690,15 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t)
dyn->n.stack+=1;
dyn->n.stack_next+=1;
dyn->n.stack_push+=1;
++dyn->n.pushed;
if(dyn->n.poped)
--dyn->n.poped;
// move all regs in cache, and find a free one
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
++dyn->n.neoncache[j].n;
int ret = -1;
dyn->n.tags<<=2;
for(int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1)
++dyn->n.x87cache[i];
@@ -639,6 +723,9 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
dyn->n.stack+=1;
dyn->n.stack_next+=1;
dyn->n.stack_push+=1;
++dyn->n.pushed;
if(dyn->n.poped)
--dyn->n.poped;
// move all regs in cache
for(int j=0; j<24; ++j)
if((dyn->n.neoncache[j].t == NEON_CACHE_ST_D) || (dyn->n.neoncache[j].t == NEON_CACHE_ST_F))
@@ -646,17 +733,12 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
for(int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1)
++dyn->n.x87cache[i];
dyn->n.tags<<=2;
if(s1)
x87_stackcount(dyn, ninst, s1);
}
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
void static internal_x87_dopop(dynarec_arm_t* dyn)
{
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, s1);
dyn->n.x87stack-=1;
dyn->n.stack_next-=1;
dyn->n.stack_pop+=1;
// move all regs in cache, poping ST0
for(int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1) {
--dyn->n.x87cache[i];
@@ -666,6 +748,30 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
}
}
}
int static internal_x87_dofree(dynarec_arm_t* dyn)
{
if(dyn->n.tags&0b11) {
MESSAGE(LOG_DUMP, "\t--------x87 FREED ST0, poping 1 more\n");
return 1;
}
return 0;
}
void x87_do_pop(dynarec_arm_t* dyn, int ninst, int s1)
{
if(dyn->n.mmxcount)
mmx_purgecache(dyn, ninst, 0, s1);
do {
dyn->n.x87stack-=1;
dyn->n.stack_next-=1;
dyn->n.stack_pop+=1;
dyn->n.tags>>=2;
++dyn->n.poped;
if(dyn->n.pushed)
--dyn->n.pushed;
// move all regs in cache, poping ST0
internal_x87_dopop(dyn);
} while(internal_x87_dofree(dyn));
}
static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3)
{
@@ -685,20 +791,11 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
}
// Setting all 8 xp_regs to "FULL"
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
MOVW(s3, 0);
for (int i=0; i<8; ++i) {
STRAI_IMM9_W(s3, s1, sizeof(fpu_p_reg_t));
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_tags));
// setup TOP => full stack so = 0
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
offs = offsetof(x86emu_t, x87);
uintptr_t offs = offsetof(x86emu_t, x87);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
@@ -709,28 +806,28 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
//Stack is full, so STi is just x87reg[i]
int j=0;
while(dyn->n.x87cache[j]!=i) ++j; // look for STi
int st = dyn->n.x87cache[j]+dyn->n.stack_pop;
#if STEP == 1
if(!next) { // don't force promotion here
// pre-apply pop, because purge happens in-between
neoncache_promote_double(dyn, ninst, dyn->n.x87cache[j]+dyn->n.stack_pop);
neoncache_promote_double(dyn, ninst, st);
}
#endif
if(next) {
// need to check if a ST_F need local promotion
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[j])>=0) {
#if STEP == 3
if(!next && neoncache_get_current_st(dyn, ninst, st)!=NEON_CACHE_ST_D) {
MESSAGE(LOG_DUMP, "Warning, incoherency with purged ST%d cache\n", st);
}
#endif
switch(neoncache_get_current_st(dyn, ninst, st)) {
case NEON_CACHE_ST_D:
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
break;
case NEON_CACHE_ST_F:
VCVT_F64_F32(0, dyn->n.x87reg[j]*2);
VSTM_64_W(0, s1); // save the value
} else {
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
}
} else {
// need to check if a ST_F need local promotion
if(neoncache_get_st_f(dyn, ninst, dyn->n.x87cache[j])>=0) {
VCVT_F64_F32(0, dyn->n.x87reg[j]*2);
VSTM_64_W(0, s1); // save the value
} else {
VSTM_64_W(dyn->n.x87reg[j], s1); // save the value
}
break;
}
if(!next) {
fpu_free_reg_double(dyn, dyn->n.x87reg[j]);
dyn->n.x87reg[j] = -1;
dyn->n.x87cache[j] = -1;
@@ -739,9 +836,13 @@ static void x87_purgecache_full(dynarec_arm_t* dyn, int ninst, int next, int s1,
}
if(!next) {
dyn->n.stack_next = 0;
dyn->n.tags = 0;
#if STEP < 2
// refresh the cached valued, in case it's a purge outside a instruction
dyn->insts[ninst].n.barrier = 1;
dyn->n.pushed = 0;
dyn->n.poped = 0;
#endif
}
MESSAGE(LOG_DUMP, "\t---Purge Full x87 Cache and Synch Stackcount\n");
@@ -776,44 +877,37 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
SUB_IMM8(s2, s2, -a);
}
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
// update tags (and top at the same time)
// update tags
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
if(a>0) {
// new tag to fulls
MOVW(s3, 0);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<a; ++i) {
SUB_IMM8(s2, s2, 1);
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
STR_REG_LSL_IMM5(s3, s1, s2, 2); // that slot is full
}
MOV_REG_LSL_IMM5(s1, s1, a*2);
} else {
// empty tags
MOVW(s3, 0b11);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offsetof(x86emu_t, p_regs));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<-a; ++i) {
STR_REG_LSL_IMM5(s3, s1, s2, 2); // empty slot before leaving it
ADD_IMM8(s2, s2, 1);
AND_IMM8(s2, s2, 7); // (emu->top + st)&7
}
MOV32(s2, 0xffff);
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
MOV_REG_LSR_IMM5(s1, s1, -a*2);
}
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
// Sub x87stack to top, with and 7
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
if(a>0) {
SUB_IMM8(s2, s2, a);
} else {
ADD_IMM8(s2, s2, -a);
}
AND_IMM8(s2, s2, 7);
STR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
} else {
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
}
// check if free is used
if(dyn->n.tags) {
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
MOV32(s3, dyn->n.tags);
ORR_REG_LSL_IMM5(s1, s1, s3, 0);
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
}
if(ret!=0) {
// --- set values
// Get top
@@ -857,9 +951,13 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
}
if(!next) {
dyn->n.stack_next = 0;
dyn->n.tags = 0;
#if STEP < 2
// refresh the cached valued, in case it's a purge outside a instruction
dyn->insts[ninst].n.barrier = 1;
dyn->n.pushed = 0;
dyn->n.poped = 0;
#endif
}
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
@@ -878,6 +976,16 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
SUB_IMM8(s2, s2, -a);
}
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
// update tags
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
if(a>0) {
MOV_REG_LSL_IMM5(s1, s1, a*2);
} else {
MOV32(s2, 0xffff);
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
MOV_REG_LSR_IMM5(s1, s1, -a*2);
}
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
// Sub x87stack to top, with and 7
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
if(a>0) {
@@ -931,6 +1039,16 @@ static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, in
ADD_IMM8(s1, s1, -a);
}
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
// update tags
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
if(a>0) {
MOV32(s2, 0xffff);
ORR_REG_LSL_IMM5(s1, s1, s2, 16);
MOV_REG_LSR_IMM5(s1, s1, a*2);
} else {
MOV_REG_LSL_IMM5(s1, s1, -a*2);
}
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
// Sub x87stack to top, with and 7
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
if(a>0) {
@@ -1133,6 +1251,65 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
}
void x87_free(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int st)
{
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
if(dyn->n.x87cache[i] == st)
ret = i;
MESSAGE(LOG_DUMP, "\tFFREE%s x87 Cache for ST%d\n", (ret!=-1)?" (and Forget)":"", st);
if(ret!=-1) {
const int reg = dyn->n.x87reg[ret];
#if STEP == 1
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F)
neoncache_promote_double(dyn, ninst, st);
#endif
// prepare offset to fpu => s1
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
// Get top
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
// Update
int ast = st - dyn->n.x87stack;
if(ast) {
if(ast>0) {
ADD_IMM8(s2, s2, ast);
} else {
SUB_IMM8(s2, s2, -ast);
}
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
// this should not happens
VCVT_F64_F32(0, reg*2); // use D0 as scratch...
VSTR_64(0, s2, 0);
} else {
VSTR_64(reg, s2, 0); // save the value
}
// and forget that cache
fpu_free_reg_double(dyn, reg);
dyn->n.neoncache[reg].v = 0;
dyn->n.x87cache[ret] = -1;
dyn->n.x87reg[ret] = -1;
} else {
// Get top
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
// Update
int ast = st - dyn->n.x87stack;
if(ast) {
if(ast>0) {
ADD_IMM8(s2, s2, ast);
} else {
SUB_IMM8(s2, s2, -ast);
}
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
}
}
// add mark in the freed array
dyn->n.tags |= 0b11<<(st*2);
MESSAGE(LOG_DUMP, "\t--------x87 FFREE for ST%d\n", st);
}
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
@@ -1141,7 +1318,8 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s1); // get fpscr
MOV_REG(s3, s1);
if (s3 >= 0)
MOV_REG(s3, s1);
BFI(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
@@ -1218,12 +1396,6 @@ void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
}
// MMX helpers
static void mmx_reset(dynarec_arm_t* dyn)
{
dyn->n.mmxcount = 0;
for (int i=0; i<8; ++i)
dyn->n.mmxcache[i] = -1;
}
static int isx87Empty(dynarec_arm_t* dyn)
{
for (int i=0; i<8; ++i)
@@ -1305,11 +1477,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
// SSE / SSE2 helpers
static void sse_reset(dynarec_arm_t* dyn)
{
for (int i=0; i<8; ++i)
dyn->n.ssecache[i].v = -1;
}
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite)
{
@@ -1765,55 +1932,6 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
}
int stack_cnt = dyn->n.stack_next;
int s3_top = 0xffff;
if(stack_cnt != cache_i2.stack) {
MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack);
int a = stack_cnt - cache_i2.stack;
// Add x87stack to emu fpu_stack
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
if(a>0) {
ADD_IMM8(s3, s3, a);
} else {
SUB_IMM8(s3, s3, -a);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
// update tags (and top at the same time)
if(a>0) {
// new tag to fulls
MOVW(s2, 0);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<a; ++i) {
SUB_IMM8(s3, s3, 1);
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
STR_REG_LSL_IMM5(s2, s1, s3, 2); // that slot is full
}
} else {
// empty tags
MOVW(s2, 0b11);
int offs = offsetof(x86emu_t, p_regs);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOVW(s1, offsetof(x86emu_t, p_regs));
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
for (int i=0; i<-a; ++i) {
STR_REG_LSL_IMM5(s2, s1, s3, 2); // empty slot before leaving it
ADD_IMM8(s3, s3, 1);
AND_IMM8(s3, s3, 7); // (emu->top + st)&7
}
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
s3_top = 0;
stack_cnt = cache_i2.stack;
}
neoncache_t cache = dyn->n;
// sanitize XMM regs alocation, cache_i2 has been sanitized in neoncacheUnwind already
for(int i=0; i<24; i+=2) {
@@ -1882,6 +2000,40 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
}
}
}
if(stack_cnt != cache_i2.stack) {
MESSAGE(LOG_DUMP, "\t - adjust stack count %d -> %d -\n", stack_cnt, cache_i2.stack);
int a = stack_cnt - cache_i2.stack;
// Add x87stack to emu fpu_stack
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
if(a>0) {
ADD_IMM8(s3, s3, a);
} else {
SUB_IMM8(s3, s3, -a);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, fpu_stack));
// update tags
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
if(a>0) {
MOV_REG_LSL_IMM5(s1, s1, a*2);
} else {
// empty tags
MOV32(s3, 0xffff);
ORR_REG_LSL_IMM5(s1, s1, s3, 16);
MOV_REG_LSR_IMM5(s1, s1, -a*2);
}
STRH_IMM8(s1, xEmu, offsetof(x86emu_t, fpu_tags));
// Sub x87stack to top, with and 7
LDR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
if(a>0) {
SUB_IMM8(s3, s3, a);
} else {
ADD_IMM8(s3, s3, -a);
}
AND_IMM8(s3, s3, 7);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, top));
s3_top = 0;
stack_cnt = cache_i2.stack;
}
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
#endif
}
@@ -1949,14 +2101,6 @@ void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
x87_unreflectcache(dyn, ninst, s1, s2, s3);
}
void fpu_reset(dynarec_arm_t* dyn)
{
x87_reset(dyn);
mmx_reset(dyn);
sse_reset(dyn);
fpu_reset_reg(dyn);
}
// get the single reg that from the double "reg" (so Dx[idx])
int fpu_get_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx)
{
@@ -1974,14 +2118,13 @@ void fpu_putback_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx, int
}
}
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4)
{
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
// by xor'ing all the bit 2 by two with a shift, pair of bits are removed, and only 1 is left if bit number if odd
XOR_REG_LSR_IMM8(s4, s1, s1, 4);
XOR_REG_LSR_IMM8(s4, s4, s4, 2);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
MVN_REG_LSL_IMM5(s4, s4, 0);
BFI(xFlags, s4, F_PF, 1);
}
@@ -1991,8 +2134,14 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
#if STEP > 1
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
dyn->n = dyn->insts[ninst].n;
#else
dyn->n = dyn->insts[reset_n].n;
#endif
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
#if STEP == 0
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "New x87stack=%d\n", dyn->n.x87stack);
#endif
#if defined(HAVE_TRACE) && (STEP>2)
if(box86_dynarec_dump)
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
@@ -2022,9 +2171,6 @@ void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
}
// propagate ST stack state, especial stack pop that are deferred
+62 -17
View File
@@ -262,8 +262,10 @@
#define CALL_1DD(F, F2, M) call_d(dyn, ninst, F, F2, 1, x3, -1, M, 0)
// CALL_1D_U64 will use S as scratch. Return value in ret/ret2, 1 ARG in D0
#define CALL_1DR_U64(R, ret, ret2, S, M) call_dr(dyn, ninst, R, 1, S, ret, ret2, M, 1)
// CALL_1D will use S as scratch. Return value in D0, 1 ARG in D0
// CALL_1DR will use S as scratch. Return value in D0, 1 ARG in D0
#define CALL_1DR(R, S, M) call_dr(dyn, ninst, R, 1, S, -1, -1, M, 0)
// CALL_1DI will use S as scratch. Return value in D0, 1 ARG in D0, 1 ARG in R0
#define CALL_1DDR(F, R, S, M) call_ddr(dyn, ninst, F, NULL, R, S, -1, M, 0)
// CALL_1RD will use S as scratch. Return value in D0, 1 ARG in R
#define CALL_1RD(F, R, S, M) call_rd(dyn, ninst, F, R, S, M, 0);
@@ -314,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) \
#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); \
@@ -325,7 +327,7 @@
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) \
#define FCOMI(s1, s2) \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
VMRS_APSR(); /* 0b111 */ \
BIC_IMM8(xFlags, xFlags, 0b1000101, 0); \
@@ -333,12 +335,41 @@
ORR_IMM8_COND(cEQ, xFlags, xFlags, 0b01000000, 0); /* zero */ \
ORR_IMM8_COND(cMI, xFlags, xFlags, 0b00000001, 0); /* less than */ \
/* greater than leave 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
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) var = x87_do_push(dyn, ninst, scratch, t)
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) x87_do_push_empty(dyn, ninst, scratch)
#define X87_POP_OR_FAIL(dyn, ninst, scratch) x87_do_pop(dyn, ninst, scratch)
#else
#define X87_PUSH_OR_FAIL(var, dyn, ninst, scratch, t) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
var = x87_do_push(dyn, ninst, scratch, t)
#define X87_PUSH_EMPTY_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==8) || (dyn->n.pushed==8)) { \
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Push, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.pushed, ninst); \
dyn->abort = 1; \
return addr; \
} \
x87_do_push_empty(dyn, ninst, scratch)
#define X87_POP_OR_FAIL(dyn, ninst, scratch) \
if ((dyn->n.x87stack==-8) || (dyn->n.poped==8)) { \
if(box86_dynarec_dump) dynarec_log(LOG_NONE, " Warning, suspicious x87 Pop, stack=%d/%d on inst %d\n", dyn->n.x87stack, dyn->n.poped, ninst); \
dyn->abort = 1; \
return addr; \
} \
x87_do_pop(dyn, ninst, scratch)
#endif
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
@@ -386,6 +417,8 @@
if(dyn->insts[ninst].x86.gen_flags) switch(B) { \
case SF_SUBSET: \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_SET_DF: dyn->f.pending = SF_SET; dyn->f.dfnone = 1; break; \
case SF_SET_NODF: dyn->f.pending = SF_SET; dyn->f.dfnone = 0; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SUBSET_PENDING: \
case SF_SET_PENDING: \
@@ -402,6 +435,9 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#ifndef SET_HASCALLRET
#define SET_HASCALLRET()
#endif
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
@@ -460,6 +496,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define call_d STEPNAME(call_d_)
#define call_ddr STEPNAME(call_ddr_)
#define call_dr STEPNAME(call_dr_)
#define call_rd STEPNAME(call_rd_)
#define grab_fsdata STEPNAME(grab_fsdata_)
@@ -562,10 +599,12 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define x87_get_neoncache STEPNAME(x87_get_neoncache)
#define x87_get_st STEPNAME(x87_get_st)
#define x87_get_st_empty STEPNAME(x87_get_st)
#define x87_free STEPNAME(x87_free)
#define x87_refresh STEPNAME(x87_refresh)
#define x87_forget STEPNAME(x87_forget)
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_unstackcount STEPNAME(x87_unstackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_setround_reset STEPNAME(x87_setround_reset)
#define x87_restoreround STEPNAME(x87_restoreround)
@@ -581,7 +620,6 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
#define fpu_purgecache STEPNAME(fpu_purgecache)
@@ -613,6 +651,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags);
void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int ret2, uint32_t mask, int saveflags);
void call_ddr(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int arg, int reg, int ret, uint32_t mask, int saveflags);
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags);
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
@@ -704,11 +743,13 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s4);
// x87 helper
// cache of the local stack counter, to avoid upadte at every call
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
int x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch);
// restore the local stack counter
void x87_unstackcount(dynarec_arm_t* dyn, int ninst, int scratch, int count);
// fpu push. Return the Dd value to be used
int x87_do_push(dynarec_arm_t* dyn, int ninst, int s1, int t);
// fpu push. Do not allocate a cache register. Needs a scratch register to do x87stack synch (or 0 to not do it)
@@ -725,6 +766,8 @@ int x87_get_neoncache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a);
int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// get vfpu register for a x87 reg, create the entry if needed. Do not fetch the Stx if not already in cache
int x87_get_st_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int t);
// Free st, using the FFREE opcode (so it's freed but stack is not moved)
void x87_free(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int st);
// refresh a value from the cache ->emu (nothing done if value is not cached)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
// refresh a value from the cache ->emu and then forget the cache (nothing done if value is not cached)
@@ -793,8 +836,6 @@ void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn);
// reset the cache with n
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n);
// propagate stack state
@@ -851,21 +892,25 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
#define MAYUSE(A)
#endif
#define NOTEST(s1) \
#define NOTEST(s1, s2) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.test)); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
MOVW(s2, offsetof(x86emu_t, test.test)); \
STR_REG_LSL_IMM5(s1, xEmu, s2, 0); \
ADD_IMM8(s2, s2, offsetof(x86emu_t, test.clean)-offsetof(x86emu_t, test.test));\
STR_REG_LSL_IMM5(s1, xEmu, s2, 0); \
}
#define SKIPTEST(s1) \
#define SKIPTEST(s1, s2) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
MOVW(s2, offsetof(x86emu_t, test.clean)); \
STR_REG_LSL_IMM5(s1, xEmu, s2, 0); \
}
#define GOTEST(s1, s2) \
if(box86_dynarec_test) { \
MOVW(s2, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, test.test)); \
MOVW(s1, offsetof(x86emu_t, test.test)); \
STR_REG_LSL_IMM5(s2, xEmu, s1, 0); \
}
#endif //__DYNAREC_ARM_HELPER_H__
+57 -15
View File
@@ -27,6 +27,12 @@
#error No STEP defined
#endif
#if STEP == 0
#ifndef PROT_READ
#define PROT_READ 0x1
#endif
#endif
uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
int ok = 1;
@@ -43,12 +49,28 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
#if STEP == 0
memset(&dyn->insts[ninst], 0, sizeof(instruction_arm_t));
#endif
fpu_reset(dyn);
int reset_n = -1;
int stopblock = 2+(FindElfAddress(my_context, addr)?0:1); // if block is in elf_memory, it can be extended with bligblocks==2, else it needs 3 // ok, go now
INIT;
#if STEP == 0
uintptr_t cur_page = (addr)&~box86_pagesize;
#endif
while(ok) {
#if STEP == 0
if(cur_page != (addr)&~box86_pagesize) {
cur_page = (addr)&~box86_pagesize;
if(!(getProtection(addr)&PROT_READ)) {
need_epilog = 1;
break;
}
}
#endif
ip = addr;
fpu_propagate_stack(dyn, ninst);
if (reset_n!=-1) {
if(reset_n==-2) {
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
@@ -70,8 +92,12 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
reset_n = -1;
}
fpu_propagate_stack(dyn, ninst);
NEW_INST;
#if STEP == 0
if(ninst && dyn->insts[ninst-1].x86.barrier_next) {
BARRIER(dyn->insts[ninst-1].x86.barrier_next);
}
#endif
if(!ninst) {
GOTEST(x1, x2);
}
@@ -116,7 +142,6 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
#if STEP > 0
if(!dyn->insts[ninst].x86.has_next && dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts!=-1)
next = dyn->insts[ninst].x86.jmp_insts;
#endif
if(dyn->insts[ninst].x86.has_next && dyn->insts[next].x86.barrier) {
if(dyn->insts[next].x86.barrier&BARRIER_FLOAT)
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
@@ -125,6 +150,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->f.dfnone = 0;
}
}
#endif
#ifndef PROT_READ
#define PROT_READ 1
#endif
@@ -133,8 +159,8 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
if(ii<dyn->size && !dyn->insts[ii].pred_sz) {
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
if(ii<dyn->size && !dyn->insts[ii].x86.alive) {
while(ii<dyn->size && !dyn->insts[ii].x86.alive) {
// may need to skip opcodes to advance
++ninst;
NEW_INST;
@@ -156,16 +182,25 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
}
#else
// check if block need to be stopped, because it's a 00 00 opcode (unreadeable is already checked earlier)
if((ok>0) && !dyn->forward && !(*(uint8_t*)addr) && !(*(uint8_t*)(addr+1))) {
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Stopping block at %p reason: %s\n", (void*)addr, "Next opcode is 00 00");
ok = 0;
need_epilog = 1;
}
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog) {
if(dyn->forward_to == addr && !need_epilog && ok>=0) {
// we made it!
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
reset_n = get_first_jump(dyn, addr);
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %s%p -> %p (ninst %d - %d)\n", dyn->forward_to-dyn->forward, dyn->insts[dyn->forward_ninst].x86.has_callret?"(opt. call) ":"", (void*)dyn->forward, (void*)dyn->forward_to, reset_n, ninst);
if(dyn->insts[dyn->forward_ninst].x86.has_callret && !dyn->insts[dyn->forward_ninst].x86.has_next)
dyn->insts[dyn->forward_ninst].x86.has_next = 1; // this block actually continue
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
ok = 1; // in case it was 0
} else if ((dyn->forward_to < addr) || !ok) {
} else if ((dyn->forward_to < addr) || ok<=0) {
// something when wrong! rollback
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Could not forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
ok = 0;
@@ -186,10 +221,14 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
// and pred table is not ready yet
reset_n = get_first_jump(dyn, next);
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
if(dyn->insts[ninst].x86.has_callret && !dyn->insts[ninst].x86.has_next) {
dyn->insts[ninst].x86.has_next = 1; // this block actually continue
} else {
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
// and pred table is not ready yet
reset_n = get_first_jump(dyn, next);
}
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %s%p -> %p (ninst=%d, jump from %d)\n", dyn, dyn->insts[ninst].x86.has_callret?"(opt. call) ":"", (void*)addr, (void*)next, ninst, dyn->insts[ninst].x86.has_callret?ninst:reset_n);
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
if(dyn->forward) {
@@ -232,12 +271,15 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
#endif
}
if((ok>0) && dyn->insts[ninst].x86.has_callret)
reset_n = -2;
++ninst;
#if STEP == 0
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
memset(&dyn->insts[ninst], 0, sizeof(instruction_arm_t));
if((ok>0) && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)))
#else
if(ok && (ninst==dyn->size))
if((ok>0) && (ninst==dyn->size))
#endif
{
#if STEP == 0
@@ -265,14 +307,14 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->insts[ninst].x86.need_after |= X_PEND;
#endif
++ninst;
NOTEST(x3);
NOTEST(x1, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
NOTEST(x3);
NOTEST(x1, x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
+5 -9
View File
@@ -12,20 +12,16 @@
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x86.set_flags = A; \
dyn->insts[ninst].x86.state_flags = B; \
dyn->insts[ninst].x86.state_flags = (B)&~SF_DF; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
dyn->f.dfnone=((B)&SF_SET)?(((B)==SF_SET_NODF)?0:1):0;
#define EMIT(A)
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C; dyn->insts[ninst].x86.jmp_insts = 0
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
#define BARRIER_NEXT(A) dyn->insts[ninst].x86.barrier_next = A
#define SET_HASCALLRET() dyn->insts[ninst].x86.has_callret = 1
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_arm_t*)dynaRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
dyn->insts[ninst].x86.addr = ip; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0; \
+4
View File
@@ -41,10 +41,13 @@ typedef struct neoncache_s {
uint8_t combined2;
uint8_t swapped; // the combined reg were swapped
uint8_t barrier; // is there a barrier at instruction epilog?
uint8_t pushed; // positive pushed value (to check for overflow)
uint8_t poped; // positive poped value (to check for underflow)
uint32_t news; // bitmask, wich neoncache are new for this opcode
// fpu cache
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int8_t x87reg[8]; // reg used for x87cache entry
int16_t tags; // similar to fpu_tags
int8_t mmxcache[8];// cache status for the 8 MMX registers
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
int8_t fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
@@ -111,6 +114,7 @@ typedef struct dynarec_arm_s {
int32_t forward_size; // size at the forward point
int forward_ninst; // ninst at the forward point
uint8_t always_test;
uint8_t abort; // abort the creation of the block
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
+9 -2
View File
@@ -24,15 +24,22 @@
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
#define SF_DF 8
#define SF_SET_DF (SF_SET|SF_DF)
#define SF_NODF 16
#define SF_SET_NODF (SF_SET|SF_NODF)
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint8_t jmp_cond; // 1 of conditionnal jump
uint8_t has_next; // does this opcode can continue to the next?
uint8_t jmp_cond:1; // 1 of conditionnal jump
uint8_t has_next:1; // does this opcode can continue to the next?
uint8_t has_callret:1; // this instruction have an optimised call setup
uint8_t alive:1; // this opcode gets executed (0 if dead code in that block)
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t barrier_next; // next instruction needs a barrier
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
+2
View File
@@ -353,8 +353,10 @@ ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>,
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 0 1 1 1 1 Rd imm12 ADR<c> <Rd>, #-<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 0 1 1 1 1 Rd imm12 ADR<c> <Rd>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
+93 -50
View File
@@ -172,7 +172,7 @@ const char* ElfPath(elfheader_t* head)
return NULL;
return head->path;
}
#define ALIGN(p) (((p)+box86_pagesize-1)&~(box86_pagesize-1))
int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
@@ -183,8 +183,6 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
uintptr_t max_align = (box86_pagesize-1);
for (size_t i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags) {
if(max_align < head->PHEntries[i].p_align-1)
max_align = head->PHEntries[i].p_align-1;
++head->multiblock_n;
}
@@ -195,16 +193,24 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
}
if(!offs && !head->vaddr)
offs = (uintptr_t)find32bitBlockElf(head->memsz, mainbin, max_align);
// prereserve the whole elf image, without populating
void* image = mmap64((void*)(head->vaddr?head->vaddr:offs), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
if(image!=MAP_FAILED && head->vaddr && image!=(void*)offs && (((uintptr_t)image)&max_align)) {
munmap(image, head->memsz);
image = mmap64(find32bitBlockElf(head->memsz, mainbin, max_align), head->memsz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
size_t sz = head->memsz;
void* raw = NULL;
void* image = NULL;
if(!head->vaddr) {
sz += head->align;
raw = mmap64((void*)offs, sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
image = (void*)(((uintptr_t)raw+max_align)&~max_align);
} else {
image = raw = mmap64((void*)head->vaddr, sz, 0, MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
}
if(image!=MAP_FAILED && !head->vaddr && image!=(void*)offs) {
printf_log(LOG_INFO, "%s: Mmap64 for (@%p 0x%zx) for elf \"%s\" returned %p(%p/0x%zx) instead\n", (((uintptr_t)image)&max_align)?"Error":"Warning", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image, raw, head->align);
offs = (uintptr_t)image;
printf_log(LOG_INFO, "Mamp64 for (@%p 0x%zx) for elf \"%s\" returned %p instead", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name, image);
if(((uintptr_t)image)&max_align) {
munmap(raw, sz);
return 1; // that's an error, alocated memory is not aligned properly
}
}
if(image==MAP_FAILED || image!=(void*)(head->vaddr?head->vaddr:offs)) {
printf_log(LOG_NONE, "%s cannot create memory map (@%p 0x%zx) for elf \"%s\"", (image==MAP_FAILED)?"Error:":"Warning:", (void*)(head->vaddr?head->vaddr:offs), head->memsz, head->name);
@@ -217,12 +223,14 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
return 1;
offs = (uintptr_t)image-head->vaddr;
}
printf_log(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
printf_dump(log_level, "Pre-allocated 0x%zx byte at %p for %s\n", head->memsz, image, head->name);
head->delta = offs;
printf_log(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\" (0x%zx bytes)\n", (void*)offs, (void*)head->vaddr, head->name, head->memsz);
printf_dump(log_level, "Delta of %p (vaddr=%p) for Elf \"%s\"\n", (void*)offs, (void*)head->vaddr, head->name);
head->image = image;
setProtection_elf((uintptr_t)image, head->memsz, 0);
head->raw = raw;
head->raw_size = sz;
setProtection_elf((uintptr_t)raw, sz, 0);
head->multiblocks = (multiblock_t*)box_calloc(head->multiblock_n, sizeof(multiblock_t));
head->tlsbase = AddTLSPartition(context, head->tlssize);
@@ -241,36 +249,35 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
uint8_t prot = PROT_READ|PROT_WRITE|((e->p_flags & PF_X)?PROT_EXEC:0);
// check if alignment is correct
uintptr_t balign = head->multiblocks[n].align-1;
if(balign<(box86_pagesize-1)) balign = (box86_pagesize-1);
head->multiblocks[n].asize = ALIGN(e->p_memsz+(e->p_paddr&balign));
if(balign<4095) balign = 4095;
head->multiblocks[n].asize = (e->p_memsz+(e->p_paddr&balign)+4095)&~4095;
int try_mmap = 1;
if(e->p_paddr&balign)
try_mmap = 0;
if(e->p_offset&(box86_pagesize-1))
try_mmap = 0;
if(e->p_memsz-e->p_filesz>(box86_pagesize-1))
if(ALIGN(e->p_memsz)!=ALIGN(e->p_filesz))
try_mmap = 0;
if(!e->p_filesz)
try_mmap = 0;
if(e->p_align<box86_pagesize)
try_mmap = 0;
if(try_mmap) {
printf_log(log_level, "Mmaping 0x%zx memory @%p for Elf \"%s\"\n", head->multiblocks[n].size, (void*)head->multiblocks[n].paddr, head->name);
printf_dump(log_level, "Mmaping 0x%lx(0x%lx) bytes @%p for Elf \"%s\"\n", head->multiblocks[n].size, head->multiblocks[n].asize, (void*)head->multiblocks[n].paddr, head->name);
void* p = mmap64(
(void*)head->multiblocks[n].paddr,
head->multiblocks[n].size,
prot,
MAP_PRIVATE|MAP_FIXED,
MAP_PRIVATE|MAP_FIXED, //((prot&PROT_WRITE)?MAP_SHARED:MAP_PRIVATE)|MAP_FIXED,
head->fileno,
e->p_offset
);
if(p==MAP_FAILED || p!=(void*)head->multiblocks[n].paddr) {
try_mmap = 0;
printf_log(log_level, "Mapping failed, using regular mmap+read");
if(p==MAP_FAILED) {
printf_log(log_level, " err=%d/%s\n", errno, strerror(errno));
} else {
printf_log(log_level, " got %p instead\n", p);
}
printf_dump(log_level, "Mapping failed, using regular mmap+read");
} else {
if(e->p_memsz>e->p_filesz && (prot&PROT_WRITE))
memset((void*)((uintptr_t)p + e->p_filesz), 0, e->p_memsz-e->p_filesz);
setProtection_elf((uintptr_t)p, head->multiblocks[n].asize, prot);
head->multiblocks[n].p = p;
@@ -279,15 +286,43 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
if(!try_mmap) {
uintptr_t paddr = head->multiblocks[n].paddr&~balign;
size_t asize = head->multiblocks[n].asize;
printf_log(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
void* p = mmap64(
(void*)paddr,
asize,
prot,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
-1,
0
);
void* p = MAP_FAILED;
if(paddr==(paddr&~(box86_pagesize-1)) && (asize==ALIGN(asize))) {
printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", asize, e->p_memsz, (void*)paddr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
p = mmap64(
(void*)paddr,
asize,
prot|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
-1,
0
);
} else {
// difference in pagesize, so need to mmap only what needed to be...
//check startint point
uintptr_t new_addr = paddr;
ssize_t new_size = asize;
while(getProtection(new_addr) && (new_size>0)) {
new_size -= ALIGN(new_addr) - new_addr;
new_addr = ALIGN(new_addr);
}
if(new_size>0) {
printf_dump(log_level, "Allocating 0x%zx (0x%zx) bytes @%p, will read 0x%zx @%p for Elf \"%s\"\n", ALIGN(new_size), e->p_memsz, (void*)new_addr, e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
p = mmap64(
(void*)new_addr,
ALIGN(new_size),
prot|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
-1,
0
);
if(p==(void*)new_addr)
p = (void*)paddr;
} else {
p = (void*)paddr;
printf_dump(log_level, "Will read 0x%zx @%p for Elf \"%s\"\n", e->p_filesz, (void*)head->multiblocks[n].paddr, head->name);
}
}
if(p==MAP_FAILED || p!=(void*)paddr) {
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%zx/0x%zx) for elf \"%s\"", (void*)paddr, asize, balign, head->name);
if(p==MAP_FAILED) {
@@ -306,6 +341,8 @@ int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
return 1;
}
}
if(!(prot&PROT_WRITE) && (paddr==(paddr&(box86_pagesize-1)) && (asize==ALIGN(asize))))
mprotect((void*)paddr, asize, prot);
}
#ifdef DYNAREC
if(box86_dynarec && (e->p_flags & PF_X)) {
@@ -347,18 +384,20 @@ void FreeElfMemory(elfheader_t* head)
if(head->multiblock_n) {
#ifdef DYNAREC
for(int i=0; i<head->multiblock_n; ++i) {
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
dynarec_log(LOG_INFO, "Free DynaBlocks %p-%p for %s\n", head->multiblocks[i].p, head->multiblocks[i].p+head->multiblocks[i].asize, head->path);
if(box86_dynarec)
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].size, 1);
cleanDBFromAddressRange((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize, 1);
freeProtection((uintptr_t)head->multiblocks[i].p, head->multiblocks[i].asize);
}
#endif
box_free(head->multiblocks);
}
// we only need to free the overall mmap, no need to free individual part as they are inside the big one
if(head->image && head->memsz)
munmap(head->image, head->memsz);
freeProtection((uintptr_t)head->image, head->memsz);
if(head->raw && head->raw_size) {
dynarec_log(LOG_INFO, "Unmap elf memory %p-%p for %s\n", head->raw, head->raw+head->raw_size, head->path);
munmap(head->raw, head->raw_size);
}
freeProtection((uintptr_t)head->raw, head->raw_size);
}
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
@@ -391,14 +430,14 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
int t = ELF32_R_TYPE(rel[i].r_info);
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel[i].r_info)];
const char* symname = SymName(h, sym);
if(t==R_386_COPY && symname && !strcmp(symname, name) && sym->st_size==size) {
if((t==R_386_COPY) && symname && !strcmp(symname, name) && (sym->st_size==size)) {
int version2 = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
*offs = sym->st_value + h->delta;
*p = (uint32_t*)(rel[i].r_offset + h->delta);
if(offs) *offs = sym->st_value + h->delta;
if(p) *p = (uint32_t*)(rel[i].r_offset + h->delta);
return 1;
}
}
@@ -551,7 +590,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
break;
case R_386_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
if((head!=my_context->elfs[0]) && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -569,11 +608,9 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
if((size==0 )&& GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
offs = globoffs;
end = globend;
}*/
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
printf_log((bind==STB_GLOBAL)?LOG_NONE:LOG_INFO, "%s: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", (bind==STB_GLOBAL)?"Error":"Warning", symname, p, *(void**)p, head->name);
@@ -860,11 +897,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
/*if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
if((size==0 )&& GetSymbolStartEnd(GetGlobalData(maplib), symname, &globoffs, &globend, version, vername, 0, globdefver)) {
offs = globoffs;
end = globend;
}*/
}
if (!offs) {
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
@@ -1773,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); \
}
@@ -1998,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)
@@ -2041,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) {
+2
View File
@@ -50,6 +50,8 @@ typedef struct elfheader_s {
intptr_t delta; // should be 0
void* image;
void* raw; // raw pointer (might be unaligned vs image and max_align of elf)
size_t raw_size;
uintptr_t entrypoint;
uintptr_t initentry;
+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; \
} \
+8 -1
View File
@@ -81,8 +81,15 @@ uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int l
intres1 = (1<<n_packed)-1;
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed-j; ++i) {
#if 1
if(!overrideIfDataInvalid(mem, lmem, reg, lreg, i+j, i, imm8)) {
intres1 &= ~(1<<j);
break;
}
#else
int k = i+j;
intres1 &= (((1<<n_packed)-1)^(1<<j)) | overrideIfDataInvalid(mem, lmem, reg, lreg, k, i, imm8)<<j;
#endif
}
break;
}
@@ -98,7 +105,7 @@ uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int l
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
CLEAR_FLAG(F_AF);
CONDITIONAL_SET_FLAG(((!intres2) && (lmem==n_packed)), F_AF);
CLEAR_FLAG(F_PF);
return intres2;
+20 -22
View File
@@ -49,11 +49,6 @@ static uint32_t x86emu_parity_tab[8] =
0x69969669,
};
uint32_t* GetParityTab()
{
return x86emu_parity_tab;
}
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
emu->context = context;
@@ -219,7 +214,7 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->fpu_tags = emu->fpu_tags;
newemu->cw = emu->cw;
newemu->sw = emu->sw;
newemu->top = emu->top;
@@ -232,10 +227,6 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
newemu->error = emu->error;
// adapt R_ESP to new stack frame
uintptr_t oldst = (uintptr_t)((emu->init_stack)?emu->init_stack:emu->context->stack);
uintptr_t newst = (uintptr_t)((newemu->init_stack)?newemu->init_stack:newemu->context->stack);
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
}
void CopyEmu(x86emu_t *newemu, const x86emu_t* emu)
@@ -252,7 +243,7 @@ void CopyEmu(x86emu_t *newemu, const x86emu_t* emu)
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->fpu_tags = emu->fpu_tags;
newemu->cw = emu->cw;
newemu->sw = emu->sw;
newemu->top = emu->top;
@@ -338,6 +329,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
{
static char buff[800];
static const char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
static const char* segname[] = {"ES", "CS", "SS", "DS", "FS", "GS"};
char tmp[80];
buff[0] = '\0';
if(trace_emm) {
@@ -358,21 +350,27 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
}
// start with FPU regs...
if(emu->fpu_stack) {
if(emu->fpu_stack<9)
for (int i=0; i<emu->fpu_stack; i++) {
//if(i==4) strcat(buff, "\n");
sprintf(tmp, "ST%d=%f", i, emu->x87[(emu->top+i)&7].d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
}
else {
sprintf(tmp, "Warning, incoherent fpu_stack=%d", emu->fpu_stack);
int stack = emu->fpu_stack;
if(stack>8) stack = 8;
for (int i=0; i<stack; i++) {
sprintf(tmp, "ST%d=%f", i, ST(i).d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
sprintf(tmp, " C3210 = %d%d%d%d", emu->sw.f.F87_C3, emu->sw.f.F87_C2, emu->sw.f.F87_C1, emu->sw.f.F87_C0);
strcat(buff, tmp);
strcat(buff, "\n");
}
for (int i=0; i<6; ++i) {
sprintf(tmp, "%s=0x%04x", segname[i], emu->segs[i]);
strcat(buff, tmp);
if(i!=_GS)
strcat(buff, " ");
}
strcat(buff, "\n");
for (int i=_AX; i<=_DI; ++i) {
sprintf(tmp, "%s=%08x ", regname[i], emu->regs[i].dword[0]);
strcat(buff, tmp);
+3 -1
View File
@@ -54,6 +54,7 @@ typedef struct x86emu_s {
reg32_t regs[8];
x86flags_t eflags;
reg32_t ip;
uintptr_t xSPSave;
// fpu / mmx
x87control_t cw;
x87flags_t sw;
@@ -61,9 +62,9 @@ typedef struct x86emu_s {
mmx87_regs_t mmx[8];
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
uint32_t fpu_tags; // tags for the x87 regs, stacked, only on a 16bits anyway
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
// sse
sse_regs_t xmm[8];
mmxcontrol_t mxcsr;
@@ -102,6 +103,7 @@ typedef struct x86emu_s {
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
JUMPBUFF* jmpbuf;
uintptr_t old_savedsp;
i386_ucontext_t *uc_link; // to handle setcontext
+15 -7
View File
@@ -43,7 +43,9 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
v = forkpty(emu->forkpty_info->amaster, emu->forkpty_info->name, emu->forkpty_info->termp, emu->forkpty_info->winp);
emu->forkpty_info = NULL;
} else
} else if(forktype==3)
v = vfork();
else
v = fork();
if(type == EMUTYPE_MAIN)
thread_set_emu(emu);
@@ -51,16 +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);
if(forktype==3) {
// vfork, the parent wait the end or execve of the son
waitpid(v, NULL, WEXITED);
}
} 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);
}
@@ -200,6 +198,8 @@ void x86Int3(x86emu_t* emu)
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "wcsncasecmp")==s) {
snprintf(buff, 256, "%04d|%p: Calling %s(\"%S\", \"%S\", %d)", tid, *(void**)(R_ESP), s, *(wchar_t**)(R_ESP+4), *(wchar_t**)(R_ESP+8), *(int*)(R_ESP+12));
} else if(strstr(s, "gtk_signal_connect_full")) {
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
} else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
@@ -270,6 +270,8 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "glXGetProcAddress")==s) {
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if (!strcmp(s, "glTexImage2D")) {
snprintf(buff, 256, "%04d|%p: Calling %s(0x%x, %d, 0x%x, %d, %d, %d, 0x%x, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(uint32_t*)(R_ESP+32), *(void**)(R_ESP+36));
} else if(strstr(s, "sscanf")==s) {
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "vsscanf")) {
@@ -300,6 +302,10 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "__tls_get_addr")) {
pu32 = *(uint32_t**)(R_ESP+4);
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, pu32, pu32[0], pu32[1]);
} else if (!strcmp(s, "FT_Outline_Get_CBox")) {
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8));
post = 7;
} else if (!strcmp(s, "XDrawImageString")) {
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %p, %i, %i, %p\"%s\", %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(char**)(R_ESP+24), *(char**)(R_ESP+24), *(int*)(R_ESP+28));
} else {
@@ -331,6 +337,8 @@ void x86Int3(x86emu_t* emu)
break;
case 6: snprintf(buff2, 63, "(%S)", pu32?((wchar_t*)pu32):L"nil");
break;
case 7: snprintf(buff2, 63, " [%d / %d / %d /%d]", pu32[0], pu32[1], pu32[2], pu32[3]);
break;
}
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
+21 -4
View File
@@ -61,6 +61,7 @@ int Run(x86emu_t *emu, int step)
uintptr_t addr = R_EIP;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int unimp = 0;
int tf_next = 0;
if(emu->quit)
return 0;
@@ -704,8 +705,12 @@ x86emurun:
Push(emu, emu->eflags.x32);
break;
case 0x9D: /* POPF */
if(ACCESS_FLAG(F_TF) && !tf_next)
--tf_next;
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
if(ACCESS_FLAG(F_TF))
++tf_next;
break;
case 0x9E: /* SAHF */
tmp8u = emu->regs[_AX].byte[1];
@@ -1090,7 +1095,15 @@ x86emurun:
R_ESP = R_EBP;
R_EBP = Pop(emu);
break;
case 0xCA: /* FAR RETN */
tmp16u = F16;
addr = Pop(emu);
emu->segs[_CS] = Pop(emu); // no check, no use....
emu->segs_serial[_CS] = 0;
R_ESP += tmp16u;
// need to check status of CS register!
STEP2;
break;
case 0xCB: /* FAR RET */
addr = Pop(emu);
emu->segs[_CS] = Pop(emu); // no check, no use....
@@ -1593,9 +1606,13 @@ x86emurun:
}
#ifndef TEST_INTERPRETER
if(ACCESS_FLAG(F_TF)) {
R_EIP = addr;
emit_signal(emu, SIGTRAP, (void*)addr, 1);
if(emu->quit) goto fini;
if(tf_next) {
tf_next = 0;
} else {
R_EIP = addr;
emit_signal(emu, SIGTRAP, (void*)addr, 1);
if(emu->quit) goto fini;
}
}
#endif
R_EIP = addr;
+47 -19
View File
@@ -89,28 +89,47 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
return 0;
}
break;
case 0x01:
case 0x01: /* XGETBV, SGDT, etc... */
// this is a privilege opcode...
nextop = F8;
switch((nextop>>3)&7) {
case 0: /* SGDT Ed */
GET_ED;
ED->word[0] = 0x7f; // dummy return...
ED->word[1] = 0x000c;
ED->word[2] = 0xd000;
GET_ED;
if(MODREG)
switch(nextop) {
case 0xD0:
#ifndef TEST_INTERPRETER
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
#endif
break;
case 1: /* SIDT Ed */
GET_ED;
ED->word[0] = 0xfff; // dummy return, like "disabled"
ED->word[1] = 0;
ED->word[2] = 0;
break;
case 4: /* SMSW Ew */
GET_ED;
// dummy for now... Do I need to track CR0 state?
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7: /* SMSW Ew */
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
break;
default:
return 0;
} else
switch((nextop>>3)&7) {
case 0: /* SGDT Ed */
ED->word[0] = 0x7f; // dummy return...
ED->word[1] = 0x000c;
ED->word[2] = 0xd000;
break;
case 1: /* SIDT Ed */
ED->word[0] = 0xfff; // dummy return, like "disabled"
ED->word[1] = 0;
ED->word[2] = 0;
break;
case 4: /* SMSW Ew */
// dummy for now... Do I need to track CR0 state?
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
break;
default:
return 0;
}
break;
@@ -210,6 +229,15 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
nextop = F8;
GET_ED_;
break;
case 0x20: /* MOV REG, crX */
case 0x21: /* MOV REG, drX */
case 0x22: /* MOV cxR, REG */
case 0x23: /* MOV drX, REG */
// this is a privilege opcode...
#ifndef TEST_INTERPRETER
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
#endif
break;
case 0x28: /* MOVAPS Gx,Ex */
nextop = F8;
@@ -242,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];
@@ -1209,7 +1237,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
break;
case 0xBC: /* BSF Ed,Gd */
case 0xBC: /* BSF Gd, Ed */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
@@ -1223,7 +1251,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
SET_FLAG(F_ZF);
}
break;
case 0xBD: /* BSR Ed,Gd */
case 0xBD: /* BSR Gd, Ed */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
+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;
}
}
+8 -8
View File
@@ -1101,12 +1101,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
GX.q[1] = GX.q[0] = 0;
GX.uw[0] = tmp32u;
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
emu->xmm[0].uw[0] = tmp32u;
}
break;
case 0x61: /* PCMPESTRI */
@@ -1128,12 +1128,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
GX.q[1] = GX.q[0] = 0;
GX.uw[0] = tmp32u;
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
emu->xmm[0].uw[0] = tmp32u;
}
break;
case 0x63: /* PCMPISTRI */
+16 -4
View File
@@ -49,7 +49,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
emu->quit = 1; // finished!
}
#else
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int (*main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
@@ -59,11 +59,16 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
if(init) {
PushExit(emu);
R_EIP=(uint32_t)*init;
printf_log(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
printf_dump(LOG_DEBUG, "Calling init(%p) from __libc_start_main\n", *init);
DynaRun(emu);
if(emu->error) // any error, don't bother with more
return 0;
emu->quit = 0;
} else {
if(my_context->elfs[0]) {
printf_dump(LOG_DEBUG, "Calling init from main elf\n");
RunElfInit(my_context->elfs[0], emu);
}
}
MarkElfInitDone(my_context->elfs[0]);
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
@@ -807,7 +812,10 @@ uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg)
const char* getAddrFunctionName(uintptr_t addr)
{
static char ret[1000];
static char rets[8][1000];
static int idx = 0;
char* ret = rets[idx];
idx = (idx+1)&7;
uint32_t sz = 0;
uintptr_t start = 0;
elfheader_t* elf = FindElfAddress(my_context, addr);
@@ -915,7 +923,11 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
if(peek==0xC3 || peek==0xC2) {
printf_log(LOG_NONE, " => %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
} else if(peek==0x55) {
} else if(peek==0x55 || peek==0x57 || peek==0x53) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "top:");
printFunctionAddr(ip, "here: ");
} else if(peek==0x83 && PK(1)==0xEC) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "top:");
printFunctionAddr(ip, "here: ");
+6 -1
View File
@@ -1,3 +1,4 @@
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -11,6 +12,7 @@
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x87emu_setround.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
@@ -32,6 +34,7 @@ uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
int oldround = fpu_setround(emu);
nextop = F8;
switch (nextop) {
@@ -192,9 +195,11 @@ uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
}
break;
default:
fesetround(oldround);
return 0;
}
}
return addr;
fesetround(oldround);
return addr;
}
#pragma GCC diagnostic pop
+63 -13
View File
@@ -1,4 +1,5 @@
#define _GNU_SOURCE
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -12,6 +13,7 @@
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x87emu_setround.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
@@ -33,6 +35,7 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
x86emu_t*emu = test->emu;
#endif
int oldround;
nextop = F8;
switch (nextop) {
case 0xC0:
@@ -110,7 +113,13 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
break;
case 0xF0: /* F2XM1 */
ST0.d = exp2(ST0.d) - 1.0;
if (ST0.d == 0)
break;
// Using the expm1 instead of exp2(ST0)-1 can avoid losing precision much,
// expecially when ST0 is close to zero (which loses the precise when -1).
// printf("%a, %a\n", LN2 * ST0.d, expm1(LN2 * ST0.d));
ST0.d = expm1(LN2 * ST0.d);
// = 2^ST0 - 1 + error. (in math)
emu->sw.f.F87_C1 = 0;
break;
case 0xF1: /* FYL2X */
@@ -119,21 +128,36 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
emu->sw.f.F87_C1 = 0;
break;
case 0xF2: /* FPTAN */
oldround = fpu_setround(emu);
ST0.d = tan(ST0.d);
fesetround(oldround);
fpu_do_push(emu);
ST0.d = 1.0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xF3: /* FPATAN */
oldround = fpu_setround(emu);
ST1.d = atan2(ST1.d, ST0.d);
fesetround(oldround);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xF4: /* FXTRACT */
ST0.d = frexp(ST0.d, &tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
if(isnan(ST1.d)) {
ST0.d = ST1.d;
} else if(isinf(ST1.d)) {
ST0.d = ST1.d;
ST1.d = INFINITY;
} else if(ST1.d==0.0) {
ST0.d = ST1.d;
ST1.d = -INFINITY;
} else {
// LD80bits doesn't have implicit "1" bit, so need to adjust for that
ST0.d = frexp(ST1.d, &tmp32s)*2;
ST1.d = tmp32s-1;
}
// C1 set only if stack under/overflow occurs
break;
@@ -184,20 +208,30 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
emu->top=(emu->top-1)&7; // this will probably break a few things
break;
case 0xF7: /* FINCSTP */
emu->top=(emu->top+1)&7; // this will probably break a few things
if(emu->fpu_tags&0b11)
fpu_do_pop(emu);
else
emu->top=(emu->top+1)&7; // this will probably break a few things
break;
case 0xF9: /* FYL2XP1 */
ST(1).d *= log2(ST0.d + 1.0);
// Using the log1p instead of log2(ST0+1) can avoid losing precision much,
// expecially when ST0 is close to zero (which loses the precise when +1).
ST(1).d = (ST(1).d * log1p(ST0.d)) / M_LN2;
// = ST1 * log2(ST0 + 1) + error. (in math)
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xFA: /* FSQRT */
oldround = fpu_setround(emu);
ST0.d = sqrt(ST0.d);
fesetround(oldround);
emu->sw.f.F87_C1 = 0;
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
oldround = fpu_setround(emu);
sincos(ST1.d, &ST1.d, &ST0.d);
fesetround(oldround);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
@@ -206,18 +240,30 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
emu->sw.f.F87_C1 = 0;
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
if (ST1.d > INT32_MAX)
tmp32s = INT32_MAX;
else if (ST1.d < INT32_MIN)
tmp32s = INT32_MIN;
else
tmp32s = ST1.d;
if(ST0.d!=0.0) {
oldround = fpu_setround(emu);
ST0.d = ldexp(ST0.d, tmp32s);
fesetround(oldround);
}
emu->sw.f.F87_C1 = 0;
break;
case 0xFE: /* FSIN */
oldround = fpu_setround(emu);
ST0.d = sin(ST0.d);
fesetround(oldround);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xFF: /* FCOS */
oldround = fpu_setround(emu);
ST0.d = cos(ST0.d);
fesetround(oldround);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
@@ -256,18 +302,22 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
break;
case 2: /* FST Ed, ST0 */
GET_ED;
if(!(((uintptr_t)ED)&3))
if(!(((uintptr_t)ED)&3)) {
oldround = fpu_setround(emu);
*(float*)ED = ST0.d;
else {
fesetround(oldround);
} else {
f = ST0.d;
memcpy(ED, &f, sizeof(float));
}
break;
case 3: /* FSTP Ed, ST0 */
GET_ED;
if(!(((uintptr_t)ED)&3))
if(!(((uintptr_t)ED)&3)) {
oldround = fpu_setround(emu);
*(float*)ED = ST0.d;
else {
fesetround(oldround);
} else {
f = ST0.d;
memcpy(ED, &f, sizeof(float));
}
@@ -303,5 +353,5 @@ uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
return 0;
}
}
return addr;
return addr;
}
+5 -2
View File
@@ -1,3 +1,4 @@
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -11,6 +12,7 @@
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x87emu_setround.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
@@ -24,7 +26,6 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
float f;
reg32_t *oped;
@@ -101,7 +102,8 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
case 0xF9:
case 0xFD:
return 0;
default:
default:;
int oldround = fpu_setround(emu);
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
GET_ED;
@@ -137,6 +139,7 @@ uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
ST0.d = (double)ED->sdword[0] / ST0.d;
break;
}
fesetround(oldround);
}
return addr;
}
+3 -3
View File
@@ -172,10 +172,10 @@ uintptr_t RunDB(x86emu_t *emu, uintptr_t addr)
break;
case 7: /* FSTP tbyte */
GET_EDT;
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, ED);
else
if(STld(0).uref && (ST0.q==STld(0).uref))
memcpy(ED, &STld(0).ld, 10);
else
D2LD(&ST0.d, ED);
fpu_do_pop(emu);
break;
default:
+5
View File
@@ -1,3 +1,4 @@
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -11,6 +12,7 @@
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x87emu_setround.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
@@ -32,6 +34,7 @@ uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
x86emu_t*emu = test->emu;
#endif
int oldround = fpu_setround(emu);
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -184,8 +187,10 @@ uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
}
break;
default:
fesetround(oldround);
return 0;
}
}
fesetround(oldround);
return addr;
}
+4
View File
@@ -11,6 +11,7 @@
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x87emu_setround.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
@@ -32,6 +33,7 @@ uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
x86emu_t*emu = test->emu;
#endif
int oldround = fpu_setround(emu);
nextop = F8;
switch (nextop) {
case 0xC0: /* FADDP STx, ST0 */
@@ -158,8 +160,10 @@ uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
fesetround(oldround);
return 0;
}
}
fesetround(oldround);
return addr;
}
+1
View File
@@ -1,3 +1,4 @@
#include <fenv.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+33
View File
@@ -555,6 +555,39 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
case 0x87: /* XCHG Ed,Gd */
return addr-1; // let the normal XCHG execute, it have integrated LOCK
case 0xFE: /* GRP 5 Eb */
nextop = F8;
GET_EB;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp8u = arm_lock_read_b(EB);
} while(arm_lock_write_b(EB, inc8(emu, tmp8u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
EB->byte[0] = inc8(emu, EB->byte[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp8u = arm_lock_read_b(EB);
} while(arm_lock_write_d(EB, dec8(emu, tmp8u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
EB->byte[0] = dec8(emu, EB->byte[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFE 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED;
+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;
+25 -13
View File
@@ -116,6 +116,7 @@ int my_socketcall(x86emu_t* emu, int n, unsigned long *args) {
#define O_NONBLOCK 04000
#endif
int my_fcntl(x86emu_t* emu, int fd, int cmd, ... /* arg */ );
long my_ptrace(x86emu_t* emu, int request, pid_t pid, void* addr, uint32_t* data);
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
typedef struct scwrap_s {
@@ -141,6 +142,7 @@ scwrap_t syscallwrap[] = {
[19] { __NR_lseek, 3 },
[20] { __NR_getpid, 0 },
[24] { __NR_getuid, 0 },
//[26] ={__NR_ptrace, 4},
#ifdef __NR_alarm
[27] { __NR_alarm, 1 },
#endif
@@ -485,6 +487,11 @@ void EXPORT x86Syscall(x86emu_t *emu)
S_EAX = -errno;
break;
#endif
case 26: // sys_ptrace
S_EAX = my_ptrace(emu, R_EBX, R_ECX, (void*)R_EDX, (void*)R_ESI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef __NR_alarm
case 27:
R_EAX = alarm(R_EBX);
@@ -581,6 +588,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
break;
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
printf_log(LOG_DEBUG, "clone syscall flags=0x%x, stack=%p, parent_tid=%d,tls=%p, child_tid=%d\n", R_EBX, (void*)R_ECX, R_EDX, (void*)R_ESI, R_EDI);
// so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, tls=R_ESI, child_tid=R_EDI
if((R_EBX&~0xff)==0x4100) {
// this is a case of vfork...
@@ -592,6 +600,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
{
void* stack_base = (void*)R_ECX;
int stack_size = 0;
uintptr_t sp = R_ECX;
if(!R_ECX) {
// allocate a new stack...
int currstack = 0;
@@ -600,18 +609,19 @@ void EXPORT x86Syscall(x86emu_t *emu)
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
if(currstack) {
memcpy(stack_base, emu->init_stack, stack_size);
else {
sp = (uintptr_t)emu->init_stack + R_ESP - (uintptr_t)stack_base;
} else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
sp = (uintptr_t)stack_base+stack_size-size_to_copy;
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
newemu->regs[_SP].dword[0] = sp; // setupnew stack pointer
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
@@ -685,7 +695,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
{
struct stat64 st;
unsigned int r = syscall(__NR_stat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
UnalignSysStat64(&st, (void*)R_ECX);
R_EAX = r;
}
@@ -696,7 +706,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
{
struct stat64 st;
unsigned int r = syscall(__NR_lstat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
UnalignSysStat64(&st, (void*)R_ECX);
R_EAX = r;
}
@@ -707,7 +717,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
{
struct stat64 st;
unsigned int r = syscall(__NR_fstat64, R_EBX, &st);
UnalignStat64(&st, (void*)R_ECX);
UnalignSysStat64(&st, (void*)R_ECX);
R_EAX = r;
}
@@ -770,7 +780,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 449:
#ifdef __NR_futex_waitv
if(box86_futex_waitv)
S_EAX = syscall(R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
S_EAX = syscall(__NR_futex_waitv, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
else
#endif
S_EAX = -ENOSYS;
@@ -850,6 +860,7 @@ long EXPORT my_syscall(x86emu_t *emu)
{
void* stack_base = p(8);
int stack_size = 0;
uintptr_t sp = u32(8);
if(!stack_base) {
// allocate a new stack...
int currstack = 0;
@@ -858,18 +869,19 @@ long EXPORT my_syscall(x86emu_t *emu)
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
if(currstack) {
memcpy(stack_base, emu->init_stack, stack_size);
else {
sp = (uintptr_t)emu->init_stack + R_ESP - (uintptr_t)stack_base;
} else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
sp = (uintptr_t)stack_base+stack_size-size_to_copy;
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (p(8))?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
newemu->regs[_SP].dword[0] = sp;
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
@@ -924,7 +936,7 @@ long EXPORT my_syscall(x86emu_t *emu)
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
return my_memfd_create(emu, (void*)R_EBX, R_ECX);
return my_memfd_create(emu, p(4), u32(8));
#endif
case 449:
#ifdef __NR_futex_waitv
+4 -4
View File
@@ -75,16 +75,16 @@ void x86test_check(x86emu_t* ref, uintptr_t ip)
for(int i=0; i<ref->fpu_stack; ++i) {
if(ref->x87[(ref->top+i)&7].d != emu->x87[(emu->top+i)&7].d) {
BANNER;
printf_log(LOG_NONE, "ST%d: %g | %g\n", i, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
printf_log(LOG_NONE, "ST%d: %g (%a) | %g (%a)\n", i, ref->x87[(ref->top+i)&7].d, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
}
}
}
//memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
//memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
/*if(ref->p_regs != emu->p_regs) {
if(ref->fpu_tags != emu->fpu_tags) {
BANNER;
printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
}*/
printf_log(LOG_NONE, "X87 TAGS: %x | %x\n", ref->fpu_tags, emu->fpu_tags);
}
if(ref->cw.x16 != emu->cw.x16) {
BANNER;
printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
+2 -2
View File
@@ -241,8 +241,8 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
for (int i=oldata->n_elfs; i<context->elfsize; ++i) {
// set pointer
dtp = (uintptr_t)ptr + GetTLSBase(context->elfs[i]);
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8) = dtp;
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8+4) = i; // index
*(uint32_t*)((uintptr_t)ptr+POS_TLS+i*8) = dtp;
*(uint32_t*)((uintptr_t)ptr+POS_TLS+i*8+4) = i; // index
}
oldata->n_elfs = context->elfsize;
}
+49 -64
View File
@@ -1,3 +1,4 @@
#include <fenv.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -17,8 +18,7 @@ void reset_fpu(x86emu_t* emu)
emu->sw.x16 = 0x0000;
emu->top = 0;
emu->fpu_stack = 0;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = 0b11; // STx is empty
emu->fpu_tags = TAGS_EMPTY;
}
void fpu_fbst(x86emu_t* emu, uint8_t* d) {
@@ -77,53 +77,45 @@ void LD2D(void* ld, void* d)
*(uint64_t*)d = *(uint64_t*)ld;
return;
}
FPU_t result;
FPU_t result;
#pragma pack(push, 1)
struct {
FPU_t f;
int16_t b;
} val;
struct {
FPU_t f;
int16_t b;
} val;
#pragma pack(pop)
#if 1
memcpy(&val, ld, 10);
#else
val.f.ud[0] = *(uint32_t*)ld;
val.f.ud[0] = *(uint32_t*)ld;
val.f.ud[1] = *(uint32_t*)(char*)(ld+4);
val.b = *(int16_t*)((char*)ld+8);
val.b = *(int16_t*)((char*)ld+8);
#endif
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
int32_t exp64final = exp64&0x7ff;
// do specific value first (0, infinite...)
// bit 63 is "integer part"
// bit 62 is sign
if((uint32_t)(val.b&0x7fff)==0x7fff) {
// infinity and nans
int t = 0; //nan
switch((val.f.ud[1]>>30)) {
case 0: if((val.f.ud[1]&(1<<29))==0) t = 1;
break;
case 2: if((val.f.ud[1]&(1<<29))==0) t = 1;
break;
}
int t = (val.f.q&0x7fffffffffffffffLL)?0:1;
if(t) { // infinite
result.d = HUGE_VAL;
} else { // NaN
result.ud[1] = 0x7ff << 20;
result.ud[1] = (val.b>>4) << 20;
result.ud[0] = 0;
} else { // NaN
result.ud[1] = (val.b>>4) << 20 | ((val.f.q>>(63-20))&0x000fffff);
result.ud[0] = (val.f.q>>(63-56))&0xffffffff;
if(!(result.q&0x000fffffffffffffLL))
result.q |= 1;
}
if(val.b&0x8000)
result.ud[1] |= 0x80000000;
*(uint64_t*)d = result.q;
return;
}
int32_t exp64 = (((uint32_t)(val.b&0x7fff) - BIAS80) + BIAS64);
int32_t exp64final = exp64&0x7ff;
if(((uint32_t)(val.b&0x7fff)==0) || (exp64<-1074)) {
//if(val.f.ll==0)
//if(val.f.q==0)
// zero
//if(val.f.ll!=0)
//if(val.f.q!=0)
// denormal, but that's to small value for double
uint64_t r = 0;
if(val.b&0x8000)
r |= 0x8000000000000000LL;
uint64_t r = (val.b&0x8000)?0x8000000000000000LL:0LL;
*(uint64_t*)d = r;
return;
}
@@ -149,12 +141,12 @@ void LD2D(void* ld, void* d)
return;
}
uint64_t mant64 = (val.f.q >> 11) & 0xfffffffffffffLL;
uint32_t sign = (val.b&0x8000)?1:0;
uint64_t mant64 = (val.f.q >> 11) & 0xfffffffffffffL;
uint32_t sign = (val.b&0x8000)?1:0;
result.q = mant64;
result.ud[1] |= (sign <<31)|((exp64final&0x7ff) << 20);
result.ud[1] |= (sign <<31)|((exp64final&0x7ff) << 20);
*(uint64_t*)d = result.q;
*(uint64_t*)d = result.q;
}
// double (64bits) -> long double (80bits)
@@ -165,40 +157,37 @@ void D2LD(void* d, void* ld)
return;
}
#pragma pack(push, 1)
struct {
FPU_t f;
int16_t b;
} val;
struct {
FPU_t f;
int16_t b;
} val;
#pragma pack(pop)
FPU_t s;
s.q = *(uint64_t*)d; // use memcpy to avoid risk of Bus Error?
// do special value first
if((s.q&0x7fffffffffffffffLL)==0) {
if((s.q&0x7fffffffffffffffL)==0) {
// zero...
val.f.q = 0;
if(s.ud[1]&0x8000)
val.b = 0x8000;
else
val.b = 0;
val.b = (s.ud[1]&0x80000000)?0x8000:0;
memcpy(ld, &val, 10);
return;
}
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
int32_t exp80 = s.ud[1]&0x7ff00000;
int32_t exp80final = (exp80>>20);
int64_t mant80 = s.sq&0x000fffffffffffffLL;
int64_t mant80final = (mant80 << 11);
int32_t sign80 = (s.ud[1]&0x80000000)?1:0;
int32_t exp80 = s.ud[1]&0x7ff00000;
int32_t exp80final = (exp80>>20);
uint64_t mant80 = s.q&0x000fffffffffffffL;
uint64_t mant80final = (mant80 << 11);
if(exp80final==0x7ff) {
// NaN and Infinite
exp80final = 0x7fff;
if(mant80==0x0)
mant80final = 0x8000000000000000LL; //infinity
mant80final = 0x8000000000000000L; //infinity
else
mant80final = 0xc000000000000000LL; //(quiet)NaN
mant80final |= 0x8000000000000000L; //(quiet)NaN
} else {
if(exp80!=0){
mant80final |= 0x8000000000000000LL;
mant80final |= 0x8000000000000000L;
exp80final += (BIAS80 - BIAS64);
} else if(mant80final!=0) {
// denormals -> normal
@@ -208,8 +197,8 @@ void D2LD(void* d, void* ld)
mant80final<<=one;
}
}
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
val.f.sq = mant80final;
val.b = ((int16_t)(sign80)<<15)| (int16_t)(exp80final);
val.f.q = mant80final;
memcpy(ld, &val, 10);
/*memcpy(ld, &f.ll, 8);
memcpy((char*)ld + 8, &val.b, 2);*/
@@ -248,9 +237,7 @@ void fpu_loadenv(x86emu_t* emu, char* p, int b16)
p+=(b16)?2:4;
// tagword: 2bits*8
// tags... (only full = 0b11 / free = 0b00)
uint16_t tags = *(uint16_t*)p;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))&0b11;
emu->fpu_tags = *(uint16_t*)p;
// intruction pointer: 16bits
// data (operand) pointer: 16bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
@@ -267,10 +254,7 @@ void fpu_savenv(x86emu_t* emu, char* p, int b16)
if(!b16) {*(uint16_t*)p = 0; p+=2;}
// tagword: 2bits*8
// tags...
uint16_t tags = 0;
for (int i=0; i<8; ++i)
tags |= (emu->p_regs[i].tag)<<(i*2);
*(uint16_t*)p = tags;
*(uint16_t*)p = emu->fpu_tags;
// other stuff are not pushed....
}
@@ -300,7 +284,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
stack = (emu->fpu_tags)?8:0;
emu->sw.f.F87_TOP = top;
p->ControlWord = emu->cw.x16;
p->StatusWord = emu->sw.x16;
@@ -308,7 +292,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
p->MxCsr_Mask = 0;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
tags |= (((emu->fpu_tags>>(i*2))&0b11)?0:1)<<i;
p->TagWord = tags;
p->ErrorOpcode = 0;
p->ErrorOffset = 0;
@@ -330,13 +314,14 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
emu->mxcsr.x32 = p->MxCsr;
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = p->TagWord;
emu->fpu_tags = 0;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = ((tags>>(i*2))&0b1)?0:0b11;
emu->fpu_tags |= (((tags>>i)&0b1)?0:0b11)<<(i*2);
// copy back MMX regs...
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
stack = (emu->fpu_tags)?0:8;
for(int i=0; i<8; ++i)
memcpy((i<stack)?&ST(i):&emu->mmx[i], &p->FloatRegisters[i].q[0], sizeof(mmx87_regs_t));
// copy SSE regs
@@ -345,7 +330,7 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
void fpu_fxam(x86emu_t* emu) {
emu->sw.f.F87_C1 = (ST0.ud[1]&0x80000000)?1:0;
if(emu->p_regs[emu->top].tag == 0b11) {
if((emu->fpu_stack<=0) || (emu->fpu_tags&0b11)) {
//Empty
emu->sw.f.F87_C3 = 1;
emu->sw.f.F87_C2 = 0;
+16 -6
View File
@@ -14,6 +14,8 @@ typedef struct x86emu_s x86emu_t;
#define LN2 0.69314718055994531
#define LG2 0.3010299956639812
#define TAGS_EMPTY 0b1111111111111111
#define ST0 emu->x87[emu->top]
#define ST1 emu->x87[(emu->top+1)&7]
#define ST(a) emu->x87[(emu->top+(a))&7]
@@ -36,7 +38,8 @@ static inline void fpu_do_push(x86emu_t* emu)
return;
}
emu->sw.f.F87_C1 = 0;
emu->p_regs[newtop].tag = 0; // full
emu->fpu_tags<<=2; // st0 full
emu->fpu_tags &= TAGS_EMPTY;
emu->top = newtop;
}
@@ -51,17 +54,24 @@ static inline void fpu_do_pop(x86emu_t* emu)
if(emu->fpu_stack>0)
--emu->fpu_stack;
emu->p_regs[curtop].tag = 0b11; // empty
emu->fpu_tags>>=2;
emu->fpu_tags |= 0b1100000000000000; // top empty
emu->top = (emu->top+1)&7;
// check tags
/*while((emu->fpu_tags&0b11) && emu->fpu_stack) {
--emu->fpu_stack;
emu->top = (emu->top+1)&7;
emu->fpu_tags>>=2;
emu->fpu_tags |= 0b1100000000000000; // top empty
}*/
}
static inline void fpu_do_free(x86emu_t* emu, int i)
{
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
emu->fpu_tags |= 0b11 << (i); // empty
// check if all empty
for(int i=0; i<8; ++i)
if(emu->p_regs[i].tag != 0b11)
return;
if(emu->fpu_tags != TAGS_EMPTY)
return;
emu->fpu_stack = 0;
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef __SETROUND_H__
#define __SETROUND_H__
#pragma STDC FENV_ACCESS ON
#include <fenv.h>
#include <stdint.h>
#include "x86emu.h"
#include "x86emu_private.h"
// set the rounding mode to the emulator's one, and return the old one
static inline int fpu_setround(x86emu_t* emu) {
int ret = fegetround();
int rounding_direction;
switch (emu->cw.f.C87_RD) {
case ROUND_Nearest:
rounding_direction = FE_TONEAREST;
break;
case ROUND_Down:
rounding_direction = FE_DOWNWARD;
break;
case ROUND_Up:
rounding_direction = FE_UPWARD;
break;
case ROUND_Chop:
rounding_direction = FE_TOWARDZERO;
break;
}
fesetround(rounding_direction);
return ret;
}
#endif
+3
View File
@@ -99,6 +99,9 @@ typedef struct box86context_s {
int envc;
char** envv;
int orig_argc;
char** orig_argv;
char* fullpath;
char* box86path; // path of current box86 executable
char* box64path; // path of box64 executable (beside box86, if it exists)
+10 -5
View File
@@ -16,6 +16,8 @@ void customFree(void* p);
#define krealloc customRealloc
#define kfree customFree
#define ALIGN(p) (((p)+box86_pagesize-1)&~(box86_pagesize-1))
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
// custom protection flag to mark Page that are Write protected for Dynarec purpose
@@ -37,11 +39,13 @@ uintptr_t getJumpTableAddress(uintptr_t addr);
uintptr_t getJumpAddress(uintptr_t addr);
#endif
#define PROT_NEVERCLEAN 0x100
#define PROT_DYNAREC 0x80
#define PROT_DYNAREC_R 0x40
#define PROT_NOPROT 0x20
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT | PROT_NEVERCLEAN)
#define PROT_NEVERPROT (PROT_NOPROT | PROT_NEVERCLEAN)
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
@@ -56,9 +60,6 @@ void loadProtectionFromMap();
void protectDB(uintptr_t addr, size_t size);
void unprotectDB(uintptr_t addr, size_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
int isprotectedDB(uintptr_t addr, size_t size);
int IsInHotPage(uintptr_t addr);
int AreaInHotPage(uintptr_t start, uintptr_t end);
void AddHotPage(uintptr_t addr);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask);
@@ -77,6 +78,10 @@ void fini_custommem_helper(box86context_t* ctx);
// ---- StrongMemoryModel
void addLockAddress(uintptr_t addr); // add an address to the list of "LOCK"able
int isLockAddress(uintptr_t addr); // return 1 is the address is used as a LOCK, 0 else
void SetHotPage(uintptr_t addr);
int isInHotPage(uintptr_t addr);
int checkInHotPage(uintptr_t addr);
#endif
#endif //__CUSTOM_MEM__H_
+4
View File
@@ -10,6 +10,8 @@ extern int box86_dynarec;
extern uintptr_t box86_pagesize;
extern uintptr_t box86_load_addr;
extern int box86_showbt;
extern int box86_maxcpu;
extern int box86_maxcpu_immutable;
#ifdef DYNAREC
extern int box86_dynarec_dump;
extern int box86_dynarec_trace;
@@ -20,6 +22,7 @@ extern int box86_dynarec_forward;
extern int box86_dynarec_strongmem;
extern int box86_dynarec_x87double;
extern int box86_dynarec_safeflags;
extern int box86_dynarec_callret;
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
extern int box86_dynarec_fastnan;
extern int box86_dynarec_fastround;
@@ -58,6 +61,7 @@ extern int box86_musl;
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
extern int box86_nogtk; // disabling the use of wrapped gtk
extern int box86_novulkan; // disabling the use of wrapped vulkan
extern int box86_nocrashhandler;
extern int box86_futex_waitv;
extern int box86_mapclean;
extern int box86_showsegv;
+2
View File
@@ -5,6 +5,8 @@ typedef struct dynablock_s dynablock_t;
typedef struct x86emu_s x86emu_t;
typedef struct instsize_s instsize_t;
#define MAX_INSTS 32760
void addInst(instsize_t* insts, size_t* size, int x86_size, int arm_size);
void CancelBlock();
+39 -9
View File
@@ -25,8 +25,11 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack);
void AlignStat64(const void* source, void* dest);
void UnalignStat64(const void* source, void* dest);
void UnalignSysStat64(const void* source, void* dest);
void UnalignStat(const void* source, void* dest);
void UnalignStatFS64(const void* source, void* dest);
void UnalignStatFS(const void* source, void* dest);
void UnalignOggVorbis(void* dest, void* source); // Arm -> x86
void AlignOggVorbis(void* dest, void* source); // x86 -> Arm
@@ -43,6 +46,9 @@ void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm
void UnalignSmpegInfo(void* dest, void* source); // Arm -> x86
void AlignSmpegInfo(void* dest, void* source); // x86 -> Arm
void Timespec2Timespec64(void* dest, const void* source);
void Timespec642Timespec(void* dest, const void* source);
// stat64 is packed on i386, not on arm (and possibly other structures)
#undef st_atime
#undef st_atime_nsec
@@ -50,19 +56,43 @@ void AlignSmpegInfo(void* dest, void* source); // x86 -> Arm
#undef st_mtime_nsec
#undef st_ctime
#undef st_ctime_nsec
struct i386_stat {
uint64_t st_dev;
uint32_t __pad1;
uint32_t st_ino;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_uid;
uint32_t st_gid;
uint64_t st_rdev;
uint32_t __pad2;
int32_t st_size;
int32_t st_blksize;
int32_t st_blocks;
int32_t st_atime_sec;
uint32_t st_atime_nsec;
int32_t st_mtime_sec;
uint32_t st_mtime_nsec;
int32_t st_ctime_sec;
uint32_t st_ctime_nsec;
uint32_t __unused4;
uint32_t __unused5;
} __attribute__((packed));
struct i386_stat64 {
uint64_t st_dev;
uint8_t __pad0[4];
uint32_t __st_ino;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_uid;
uint32_t st_gid;
uint32_t __pad0;
uint32_t __st_ino;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_uid;
uint32_t st_gid;
uint64_t st_rdev;
uint8_t __pad3[4];
uint32_t __pad3;
int64_t st_size;
uint32_t st_blksize;
uint64_t st_blocks;
uint32_t st_blksize;
uint64_t st_blocks;
uint32_t st_atime;
uint32_t st_atime_nsec;
uint32_t st_mtime;
+18
View File
@@ -0,0 +1,18 @@
#include <stdint.h>
#ifndef RBTREE_H
#define RBTREE_H
typedef struct rbtree rbtree;
rbtree* init_rbtree();
void delete_rbtree(rbtree *tree);
uint32_t rb_get(rbtree *tree, uintptr_t addr);
int rb_get_end(rbtree* tree, uintptr_t addr, uint32_t* val, uintptr_t* end);
int rb_set(rbtree *tree, uintptr_t start, uintptr_t end, uint32_t data);
int rb_unset(rbtree *tree, uintptr_t start, uintptr_t end);
void print_rbtree(const rbtree *tree);
#endif // RBTREE_H
-4
View File
@@ -20,10 +20,6 @@ typedef union {
uint8_t byte[4];
} reg32_t;
typedef struct {
uint32_t tag;
} fpu_p_reg_t;
typedef enum {
ROUND_Nearest = 0,
ROUND_Down = 1,
+9
View File
@@ -0,0 +1,9 @@
#ifndef __STAT64_HELPER_H_
#define __STAT64_HELPER_H_
int stat64_time64_helper(void *path, void *buf);
int fstatat64_time64_helper(int dirfd, void *path, void *buf, int flags);
int fstat64_time64_helper(int fd, void *buf);
int lstat64_time64_helper(void *path, void *buf);
#endif
-1
View File
@@ -14,7 +14,6 @@ void CopyEmu(x86emu_t *newemu, const x86emu_t* emu);
void SetTraceEmu(uintptr_t trace_start, uintptr_t trace_end);
box86context_t* GetEmuContext(x86emu_t* emu);
uint32_t* GetParityTab();
uint32_t GetEAX(x86emu_t *emu);
uint64_t GetEDXEAX(x86emu_t *emu);
+13 -3
View File
@@ -20,7 +20,7 @@
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
} else \
} \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
@@ -30,7 +30,7 @@
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
} else \
} \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
@@ -130,6 +130,11 @@ void my_updateGlobalOpt()
TOGLOB(optind, "GLIBC_2.2.5");
TOGLOB(opterr, "GLIBC_2.2.5");
TOGLOB(optopt, "GLIBC_2.2.5");
TOGLOB(optarg, "GLIBC_2.0");
TOGLOB(optind, "GLIBC_2.0");
TOGLOB(opterr, "GLIBC_2.0");
TOGLOB(optopt, "GLIBC_2.0");
}
void my_checkGlobalOpt()
@@ -139,4 +144,9 @@ void my_checkGlobalOpt()
GLOB(optind, "GLIBC_2.2.5");
GLOB(opterr, "GLIBC_2.2.5");
GLOB(optopt, "GLIBC_2.2.5");
}
GLOB(optarg, "GLIBC_2.0");
GLOB(optind, "GLIBC_2.0");
GLOB(opterr, "GLIBC_2.0");
GLOB(optopt, "GLIBC_2.0");
}
+2 -2
View File
@@ -39,12 +39,12 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
library_t* owner = (*maplib)->owner;
(*maplib)->owner = NULL; // to avoid recursive free...
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
if((*maplib)->ownlibs && (*maplib)->libsz) {
for(int i=0; i<(*maplib)->libsz; ++i) {
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
DecRefCount(&(*maplib)->libraries[i], emu);
}
}*/
}
box_free((*maplib)->libraries);
(*maplib)->libraries = NULL;
+97 -18
View File
@@ -98,11 +98,15 @@ void WrappedLib_CommonInit(library_t *lib) {
lib->w.mydatamap = kh_init(datamap);
}
static void initDummyLib(library_t *lib);
void EmuLib_Fini(library_t* lib)
{
}
void WrappedLib_FinishFini(library_t* lib)
{
if(lib->type!=LIB_WRAPPED)
return;
if(lib->w.lib)
dlclose(lib->w.lib);
lib->w.lib = NULL;
@@ -115,6 +119,9 @@ void WrappedLib_FinishFini(library_t* lib)
}
FreeBridge(&lib->w.bridge);
}
void DummyLib_Fini(library_t* lib)
{
}
int WrappedLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
@@ -148,6 +155,11 @@ int EmuLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t
}
return 0;
}
int DummyLib_GetWeak(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
return 0;
}
int WrappedLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
// ignoring asked size on wrapped libs
@@ -178,6 +190,10 @@ int EmuLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_
}
return 0;
}
int DummyLib_GetGlobal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
return 0;
}
int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
// ignoring asked size on wrapped libs
@@ -197,6 +213,11 @@ int WrappedLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintp
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
return 0;
}
int DummyLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t asked_size, int* weak, int version, const char* vername, int local, const char* defver)
{
(void)lib; (void)name; (void)offs; (void)sz; (void)version; (void)vername; (void)local;
return 0;
}
static void initWrappedLib(library_t *lib, box86context_t* context) {
int nb = sizeof(wrappedlibs) / sizeof(wrappedlib_t);
@@ -345,16 +366,28 @@ static void initEmulatedLib(const char* path, library_t *lib, box86context_t* co
}
}
static void initDummyLib(library_t *lib)
{
memset(lib, 0, sizeof(library_t));
lib->fini = DummyLib_Fini;
lib->getglobal = DummyLib_GetGlobal;
lib->getweak = DummyLib_GetWeak;
lib->getlocal = DummyLib_GetLocal;
lib->name = NULL;
lib->path = NULL;
lib->type = LIB_UNNKNOW;
}
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)
@@ -363,10 +396,34 @@ static int isEssentialLib(const char* name) {
return 0;
}
#define NLIBS 16
typedef struct lib_brick_s {
library_t libs[NLIBS];
struct lib_brick_s* next;
} lib_brick_t;
static lib_brick_t* lib_head = NULL;
static lib_brick_t* cur_brick = NULL;
static size_t cur_lib = 0;
static size_t lib_cap = 0;
library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* verneeded)
{
printf_dump(LOG_DEBUG, "Trying to load \"%s\"\n", path);
library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
//library_t *lib = (library_t*)box_calloc(1, sizeof(library_t));
if(cur_lib==lib_cap) {
lib_brick_t *new_brick = calloc(1, sizeof(lib_brick_t));
if(!lib_head)
cur_brick = lib_head = new_brick;
else {
cur_brick->next = new_brick;
cur_brick = new_brick;
}
lib_cap += NLIBS;
}
library_t *lib = &cur_brick->libs[cur_lib%NLIBS];
++cur_lib;
memset(lib, 0, sizeof(library_t));
lib->path = box_realpath(path, NULL);
if(!lib->path)
lib->path = box_strdup(path);
@@ -381,7 +438,8 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
box_free(lib->name);
box_free(lib->path);
box_free(lib);
initDummyLib(lib);
//box_free(lib);
return NULL;
}
}
@@ -389,7 +447,17 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
if(strstr(lib->name, "libvulkan.so")==lib->name) {
box_free(lib->name);
box_free(lib->path);
box_free(lib);
initDummyLib(lib);
//box_free(lib);
return NULL;
}
}
if(box86_nocrashhandler) {
if(strstr(lib->name, "crashhandler.so")==lib->name) {
box_free(lib->name);
box_free(lib->path);
initDummyLib(lib);
//box_free(lib);
return NULL;
}
}
@@ -418,7 +486,8 @@ library_t *NewLibrary(const char* path, box86context_t* context, elfheader_t* ve
{
box_free(lib->name);
box_free(lib->path);
box_free(lib);
initDummyLib(lib);
//box_free(lib);
return NULL;
}
lib->gbridgemap = kh_init(bridgemap);
@@ -495,7 +564,7 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
library_t* lib = *the_lib;
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name);
printf_dump(LOG_DEBUG, "Free1Library %s\n", lib->name?:"???");
// remove lib from maplib/local_maplib...
if(my_context) {
MapLibRemoveLib(my_context->maplib, lib);
@@ -558,10 +627,11 @@ void Free1Library(library_t **the_lib, x86emu_t* emu)
kh_destroy(symbol2map, lib->w.symbol2map);
}
// remove frim the dlopen collection
// remove from the dlopen collection
if(lib->dlopen)
RemoveDlopen(the_lib, lib->dlopen);
box_free(lib);
initDummyLib(lib);
//box_free(lib);
if(*the_lib == lib)
*the_lib = NULL;
}
@@ -604,7 +674,7 @@ int IsSameLib(library_t* lib, const char* path)
}
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
{
if(!lib || !name[0])
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
// get a new symbol
@@ -631,7 +701,7 @@ int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start,
}
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
{
if(!name[0] || !lib)
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
// get a new symbol
@@ -658,7 +728,7 @@ int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* star
}
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver)
{
if(!name[0])
if(!name[0] || !lib || (lib->type==LIB_UNNKNOW))
return 0;
khint_t k;
// get a new symbol
@@ -1105,23 +1175,28 @@ void setNeededLibs(library_t* lib, int n, ...)
va_end (va);
}
#define LIB_MAXCNT 255
void IncRefCount(library_t* lib, x86emu_t* emu)
{
if(!lib || lib->type==LIB_UNNKNOW)
return;
switch (lib->type) {
case LIB_WRAPPED:
if(lib->w.refcnt==LIB_MAXCNT)
return;
++lib->w.refcnt;
/*if(lib->w.needed)
if(lib->w.needed)
for(int i=0; i<lib->w.needed->size; ++i) {
IncRefCount(lib->w.needed->libs[i], emu);
}*/
}
break;
case LIB_EMULATED:
if(lib->e.elf->refcnt==LIB_MAXCNT)
return;
++lib->e.elf->refcnt;
/*if(lib->e.elf->needed)
if(lib->e.elf->needed)
for(int i=0; i<lib->e.elf->needed->size; ++i) // some libs may not be loaded yet
IncRefCount(lib->e.elf->needed->libs[i], emu);*/
IncRefCount(lib->e.elf->needed->libs[i], emu);
}
}
@@ -1138,6 +1213,8 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
int freed = 0;
switch ((*lib)->type) {
case LIB_WRAPPED:
if((*lib)->w.refcnt==LIB_MAXCNT)
return ret;
needed = (*lib)->w.needed;
ret=--(*lib)->w.refcnt;
if(!ret) {
@@ -1147,6 +1224,8 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
}
break;
case LIB_EMULATED:
if((*lib)->e.elf->refcnt==LIB_MAXCNT)
return ret;
needed = (*lib)->e.elf->needed;
ret=--(*lib)->e.elf->refcnt;
if(!ret) {
@@ -1158,9 +1237,9 @@ int DecRefCount(library_t** lib, x86emu_t* emu)
}
break;
}
/*if(needed)
if(needed)
for(int i=0; i<needed->size; ++i)
DecRefCount(&needed->libs[i], emu);*/
DecRefCount(&needed->libs[i], emu);
if(freed)
free_neededlib(needed);
return ret;
+2 -2
View File
@@ -230,8 +230,8 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t* s = MatchVersion(v, ver, vername, 0, local, defver);
if(s) {
*start = s->sym.offs;
*end = *start + s->sym.sz;
if(start) *start = s->sym.offs;
if(end) *end = *start + s->sym.sz;
return 1;
}
return 0;
+4 -2
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)
@@ -265,5 +267,5 @@ GO("libxml2.so.2", xml2)
GO("ld-linux.so.2", ldlinux)
GO("crashhandler.so", crashhandler)
//GO("crashhandler.so", crashhandler)
GO("libv4l2.so.0", libv4l2)
+87
View File
@@ -1,5 +1,6 @@
#undef _LARGEFILE_SOURCE
#undef _FILE_OFFSET_BITS
#undef _TIME_BITS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -7,6 +8,8 @@
#include <wchar.h>
#include <sys/epoll.h>
#include <fts.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include "x86emu.h"
#include "emu/x86emu_private.h"
@@ -917,3 +920,87 @@ void unalignNGValue(void* value, my_GValue_t* v, int n)
--n;
}
}
void UnalignStat(const void* source, void* dest)
{
struct i386_stat *i386st = (struct i386_stat*)dest;
struct stat *st = (struct stat*) source;
i386st->__pad1 = 0;
i386st->__pad2 = 0;
i386st->st_dev = st->st_dev;
i386st->st_ino = st->st_ino;
i386st->st_mode = st->st_mode;
i386st->st_nlink = st->st_nlink;
i386st->st_uid = st->st_uid;
i386st->st_gid = st->st_gid;
i386st->st_rdev = st->st_rdev;
i386st->st_size = st->st_size;
i386st->st_blksize = st->st_blksize;
i386st->st_blocks = st->st_blocks;
#if defined(__USE_XOPEN2K8) || defined(ANDROID) || defined(PANDORA)
i386st->st_atime_sec = st->st_atim.tv_sec;
i386st->st_atime_nsec = st->st_atim.tv_nsec;
i386st->st_mtime_sec = st->st_mtim.tv_sec;
i386st->st_mtime_nsec = st->st_mtim.tv_nsec;
i386st->st_ctime_sec = st->st_ctim.tv_sec;
i386st->st_ctime_nsec = st->st_ctim.tv_nsec;
#else
i386st->st_atime_sec = st->st_atime;
i386st->st_atime_nsec = st->st_atimensec;
i386st->st_mtime_sec = st->st_mtime;
i386st->st_mtime_nsec = st->st_mtimensec;
i386st->st_ctime_sec = st->st_ctime;
i386st->st_ctime_nsec = st->st_ctimensec;
#endif
}
void UnalignStatFS(const void* source, void* dest)
{
struct i386_statfs *i386st = (struct i386_statfs*)dest;
struct statfs *st = (struct statfs*) source;
i386st->f_type = st->f_type;
i386st->f_bsize = st->f_bsize;
i386st->f_blocks = st->f_blocks;
i386st->f_bfree = st->f_bfree;
i386st->f_bavail = st->f_bavail;
i386st->f_files = st->f_files;
i386st->f_ffree = st->f_ffree;
memcpy(&i386st->f_fsid, &st->f_fsid, sizeof(i386st->f_fsid));
i386st->f_namelen = st->f_namelen;
i386st->f_frsize = st->f_frsize;
#ifndef PANDORA
i386st->f_flags = st->f_flags;
#endif
i386st->f_spare[0] = st->f_spare[0];
i386st->f_spare[1] = st->f_spare[1];
i386st->f_spare[2] = st->f_spare[2];
i386st->f_spare[3] = st->f_spare[3];
}
typedef struct my_timespec_s {
int tv_sec;
int tv_nsec;
} my_timespec_t;
typedef struct my_timespec64_s {
int64_t tv_sec;
int tv_nsec;
int :32;
} my_timespec64_t;
void Timespec2Timespec64(void* dest, const void* source)
{
my_timespec64_t* dst = (my_timespec64_t*)dest;
my_timespec_t* src = (my_timespec_t*)source;
dst->tv_sec = src->tv_sec;
dst->tv_nsec = src->tv_nsec;
}
void Timespec642Timespec(void* dest, const void* source)
{
my_timespec_t* dst = (my_timespec_t*)dest;
my_timespec64_t* src = (my_timespec64_t*)source;
dst->tv_sec = src->tv_sec;
dst->tv_nsec = src->tv_nsec;
}
+29 -11
View File
@@ -5,27 +5,28 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <asm/stat.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <signal.h>
#include <stddef.h>
#include "x86emu.h"
#include "emu/x86emu_private.h"
#include "myalign.h"
#include "debug.h"
void UnalignStat64(const void* source, void* dest)
{
struct i386_stat64 *i386st = (struct i386_stat64*)dest;
struct stat64 *st = (struct stat64*) source;
memset(i386st->__pad0, 0, sizeof(i386st->__pad0));
memset(i386st->__pad3, 0, sizeof(i386st->__pad3));
i386st->__pad0 = 0;
i386st->__pad3 = 0;
i386st->st_dev = st->st_dev;
#ifndef POWERPCLE
i386st->__st_ino = st->__st_ino;
#if defined(__USE_TIME64_REDIRECTS) || defined(POWERPCLE) || !defined(HAVE_ST_INO)
i386st->__st_ino = st->st_ino;
#else
i386st->__st_ino = st->st_ino; // Separate __st_ino doesn't
// exist on powerpc
i386st->__st_ino = st->__st_ino;
#endif
i386st->st_mode = st->st_mode;
i386st->st_nlink = st->st_nlink;
@@ -35,12 +36,21 @@ void UnalignStat64(const void* source, void* dest)
i386st->st_size = st->st_size;
i386st->st_blksize = st->st_blksize;
i386st->st_blocks = st->st_blocks;
#if defined(__USE_XOPEN2K8) || defined(ANDROID) || defined(PANDORA)
i386st->st_atime = st->st_atim.tv_sec;
i386st->st_atime_nsec = st->st_atim.tv_nsec;
i386st->st_mtime = st->st_mtim.tv_sec;
i386st->st_mtime_nsec = st->st_mtim.tv_nsec;
i386st->st_ctime = st->st_ctim.tv_sec;
i386st->st_ctime_nsec = st->st_ctim.tv_nsec;
#else
i386st->st_atime = st->st_atime;
i386st->st_atime_nsec = st->st_atime_nsec;
i386st->st_mtime = st->st_mtime;
i386st->st_mtime_nsec = st->st_mtime_nsec;
i386st->st_ctime = st->st_ctime;
i386st->st_ctime_nsec = st->st_ctime_nsec;
#endif
i386st->st_ino = st->st_ino;
}
@@ -50,11 +60,10 @@ void AlignStat64(const void* source, void* dest)
struct i386_stat64 *i386st = (struct i386_stat64*)source;
st->st_dev = i386st->st_dev;
#ifndef POWERPCLE
st->__st_ino = i386st->__st_ino;
#if defined(__USE_TIME64_REDIRECTS) || defined(POWERPCLE)|| !defined(HAVE_ST_INO)
// Separate __st_ino doesn't exist
#else
st->st_ino = i386st->__st_ino; // Separate __st_ino doesn't
// exist on powerpc
st->__st_ino = i386st->__st_ino;
#endif
st->st_mode = i386st->st_mode;
st->st_nlink = i386st->st_nlink;
@@ -64,12 +73,21 @@ void AlignStat64(const void* source, void* dest)
st->st_size = i386st->st_size;
st->st_blksize = i386st->st_blksize;
st->st_blocks = i386st->st_blocks;
#if defined(__USE_XOPEN2K8) || defined(ANDROID) || defined(PANDORA)
st->st_atim.tv_sec = i386st->st_atime;
st->st_atim.tv_nsec = i386st->st_atime_nsec;
st->st_mtim.tv_sec = i386st->st_mtime;
st->st_mtim.tv_nsec = i386st->st_mtime_nsec;
st->st_ctim.tv_sec = i386st->st_ctime;
st->st_ctim.tv_nsec = i386st->st_ctime_nsec;
#else
st->st_atime = i386st->st_atime;
st->st_atime_nsec = i386st->st_atime_nsec;
st->st_mtime = i386st->st_mtime;
st->st_mtime_nsec = i386st->st_mtime_nsec;
st->st_ctime = i386st->st_ctime;
st->st_ctime_nsec = i386st->st_ctime_nsec;
#endif
st->st_ino = i386st->st_ino;
}
Loaded 100 of 163 files, more files were not shown because too many files have changed in this diff. Show more