653 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
ptitSeb f191228318 Bumped version to v0.3.4 2023-12-15 19:25:05 +01:00
ptitSeb 7c3730f4e6 That debian changelog was outdated a bit 2023-12-15 17:20:42 +01:00
ptitSeb 772aca08b8 Update README.md 2023-12-15 16:41:02 +01:00
ptitSeb 0f19b73dfe Limit the number of CPU Core reported to 32 when running wine (or proton) 2023-12-15 13:24:47 +01:00
ptitSeb b7dccd065f Added lldb option to JITGDB 2023-12-15 13:19:03 +01:00
ptitSeb 57c1ed7118 [DYNAREC] Fixed a bug with latest dynarec changes 2023-12-13 15:56:31 +01:00
ptitSeb 5a348e1de9 [DYNAREC] Improve dynarec speed for larger blocks 2023-12-13 13:04:43 +01:00
ptitSeb 76a5f3b7c9 Added 1 more symbol to libcups (for wine 8.21+) 2023-12-11 16:55:12 +01:00
ptitSeb c317bf94c8 [DYNAREC] Reworked 0F 51 opcode to use more precise operations (fixed wrong physics with NFS the Run, probably others too) 2023-12-10 11:18:52 +01:00
ptitSeb cbe0ef830b [DYNAREC] Added 66 FF /6 opcode 2023-12-10 10:20:47 +01:00
ptitSeb 5c54463c32 Forgot to keep sink struct alignment function in pulse refactor (fixes steam crashing at launch) 2023-12-09 23:10:34 +01:00
ptitSeb 531ccfaf6a That mutex was destroyed 2 times or 0 times... 2023-12-09 21:47:05 +01:00
KreitinnSoftware 339af4a13e [ANDROID] Fix pthread_mutex_destroy called on destroyed mutex (#909) 2023-12-09 21:15:16 +01:00
ptitSeb d4f7ec6ee4 Refactored wrapping of libpulse (again, works now) 2023-12-09 17:43:14 +01:00
ptitSeb 2de4ce82f3 Small changes to alternate address handling 2023-12-09 12:15:33 +01:00
ptitSeb d2f033e97a [DYNAREC] Improved a bit running unreadable memory 2023-12-09 11:53:12 +01:00
ptitSeb c2375d030b Added wrapped libpcre (backported from box64) 2023-12-09 11:48:24 +01:00
ptitSeb 786680a288 Do not try to get nearest function name if pointer is to small 2023-12-09 10:50:06 +01:00
ptitSeb 0883cdc9ac Added wrapped libayatana-appindicator3.so.1 (backported from box64) 2023-12-09 10:47:47 +01:00
ptitSeb e35d6d22a4 Added wrapped libatomic (backported from box64) 2023-12-09 10:43:16 +01:00
ptitSeb 14a53affc0 Don't track internal used mmap as emulated program one 2023-12-09 10:37:32 +01:00
ptitSeb 18e8b06dfb [DYNAREC] Improved strong memory model emulation (backported from box64) 2023-12-09 10:21:34 +01:00
ptitSeb ac8ae8f0ec [DYNAREC] Small improvment to x87_forget utility function 2023-12-09 10:08:45 +01:00
ptitSeb 274fe75017 [DYNAREC] Small optim for D9 F2 opcode 2023-12-09 09:59:34 +01:00
ptitSeb 278d8fe8d9 Adjusted some i386 signal translation 2023-12-08 17:52:35 +01:00
ptitSeb dcf89339b8 Added wrapped libOpenCL.so (backported from box64) 2023-12-08 17:00:51 +01:00
ptitSeb 1c3c3a209a [EMU] Set segment to be 16bits 2023-12-08 16:54:27 +01:00
ptitSeb d91ac13592 Fixed some functions signature on gobject2 2023-12-08 16:15:16 +01:00
ptitSeb aafa791f4a Small improvment in global hacking 2023-12-08 15:00:26 +01:00
ptitSeb 3b08ace904 [EMU] Potential fix for calling a function when uc_link is set 2023-12-08 14:46:42 +01:00
ptitSeb fefa13f655 Better way to handle syscall array with c99 sparse array init 2023-12-08 14:44:04 +01:00
ptitSeb 949e7b7809 Rollback of 9803591643, something is wrong 2023-12-08 13:27:09 +01:00
ptitSeb 7fe38de5f6 [INTERPRETER] Slightly better way to handle 3E/F2/F3 prefixes 2023-12-08 12:13:49 +01:00
ptitSeb 9803591643 Refactored wrapping of libpulse (backported from box64) 2023-12-08 12:07:26 +01:00
Lily d87033837b [TERMUX] Complex math fix in libm (#905) 2023-12-07 12:07:00 +01:00
ptitSeb 507b68358f Merge branch 'master' of https://github.com/ptitSeb/box86 2023-12-06 17:57:48 +01:00
ptitSeb 1b721a536e Downgrade libstdc++ and libgcc_s for now 2023-12-06 17:57:42 +01:00
ptitSeb 77706f8142 [DYNAREC] Added some detection of divide by 0 used by some anti-debug software (for #902) 2023-12-06 17:02:29 +01:00
ptitSeb 8a71575487 [INTERPRETER] Added addling to divide by 0 exception 2023-12-05 21:28:58 +01:00
ptitSeb dd0a57ab30 [INTERPRETER] Call opcode also need getAlternate redirection 2023-12-05 15:30:08 +01:00
ptitSeb 07b0f6673a Show TLS resize warning only if old size is not 0 2023-12-05 13:20:02 +01:00
ptitSeb 88e84a6c1c Refactored Interpreter and Dynarec to use MODREG macro, and check if LDS/LES are an unsupported VEX prefix 2023-12-05 13:15:43 +01:00
ptitSeb 767e94aae1 [TRACE] Fixes some crash when setting a trace in a lib load later 2023-12-05 12:58:25 +01:00
ptitSeb 0c211a0164 [MALLOCHOOK] Small improvments to mallochook_2 (backported from box64) 2023-12-05 10:46:17 +01:00
ptitSeb be6e2fe1da Added some more wrapped function to libdrm 2023-12-05 10:38:33 +01:00
ptitSeb d94dce18c5 [DYNAREC] Added optionnal memory barrier to MOVS/STOS 2023-12-05 09:07:55 +01:00
ptitSeb a0f180e86b ELFLOADER] Some fixes to localy openned libs when symbols might collide with main binary (backported from box64) 2023-12-05 08:55:45 +01:00
ptitSeb 8f2fe64afc Better wrapping for vkCreateInstance 2023-12-04 20:07:43 +01:00
Lily d64248b1f8 [CMAKE] Enable Re-Building Wrappers in TERMUX build (#901) 2023-12-04 18:04:52 +01:00
Lily cc67b01aa8 [TERMUX] Some fixes (#900)
* [TERMUX] Fix debian dependency

* [TERMUX] Library path and rc file load fix
2023-12-04 17:16:17 +01:00
ptitSeb 90a18265b9 [DYNAREC] Refactore STRONGMEM emulation (backported from box64) 2023-12-04 15:55:31 +01:00
Lily 08f8d8d721 [TERMUX] Fix debian packaging (#899)
* [MAIN] Making same as box64 output and fix termux make install

* [MAIN] Revert default log level

* [TERMUX] Fix debian packaging
2023-12-03 17:47:52 +01:00
Lily df2504f976 [MAIN] Making same as box64 output and fix termux make install (#898)
* [MAIN] Making same as box64 output and fix termux make install

* [MAIN] Revert default log level
2023-12-03 16:38:54 +01:00
Lily 117fe48b5e [TERMUX] Fix Building (#897) 2023-12-02 19:37:43 +01:00
ptitSeb e02844fb93 Fixed some potential segfault with wine apps (maybe others too) 2023-12-01 17:41:03 +01:00
ptitSeb ca1f0d0cf2 [ANDROID] Try to fix libbsd issues 2023-12-01 10:44:30 +01:00
ptitSeb 2e6bc42a49 Added support for wrapped libbsd (needed for latest libstdc++ lib) 2023-11-30 21:51:42 +01:00
ptitSeb cf2e754447 [X86LIBS] Updated libstdc++ and libgcc_s 2023-11-30 17:39:44 +01:00
ptitSeb 708986a3c6 [ELFLOADER] Use a fallback if allocated memory not at expected address for elf with vaddr 2023-11-29 10:51:10 +01:00
ptitSeb e8fabe23ec [DYNAREC] Fixed some rare issue with flags not correctly updated on a forward jump 2023-11-29 10:50:38 +01:00
Creeper-xie fa2374a7a7 [ANDROID]Fix Termux installation path (#895)
* Add files via upload

* [ANDROID]Fix Termux installation path

[ANDROID]Fix Termux installation path
2023-11-28 12:10:29 +01:00
Lily a70e5d7aa7 [ANDROID] Fix Clang Compiling (#894) 2023-11-28 08:56:20 +01:00
Lily e87915bcfb [ANDROID] Fix Compiling (#893)
* [ANDROID] Fix Compiling

* [ANDROID] Use TERMUX Define Instead ANDROID
2023-11-27 17:37:19 +01:00
ptitSeb c540942294 Fixed a build Warning (or Error in certain configuration) (for #892) 2023-11-26 08:47:23 +01:00
ptitSeb 3869cc2bc0 [ANDROID] This should fix Android build, again and again 2023-11-23 21:45:18 +01:00
ptitSeb f3ddb6bcf4 [ANDROID] This should fix Android build, again 2023-11-23 20:19:28 +01:00
ptitSeb 26f30a3c09 [ANDROID] This should fix Android build 2023-11-23 19:54:49 +01:00
ptitSeb b831475d1b [DYNAREC] Various fixes and improvment to some opcodes 2023-11-23 18:27:16 +01:00
ptitSeb 431eb604e4 Small improvment to cpuid opcode 2023-11-23 18:26:27 +01:00
ptitSeb 0d2bf2fe30 Small improvment on INT handling 2023-11-23 18:26:00 +01:00
ptitSeb 94f9f5d0b5 Fixed some wrapped aio_ functions signature of librt 2023-11-23 18:25:08 +01:00
ptitSeb 8349acb93a Fixed cpu name gathering 2023-11-22 10:00:08 +01:00
ptitSeb 8c00a1100f Added a few wrapped function to libxft (for #888) 2023-11-21 18:10:42 +01:00
Raezroth 0cdd36bac6 Backport of 64mb block size change from box64 (#886) 2023-11-18 08:31:18 +01:00
ptitSeb fd3dcf3873 Huge refactor on signal and main run loop ([DYNAREC] too) 2023-11-17 15:50:21 +01:00
ptitSeb 72d3098ba4 [INTERPRETER] Fixed repnz cmpsd opcode 2023-11-17 10:40:32 +01:00
ptitSeb 177abf2e44 Adjuested a few wrapped libc signature functions 2023-11-17 10:36:01 +01:00
ptitSeb 077764251d Fixed OF flags for shld/shrd opcodes ([DYNAREC] too) 2023-11-17 10:35:34 +01:00
ptitSeb 90fbf7237f [DYNAREC] Optimized 66 C1, D1, D3 opcodes 2023-11-15 16:10:16 +01:00
ptitSeb d9ec366ce4 [DYNAREC] Reorganised D1/D3 opcode and optimized D1 /0 and D1 / 1 opcodes 2023-11-15 15:43:37 +01:00
ptitSeb c854b23d35 [DYNAREC] optimized C0 /7 and D0 /7 opcodes 2023-11-15 15:31:59 +01:00
ptitSeb fd137915b6 [DYNAREC] optimized D2 /7 opcode 2023-11-15 15:26:35 +01:00
ptitSeb dad0e5ef2f [DYNAREC] optimized C0 /5 and D0 /5 opcodes 2023-11-15 14:46:59 +01:00
ptitSeb 5abf1fa24e [DYNAREC] Don't consume X_PEND if opcode MAY emit flags 2023-11-15 14:37:35 +01:00
ptitSeb b5bc46e13a [DYNAREC] optimized D2 /5 opcode 2023-11-15 14:30:12 +01:00
ptitSeb c39a8ebd51 [DYNAREC] optimized C0 /4 /6 and D0 /4 /6 opcodes 2023-11-15 14:29:51 +01:00
ptitSeb 38d35cbef0 [DYNAREC] Optimized D2 /1 opcode 2023-11-15 13:49:02 +01:00
ptitSeb 3058fefe93 [DYNAREC] Optimized D2 /0 opcode 2023-11-15 13:44:23 +01:00
ptitSeb f03d09b949 [DYNAREC] Reorganised D2 & D2 ocpodes, and optimized D2 /4 and D2 /6 2023-11-15 13:36:59 +01:00
ptitSeb 2343533b41 Cleaned up syscall and signed register access 2023-11-15 12:12:04 +01:00
ptitSeb fa2f3c0577 [ELFLOADER] Better tracking of mmaped memory 2023-11-15 11:51:20 +01:00
ptitSeb 6c28b3584e Better dependancies for fontconfig lib 2023-11-15 11:23:36 +01:00
ptitSeb 8fa5ec74ec Added 64/65 [64/65] 90 opcode ([DYNAREC] too) 2023-11-15 11:22:15 +01:00
ptitSeb 868ad666ed Workaround to handle MAX_SIGNAL properly 2023-11-15 11:17:00 +01:00
ptitSeb 150b035a1b [ELFLOADER] Some more fixes to elf memory manager 2023-11-13 10:15:59 +01:00
ptitSeb fdd775790a Added BOX86_FUTEX_WAITV, disable b default for BAD_SIGNAL, enabled elsewhere 2023-11-10 18:10:26 +01:00
ptitSeb 68ff10a18e [DYNAREC] Some more fixes and improvment to shifting opcodes 2023-11-10 14:22:56 +01:00
ptitSeb 3f072c8aa8 [DYNAREC] Fixed 0F C1 opcode 2023-11-10 12:43:17 +01:00
ptitSeb 7b0c1689bb [DYNAREC] Some fixes for potentially missing flags computation in some opcodes 2023-11-10 12:35:09 +01:00
ptitSeb 6946198045 [INTERPRETER] Fixed some edge-case flags with some shift ocpodes 2023-11-10 12:32:59 +01:00
ptitSeb 8f76973fcf [INTERPRETER] Fixed 66 D9/DD opcodes 2023-11-10 12:25:09 +01:00
ptitSeb b9ded7320a [ELFLOADER] Improved wine compatibility (should help #885) 2023-11-08 15:28:05 +01:00
ptitSeb fc14382a07 [DYNAREC] Added 66 0F 3A 20 opcode 2023-11-08 11:47:51 +01:00
ptitSeb 35cc9af4ff Added F3 0F B8 opcode 2023-11-08 11:38:53 +01:00
ptitSeb 0c2d9acd99 [DYNAREC] Removed DMB_ISH before jmpnext, it slows things down and doesn't solve anything 2023-11-08 11:38:04 +01:00
ptitSeb 9c0ecf0427 [DYNAREC] Added 66 0F 3A 63 opcode 2023-11-07 21:30:48 +01:00
ptitSeb 10529d007c [DYNAREC] Added 66 0F 3A 16/22 opcodes 2023-11-07 18:58:59 +01:00
ptitSeb ac356fc146 [DYNAREC] Added 66 0F 3A DF opcode 2023-11-07 18:26:46 +01:00
ptitSeb 0b584bbb48 [DYNAREC] Added BOX86_DYNAREC_MISSING to show missing dynarec opcode 2023-11-07 18:13:07 +01:00
ptitSeb c10b105f5f Added SSE4.1 and SSE4.2 spport (backported from box64) 2023-11-07 18:06:11 +01:00
ptitSeb 236de084ea Refined ptrace hacks around POKEUSER/PEEKUSER (should help Wine Unity3D games) 2023-11-07 15:33:37 +01:00
ptitSeb 72e917bb06 Added wrapped function __wcstombs_chk to libc 2023-11-06 10:02:24 +01:00
ptitSeb 0d64ab09bb [STEAM] Improved install_steam script 2023-11-05 13:43:23 +01:00
ptitSeb ff0b7683e7 Added i386 versionof libunwind.so.8 2023-11-04 15:27:19 +01:00
ptitSeb d210f12f25 [ELFLOADER] More changes to elf memory managment 2023-11-04 09:10:04 +01:00
ptitSeb 87d346230c [ELFLOADER] Some more regression fixes on elf memory managment 2023-11-03 12:11:34 +01:00
KreitinnSoftware 47c65e1e3a Added wrapped symbol posix_spawn_file_actions_addclose to libc (#881)
* Added wrapped symbol posix_spawn_file_actions_addclose to libc

* Fix wrapping signature for posix_spawn_file_actions_addclose
2023-11-02 16:01:11 +01:00
ptitSeb 57440bd102 [ELFLOADER] Fixed a warning 2023-11-02 10:38:46 +01:00
ptitSeb 389c803929 [ELFLOADER] Fixed loading of elf with huge alignment 2023-11-01 20:13:53 +01:00
ptitSeb 08d8407056 [ELFLOADER] Last improvment to elfloader memory managment, should be good now 2023-11-01 18:13:34 +01:00
ptitSeb 3f12bde9ff [ELFLOADER] Even more improvment to elfloader memory managment 2023-11-01 16:14:05 +01:00
ptitSeb a47a9d95d7 [ELFLOADER] Some more improvment to elfloader memory managment 2023-11-01 14:35:03 +01:00
ptitSeb f2a4125ab8 [ELFLOADER] Changed how memory is managed in elfloader 2023-10-31 16:37:59 +01:00
ptitSeb 2d3f244935 [DYNAREC] Fixed issue with aes-ni extension when aes is not supported in hardware 2023-10-31 10:17:12 +01:00
ptitSeb 2a1342c5b3 [ARM] Check if PMULL is available before using it 2023-10-30 14:30:56 +01:00
ptitSeb 82bf0a99d2 Fixed intepreter for 66 0F 3A 44 opcode on x86 2023-10-29 14:00:19 +01:00
ptitSeb c6275bcb62 Added AES-NI and PCLMULQDQ support 2023-10-29 12:25:02 +01:00
ptitSeb 7a175a9733 Improve CPU detection and printing (backported from box64) 2023-10-28 18:54:43 +02:00
ptitSeb 75759f9ba7 [DYNAREC] Use precise method for FPREM/FPREM1 opcodes 2023-10-18 11:10:17 +02:00
ptitSeb 6f966fe468 Rollback to previous way of handling tls key destructors (was breaking steam) 2023-10-16 12:40:07 +02:00
ptitSeb f716212932 Added BOX86_MUTEX_ALIGNED to use pthread_mutext_t as-is 2023-10-15 16:54:46 +02:00
ptitSeb 4b1b214663 [ANDROID] Second try to fix build 2023-10-15 16:52:04 +02:00
ptitSeb 5e7a7db60d [ANDROID] Try to fix build 2023-10-15 16:17:31 +02:00
ptitSeb 968da3a4d4 Simplify handling of pthread_cleanup push/pop handling, and tls destructor (backported from box64) 2023-10-15 15:56:46 +02:00
ptitSeb 347c645e95 Update README.md 2023-10-14 08:44:19 +02:00
ptitSeb e50f152355 Update README.md 2023-10-14 08:43:48 +02:00
ptitSeb 59f85c8fbb Update README.md 2023-10-14 08:42:46 +02:00
ptitSeb 9fbab85232 Refreshed README.md 2023-10-14 08:36:36 +02:00
ptitSeb a0a3389651 Added BOX86_SDL2_JGUID, a workaround for game using old SDL_GetJoystickGUIDInfo funciton on recent wrapped SDL2 (backported from box64) 2023-10-11 12:20:47 +02:00
ptitSeb 6e51e73a1e Updated and improved SDL_GetJoystickGUIDInfo wrapped function (backported from box64, for newer SDL2) 2023-10-10 17:49:33 +02:00
ptitSeb 35e64fd56c Added a few more wrapped symbols to libc (for #876) 2023-10-08 19:21:51 +02:00
ptitSeb 402496c93e Improved cpu speed detection 2023-10-07 11:58:38 +02:00
ptitSeb 84d415c211 Fixed wrapping of fstatat for non-Android build 2023-10-07 09:25:56 +02:00
KreitinnSoftware 020b2ba8d0 Add fstatat, use --image-base instead of -Ttext-segment on Clang, and Fix PreInit Array Warning for Android (#874)
* Use --image-base instead of -Ttext-segment on Clang Compilers

* Add fstatat

* [ANDROID] Fix PreInit Array Warning
2023-10-07 09:22:29 +02:00
KreitinnSoftware 2890c05fba [ANDROID] Remove PreInit Array Warning and Fixed libc name when called by libdl (#871) 2023-09-30 22:07:35 +02:00
KreitinnSoftware 829d39f8a3 [ANDROID] Fix libdl.so name (#869) 2023-09-30 21:12:44 +02:00
ptitSeb 197cdafa22 [ANDROID] Fix build 2023-09-30 20:35:00 +02:00
ptitSeb aa75d5a434 [ANDROID] No mallochack on Android 2023-09-30 20:20:12 +02:00
KreitinnSoftware 38b8d9b8a5 [ANDROID] Fix Most Library Names (#868) 2023-09-30 19:48:26 +02:00
ptitSeb a1091a9a72 [DYNAREC] Fixed a warning 2023-09-30 18:16:15 +02:00
ptitSeb 8d1561f6e5 Added a few more wrapped function to libgssapi_krb5 (for wine) 2023-09-30 15:40:42 +02:00
ptitSeb 375bc45b51 Try to fix i386 build 2023-09-30 09:59:08 +02:00
ptitSeb 334b891364 Added 64/65 20 and 64/65 88 opcodes ([DYNAREC] too) (for #857) 2023-09-30 09:55:39 +02:00
ptitSeb a8f3d57afb [DYNAREC] Disabled use of custom mutex for now (should help #823) 2023-09-30 09:37:47 +02:00
ptitSeb 3023c8262d [DYNAREC] Fixed typo with dec8 emitter 2023-09-27 11:30:53 +02:00
ptitSeb bc166ae3b3 [ELFLOADER] Fixed R_386_TLS_TPOFF32 reloc (fixed FEZ, probably many other too) 2023-09-26 21:09:27 +02:00
ptitSeb 4e29df8a56 Added ADLink AmpereAltra profile 2023-09-25 19:45:58 +08:00
Jai A P e24c1f048b Update README.md 2023-09-17 19:11:46 +01:00
ptitSeb daef5cbdc9 Added 1 vk extension 2023-09-03 14:06:05 +02:00
ptitSeb 699af54183 [ANDROID] Do not set ASM flags for ARM_DYNAREC on Android 2023-09-02 12:44:22 +02:00
ptitSeb 731d9a249d [ANDROID] Try to use longjmp/setjmp correctly 2023-09-02 12:38:28 +02:00
ptitSeb 3e67c4573b Fixed build 2023-09-02 12:25:17 +02:00
ptitSeb ef25a75b86 [ANDROID] This should fix Dynarec build on Android 2023-09-02 12:16:40 +02:00
ptitSeb c4b182048c [ANDROID] Enable Dynarec on CI Android build 2023-09-02 11:15:28 +02:00
ptitSeb 6079f39655 [DYNAREC] Added a DMB_ISH before fetching jmp address (helps Bastion, probably other too) 2023-08-27 17:13:47 +02:00
ptitSeb 2dcd2741c7 [PANDORA] Emit nothing for DMB_ISH as it's single core 2023-08-27 16:53:44 +02:00
ptitSeb 399b2c7f8a [ELFLOADER] Improved handling of dlopen local lib (helps Half-Life, Garry's Mod, and probably many other) 2023-08-26 16:26:30 +02:00
ptitSeb 7ae3200c6f [TRACE] Added from with function name in dlopen trace 2023-08-26 15:13:15 +02:00
ptitSeb 299ddb22a5 [TRACE] Added stack top function name decoding when applicable 2023-08-26 15:12:49 +02:00
ptitSeb df8930a78a [ANDROID] Try to fix build 2023-08-26 11:10:26 +02:00
ptitSeb a37cd0bd91 Fixed detection and loadig of program linked with glibc 2.34+ 2023-08-26 10:27:36 +02:00
ptitSeb ee10226614 [ELFLOADER] This was missing with the last elfloader update 2023-08-24 17:11:04 +02:00
ptitSeb ad934455c1 Removed unused function 2023-08-20 15:01:58 +02:00
ptitSeb c0e7062b03 Refactored how wrapped symbols are fetch and stored 2023-08-20 14:58:36 +02:00
ptitSeb 04d03af8ac Start of a new dev. cycle 2023-08-20 14:58:11 +02:00
ptitSeb 32accd0e77 Hotfix for steam not launching when libudev1 is wrapped 2023-08-19 19:07:30 +02:00
ptitSeb c4b3fc25e0 Bumped to version 0.3.2 2023-08-19 17:17:47 +02:00
ptitSeb 676b02b5aa Added a profile to fix PixelJunk Shooter linux version 2023-08-19 17:15:31 +02:00
ptitSeb 3c8e34f691 Removed a debug leftover 2023-08-19 16:39:06 +02:00
ptitSeb 630f42e9e2 [ELFLOADER] Adjusted fetching of symbol 2023-08-19 16:36:15 +02:00
ptitSeb 58b0338dff Fixed wrapped __gmp_get_memory_functions and added __gmp_set_memory_functions 2023-08-18 21:28:39 +02:00
ptitSeb 80c77bad96 Added 2 structures to vkalign 2023-08-15 18:14:36 +02:00
ptitSeb 771ff1b2e2 Added many wrapped symbols to libgmp (for Steam beta client) 2023-08-15 10:41:06 +02:00
ptitSeb cef87f7f7d Fixed a few warning 2023-08-15 10:37:56 +02:00
ptitSeb e8d4ffc782 [DYNAREC] Fixed 0F 52/53 opcodes (for #848) 2023-07-31 15:37:32 +02:00
ptitSeb 85397e9895 [DYNAREC] Fixed BOX86_NODYNAREC inside an rcfile 2023-07-31 14:28:20 +02:00
Ilya114 8194ad9728 Update README_CN.md 2023-07-27 13:19:08 +02:00
Ilya114 b82f203a9d Update README.md 2023-07-27 13:19:08 +02:00
Ilya114 151e2ae3a4 Update README_UK.md 2023-07-27 13:08:18 +02:00
Ilya114 0072524d5d Update README_UK.md 2023-07-27 13:08:18 +02:00
Ilya114 949417f412 Update README_CN.md 2023-07-27 13:08:18 +02:00
Ilya114 21fea0f195 Update README.md 2023-07-27 13:08:18 +02:00
Ilya114 9c1317f899 Ukrainian translate of README 2023-07-27 13:08:18 +02:00
ptitSeb 127a48f199 [ELFLOADER] Fixed a potential segfault when resizing tlsdata 2023-07-25 17:29:42 +02:00
ptitSeb 66b8c58cc1 Added some more extensions and structure to wrapped vulkan 2023-07-24 20:49:39 +02:00
ptitSeb 39bb606c06 Some improvment to get UPlay a bit more stable 2023-07-24 19:23:49 +02:00
ptitSeb 626826f33e [DYNAREC] Added a profile for TINTIN.exe to disable BOX86_DAYNREC_FORWARD, that tend go crazy on the obfuscated code 2023-07-23 13:01:26 +02:00
ptitSeb a9082f60b6 [DYNAREC] Improvments to BOX86_DYNAREC_FORWARD handling 2023-07-23 13:00:31 +02:00
ptitSeb 3b394b8f0d Hacked wrapped ptrace to avoid crash when wine handle exception (and debug registers in general) 2023-07-22 20:51:44 +02:00
ptitSeb a108a23c56 [TRACE] Fixed crash when tracing a function that is not defined in main at beggining 2023-07-22 20:51:35 +02:00
rajdakin 51baede9c1 [PRINTER] Fixed the ARM printer
(overwritten warning fix)
2023-07-17 22:20:25 +02:00
rajdakin d601b42ddc [WRAPPERS] Version bump 2023-07-17 22:20:25 +02:00
rajdakin d430332c45 [WRAPPERS] Cleaned up the rebuild_wrappers script 2023-07-17 22:20:25 +02:00
ptitSeb 63fae1b6c8 Another try to fix Android build (I'm considering removing this useless port) 2023-07-16 19:40:50 +02:00
ptitSeb c45d3d80ab Another try to fix Android build 2023-07-16 19:23:49 +02:00
ptitSeb 57e9e95411 Improved a bit my_execv wrapped function 2023-07-16 19:17:20 +02:00
ptitSeb 68fb291c83 Try to fix Android build 2023-07-16 18:39:47 +02:00
ptitSeb f3ee727bc4 Fixed a warning 2023-07-16 18:39:32 +02:00
ptitSeb 21ed47c4cb Added some more libgio2 wrapped symbols 2023-07-16 18:30:33 +02:00
ptitSeb 2147d92d9d Added missing docs in USAGE.md 2023-07-16 18:22:47 +02:00
ptitSeb 1465ff8aad Added BOX86_NOSANDBOX handling 2023-07-16 18:20:46 +02:00
ptitSeb ac895e3dad [ELFLOADER] Major refactor of elfloader, now on par with box64 one 2023-07-16 18:10:22 +02:00
ptitSeb 983a3d9926 Removed useless box86context_t parameter to RunFunction and friend 2023-07-16 14:37:29 +02:00
ptitSeb ecec73547f Added a few wrapped function to libgio2 2023-07-16 14:21:50 +02:00
ptitSeb 6ed82e7f7d Improved BOX64_MALLOC_HACK=2 and the glAleternate mecanism 2023-07-16 14:17:20 +02:00
ptitSeb 83a9b2cab5 Better wrapping for __libc_stack_end symbol 2023-07-16 13:51:45 +02:00
ptitSeb 666e41a0cb Improved wrapping of XextAddDisplay libxext function 2023-07-16 13:48:37 +02:00
ptitSeb c78be09d7f Fixed a few gio2 wrapped function signature 2023-07-16 13:41:48 +02:00
ptitSeb 21023e9802 [DYNAREC] Made dynarec use regular malloc memory for now (changeable with a define) 2023-07-16 13:35:59 +02:00
ptitSeb 38c07f2a2f [DYNAREC] Small improvment to dynarec memory handling 2023-07-16 13:35:11 +02:00
ptitSeb e6d124aed4 Fixed some edge case 16bits opcodes ([DYNAREC] too) 2023-07-16 11:09:35 +02:00
ptitSeb 8335a8c2d9 Added workaround for the still unimplemented PR_CreateIOLayerStub function fpr Garry's Mod 2023-07-15 17:44:24 +02:00
ptitSeb 6f7a513051 [DYNAREC] Better handling if wrapped function that return float/double in x87 register 2023-07-14 14:02:00 +02:00
ptitSeb 43189a2914 [DYNAREC] Fixed an issue with forward jump state retreival 2023-07-14 11:04:59 +02:00
ptitSeb 3bf9e4d989 Added 2 more wrapped function to libsdbus 2023-07-06 15:20:27 +02:00
ptitSeb fe3419957e and converted d3dadapter9 to RunFunctionFmt too 2023-07-04 18:09:17 +02:00
ptitSeb f8c8a5d596 Even more RunFunctionFmt conversions 2023-07-04 18:01:49 +02:00
ptitSeb 9ee7f84015 Finsihed converting wrapped lib to RunFunctionFmt 2023-07-04 16:45:52 +02:00
ptitSeb 36b316746b More wrapped lib converted to RunFunctionFmt 2023-07-04 15:13:49 +02:00
ptitSeb 0131572edf Fixed signature for wrapped vkGetPhysicalDeviceQueueFamilyProperties2 function 2023-07-02 19:08:32 +02:00
ptitSeb d74e873a85 Improved libz wrapping (backported from box64) 2023-07-02 18:31:31 +02:00
ptitSeb be53b823d3 More wrappers conversion to RunFunctionFmt 2023-07-02 18:28:56 +02:00
ptitSeb e5b6c8b6e0 Introduced RunFunctionFmt and started migrating wrapper to use it 2023-07-02 18:19:11 +02:00
ptitSeb ecf7bfd848 Added 4 syscalls (for #842) 2023-07-02 10:11:28 +02:00
ptitSeb 2a7b848d0e Reworked handling of privileged instruction, backported from box64 (|DYNAREC] too) 2023-06-27 17:24:58 +02:00
ptitSeb fa5fa7b5c0 Allow winedbg to run with undocumented BOX86_WINDBG (but it will not work, except for the backtrace) 2023-06-24 18:01:05 +02:00
ptitSeb b7283b8d9d Added 1 Vulkan extension 2023-06-24 17:58:56 +02:00
ptitSeb b8d72023c5 Try to improve custom memory allocator 2023-06-24 17:58:15 +02:00
ptitSeb e10a710591 Added another function to wrapped SDL2 (for #836) 2023-06-23 18:25:06 +02:00
ptitSeb 9ee030a566 Added 1 more function to wrapped SDL2 (for #836) 2023-06-23 16:42:10 +02:00
ptitSeb a8e96764b5 Fixed some warnings 2023-06-23 15:22:26 +02:00
ptitSeb c43f1d882c Fixed segment order in x86 emulator 2023-06-23 15:22:09 +02:00
ptitSeb 1e67cefc43 Added 1 wrapped function to recent SDL2 (for #836, but might need a recent native SDL2 lib) 2023-06-23 15:20:45 +02:00
ptitSeb 5cdc1b9fa2 Allow running at NULL, and trigger a segfault (for #830) 2023-06-07 09:49:49 +02:00
ptitSeb ab75a3e2d3 Added a few wrapped function to libgcrypt and libgnutls (for wine) 2023-06-05 10:05:40 +02:00
ptitSeb 21d097853b [ELF_LOAD] Also use SONAME of loaded elf to match loaded libs 2023-06-04 13:01:38 +02:00
ptitSeb 2e3bdbefc7 Added 1 more structure to vkalign 2023-06-04 12:57:36 +02:00
澪 a19773cfb0 fix typo 2023-06-03 16:32:18 +02:00
ptitSeb 1988eb0366 [DYNAREC] Do not track memory that is not accessible (should save some memory) 2023-05-28 14:37:26 +02:00
ptitSeb 54d5aaa11d Added partial support to TF flags ([DYNAREC] too) (Helps #671 and uplay) 2023-05-24 19:33:36 +02:00
ptitSeb 205ec1f4dc [DYNAREC] Free jmptable memory when destroying DB 2023-05-19 18:47:54 +02:00
Ilya114 005367ea3c -noreactlogin deleted from Steam 2023-05-16 13:43:01 +02:00
ptitSeb 8ac9bc30a2 Added memfd_create to wrapped libc 2023-05-15 20:20:02 +02:00
ptitSeb f0691e56fc Added more bits to CPUID, and 0F AE /7 opcode ([DYNAREC] too) (for Burning Paradise) 2023-05-13 18:42:46 +02:00
ptitSeb bc06c277ec This make disblaed code clearer 2023-05-13 18:12:03 +02:00
ptitSeb 1341a4a55f Optimized Exit bridge managment 2023-05-10 17:29:25 +02:00
ptitSeb 82cf77b9d9 Improved custom memory allocator 2023-05-10 17:29:25 +02:00
ptitSeb 10db79df4a Fixed a nasty small memory leak 2023-05-10 17:29:25 +02:00
ptitSeb bce188e217 [DYNAREC] Removed all remaining trace of dynablocklist_t 2023-05-10 17:29:25 +02:00
ptitSeb 220a64af1f Added some more libgstreamer wrapped functions 2023-05-10 17:29:25 +02:00
ptitSeb e73fa8f3fb [DYNAREC] Fixed some remaining issues (PvZ works now) 2023-05-10 17:29:25 +02:00
ptitSeb 053a75f5d5 [DYNAREC] Removed DynablockList, backported from Box64 (PvZ broken for now) 2023-05-10 17:29:25 +02:00
ptitSeb bcb19dbe5d Improved fpu_fxsave/fpu_fxrstor 2023-05-08 13:30:10 +02:00
ptitSeb 039c62f740 [DYNAREC] Removed dynablocks sons handling, it makes things compicated for not enough benefits (fixed GoG Windows installers) 2023-05-04 21:30:07 +02:00
ptitSeb 7663aacd1b Added some Hack for wine int 2d calls 2023-05-04 21:28:41 +02:00
ptitSeb fd5bf804ec [DYNAREC] Slightly better handling of dynablock getting dirty during signal 2023-05-04 17:26:28 +02:00
ptitSeb 70d18cfb7c [DYNAREC] Slightly better signal handling for running dynablock getting dirty durring signal 2023-05-04 17:25:40 +02:00
ptitSeb 1e32ccc9c7 Try to fix a wine error message 2023-05-04 17:24:56 +02:00
ptitSeb 23fa99d148 [DYNAREC_TEST] Fixed 0F AE opcodes handling 2023-05-04 17:23:58 +02:00
josch 0e3ce6d8b1 add NO_LIB_INSTALL and NO_CONF_INSTALL (#822)
This adds commits 6ff68849f88cbec622fe7a485e301111319ab8d6 and
53687387ebca091043cecbfc2d99494865336b94 from box64.

This allows installation of box86 without any configuration files or
libraries involved. Intended usecases are

 * packaging box86 with multiple variants in one package, where multiple
   variants would step on each other during installation.
 * packaging box86 for distributions shipping their own armhf shared
   library versions of libc and c++ (for example via multiarch)
2023-05-03 21:43:16 +02:00
ptitSeb 970384559f [DYNAREC] Another fix for DYNAEC_TEST 2023-05-01 09:42:59 +02:00
ptitSeb 2f8a939485 [DYNAREC] Some more improvement to DYNAREC_TEST to avoid some false-positive 2023-04-30 19:05:45 +02:00
ptitSeb 4f13c33628 [DYNAREC] Various small improvement for DYNAREC_TEST and DYNARCE_X87DOUBLE 2023-04-30 12:21:44 +02:00
ptitSeb 4ef5da404c Small optimto some float 66 0F opcodes 2023-04-30 11:02:08 +02:00
ptitSeb 15fa9f687c [DYNAREC] Added fastnan=0 handling for MINPS/MAXPS opcodes 2023-04-30 11:00:42 +02:00
ptitSeb 331e5700a2 [DYNAREC] Fixed DYAREC_TEST false-positive when opcode use NOTEST and next opcode found a difference 2023-04-30 11:00:14 +02:00
ptitSeb 1411d44b51 [DYNAREC] Backported DYNAREC_TEST to compare dynarec vs interpreter state 2023-04-29 19:30:35 +02:00
ptitSeb bf53a76223 [INTERPRETER] Reverted the label jumtables and go back to classic switch/case, and prepare for TEST_DYNAREC too 2023-04-29 14:14:37 +02:00
ptitSeb ecbc1e6642 Small improment on x87 interpreter 2023-04-29 10:07:29 +02:00
ptitSeb 7dc5b501f3 Fixed regression on wrapped libGL 2023-04-29 09:13:37 +02:00
ptitSeb af67f69ee2 Refactored libgL symbol fetching (backported from box64) 2023-04-23 17:39:18 +02:00
ptitSeb 8f2a4ea880 Added 1 libatk wrapped function 2023-04-23 17:02:07 +02:00
ptitSeb eb44fd62fb Added more gstvideo wrapped function and fixed wrapped gst_pad_set_getrange_function_full callback (for #815 and #811) 2023-04-19 11:43:13 +02:00
ptitSeb 46f015da9d Added 1 gtk2 function 2023-04-19 10:33:22 +02:00
ptitSeb 705414a3d0 [DYNAREC] Reorganized pass3 to reduce size of box binary and lower compilation time 2023-04-15 09:20:04 +02:00
Ryan Fortner 4591d337cb add missing \ to debian rules (#812) 2023-04-09 22:22:24 +02:00
ptitSeb 54e13be02a Added some more gstreamer wrapped function (for #811) 2023-04-09 09:53:15 +02:00
ptitSeb 1524e883cd Added 0F 08 opcode 2023-04-08 17:02:33 +02:00
ptitSeb 7a65bd60e9 Added 66 0F 07 opcode 2023-04-08 16:58:32 +02:00
ptitSeb 8c1694e530 Added 0F 01/02/03/05/06/07 opcodes 2023-04-08 16:56:51 +02:00
ptitSeb 292d1455b6 Added 66 0F 2B MOVNTPD opcode ([DYNAREC] too) 2023-04-08 16:34:57 +02:00
ptitSeb 9c69702011 Fixed various rounding error in interpreter 2023-04-08 16:26:10 +02:00
ptitSeb 3554d6decb Added 66 0F 38 06 opcode 2023-04-08 15:28:48 +02:00
ptitSeb 7fb36acf85 Added libfuse support, and so appimage support (back ported from box64) 2023-04-06 21:09:33 +02:00
ptitSeb ed3296978e [DYNAREC] Never protect bridge memory (improve Steam stability a lot) 2023-04-02 18:44:44 +02:00
Jai A P 4b212f91bf Latest Batch of PKGBUILDS (#804)
* Latest Batch of PKGBUILDS

* Fix

* Fix
2023-03-31 14:33:50 +02:00
wannacu 94f451c4b7 Add a tool to generate wrapping library (#803)
This tool will automatically generate part of the wrapping library, certainly to avoid a lot of manual writing
hoping to bring some help.
2023-03-30 09:57:06 +02:00
ptitSeb 13bbf105ad Better wrapping for syscall 102 2023-03-23 10:36:54 +01:00
ptitSeb 3eb16fb7bd Wrapped __isoc99_swscanf libc function 2023-03-23 10:36:39 +01:00
wannacu e85bcb671a Fix libjpeg62 wrapping error (#793) 2023-03-23 08:06:28 +01:00
Sevan Janiyan 1a0888ca51 docs/COMPILE.md: Use trusted.gpg.d (#792)
add-key(8) is deprecated and causes warnings to be reported when running apt-get update after adding the repo.
2023-03-22 18:27:50 +01:00
Sevan Janiyan 3043f5066f install_steam.sh: More deps (#790)
Needed to get steam started.
2023-03-21 08:26:15 +01:00
ptitSeb b3b55d2d74 [DYNAREC] Fixed a potential issue when Neon Cache is converted and contains both single and double (quad) elements (for #789) 2023-03-19 16:31:29 +01:00
ptitSeb 58426cbfb6 [DYNAREC] Roolback previous commit and do a better one (still for #789, probably others too) 2023-03-18 18:57:27 +01:00
ptitSeb 4a88ff38ea [DYNAREC] Fixed a type in a SSE2 helper function (should help #789, probably others too) 2023-03-18 18:44:38 +01:00
ptitSeb 8d96ff02e3 Added a few wrapped function to libgio2 2023-03-18 18:43:50 +01:00
Alex eaa6ecb9cc steam: install mesa for armhf if present for arm64 (#786)
* steam: install mesa for armhf if present for arm64

* fix a copy-pasting issue
2023-03-14 16:06:54 +01:00
Alex 027909bddc steam: install additional libraries to suppress wrong ELF class errors (#784) 2023-03-14 15:29:51 +01:00
ptitSeb 0eca6a8b94 [DYNAREC] Fix some potential issue in the next jump handling 2023-03-12 18:12:30 +01:00
ptitSeb 24494ba143 Don't quit on unsupported (non-libc) syscalls (for #782) 2023-03-12 12:26:52 +01:00
ptitSeb a813321ad4 Start of a new dev. cycle 2023-03-12 12:00:22 +01:00
Fancy2209 a43884ff66 Fix ARM64 Compile Instructions (#779)
CMake needs it to be -DARM64=1 from my experience at least
2023-03-10 21:30:29 +01:00
Ryan Fortner 27b269f53a add -dnogit=1 flag to debian rules (#778) 2023-03-10 20:16:18 +01:00
ptitSeb d698861478 Bumped to v0.3.0 2023-03-10 17:09:12 +01:00
wannacu be02c88792 Fix some wrapping error (#777) 2023-03-09 08:52:18 +01:00
wannacu 99059ffb19 Fix some errors (#776)
* Fix some wrapping error

* Fix multithreading error
2023-03-08 12:17:54 +01:00
ptitSeb a4752afacf [DYNAREC] Added BOX86_DYNAREC_FORWARD parameter, with a default value to 128 (unfortunatly, it doesn't seems to help performances much on box86) 2023-03-07 22:02:59 +01:00
ptitSeb a320c37681 Removed ONCE optim in gtkclass (fixed regression on Kega-Fusion) 2023-03-07 13:15:30 +01:00
ptitSeb 42a9a40ac4 Added some special case to the CPU Name grabbing 2023-03-06 18:39:32 +01:00
ptitSeb 6320a07d17 Fixed cpu name extraction for big.LITTLE configurations 2023-03-06 14:33:20 +01:00
ptitSeb 5e251cf478 [CI] Ubuntu 18 is deprecated, moved to 20 2023-03-06 14:24:53 +01:00
ptitSeb 355a2fa8e5 [DYNAREC] Put box86 dynarec and cpu info on the same line 2023-03-06 14:19:06 +01:00
ptitSeb 78ed9d07f2 Change branding of Cpu to refect Box86 and the cpu it's running on 2023-03-06 14:10:10 +01:00
ptitSeb 8c38d5dd36 Forcing BAD_SIGNAL for RK3588 config 2023-03-06 10:40:58 +01:00
wannacu f682ca6bf0 Fix some wrapping error (#771) 2023-03-06 10:07:59 +01:00
ptitSeb 70a2a2dd1b Made the Signal workaround more generic, so it can be used by Termux user 2023-03-05 20:58:33 +01:00
ptitSeb 3678f44945 [README] Fixed the Steam section according the latest Valve changes 2023-03-05 20:48:33 +01:00
ptitSeb 5bb473158b Added wrapped libibus and a few other libgtk fixed 2023-03-04 13:09:38 +01:00
ptitSeb 3f549749c1 Improved install_steam script a bit 2023-03-04 13:08:18 +01:00
ptitSeb 11535dabe0 [RK3588] fixed build 2023-02-26 09:51:00 +01:00
ptitSeb 1c2d36f98a [RK3588] Added a Signal workaround specific to RK3588 (because of old/hacked Kernel) 2023-02-26 09:49:36 +01:00
ptitSeb 8563ba8b70 Forgot an essencial part in RK3588 and generic ARM64 compile profile 2023-02-24 18:08:31 +01:00
ptitSeb 4b43da2081 Added RK3588 and generic ARM64 compile profile 2023-02-24 18:02:29 +01:00
ptitSeb 49c650781f [TRACE] Fixed a regression on BOX86_TRACE that was not working as intended 2023-02-22 20:36:27 +01:00
ptitSeb 36e5bf731c [D3DADAPTER9] Added support for CreateDeviceEx 2023-02-22 14:59:34 +01:00
ptitSeb f4d4116590 libssl depends on libcrypto 2023-02-22 14:37:37 +01:00
ptitSeb 11281589e0 Some fixes for program using __sprintf_chk and __vsnprintf_chk 2023-02-22 14:37:13 +01:00
ptitSeb 756811a901 [DYNAREC] Small optim on F3 0F 70 opcode 2023-02-22 14:36:18 +01:00
ptitSeb dd405c7c49 Added some more wrapped functions to gstreamer and gsttag 2023-02-19 15:13:15 +01:00
ptitSeb 20237019e4 Improved convertion to/from 80bits double, and added BOX86_X87_NO80BITS to not handle them 2023-02-19 14:51:54 +01:00
ptitSeb 7682cdce57 [DYNAREC] Small improvment in jmp/ret 2023-02-15 10:50:26 +01:00
ptitSeb 1dcac1b868 Added 64 87 opcode 2023-02-14 18:24:13 +01:00
ptitSeb 5f0add0e82 [DYNAREC] Don't forget to Cancel the block itself before bailling out of a failled FillBlock 2023-02-14 14:58:02 +01:00
ptitSeb 8f2ef48e25 Merge pull request #758 from rajdakin/master
Bug and warning fixes
2023-02-13 18:05:05 +01:00
rajdakin 4f98f568a7 Fixed the getline return type in libc 2023-02-13 17:52:17 +01:00
rajdakin 0e0e346e45 Fixed nearly all GCC warnings (-Wall -Wextra) 2023-02-13 14:56:28 +01:00
rajdakin 4388092f11 Fixed some copy-paste issues and save_fpreg/load_fpreg 2023-02-13 14:55:59 +01:00
ptitSeb b83c693192 Fixed a small issue on previous commit 2023-02-13 13:24:41 +01:00
ptitSeb 9de1bd884f Fixed another minor warnings 2023-02-13 10:20:36 +01:00
ptitSeb 1b462b8200 Fixed some minor warnings 2023-02-13 10:14:22 +01:00
ptitSeb d7c75be001 Various small (or less small) fixes 2023-02-12 19:16:54 +01:00
ptitSeb 957fcc2449 Fix non-dynarec builds 2023-02-12 17:52:05 +01:00
ptitSeb 328794e4d6 Fixed wrapped fcnt syscall 2023-02-12 17:15:03 +01:00
ptitSeb af519f6046 Small improvment for emu thread tracking (will help #728) 2023-02-12 17:05:27 +01:00
ptitSeb fa9a059921 [DYNAREC] Create empty block instead of NULL for blocks in forbidden zone (to not try to create a block again) 2023-02-12 16:46:05 +01:00
ptitSeb 771d65dc10 [DYNAREC] Better handling of Signal while Fillblock is running 2023-02-12 16:45:08 +01:00
ptitSeb 1dc92c216f [TRACE] Fixed printing of details of pthread_mutex_lock call in LOG=2 2023-02-12 16:41:27 +01:00
ptitSeb db4ff551cc [DYNAREC] Remove a debug leftover 2023-02-12 12:04:58 +01:00
ptitSeb 7abb9a1893 [DYNAREC] Better way to not UpdateFlags when only X_PEND is used 2023-02-12 11:52:06 +01:00
ptitSeb 60f987ff90 [DYNAREC] Use Dynarec in signal if it seems safe (no SIGSEGV and no dynarec mutex) 2023-02-11 21:53:39 +01:00
ptitSeb f38d122b67 [DYNARCE] Free dynablocklists when possible 2023-02-11 21:52:33 +01:00
ptitSeb a654193f1d Added some more function to wrapped libgcrypt.so 2023-02-11 20:06:47 +01:00
ptitSeb 632a01dbe6 [DYNAREC] Use custom mutex, and improved atomic handling 2023-02-11 17:19:05 +01:00
ptitSeb ae2e3aed0f [DYNAREC] Don't UpdateFlags if only X_PEND is used 2023-02-11 17:04:20 +01:00
ptitSeb 244b273250 Added RPI3ARM64 config in CMakeFile project (and fixed COMPILE.md about it) 2023-02-10 15:11:29 +01:00
ptitSeb 27756113ef Added ODROID N2/N2+ Compile instructions (for #755) 2023-02-03 16:27:35 +01:00
ptitSeb d550293ccc Added wrapped libXpresent.so.1 (backported from box64) 2023-01-29 22:27:42 +01:00
ptitSeb 74bb2e84f2 More work on vulkan wrapper 2023-01-29 22:27:42 +01:00
ptitSeb 09d2b067b5 Added some more vulkan structure alignment hint 2023-01-29 22:27:42 +01:00
ptitSeb 6d7f901167 Fixed test on i386 platforms 2023-01-29 19:12:10 +01:00
ptitSeb bdc839ef87 More work on sse opcode and testing ([DYNAREC] too) 2023-01-29 18:39:30 +01:00
ptitSeb 52f7e89fdb A few more improvment to SSE convert to int functions and tests 2023-01-29 17:12:08 +01:00
ptitSeb 6a2b45ec5c [DYNAREC] Small optim on x87 convert to int opcodes 2023-01-29 17:11:44 +01:00
ptitSeb ac0fd0278b More precise flost/double -> int SSE conversion 2023-01-29 16:42:23 +01:00
ptitSeb db06cec325 Improved precision for SSE rounding ([DYNAREC] too, with BOX86_DYNAREC_FASTROUND to control it) 2023-01-29 15:40:48 +01:00
ptitSeb d93e7f92f2 [DYNAREC] Improved Strong Memory Model emulation 2023-01-29 10:59:52 +01:00
ptitSeb d8e94908ff Added a couple of extension to libGL wrapper 2023-01-29 10:50:49 +01:00
ptitSeb 8e9d31e670 Improved wrapping of VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO structure for wrapped Vulkan 2023-01-29 10:47:24 +01:00
ptitSeb 6ed7bbdb21 Fix regression on readdir wrapped function (fixes unreal / ut99 not loading) 2023-01-29 10:46:39 +01:00
ptitSeb 8338ebaa46 [RCFILE] Disable the BOX86_PREFER_EMULATED for hl2_linux, the emulated sdl2 seems to have mouse issue with current box86 2023-01-28 11:35:03 +01:00
ptitSeb d4c08eb083 [DYNAREC] Fixed 65 D1 /2 and /3 opcodes (might help #425) 2023-01-28 11:30:40 +01:00
ptitSeb c62dc24155 Merge pull request #756 from q4a/dont-starve
[BOX86RC] add EMULATED_LIBS for dontstarve_steam
2023-01-28 10:18:48 +01:00
Aleksey Komarov f8e2b81160 [BOX86RC] add EMULATED_LIBS for dontstarve_steam
Works with steam versions of Don't Starve and Don't Starve Together
2023-01-28 12:06:44 +03:00
ptitSeb 06b38df650 [RCFILE] Added BOX86_LD_PRELOAD handling 2023-01-28 09:38:18 +01:00
ptitSeb 00e6ed3feb Added commented code, it works better wihtout it but keeping it for reference (linked to #753) 2023-01-23 13:50:23 +01:00
ptitSeb 6ffbacd808 Try to improve tls hadnling(for some old java distrib for #753) 2023-01-23 13:49:34 +01:00
ptitSeb 8e88ca6985 Added some more wrapped function to libfontconfig and libxcb (for #755) 2023-01-23 10:57:32 +01:00
ptitSeb ada65fc0da Added 1 more libx11 wrapped function (for #751) 2023-01-22 15:47:44 +01:00
ptitSeb 52002ebc64 Added some workaround for spr_readdir.so lib so it can redirect readdir and friends (for #751) 2023-01-21 13:30:07 +01:00
ptitSeb a3e25e32a4 More deitalled trace for LOG=2 for XDrawImageString function 2023-01-21 13:29:18 +01:00
ptitSeb 8aedf8957e Fixed some issue with readdir and some wrapped libc function (help #751) 2023-01-19 14:37:21 +01:00
ptitSeb db7924e26a Added a few more wrapped libX11 functions (for #751) 2023-01-19 13:55:16 +01:00
ptitSeb 2b2478381a [DYNAREC] Another attempt to force defered flags on FF/4 JMP (for #742) 2023-01-03 13:49:34 +01:00
ptitSeb 59b1e323f7 Fixed some more warning on wrapped libnm, libmimalloc and libtbbmalloc 2023-01-03 12:12:19 +01:00
ptitSeb 31e7957362 Fixed some wrapped libsdl1 warning 2023-01-03 12:08:16 +01:00
ptitSeb 917a9ba11f Fixed some wrapped libx11 warning 2023-01-03 12:07:55 +01:00
ptitSeb 71f6654062 [DYNAREC] Fixed a warning with custommem handling 2023-01-03 12:07:30 +01:00
ptitSeb 5b1670390a Added F2 0F 7D opcode (for #744) 2023-01-03 12:07:03 +01:00
ptitSeb f4999d71f3 [DYNAREC] Try to fix some FF/4 JMP opcode are not propagating proper defered flags need (for #742) 2023-01-03 12:06:14 +01:00
ptitSeb 64f52cb1b9 Added a wrapped function libxi (fixed a crash at steam big picture exit) 2022-12-28 10:50:20 +01:00
ptitSeb 905780e47d Added experimental BOX86_SSE_FLUSHTO0 env. var. 2022-12-28 09:53:50 +01:00
ptitSeb 6f176bceae [DYNAREC] Fixed call_rd helper function, and some optimization to x87/mmx flag handling (helps #740) 2022-12-28 09:49:51 +01:00
ptitSeb 21a8e20b94 Improved BOX86_NODYNAREC handling 2022-12-26 17:22:08 +01:00
ptitSeb 20b2b083f5 Added a few more wrapped function to libm and libgnutls 2022-12-26 10:14:22 +01:00
ptitSeb bfeedef03b [PYRA] Added mojo install hack to PYRA profile too 2022-12-25 16:05:06 +01:00
ptitSeb d42767414d Removed some trace to get bash working fine again 2022-12-25 15:50:31 +01:00
ptitSeb c83f21cc38 Merge pull request #738 from ye-yeshun/master
Add some instructions.
2022-12-22 08:38:09 +01:00
YeshunYe f1ce0668f8 Remove redundant code.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 20e6869e53 add: 0f1c as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 75a3fb0d89 add: 0f1d as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:06 +08:00
YeshunYe 0145c5bb34 add: 0f1e as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
YeshunYe 8e3d0835a2 add: 0f19 as NOP instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
YeshunYe 9fe432ac60 add: 'into' instruction.
Signed-off-by: YeshunYe <[email protected]>
2022-12-22 14:48:05 +08:00
ptitSeb 5e46f8825b Merge pull request #737 from ChisBread/master
Ignore steam dbus warning
2022-12-20 10:14:42 +01:00
ChisBread 359ba4836d Ignore steam dbus warning 2022-12-20 08:44:57 +00:00
ptitSeb fe57003477 Added strange F3 64 F1 opcode (fixed Login screen for DONTFORGET) 2022-12-19 11:40:27 +01:00
ptitSeb 067eb6d7da Fixed a warning 2022-12-18 15:54:49 +01:00
ptitSeb 69ec807d56 Of course Android doesn't have dladdr1 2022-12-18 11:20:25 +01:00
ptitSeb 8462b62c0b Improved handling of dladdr/dladdr1 with wrapped symbol (help NWN movie conversion tool) 2022-12-18 11:06:10 +01:00
ptitSeb 3313d7a158 Added init of lib n PltResolver 2022-12-17 15:54:45 +01:00
ptitSeb 47581ddb50 Added more wrapped function to libgnutls (should helps #732) 2022-12-14 11:43:46 +01:00
ptitSeb ccf1249b24 Added 1 wrapped function to libgnutls (should helps #732) 2022-12-13 23:05:21 +01:00
ptitSeb ebab21f211 Merge pull request #733 from ryanfortner/master
update debian pkg changelog for 0.2.8 release
2022-12-12 18:49:56 +01:00
Ryan Fortner 0de956191b update debian pkg changelog for 0.2.8 release 2022-12-12 12:42:22 -05:00
ptitSeb 1e648aa3d6 Reworked Local/TLS Relocation (helps #641) 2022-12-11 16:46:01 +01:00
ptitSeb 89e5517961 Added hndling of # and z modifier for printf fmt alignment (fixes graphical issues of Borderland 2 / Borderland PreSequel, probably other stuff too) 2022-12-11 12:52:33 +01:00
ptitSeb a4cfa477d6 [RCFILE] Small improvement to BOX86_ROLLING_LOG handling 2022-12-11 12:41:29 +01:00
ptitSeb 66d5fa5ef8 [TRACE] Various small improvment to LOG=2/ROLLING_LOG 2022-12-11 12:40:50 +01:00
ptitSeb cb09b0978a [DYNAREC] Added some precise rounding to 2 SSE opcodes 2022-12-03 16:32:04 +01:00
ptitSeb dbd5e1b565 [RCFILE] Fixed String reading 2022-12-03 14:28:26 +01:00
ptitSeb 66ef165184 Use DynaCall instead of EmuCall for pthread_once callback (speedup some init code= 2022-12-03 13:21:41 +01:00
ptitSeb f92b5851d0 [DYNAREC] Fixed updateProtection 2022-12-03 13:21:09 +01:00
ptitSeb 36b62b9464 [DYNAREC] This was UB on armv7 doc (store re to same reg address with pre-index), so use alternate code for everyone 2022-12-03 10:04:04 +01:00
ptitSeb d867acd295 [BOX86RC] Added some more optimized profiles 2022-12-02 23:56:57 +01:00
ptitSeb f0d525ddcc Fixed a vulkan wrapped function that was not returning it's result 2022-12-02 22:42:22 +01:00
ptitSeb f82ea51a2b [PANDORA] Fix build on CI for Pandora 2022-12-02 22:42:01 +01:00
ptitSeb 1be3d617c7 [DYNAREC] Reworked memory protection tracking, improving stability of JIT+multi-threading programs 2022-12-02 20:06:32 +01:00
ptitSeb 8bc26298a0 [DYNAREC] Protect memory even if MAP_FIXED_NOREPLACE flags was not repected 2022-12-02 18:55:58 +01:00
ptitSeb e6cf41c381 Ignore error relocating data_start, __data_start or __gmon_start__ symbols with R_386_32 type 2022-12-02 18:45:26 +01:00
ptitSeb 657f19d357 Fixed handing of special case BOX86_ROLLING_LOG=1 in rcfile 2022-12-02 14:22:32 +01:00
ptitSeb e681acaf36 Fixed handing of BOX86_ROLLING_LOG in rcfile 2022-12-02 14:18:44 +01:00
ptitSeb 5142245b1f [DYNAREC] Added BOX64_DYNAREC_BLEEDING_EDGE to control detection of MonoBleedingEdge 2022-12-02 11:41:45 +01:00
ptitSeb 6a49000bc5 [DYNAREC] More control over HotPage handling with BOX86_DYNARC_HOTPAGE 2022-12-02 11:19:00 +01:00
ptitSeb 8d06a36508 Added 3 function to wrapped libpng16 2022-12-02 10:46:42 +01:00
ptitSeb f120154675 Merge pull request #729 from Jai-JAP/patch-1
Fix typos in README.md
2022-12-01 14:45:18 +01:00
Jai A P ef84c8a635 Update README.md 2022-12-01 19:05:17 +05:30
ptitSeb 33a2716c43 [DYNAREC] Added HotPage handling (help C# and other JIT/Dynarec program) 2022-12-01 11:56:53 +01:00
ptitSeb 3fcdee46b9 Added hl_linux to box86.box86rc 2022-11-29 18:49:40 +01:00
ptitSeb 8b28872b0e Fixed wrapping of mallinfo (this fixes Garry's Mod missing UI) 2022-11-28 21:32:07 +01:00
ptitSeb 29158238bc Fixed 2 logs when applay trace setting from RCFiles 2022-11-28 19:04:41 +01:00
ptitSeb a0191247b9 Fixed an issue when an entry is found 2 times in RCFiles 2022-11-28 18:36:55 +01:00
ptitSeb f07af5825c Fixed Dynarec non-trace build 2022-11-27 19:06:07 +01:00
ptitSeb fcc5528d77 Added 1 more structure aligment info on vulkan 2022-11-27 18:53:08 +01:00
ptitSeb ab13305bc0 Added box86rc configuration file handling 2022-11-27 18:50:58 +01:00
ptitSeb 61075afbb9 Update release.yml 2022-11-27 10:18:48 +01:00
ptitSeb b4ee108c9c Fixed an issue with grabNCpu function, as getline might use realloc, don't use alloca to allocate initial line (for #728) 2022-11-27 09:42:45 +01:00
ptitSeb e31348b6d5 [DYNAREC] Refactored Strong Memory Model emulation 2022-11-26 20:04:43 +01:00
ptitSeb d76efc849f Merge pull request #727 from Itai-Nelken/patch-1
Docs: Add note about installing the correct package from my apt repo on arm64.
2022-11-24 17:13:35 +01:00
ptitSeb 76700c1dab Fixed alignment issue for pa_sink_info (fixes Steam) (for #726) 2022-11-24 17:11:05 +01:00
ptitSeb 3f58046288 Small trace improvment for new x86emu_t structure 2022-11-24 17:09:36 +01:00
ptitSeb 069f488f7b Small optim on bridge brick creation (no need to get an x86emu_t structure) 2022-11-24 17:09:03 +01:00
Itai Nelken 320977d84a Update COMPILE.md 2022-11-24 17:09:24 +02:00
ptitSeb 2e7af32cd9 Improve (non-libc) syscall 2022-11-24 13:56:52 +01:00
ptitSeb c10c86e1d4 Simplified alignment of epoll_event structure 2022-11-23 18:29:39 +01:00
ptitSeb a4bf1d2c72 Improve stack management on signal handler 2022-11-23 18:26:44 +01:00
ptitSeb b3d45c348d Added wrapped libcairoobject-2 and a bunch of other gtk related wrapped functions 2022-11-23 18:24:14 +01:00
ptitSeb a4ce2bd549 Start of a new Dev. cycle 2022-11-22 14:00:32 +01:00
948 changed files with 46278 additions and 18039 deletions

No files matched your search

+4 -1
View File
@@ -14,7 +14,7 @@ on:
- GENERIC_ARM
- A64
- GAMESHELL
- ODROID
- ODROIDXU4
- PANDORA
- PHYTIUM
- PYRA
@@ -23,6 +23,9 @@ on:
- RPI4
- RPI4ARM64
- SD845
- SD888
- ADLINK
- PHYTIUM
build_type:
description: 'Build type'
required: true
+11 -11
View File
@@ -27,28 +27,28 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, 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-18.04
os: ubuntu-22.04
- platform: TEGRAX1
type: Trace
os: ubuntu-18.04
os: ubuntu-22.04
- platform: TEGRAX1ARM32
type: Release
os: ubuntu-18.04
os: ubuntu-22.04
- platform: TEGRAX1ARM32
type: Trace
os: ubuntu-18.04
os: ubuntu-22.04
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Environment preparation"
run: |
@@ -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 -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@v2
uses: actions/upload-artifact@v4
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box86
+2 -1
View File
@@ -5,4 +5,5 @@ build*/
src/git_head.h
backup/
box86_update.sh
restore_backup.sh
restore_backup.sh
.cache
+270 -43
View File
@@ -5,33 +5,54 @@ option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
option(RPI3ARM64 "Set to ON if targeting an RaspberryPI3 device with multiarch arm64 and armhf" ${RPI3ARM64})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
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(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
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(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(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})
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(TERMUX "Set to ON if targeting an Android device with Termux" ${TERMUX})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
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 RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A)
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 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 "")
if(RK3588)
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
endif()
if(TERMUX)
set(ANDROID ON CACHE BOOL "")
set(TERMUX_PATH "/data/data/com.termux/files")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
@@ -56,21 +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)
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A))
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.")
@@ -81,6 +110,7 @@ endif()
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp")
elseif(GAMESHELL)
add_definitions(-DGAMESHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
@@ -104,15 +134,20 @@ elseif(RPI4)
add_definitions(-DRPI4)
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(RPI3ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI3ARM64)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(RPI4ARM64)
add_definitions(-DRPI)
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)
@@ -121,6 +156,19 @@ 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)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ADLINK)
add_definitions(-DADLINK)
add_definitions(-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(A64)
add_definitions(-DA64)
add_definitions(-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
@@ -133,6 +181,15 @@ elseif(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(RK3588)
add_definitions(-DRK3588)
add_definitions(-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
add_definitions(-DBAD_SIGNAL)
set(CMAKE_ASM_FLAGS "-pipe -mcpu=cortex-a76.cortex-a55+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ARM64)
add_definitions(-DARM64)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ODROIDN2)
add_definitions(-DODROIDN2)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard)
@@ -145,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)
@@ -153,11 +218,20 @@ elseif(LX2160A)
add_definitions(-DLX2160A)
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ANDROID)
add_definitions(-DANDROID)
elseif(ARM_DYNAREC)
#if DYNAREC is selected alone, without any arch
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
if(NOT ANDROID)
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
endif()
endif()
if(ANDROID)
add_definitions(-DANDROID)
endif()
if(TERMUX)
add_definitions(-DTERMUX)
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
if(POWER9)
@@ -176,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")
@@ -260,6 +340,8 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/tools/box86stack.c"
"${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"
@@ -269,10 +351,8 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/librarian/dictionnary.c"
"${BOX86_ROOT}/src/librarian/symbols.c"
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
"${BOX86_ROOT}/src/emu/x86compstrings.c"
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
"${BOX86_ROOT}/src/emu/x86run660f.c"
"${BOX86_ROOT}/src/emu/x86run_private.c"
"${BOX86_ROOT}/src/emu/x86syscall.c"
"${BOX86_ROOT}/src/emu/x86primop.c"
@@ -280,10 +360,11 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/emu/x86int3.c"
"${BOX86_ROOT}/src/emu/x86tls.c"
"${BOX86_ROOT}/src/emu/x87emu_private.c"
"${BOX86_ROOT}/src/emu/x87run.c"
"${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"
@@ -297,12 +378,42 @@ if(NOT ANDROID)
list(APPEND ELFLOADER_SRC "${BOX86_ROOT}/src/libtools/obstack.c")
endif()
set(INTERPRETER
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run0f.c"
"${BOX86_ROOT}/src/emu/x86run64.c"
"${BOX86_ROOT}/src/emu/x86run640f.c"
"${BOX86_ROOT}/src/emu/x86run6466.c"
"${BOX86_ROOT}/src/emu/x86run6467.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
"${BOX86_ROOT}/src/emu/x86run660f.c"
"${BOX86_ROOT}/src/emu/x86run66d9.c"
"${BOX86_ROOT}/src/emu/x86run66dd.c"
"${BOX86_ROOT}/src/emu/x86run66f20f.c"
"${BOX86_ROOT}/src/emu/x86run67.c"
"${BOX86_ROOT}/src/emu/x86run6766.c"
"${BOX86_ROOT}/src/emu/x86rund8.c"
"${BOX86_ROOT}/src/emu/x86rund9.c"
"${BOX86_ROOT}/src/emu/x86runda.c"
"${BOX86_ROOT}/src/emu/x86rundb.c"
"${BOX86_ROOT}/src/emu/x86rundc.c"
"${BOX86_ROOT}/src/emu/x86rundd.c"
"${BOX86_ROOT}/src/emu/x86runde.c"
"${BOX86_ROOT}/src/emu/x86rundf.c"
"${BOX86_ROOT}/src/emu/x86runf0.c"
"${BOX86_ROOT}/src/emu/x86runf066.c"
"${BOX86_ROOT}/src/emu/x86runf20f.c"
"${BOX86_ROOT}/src/emu/x86runf30f.c"
)
set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibrt.c"
"${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"
@@ -327,6 +438,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedpng16.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxrandr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxpresent.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxext.c"
"${BOX86_ROOT}/src/wrapped/wrappedxinerama.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxfixes.c"
@@ -359,6 +471,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX86_ROOT}/src/wrapped/wrappedalure.c"
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedopencl.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
@@ -408,16 +521,19 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibibus.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator3.c"
"${BOX86_ROOT}/src/wrapped/wrappedayatanaappindicator3.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedgthread2.c"
"${BOX86_ROOT}/src/wrapped/wrappedcairo.c"
"${BOX86_ROOT}/src/wrapped/wrappedcairogobject.c"
"${BOX86_ROOT}/src/wrapped/wrappedpango.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX86_ROOT}/src/wrapped/wrappedgudev1.c"
@@ -462,6 +578,9 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedpcap.c"
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibfuse.c"
"${BOX86_ROOT}/src/wrapped/wrappedatomic.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibpcre.c"
)
if(ANDROID)
list(APPEND WRAPPEDS
@@ -491,7 +610,7 @@ add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
"${BOX86_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "TERMUX" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
@@ -515,7 +634,9 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_jmpnext.c"
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
"${BOX86_ROOT}/src/emu/x86test.c"
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
@@ -563,6 +684,8 @@ if(ARM_DYNAREC)
set_target_properties(arm_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
add_library(arm_pass3 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
add_library(test_interpreter OBJECT ${INTERPRETER})
set_target_properties(test_interpreter PROPERTIES COMPILE_FLAGS "-DTEST_INTERPRETER")
add_dependencies(arm_pass0 WRAPPERS)
add_dependencies(arm_pass1 WRAPPERS)
add_dependencies(arm_pass2 WRAPPERS)
@@ -574,6 +697,7 @@ if(ARM_DYNAREC)
$<TARGET_OBJECTS:arm_pass1>
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
$<TARGET_OBJECTS:test_interpreter>
)
endif()
@@ -583,16 +707,18 @@ if(ARM_DYNAREC)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
DEPENDS dynarec ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
DEPENDS ${ELFLOADER_SRC} ${INTERPRETER} ${WRAPPEDS}
VERBATIM)
endif()
add_library(interpreter OBJECT ${INTERPRETER})
if(BOX86LIB)
#build a static or dynamic lib...
if(BOX86DYNAMIC)
@@ -602,9 +728,13 @@ else()
endif()
if(ARM_DYNAREC)
if(ANDROID)
target_link_libraries(${BOX86} dynarec m dl)
if(TERMUX)
target_link_libraries(${BOX86} dynarec interpreter m dl android-sysv-semaphore android-spawn)
else()
target_link_libraries(${BOX86} dynarec interpreter m dl)
endif()
else()
target_link_libraries(${BOX86} dynarec m dl rt pthread resolv)
target_link_libraries(${BOX86} dynarec interpreter m dl rt pthread resolv)
endif()
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
@@ -624,37 +754,78 @@ add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
if(ANDROID)
if(TERMUX)
target_link_libraries(${BOX86} dynarec interpreter m dl android-complex-math android-sysv-semaphore android-spawn )
else()
target_link_libraries(${BOX86} dynarec interpreter m dl)
endif()
target_link_libraries(${BOX86} c m dl)
else()
#target_link_libraries(${BOX86} c m dl rt pthread resolv)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
target_link_libraries(${BOX86} dynarec interpreter)
else()
target_link_libraries(${BOX86} interpreter)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,--image-base,${BOX86_ELF_ADDRESS}")
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
endif()
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
endif()
else()
target_link_options(${BOX86} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${BOX86} PUBLIC -Wl,--image-base,${BOX86_ELF_ADDRESS})
else()
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
endif()
endif()
endif()
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
if(NOT TERMUX)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
configure_file(system/box86.conf.cmake system/box86.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
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/)
else()
install(TARGETS ${BOX86}
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
endif()
if(NOT NO_CONF_INSTALL)
configure_file(system/box86.conf.cmake system/box86.conf)
if(NOT TERMUX)
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
else()
#install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
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 ${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}${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()
if(NOT TARGET uninstall)
@@ -671,7 +842,11 @@ set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION "Box86 - Linux Userspace x86 Emulator with a twist")
if(TERMUX)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libandroid-sysv-semaphore, libandroid-spawn")
else()
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
endif()
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MAJOR\\s*")
string(REGEX REPLACE "BOX86_MAJOR" "" TEMP_STRING ${TEMP_STRING})
@@ -685,16 +860,29 @@ string(REGEX MATCH "[0-9]" BOX86_REVISION ${TEMP_STRING})
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX86_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${BOX86_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${BOX86_REVISION})
if(NOT TERMUX)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
if(_aarch64 OR _armhf)
endif()
if(_aarch64 OR _armhf OR _arm OR _armv8l)
if(TERMUX)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm")
else()
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
endif()
elseif(_x86_64 OR _x86)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
else()
#probably wrong...
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
endif()
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
if(TERMUX)
set(CPACK_PACKAGING_INSTALL_PREFIX "${TERMUX_PATH}/usr")
endif()
if(NOT TERMUX)
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_${CMAKE_SYSTEM_NAME}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
else()
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Termux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
endif()
INCLUDE(CPack)
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
@@ -784,7 +972,7 @@ add_test(NAME sse COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/$
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0")
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
@@ -801,13 +989,52 @@ add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(NAME multiple_dlopen COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME aes COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endforeach()
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23 -D TEST_OUTPUT=tmpfile23.txt
-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(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)
+127
View File
@@ -1,3 +1,130 @@
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
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* ElfLoader: rework how elf memory is handled
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support for ADLink Ampere Altra
* OS: Added profile to build for Android and Termux.
* => Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
* => Some work also to reduce the memory footprint
-- Sebastien Chevalier <[email protected]> Thu, 15 Dec 2023 17:30:33 -0100
box86 (0.3.2) unstable; urgency=low
* Better syscall handling
* Fixed some wrapped functions, added some others
* Introduced another wrapper helper
* Added some more opcodes
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
* Added support of FASTNAN for some more opcodes
* Reduced memory footprint
* Added BOX86_NOSANDBOX (adds an argument to the command line)
* Added an ukrainian translation
* => Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
box86 (0.3.0) unstable; urgency=low
* Added rcfile handling: box86 now read "/etc/box86.box86rc" and "~/.box86rc" and apply per process parameters
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
* Refactored Strong Memory Model emulation (faster and more accurate)
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
* Improved memory protection tracking and signal handling, again
* More wrapped libs (especially on the gtk familly)
* More wrapped functions
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
* Improved dladdr/dladdr1 wrapped function
* Some fixes to flags handling in the Dynarec on some special cases
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
box86 (0.2.8) unstable; urgency=low
* Wrapped more Vulkan functions, dxvk2.0 now works
* Added support for overridden malloc/free functions
* Improved elf loader
* Improved dlsym handling with RTLD_NEXT
* Added BOX86_DYNAREC_SAFEFLAGS to allow finetuning Dynarec generated code handling of flags accross function calls and returns.
* Added BOX86_BASH to setup x86 bash binary, so shell script can be run in x86 world
* Added BOX86_ROLLING_LOG to have details log only on crash
* Improved TLS Size handling (Unity3D games now works)
* Improved execv family of function to have better box86 integration
* Added a few more wrapped libs, like FAudio
* Improved gtk, SDL2, GL, vulkan (and more) wrapping
* Improved Signal Handling and memory protection traking
* Added some basic support for statically linked program. Thread are not working yet, but memory allocation and file access does.
* add LX2160A config by @lizthegrey in #612
* Grammar and formatting COMPILE.md by @Radiicall in #615
* Update README.md by @everypizza1 in #617
* docs: add instructions for Debian-based Linux by @ryanfortner in #622
* Fix typoes in readme by @ryanfortner in #621
* Various improvements to install_steam.sh by @ryanfortner in #620
* docs: remove unnecessary newline by @ryanfortner in #624
* fix: the first parameter of realpath may be null by @ye-yeshun in #630
* Add 6 wrapped function to libdrm, and 2 to libexpat. by @cjy880927 in #632
* Fix #610 by @rajdakin in #634
* some floating point instructions by @ye-yeshun in #637
* Fix Typo in readme x86_64 -> x86 by @Jai-JAP in #642
* Fix grammar by @Jai-JAP in #645
* Test wine preload by @ptitSeb in #649
* Align address when call mprotect by @wannacu in #651
* Added 66 0F 7D HSUBPD opcode by @wannacu in #652
* add TEGRAX1 and TEGRAX1ARM32 targets on ubuntu-18.04 by @theofficialgman in #654
* automatically install 32 bit libraries if 64 bit OS is detected in install_steam.sh by @Moldytzu in #659
* mention gcc-arm-linux-gnueabihf in compile.md by @Moldytzu in #660
* Add libc6:armhf install to RPi4 aarch64 build info by @WheezyE in #685
* Updated wine install for RPiOS bullseye 32/64bit by @WheezyE in #689
* Add atomic add opcodes by @Trass3r in #695
* steam: disable modern login and pass arguments to client by @Moldytzu in #700
* Modify sizeof(instsize_t) to 1 byte by @liuli0217 in #721
* Add MOV GS:od, AL by @liuli0217 in #722
-- Sebastien Chevalier <[email protected]> Thu, 17 Nov 2022 11:20:33 -0500
box86 (0.2.6) unstable; urgency=low
* Added an option to get generated -NAN on SSE2 operation
+8 -2
View File
@@ -6,7 +6,13 @@
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DARM_DYNAREC=1
-DARM_DYNAREC=1 \
-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
+82
View File
@@ -1,3 +1,85 @@
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
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* ElfLoader: rework how elf memory is handled
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support for ADLink Ampere Altra
* OS: Added profile to build for Android and Termux.
=> Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
=> Some work also to reduce the memory footprint
v0.3.2
======
* Better syscall handling
* Fixed some wrapped functions, added some others
* Introduced another wrapper helper
* Added some more opcodes
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
* Added support of FASTNAN for some more opcodes
* Reduced memory footprint
* Added BOX86_NOSANDBOX (adds an argument to the command line)
* Added an ukrainian translation
=> Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
v0.3.0
======
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
=> Every program can be finetuned, for speed or just to make them work
* Added BOX86_DYNAREC_FORWARD to allow bigger Dynarec block to be build
* Refactored Strong Memory Model emulation (faster and more accurate)
* Box86 now return a custom name for the CPU instal of P4, build with Box86 and the cpu name it's running on
* Improved memory protection tracking and signal handling, again
* More wrapped libs (especially on the gtk familly)
* More wrapped functions
* Added support for CreateDeviceEx in d3dadapter9, for better gallium nine support
* Improved dladdr/dladdr1 wrapped function
* Some fixes to flags handling in the Dynarec on some special cases
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
* Lots of improvment in the Rounding of float & double (Dynarec and Interpretor), and proper handling of denormals when converting to/from 80 bits long double
* Added specific suppport for RK3588 board (needed some hack in signal handling, probably due to the use of a non mainlined kernel)
v0.2.8
======
* Wrapped more vulkan function, dxvk 2.0 now works
+98 -16
View File
@@ -1,16 +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 apt-key add -
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
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
And of course you will need to install much more library to be able to run software and games (like X11, mesa, SDL, pulseaudio...)
## Per-platform compiling instructions
----
#### for Pandora
@@ -52,15 +57,15 @@ _Build box86:armhf on RPiOS 64-bit ARM (aarch64)_
sudo apt install gcc-arm-linux-gnueabihf # building 32-bit ARM code on aarch64 requires this armhf gcc cross-compiler toolchain
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI2ARM64=1` etc for other models)
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI3ARM64=1` for a PI3 model)
make -j2
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
@@ -70,6 +75,22 @@ As most RK3399 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 RK3588 / RK3588S
`mkdir build; cd build; cmake .. -DRK3588=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most RK3588 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.
#### 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`.
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 Tinker Board (1/1S) or RK3288
`mkdir build; cd build; cmake .. -DRK3288=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
@@ -82,11 +103,13 @@ As most Allwinner A64 devices run an AARCH64 OS, you'll need an `armhf` multiarc
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 Snapdragon 845
#### for Snapdragon
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
or
`mkdir build; cd build; cmake .. -DSD888=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Depending how old/recent you SD is. As most Snapdragon devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Phytium
@@ -94,12 +117,31 @@ As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiar
As most Phytium (D2000 or FT2000/4) 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.
#### for ADLink AmpereAltra
`mkdir build; cd build; cmake .. -DADLINK=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j`
As ADLINK AmpereAltra computers 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`.
#### for Other ARM64 64bits Linux platform
`mkdir build; cd build; cmake .. -DARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
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.
#### for Other ARM Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
You can also add `-DBAD_SIGNAL=ON` to the cmake command if you are on Linux Kernel mixed with Android, like on RK3588 or maybe Termux
#### for x86 Linux
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
@@ -125,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.*
@@ -132,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
@@ -145,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.
@@ -161,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 with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`.
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
```
+23 -14
View File
@@ -2,7 +2,7 @@
Linux Userspace x86 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
[View changelog](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) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![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)
@@ -12,9 +12,9 @@ Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems,
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environment).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/). That also means that you will need a 32bits userspace on 64bits OS, like `armhf` on top an ̀`aarch64` 64bits OS.
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/). That also means that you will need a 32bits userspace on 64bits OS, like `armhf` on top an `aarch64` 64bits OS.
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) might be necessary. (Some ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) might be necessary. (Some ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy. (see OpenGL on Android))
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
@@ -28,8 +28,8 @@ Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
> Compilation instructions can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/X86WINE.md)
----
@@ -76,10 +76,19 @@ If you look at a 64bits version of box86, look at [Box64](https://github.com/pti
----
Notes about Box86 configuration
----
Box86 now have configurations files. There are 2 files loaded. `/etc/box4.box86rc` and `~/.box86rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box86 comes with a default file that should be installed for better stability. The file in in `system/box86.box86rc` and should be installed to `/etc/box86.box86rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box86rc` or some game may not function correctly.
Note that the priority is: `~/.box86rc` > `/etc/box86.box86rc` > command line
So, your settings in `~/.box86rc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Running Unity games should generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
@@ -87,15 +96,15 @@ Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA
Notes about Steam
----
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works:
- First problem is Steam crashing after the sign-in window, if you encounter this issue, you may need to add libappindicator. To install it on Debian, run `sudo apt install libappindicator1`.
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm installed. To install it on Debian, run `sudo apt install libnm0`.
Linux Steam's can run now with box86. but you also need box64 for it to completly usable.
It is advised to run steam in the Small mode, as it use the less memory, but steamwebhelper (a 64bits process) will still be loaded even if not used.
The login screen cannot run without steamwebhelper, and will just show a blank windows without box64 properly setup in the system.
File note, Steam will use a lot of memory, and barely fit on system with 4GB of RAM. It will not work anymore on system with less memory (as a workaround, create a swap file, login and check "remember me", the use box64rc to disable steamwebhelper and run only in small mode without swap after the 1st login)
Final note: the Steam BigPicture will work, but also need steamwebhelper (and so box64), and lots of memory. It will not start on system with only 4GB of RAM without swap.
- 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.
- Once open, Steam will only work on "Small Mode" and in "Big Picture", not in the regular "Large Mode". This is because some Steam components used in the browser view are only 64-bit now. So go in the "View" menu and switch to "Small view", else the list will stay empty. Alternatively, Steam can be started in small mode directly by using `+open steam://open/minigameslist` command line arguments.
- 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)
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aforementioned feature, it is safer to add it to your system if you intend to play those games. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
Steam for Windows installs fine but doesn't work yet.
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`.
----
@@ -120,8 +129,8 @@ I want to thank everyone who has contributed to box86 development.
There are many ways to contribute: code, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, icecream95, M-HT
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For their hardware contribution: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/), [AYN](https://www.ayntec.com/)
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
And I also thank the many other people who participated even once in the project.
+2 -2
View File
@@ -2,7 +2,7 @@
Linux用户空间的x86应用模拟器
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![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)
@@ -127,7 +127,7 @@ Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序
以下感谢不分先后:
* 代码贡献:rajdakin, icecream95, M-HT
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 硬件捐赠:[ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
我还要感谢很多人,即使他们只参与了一次本项目。
+138
View File
@@ -0,0 +1,138 @@
![Official logo](img/Box86Logo.png "Official Logo")
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](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)
----
Box86 дозволяє запускати x86 Linux програми (наприклад, ігри) на системах Linux відмінних від x86, наприклад ARM (хост-система має мати 32-розрядний порядок редагування).
Вам *ПОТРІБНА* 32-розрядна підсистема для запуску та створення Box86. Box86 марний лише на 64-розрядних системах. Крім того, вам *ПОТРІБЕН* 32-розрядний інструментарій для створення Box86. Ланцюжок інструментів, який підтримує лише 64-розрядні версії, не компілює Box86, і ви отримаєте помилки (зазвичай на aarch64 ви отримуєте що «-marm» не розпізнається, і вам знадобиться середовище з мультиархітектурою або chroot).
Оскільки Box86 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/). Це також означає, що вам знадобиться 32-бітний простір користувача на 64-бітній ОС, наприклад `armhf` поверх `aarch64` 64-бітної ОС.
Більшість x86-ігор потребують OpenGL, тому на платформах ARM може знадобитися таке рішення, як [gl4es](https://github.com/ptitSeb/gl4es). (Деякі платформи ARM підтримують лише OpenGL ES і/або їх реалізація OpenGL хитра. (див. OpenGL на Android))
Box86 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 5-10 разів, ніж використання лише інтерпретатора. Деякі високорівневі відомості про те, як працює DynaRec, можна знайти [тут](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Багато ігор просто працюють без особливих налаштувань, наприклад: WorldOfGoo, Airline Tycoon Deluxe і FTL. Багато ігор GameMaker Linux також працюють нормально. (є довгий список, серед них UNDERTALE, A Risk of Rain і Cook Serve Delicious). Ігри Unity3D також працюють добре, але вимога OpenGL може бути проблемою на деяких платформах ARM.
Якщо ви серйозно ставитеся до розробки Box86, вам слід встановити ccache та створити Box86 з ним. (Використовуйте, наприклад, ccmake.)
Щоб увімкнути TRACE (тобто скидання в stdout усіх окремих виконаних інструкцій x86 із дампом регістрів), вам також знадобиться [бібліотека Zydis](https://github.com/zyantific/zydis), доступна у вашій системі.
Деякі внутрішні коди операцій x86 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x86primop.c](../src/emu/x86primop.c) для детальної інформації про авторські права.
----
Компіляція/Встановлення
----
> Інструкцію зі складання Box86 можна знайти [тут](COMPILE.md).\
> Інструкцію з встановлення Wine для Box86 можна знайти [тут](X86WINE.md).
----
Ось 6 відео, перші 2 відео – це відео "Airline Tycoon Deluxe" і "Heretic 2", які працюють на GigaHertz OpenPandora (друге використовує Dynarec), а наступні 2 відео – це відео "Bit.Trip.Runner" і "Neverwinter Night", які працюють на ODroid XU4 (без dynarec), а останні 2 відео на Pi4: Shovel Knight (відео від @ITotalJustice) і Freedom Planet (відео від @djazz), також без Dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
Ви можете знайти багато інших відео про Box86 у YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA).
Список сумісності доступний тут: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
Логотип і піктограма зроблені @grayduck, дякую!
Зауважте, що цей проект не слід плутати з [86box](https://github.com/86Box/86Box), гарним емулятором "повної системи", що спеціалізується на ранньому (до відносно недавньому) апаратному забезпеченні ПК.
----
Використання
----
Є кілька змінних середовища для керування поведінкою Box86.
Дивіться [тут](USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
Примітка: Dynarec від Box86 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
----
Історія версій/Журнал змін
----
Історія версій доступна [тут](docs/CHANGELOG.md).
----
Примітки щодо 64-розрядних платформ
----
Оскільки Box86 працює шляхом прямого перекладу викликів функцій із x86 на хост-систему, хост-система (на якій працює Box86) повинна мати 32-розрядні бібліотеки. Box86 не містить 32-біт <-> 64-біт перекладу. Отже, щоб запустити Box86, наприклад, на платформі ARM64, вам потрібно буде зібрати Box86 для 32-бітної ARM, а також потрібно мати chroot з 32-бітними бібліотеками.
Якщо ви дивитесь на 64-розрядну версію box86, подивіться на [Box64](https://github.com/ptitSeb/box64): він може запускати двійкові файли x86_64 на 64-розрядних платформах. Але зауважте, що вам все одно потрібен Box86 (і 32-розрядний chroot) для запуску бінарних файлів x86 (як це також трапляється в реальному Linux x86_64, для запуску якого потрібні бібліотеки x86 і двійковий файл в multiarch).
----
Примітки щодо конфігурації Box86
----
Box86 тепер має конфігураційні файли. Завантажуються 2 файли: `/etc/box4.box86rc` і `~/.box86rc`. Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться на [використання](docs/USAGE.md), щоб дізнатися, які параметри можна використовувати. Box86 поставляється з файлом за замовчуванням, який слід інсталювати для кращої стабільності. Файл знаходиться в `system/box86.box86rc` і має бути встановлено в `/etc/box86.box86rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box86rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box86.box86rc` > командний рядок
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
----
Примітки щодо емуляції ігор Unity
----
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
----
Примітки щодо Steam
----
Linux версія Steam тепер може працювати з Box86, але вам також потрібен Box64, щоб його можна було повністю використовувати.
Рекомендується запускати Steam у small режимі, оскільки він використовує менше пам’яті, але steamwebhelper (64-бітний процес) усе одно завантажуватиметься, навіть якщо він не використовується.
Екран входу не може працювати без steamwebhelper, і буде показувати лише порожні вікна без належного налаштування box64 у системі.
Зауважте, що Steam використовуватиме багато пам’яті та ледве поміститься в систему з 4 ГБ оперативної пам’яті. Він більше не працюватиме в системі з меншим об’ємом пам’яті (як обхідний шлях, створіть файл підкачки, увійдіть і поставте прапорець «запам’ятати мене», використовуйте box64rc, щоб вимкнути steamwebhelper і запускати лише в малому режимі без підкачки після першого входу в систему)
Останнє зауваження: Steam BigPicture працюватиме, але також потрібен steamwebhelper (і box64) і багато пам’яті. Він не запуститься в системі лише з 4 ГБ оперативної пам’яті без файлу підкачки.
- Якщо у вас виникли проблеми зі встановленням Steam, ви можете знайти `install_steam.sh` у кореневій папці сховища box86. Цей простий скрипт завантажить і встановить Steam у вашу домашню папку, а потім створить ярлик steam у `/usr/local/bin` (для цього він запитає дозвіл sudo). Просто використовуйте `steam` для запуску після встановлення. Зауважте, що інсталяція, яка знаходиться в папці Home, працюватиме лише для одного користувача. Не використовуйте цей скрипт, якщо вам потрібна багатокористувацька інсталяція.
- Щоб уникнути повідомлення «libc.so.6 відсутній», ви можете використовувати `STEAMOS=1` і `STEAM_RUNTIME=1` як змінні середовища (воно автоматично з’являється, якщо ви використовували сценарій `install_steam.sh`)
Якщо у вас виникла проблема із запуском Steam (не запускається `steamwebhelper`), вам потрібно запустити Steam за допомогою `-cef-disable-gpu` або `-cef-disable-gpu-compositor`.
----
Примітки щодо Wine
----
Wine тепер підтримується. Інтегровани програми Wine працює як і багато програм та ігор для Windows. Не забувайте, що більшість ігор для Windows використовують Direct3D, для цього може знадобитися повний драйвер OpenGL і якомога більш високий профіль (і gl4es з бекендом ES2 наразі мають проблеми з Wine).
Примітка: якщо ви плануєте використовувати box86 з Wine на Raspberry Pi 3 або ранішої версії, ці моделі використовують ОС за замовчуванням, яка має ядро ​​з розділенням 2/2 (тобто 2G місця для програми користувача та 2 Г місця для ядра). Це несумісно з програмами Wine, яким потрібен доступ до пам’яті > 2 Гб адреси. Тож вам потрібно буде переналаштувати ядро ​​для розділення 3G/1G.
----
Примітки щодо Vulkan
----
Box86 вже використовує Vulkan. Якщо у вашій системі є 32-розрядний драйвер Vulkan, Box86 використовуватиме його за потреби. Профіль 1.0, 1.1, 1.2 і 1.3, з деякими розширеннями, має бути в порядку. DXVK, включаючи 2.0, працює. Я знаю, що деякі демонстраційні версії працюють на Pi4 (демонстраційні версії Sascha Willems для x86 працюють так само, як якщо б створювати безпосередньо на armhf). Зауважте, що драйвер Vulkan для Pi4 наразі НЕ підтримує DXVK (обгортка Wine DirectX->Vulkan). Це не проблема Box86, у драйвері відсутні розширення (підтримка апаратного забезпечення) та кілька інших речей, через які DXVK не працює на pi4. З боку Panfrost, PanVK трохи молодий, і я ще не тестував DXVK з ним.
----
Останнє слово
----
Я хочу подякувати всім, хто зробив внесок у розвиток box86.
Є багато способів зробити свій внесок: код, фінанси, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, icecream95, M-HT
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
* За постійну рекламу Box86: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[Команда TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
І я також дякую багатьом іншим людям, які хоч раз брали участь у проекті.
(Якщо ви використовуєте Box86 у своєму проекті, будь ласка, не забудьте згадати про це!)
+149 -47
View File
@@ -3,20 +3,21 @@ Usage
----
There are many environment variables to control Box86 behaviour.
Env. var with * can also be put inside box64rc files
#### BOX86_LOG
#### BOX86_LOG *
Controls the Verbosity level of the logs
* 0: NONE : No message (except some fatal error). (Default.)
* 1: INFO : Show some minimum log (Example: librairies not found)
* 2: DEBUG : Details a lot of stuff (Example: relocations or functions called).
* 3: DUMP : All DEBUG plus DUMP of all ELF Info (so same as `BOX86_LOG=2 BOX86_DUMP=1`)
#### BOX86_DUMP
#### BOX86_DUMP *
Controls the Dump of elf content
* 0: No dump of elf information (Default)
* 1: Dump elf sections and relocations and other information (also active if using `BOX86_LOG=3`)
#### BOX86_ROLLING_LOG
#### BOX86_ROLLING_LOG *
Show last few wrapped function call when a Signal is caught
* 0: No last function call printed (Default.)
* 1: Last 16 wrapped functions calls printed when a signal is printed. Incompatible with BOX86_LOG>1 (may need BOX86_SHOWSEGV=1 also)
@@ -27,177 +28,263 @@ Disables Box86 printing its version and build
* 0 : Enable printing its banner. (Default.)
* 1 : Disable printing its banner.
#### BOX86_LD_LIBRARY_PATH
#### 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
#### BOX86_PATH *
Path to look for x86 executable. Default is current folder and `bin` in current folder.
#### BOX86_DLSYM_ERROR
#### BOX86_DLSYM_ERROR *
Enables/Disables the logging of `dlsym` errors.
* 0 : Don't log `dlsym` errors. (Default.)
* 1 : Log dlsym errors.
#### BOX86_TRACE_FILE
#### BOX86_TRACE_FILE *
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box86 instance
Use `stderr` to use this instead of default `stdout`
#### BOX86_TRACE
#### BOX86_TRACE *
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
* 0 : No trace. (Default.)
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done.
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found).
* 0xXXXXXXX-0xYYYYYYY : Trace only between the 2 addresses.
#### BOX86_TRACE_INIT
#### BOX86_TRACE_INIT *
Use BOX86_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
* 0 : No trace. (Default.)
* 1 : Trace enabled. The trace start with the initialisation of all depending libraries is done.
#### BOX86_TRACE_START
#### BOX86_TRACE_START *
Only on builds with trace enabled.
* NNNNNNN : Start trace only after NNNNNNNN opcode execute (number is an `uint64_t`).
#### BOX86_TRACE_XMM
#### BOX86_TRACE_XMM *
Only on builds with trace enabled.
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the XMM registers.
#### BOX86_LOAD_ADDR
#### BOX86_TRACE_EMM *
Only on builds with trace enabled.
* 0 : The EMM (i.e. MMX) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the EMM registers.
#### BOX86_LOAD_ADDR *
Try to load at 0xXXXXXX main binary (if binary is a PIE)
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
#### BOX86_NOSIGSEGV
#### BOX86_NOSIGSEGV *
Disable handling of SigSEGV. (Very useful for debugging.)
* 0 : Let the x86 program set sighandler for SEGV (Default.)
* 1 : Disable the handling of SigSEGV.
#### BOX86_NOSIGILL
#### BOX86_NOSIGILL *
Disable handling of SigILL (to ease debugging mainly).
* 0 : Let x86 program set sighandler for Illegal Instruction
* 1 : Disables the handling of SigILL
#### BOX86_X11COLOR16
#### BOX86_X11COLOR16 *
PANDORA only: Try converting X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows).
* 0 : Don't touch X11 colors. (Default.)
* 1 : Change colors arguments in XSetForeground, XSetBackground and XCreateGC.
#### BOX86_X11THREADS
#### BOX86_X11THREADS *
Call XInitThreads when loading X11. (This is mostly for old Loki games with the Loki_Compat library.)
* 0 : Don't force call XInitThreads. (Default.)
* 1 : Call XInitThreads as soon as libX11 is loaded.
#### BOX86_X11GLX
#### BOX86_X11GLX *
Force libX11's GLX extension to be present.
* 0 : Do not force libX11's GLX extension to be present.
* 1 : GLX will always be present when using XQueryExtension. (Default.)
#### BOX86_DYNAREC_DUMP
#### BOX86_DYNAREC_DUMP *
Enables/disables Box86's Dynarec's dump.
* 0 : Disable Dynarec's blocks dump. (Default.)
* 1 : Enable Dynarec's blocks dump.
* 2 : Enable Dynarec's blocks dump with some colors.
#### BOX86_DYNAREC_LOG
#### BOX86_DYNAREC_LOG *
Set the level of DynaRec's logs.
* 0 : NONE : No Logs for DynaRec. (Default.)
* 1 :INFO : Minimum Dynarec Logs (only unimplemented OpCode).
* 2 : DEBUG : Debug Logs for Dynarec (with details on block created / executed).
* 3 : VERBOSE : All of the above plus more.
#### BOX86_DYNAREC
#### BOX86_DYNAREC *
Enables/Disables Box86's Dynarec.
* 0 : Disables Dynarec.
* 1 : Enable Dynarec. (Default.)
#### BOX86_DYNAREC_TRACE
#### BOX86_DYNAREC_TRACE *
Enables/Disables trace for generated code.
* 0 : Disable trace for generated code. (Default.)
* 1 : Enable trace for generated code (like regular Trace, this will slow down the program a lot and generate huge logs).
#### BOX86_NODYNAREC
#### BOX86_NODYNAREC *
Forbid dynablock creation in the interval specified (helpfull for debugging behaviour difference between Dynarec and Interpretor)
* 0xXXXXXXXX-0xYYYYYYYY : define the interval where dynablock cannot start (inclusive-exclusive)
#### BOX86_DYNAREC_BIGBLOCK
#### BOX86_DYNAREC_TEST *
Dynarec will compare it's execution with the interpreter (super slow, only for testing)
* 0 : No comparison
* 1 : Each opcode runs on interepter and on Dynarec, and regs and memory are compared and print if different
#### BOX86_DYNAREC_BIGBLOCK *
Enables/Disables Box86's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps)
#### BOX86_DYNAREC_STRONGMEM
#### BOX86_DYNAREC_FORWARD *
Define Box86's Dynarec max allowed forward value when building Block.
* 0 : No forward value. When current block end, don't try to go further even if there are previous forward jumps
* XXX : Allow up to XXXX bytes of gap when building a Block after the block end to next forward jump (Default: 128)
#### BOX86_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
* 1 : Enable some Memory Barrier when writting to memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : All 1. plus a memory barrier on every write to memory using MOV
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
#### BOX86_DYNAREC_X87DOUBLE
#### BOX86_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (faster, Default)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis were it's enable automatically)
#### BOX86_DYNAREC_FASTNAN
#### BOX86_DYNAREC_FASTNAN *
Enable/Disable generation of -NAN
* 0 : Generate -NAN like on x86 (slower, more x86 accurate)
* 1 : Don't do anything special with NAN, to go as fast as possible (Default)
#### BOX86_DYNAREC_SAFEFLAGS
#### BOX86_DYNAREC_FASTROUND *
Enable/Disable generation of precise x86 rounding
* 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
* 0 : Treat CALL/RET as if it never needs any flags (faster but may have side-effects)
* 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_LIBGL
#### 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
* 0 : Don't detect MonoBleedingEdge
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_DYNAREC_JVM *
Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
#### BOX86_DYNAREC_MISSING *
Dynarec print the missing opcodes
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
* 1 : Will print the missing opcodes
#### BOX86_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
* 1 : Direct apply of SSE Flush to 0 flag
#### BOX86_X87_NO80BITS *
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
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
#### BOX86_SDL2_JGUID *
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
* 0 : Don't use any workaround
* 1 : Use a workaround for program that use the private SDL_GetJoystickGUIDInfo function with 1 missing argument
#### BOX86_MUTEX_ALIGNED *
Will mutex are used as-is or wrapped to handle unaligned used
* 0 : Mutex will be wrapped in case unaligned mutexes are used (Default)
* 1 : Do no wrap mutex and use them as-is (faster, but might crash with SEGBUS error)
#### BOX86_LIBGL *
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
You can also use SDL_VIDEO_GL_DRIVER
#### BOX86_LD_PRELOAD
#### BOX86_LD_PRELOAD *
* XXXX[:YYYYY] force loading XXXX (and YYYY...) libraries with the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary
PreLoaded libs can be emulated or native, and are treated the same way as if they were comming from the binary (not that using this inside a rcfile might not work if the process needs to be renamed, for example for Wine process)
#### BOX86_EMULATED_LIBS
#### BOX86_EMULATED_LIBS *
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSING_LIBS
#### BOX86_ALLOWMISSING_LIBS *
Allow Box86 to continue even if a library is missing (renamed from BOX86_ALLOWMISSINGLIBS).
* 0 : Box86 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_ALLOWMISSING_SYMBOLS
#### BOX86_ALLOWMISSING_SYMBOLS *
Allow dlopen with RTLD_NOW flag to not resolve all symbols.
* 0 : Box86 will stop if a library have unresolved symbols. (Default.)
* 1 : Continue even if a needed library have unresolved symbols (like symbols not yet wrapped).
#### BOX86_PREFER_WRAPPED
#### BOX86_PREFER_WRAPPED *
Box86 will use wrapped libs even if the lib is specified with absolute path
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
* 1 : Use Wrapped native libs even if path is absolute
#### BOX86_PREFER_EMULATED
#### BOX86_PREFER_EMULATED *
Box86 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
#### BOX86_NOPULSE
#### BOX86_NOPULSE *
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
* 1 : Disables the load of pulse audio libraries (libpulse and libpulse-simple), both the native library and the x86 library
#### BOX86_NOGTK
#### BOX86_NOGTK *
Disables the loading of wrapped GTK libraries.
* 0 : Load wrapped GTK libraries if found. (Default.)
* 1 : Disables loading wrapped GTK libraries.
#### BOX86_NOVULKAN
#### BOX86_NOVULKAN *
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)
* 1 : let program use the syscall if the host system support it (Default for other build)
#### BOX86_ENV
* XXX=yyyy
will add XXX=yyyy env. var.
@@ -206,22 +293,27 @@ Disables the load of vulkan libraries.
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX86_FIX_64BIT_INODES
#### 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.)
* 1 : Fix 64bit inodes. Helps when running on Filesystems with 64bit inodes. Is useful when a program uses API functions which doesn't support it and the program doesn't use inodes information.
#### BOX86_SHOWSEGV
#### BOX86_SHOWSEGV *
Show Segfault signal even if a signal handler is present
* 0 : Don't force segfault details when a signal handler is install (Default, to limit message spamming)
* 1 : Show segfault details
#### BOX86_BACKTRACE
#### BOX86_SHOWBT *
Show a backtrace (native and emulated) on Signal
* 0 : Don't show any backtrace (Default.)
* 1 : Show native backtrace when a signal is dumped (not available on Andoid build)
#### BOX86_BASH
#### BOX86_BASH *
Define x86 bash to launch script
* yyyy
Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a valid x86 version of bash. Note that is Box64 is available, an x86_64 version of bash can also be used. Also, BOX64_BASH env. var. will also be read if BOX86_BASH is not defined.
@@ -229,8 +321,9 @@ 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
#### BOX86_JITGDB
Will use yyyy as x86_64 interpreter, to launch x64_64 binaries
#### BOX86_JITGDB *
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
@@ -241,3 +334,12 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
Use `gdb /PATH/TO/box86` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX86_JITGDB=1`.
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
#### BOX86_NORCFILES
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
#### BOX86_NOSANDBOX
* 0 : Nothing special
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
+2 -2
View File
@@ -42,7 +42,7 @@ rm ~/wine.tgz # clean up
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could also just make a symlink, but box86 only works for 32bit apps at the moment
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
@@ -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
+15 -4
View File
@@ -18,22 +18,33 @@ mv ./usr/* ../
cd ../ && rm -rf ./tmp/
# create run script
echo "#!/bin/bash
echo '#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam $@' > steam
# make script executable and move
chmod +x steam
sudo mv steam /usr/local/bin/
# detect if we're running on 64 bit Debian
# detect if we're running on 64 bit Debian (maybe this can be moved in another script then mentioned in documentation for the people that don't use steam but don't want a headache)
MACHINE_TYPE=`uname -m`
if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
echo "Detected 64 bit ARM Debian. Installing 32 bit libraries"
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
sudo apt update # update package lists with the newly added arch
sudo apt install libc6:armhf libncurses5:armhf libsdl2*:armhf libopenal*:armhf libpng*:armhf libfontconfig*:armhf libXcomposite*:armhf libbz2-dev:armhf libXtst*:armhf # install the libraries that Steam requires
# 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 libibus-1.0-5
# this one is not there all the time, so just try it...
sudo apt install libncurses5:armhf
# install mesa for armhf if already installed
if dpkg-query -W libgl1-mesa-dri 2>/dev/null; then
echo "Detected mesa driver for 64 bit ARM. Installing complementary 32 bit one"
sudo apt install libgl1-mesa-dri:armhf
fi
echo "Don't forget to compile/install Box64!"
fi
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=r3858.5368285
pkgname=box86-a64-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -9,21 +9,28 @@ url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
provides=("${pkgname%-git}" "${pkgname%-a64-git}-git" "${pkgname%-a64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-a64-git}-git" "${pkgname%-a64-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
cd "${srcdir}/${pkgname%-a64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-a64-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DA64=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-rk3399-git}" -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-a64-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-a64-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-arm-git}"
cd "${srcdir}/${pkgname%-arm-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-arm-git}" -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-arm-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-arm64-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('aarch64')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
conflicts=("${pkgname%-git}" "${pkgname%-arm64-git}-git" "${pkgname%-arm64-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-arm64-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm64-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DARM64=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-arm64-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-arm64-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-gameshell-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-gameshell-git}"
cd "${srcdir}/${pkgname%-gameshell-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-gameshell-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DGAMESHELL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-gameshell-git}" -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-gameshell-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-gameshell-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-goaclone-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-goaclone-git}-git" "${pkgname%-goaclone-git}")
conflicts=("${pkgname%-git}" "${pkgname%-goaclone-git}-git" "${pkgname%-goaclone-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-goaclone-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-goaclone-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DGOA_CLONE=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-goaclone-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-goaclone-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-lx2610a-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-lx2610a-git}-git" "${pkgname%-lx2610a-git}")
conflicts=("${pkgname%-git}" "${pkgname%-lx2610a-git}-git" "${pkgname%-lx2610a-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-lx2610a-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-lx2610a-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DLX2610A=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-lx2610a-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-lx2610a-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-odroid-git}"
cd "${srcdir}/${pkgname%-odroid-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-odroid-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DODROID=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-odroid-git}" -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-odroid-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-odroid-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-odroidn2-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-odroidn2-git}-git" "${pkgname%-odroidn2-git}")
conflicts=("${pkgname%-git}" "${pkgname%-odroidn2-git}-git" "${pkgname%-odroidn2-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-odroidn2-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-odroidn2-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DODROID=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-odroidn2-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-odroidn2-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pandora-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-pandora-git}"
cd "${srcdir}/${pkgname%-pandora-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pandora-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DPANDORA=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-pandora-git}" -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-pandora-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-pandora-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-phytium-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-phytium-git}"-git "${pkgname%-phytium-git}")
conflicts=("${pkgname%-git}" "${pkgname%-phytium-git}"-git "${pkgname%-phytium-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-phytium-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-phytium-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DPHYTIUM=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-phytium-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-phytium-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pyra-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -15,15 +15,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-pyra-git}"
cd "${srcdir}/${pkgname%-pyra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pyra-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DPYRA=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-pyra-git}" -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-pyra-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-pyra-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -7
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rpi-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -16,11 +16,12 @@ md5sums=('SKIP')
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
cd "${srcdir}/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
build() {
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
# Check for Pi version number
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
_piversion=4
@@ -31,15 +32,20 @@ build() {
else
# This RPI is not supported or this device is not a pi.
# We should cancel then the build.
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 isn't supported yet).\033[00m"
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RPi model 4/3/2 (1/0 isn't supported).\033[00m"
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DRPI${_piversion}=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
cmake -B build -S "${pkgname%-rpi-git}" -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
build() {
cd "${srcdir}/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
cd "${srcdir}/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
}
+51
View File
@@ -0,0 +1,51 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3xxx-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
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}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3xxx-git}"
# Check for RockChip version number
if [[ ${_rkmodel} =~ "rk3288" ]]; then
_rksuffix=3288
elif [[ ${_rkmodel} =~ "rk3399" ]]; then
_rksuffix=3399
elif [[ ${_rkmodel} =~ "rk3588" ]]; then
_rksuffix=3588
else
# This RKxxxx is not supported or this device is not RockChip based.
# We should cancel then the build.
echo -e "\033[01m\033[01;31m==> ERROR:\033[00;01m Your device is not supported! This script is for RockChip model 3399/3588.\033[00m"
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected RockChip verion number is: \033[01;31m${_rksuffix}\033[01m.\033[00m"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DRK${_rksuffix}=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-rk3xxx-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-sd845-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
conflicts=("${pkgname%-git}" "${pkgname%-sd845-git}-git" "${pkgname%-sd845-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-sd845-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-sd845-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DSD845=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-sd845-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-sd845-git}/build"
make DESTDIR="${pkgdir}/" install
}
+36
View File
@@ -0,0 +1,36 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-tegra-git
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
url="https://github.com/ptitSeb/box86"
license=('MIT')
optdepends=('gl4es: OpenGL 2 for GLES 2 devices')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-git}" "${pkgname%-tegra-git}"-git "${pkgname%-tegra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-tegra-git}"-git "${pkgname%-tegra-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "${srcdir}/${pkgname%-tegra-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-tegra-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DTEGRAX1ARM32=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cd "${srcdir}/${pkgname%-tegra-git}/build"
make -j$(nproc)
}
package() {
cd "${srcdir}/${pkgname%-tegra-git}/build"
make DESTDIR="${pkgdir}/" install
}
+13 -6
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <[email protected]>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
pkgver=r3858.5368285
pkgver=r4581.d698861
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
@@ -14,15 +14,22 @@ source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-x86-git}"
cd "${srcdir}/${pkgname%-x86-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x86-git}"
[[ ! -d ./build ]] && mkdir build
cmake -B build -DLD80BITS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
}
build() {
cmake -B build -S "${pkgname%-x86-git}" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
cd "${srcdir}/${pkgname%-x86-git}/build"
make -j$(nproc)
}
package() {
make -C build DESTDIR="${pkgdir}/" install
}
cd "${srcdir}/${pkgname%-x86-git}/build"
make DESTDIR="${pkgdir}/" install
}
+1 -1
View File
@@ -12,7 +12,7 @@ This will copy the PKGBUILD for your platform (where you type your platform name
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
### 2. What platforms are currently supported.
All specified in [COMPILE.md](../docs/COMPILE.md).
Most specified in [COMPILE.md](../docs/COMPILE.md). Except PowerPC based.
### 3. Any advantages with that sollution?
This might give you some advantages like those:
+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
+3 -3
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?
@@ -1834,7 +1834,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
+43 -17
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
@@ -679,12 +679,12 @@ class Clauses:
return isinstance(o, Clauses) and (self.clauses == o.clauses)
JumbledFunctions = CustOrderedDictList[Clause, Function]
FilesSpecific = Dict[Filename, FileSpec]
FileSpecifics = Dict[Filename, FileSpec]
SortedGlobals = CustOrderedDictList[Clauses, FunctionType]
SortedRedirects = CustOrderedDictList[Clauses, FunctionType]
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FilesSpecific]:
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FileSpecifics]:
"""
readFiles
@@ -693,7 +693,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
gbls: JumbledFunctions = CustOrderedDictList()
redirects: JumbledFunctions = CustOrderedDictList()
filespecs: FilesSpecific = {}
filespecs: FileSpecifics = {}
symbols: Dict[str, Filename] = {}
need_halt: bool = False
@@ -751,6 +751,9 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("gstinterfaces010","gstaudio")\
or match("gstreamer010","gstreamer") \
or match("appindicator","appindicator3")\
or match("appindicator","ayatanaappindicator3")\
or match("appindicator3","ayatanaappindicator3")\
or match("libgl", "libglx") \
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
@@ -880,7 +883,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
return gbls, redirects, filespecs
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FilesSpecific) \
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FileSpecifics) \
-> Tuple[SortedGlobals, SortedRedirects]:
# First sort file specific stuff
for fn in filespecs:
@@ -944,13 +947,13 @@ def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespe
redirects[red_vals[funtype]].append(funtype)
redirects.sort(key=Clauses.splitdef)
def fail(): assert(False)
def fail(): assert False
for clauses in redirects:
redirects[clauses].sort(key=lambda v: fail() if v.redirected is None else v.splitchar() + v.redirected.splitchar())
return gbls, redirects
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filesspec: FilesSpecific) -> Optional[str]:
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filespecs: FileSpecifics) -> Optional[str]:
# Check if there was any new functions compared to last run
functions_list: str = ""
for clauses in gbls:
@@ -960,18 +963,18 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
for v in redirects[clauses]:
assert(v.redirected is not None)
functions_list = functions_list + "#" + str(clauses) + " " + v.orig + " -> " + v.redirected.orig + "\n"
for filename in sorted(filesspec.keys()):
for filename in sorted(filespecs.keys()):
functions_list = functions_list + filename + ":\n"
for st in filesspec[filename].structs:
struct = filesspec[filename].structs[st]
for st in filespecs[filename].structs:
struct = filespecs[filename].structs[st]
functions_list = functions_list + \
"% " + st + " " + struct.name + " " + struct.repl + "\n"
for _bare in filesspec[filename].typedefs:
for _bare in filespecs[filename].typedefs:
functions_list = functions_list + "- " + _bare.orig + ":\n"
for fn in filesspec[filename].typedefs[_bare]:
for fn in filespecs[filename].typedefs[_bare]:
if fn.no_dlsym: continue
functions_list = functions_list + " - " + fn.name + "\n"
for funtype in filesspec[filename].structsuses:
for funtype in filespecs[filename].structsuses:
assert(funtype.redirected is not None)
functions_list = functions_list + "% " + funtype.orig + " -> " + funtype.redirected.orig + "\n"
@@ -992,7 +995,7 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
return functions_list
def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobals, redirects: SortedRedirects, \
filespecs: FilesSpecific) -> None:
filespecs: FileSpecifics) -> None:
# Files header and guard
files_header = {
"wrapper.c": """
@@ -1148,6 +1151,13 @@ 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 information below in a structure (like in box64, where
# typedefs & co. are stored in an ABI-specific structure)
return_x87: str = "DKdf"
if any(c not in FileSpec.values for c in return_x87):
raise NotImplementedError("Invalid character")
# Typedefs
# E v c w i I C W u U f d D K l L p V O S 2 P G N M s
tdtypes = ["x86emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*", "...", "...", "void*"]
@@ -1249,7 +1259,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N.orig, W, "{"))
if N.orig == 'vFv':
f.write("(void)fcn; ")
f.write("(void)emu; ")
args = N.orig[2:]
if args == 'Ev': args = 'E'
@@ -1309,6 +1319,22 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
if not clauses.empty():
file.write("#endif\n")
# Finally, write predicate functions
# isRetX87Wrapper
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
for clauses in gbls:
empty = True
for funtype in gbls[clauses]:
if funtype.orig[0] in return_x87: # TODO: put this in a function (functions would request the ABI for more info)
if empty and (not clauses.empty()):
file.write("#if " + str(clauses) + "\n")
empty = False
file.write("\tif (fun == &" + funtype.orig + ") return 1;\n")
if not empty:
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
# Rewrite the wrapper.h file:
@@ -1398,6 +1424,6 @@ if __name__ == '__main__':
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.10") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.11") != 0:
exit(2)
exit(0)
+93 -30
View File
@@ -22,6 +22,8 @@
#include <sys/mman.h>
#include "custommem.h"
#include "dictionnary.h"
#include "rcfile.h"
#include "gltools.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
@@ -48,6 +50,7 @@ void finiAllHelpers(box86context_t* context)
static int finied = 0;
if(finied)
return;
DeleteParams();
fini_pthread_helper(context);
fini_signal_helper();
fini_bridge_helper();
@@ -76,17 +79,28 @@ void free_tlsdatasize(void* p)
tlsdatasize_t *data = (tlsdatasize_t*)p;
box_free(data->ptr);
box_free(p);
if(my_context)
pthread_setspecific(my_context->tlskey, NULL);
}
int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#ifdef USE_CUSTOM_MUTEX
void* tid = (void*)GetTID();
#define GO(A, B) \
i = (arm_lock_storeifref2(&A, NULL, tid)==tid); \
if(i) { \
ret|=(1<<B); \
}
#else
#define GO(A, B) \
i = checkUnlockMutex(&A); \
if(i) { \
ret|=(1<<B); \
}
#endif
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
@@ -100,7 +114,6 @@ int unlockMutex()
GO(my_context->mutex_thread, 10)
GO(my_context->mutex_bridge, 11)
#undef GO
return ret;
}
@@ -108,7 +121,7 @@ void relockMutex(int locks)
{
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
mutex_lock(&A); \
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
@@ -127,22 +140,45 @@ void relockMutex(int locks)
static void init_mutexes(box86context_t* context)
{
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
arm_lock_stored(&context->mutex_dyndump, 0);
arm_lock_stored(&context->mutex_once, 0);
arm_lock_stored(&context->mutex_once2, 0);
arm_lock_stored(&context->mutex_trace, 0);
arm_lock_stored(&context->mutex_tls, 0);
arm_lock_stored(&context->mutex_thread, 0);
arm_lock_stored(&context->mutex_bridge, 0);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_dyndump, &attr);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutexattr_destroy(&attr);
#endif
pthread_mutex_init(&context->mutex_lock, NULL);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_dyndump, &attr);
#else
pthread_mutex_init(&context->mutex_lock, &attr);
#endif
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutex_init(&context->mutex_lock, &attr);
pthread_mutexattr_destroy(&attr);
#endif
}
static void atfork_child_box64context(void)
@@ -193,7 +229,7 @@ box86context_t *NewBox86Context(int argc)
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
context->deferedInit = 1;
context->deferredInit = 1;
#endif
context->sel_serial = 1;
@@ -203,11 +239,12 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
#ifdef BUILD_LIB
context->box86lib = RTLD_DEFAULT; // not ideal
#else
@@ -221,7 +258,7 @@ box86context_t *NewBox86Context(int argc)
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
pthread_key_create(&context->tlskey, free_tlsdatasize);
pthread_key_create(&context->tlskey, NULL/*free_tlsdatasize*/);
InitFTSMap(context);
@@ -229,11 +266,13 @@ box86context_t *NewBox86Context(int argc)
context->canary[/*getrand(4)*/0] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
context->globdata = NewMapSymbols();
initAllHelpers(context);
return context;
}
void freeALProcWrapper(box86context_t* context);
EXPORTDYN
void FreeBox86Context(box86context_t** context)
{
@@ -249,6 +288,7 @@ void FreeBox86Context(box86context_t** context)
box86context_t* ctx = *context; // local copy to do the cleanning
//clean_current_emuthread(); // cleaning main thread seems a bad idea
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib, NULL);
if(ctx->maplib)
@@ -271,8 +311,8 @@ void FreeBox86Context(box86context_t** context)
if(ctx->zydis)
DeleteX86Trace(ctx);
if(ctx->deferedInitList)
box_free(ctx->deferedInitList);
if(ctx->deferredInitList)
box_free(ctx->deferredInitList);
/*box_free(ctx->argv);*/
@@ -319,7 +359,6 @@ void FreeBox86Context(box86context_t** context)
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific(ctx->tlskey, NULL);
}
pthread_key_delete(ctx->tlskey);
@@ -333,26 +372,25 @@ void FreeBox86Context(box86context_t** context)
}
}
free_neededlib(&ctx->neededlibs);
free_neededlib(ctx->neededlibs);
ctx->neededlibs = NULL;
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
FreeMapSymbols(&ctx->globdata);
finiAllHelpers(ctx);
#ifndef USE_CUSTOM_MUTEX
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_dyndump);
#else
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
#endif
pthread_mutex_destroy(&ctx->mutex_lock);
freeCycleLog(ctx);
@@ -360,20 +398,45 @@ void FreeBox86Context(box86context_t** context)
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
int idx = ctx->elfsize;
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
int idx = 0;
while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
if(idx == ctx->elfsize) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
} else {
ctx->elfs[idx] = head;
}
ctx->elfs[idx] = head;
ctx->elfsize++;
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
return idx;
}
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head) {
if(GetTLSBase(head)) {
// should remove the tls info
int tlsbase = GetTLSBase(head);
/*if(tlsbase == -ctx->tlssize) {
// not really correct, but will do for now
ctx->tlssize -= GetTLSSize(head);
if(!(++ctx->sel_serial))
++ctx->sel_serial;
}*/
}
for(int i=0; i<ctx->elfsize; ++i)
if(ctx->elfs[i] == head) {
ctx->elfs[i] = NULL;
return;
}
}
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
// should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
context->tlssize += tlssize;
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX86_VERSION_H_
#define BOX86_MAJOR 0
#define BOX86_MINOR 2
#define BOX86_REVISION 8
#define BOX86_MINOR 3
#define BOX86_REVISION 9
#endif //__BOX86_VERSION_H_
+760 -530
View File
File diff suppressed because it is too large. Load diff
+55
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) )
@@ -222,6 +225,8 @@ Op is 20-27
// add dst, src1, src2, lsr #imm
#define ADD_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
#define ADD_REG_LSR_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT((cond) | 0x00800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
#define ADC_IMM8(dst, src, imm8) \
EMIT(0xe2a00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add.s dst, src, #(imm8)
@@ -390,6 +395,8 @@ Op is 20-27
#define LDRD_IMM8(reg, addr, imm8) EMIT(c__ | 0b000<<25 | 1<<24 | (((imm8)<0)?0:1)<<23 | 1<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | ((abs(imm8))&0xf0)<<(8-4) | (0b1101<<4) | ((abs(imm8))&0x0f) )
// ldrd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
#define LDRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1101<<4 | (rm) )
// ldr reg, [pc+imm]
#define LDR_literal(reg, imm12) EMIT(c__ | 0b010<<25 | 1<<24 | (((imm12)>=0)?1:0)<<23 | 0<<21 | 1<<20 | 0b1111<<16 | (reg)<<12 | (abs(imm12)))
// str reg, [addr, #+/-imm9]
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
@@ -423,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))
@@ -430,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))
@@ -589,8 +602,12 @@ Op is 20-27
// Count leading 0 bit of Rm, store result in Rd
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
// Count leading 0 bit of Rm, store result in Rd with cond
#define CLZ_COND(cond, Rd, Rm) EMIT(cond | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
// Reverse bits of Rm, store result in Rd
#define RBIT(Rd, Rm) EMIT(c__ | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
// Reverse bits of Rm, store result in Rd with cond
#define RBIT_COND(cond, Rd, Rm) EMIT(cond | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
#define PLD_gen(U, R, Rn, Imm5, type, Rm) (0b1111<<28 | 0b0111<<24 | (U)<<23 | (R)<<22 | 0b01<<20 | (Rn)<<16 | 0b1111<<12 | (Imm5)<<7 | (type)<<5 | (Rm))
// Preload Cache Rn+Rm
@@ -600,7 +617,21 @@ Op is 20-27
#define DMB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0101<<4 | (opt))
// Data memory barrier Inner Sharable
#ifdef PANDORA
// The Pandora is single core and ordered, DMB is not usefull here so just emit nothing
#define DMB_ISH()
#else
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#endif
#define DSB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0100<<4 | (opt))
// Data memory barrier Inner Sharable
#ifdef PANDORA
// The Pandora is single core and ordered, DSB is not usefull here so just emit nothing
#define DSB_ISH()
#else
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#endif
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
@@ -626,11 +657,15 @@ Op is 20-27
#define VMRS(Rt) EMIT(c__ | (0b1110<<24) | (0b1111<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm register
#define VMSR(Rt) EMIT(c__ | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm register with cond
#define VMSR_cond(cond, Rt) EMIT(cond | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm flags APSR
#define VMRS_APSR() VMRS(15)
// Move between Rt to Sm
#define VMOVtoV(Sm, Rt) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
// Move between Rt to Sm with condition
#define VMOVtoVcond(cond, Sm, Rt) EMIT(cond | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
// Move between Sm to Rt
#define VMOVfrV(Rt, Sm) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (1<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
@@ -820,6 +855,8 @@ Op is 20-27
#define VLD1_32(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 15))
// Load [Rn]! => Dd. Align is 4
#define VLD1_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
// Load [Rn]! => Dd. Align is 8
#define VLD1_64_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
// Load [Rn]! => Dd/Dd+1. Align is 4
#define VLD1Q_32_W(Dd, Rn) EMIT(Vxx1gen(1, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 13))
// Load [Rn, Rm]! => Dd/Dd+1. If Rm==15, no writeback, Rm ignored, else writeback Rn <- Rn+Rm. Align is 4
@@ -841,6 +878,8 @@ Op is 20-27
// Store [Rn]! => Dd. Align is 4
#define VST1_32_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 2, 0, 13))
// Store [Rn]! => Dd. Align is 8
#define VST1_64_W(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b0111, 3, 0, 13))
// Store [Rn] => Dd/Dd+1. Align is 4
#define VST1Q_32(Dd, Rn) EMIT(Vxx1gen(0, ((Dd)>>4)&1, Rn, ((Dd)&0x0f), 0b1010, 2, 0, 15))
// Store [Rn]! => Dd/Dd+1. Align is 4
@@ -879,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
@@ -1089,6 +1130,7 @@ Op is 20-27
#define VMULL_U32_U16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_S64_S32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_U64_U32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_P64(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 1, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMUL_NEON_gen(op, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (op)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1001<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VMULQ_32(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -1386,4 +1428,17 @@ Op is 20-27
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// AES
#define AESD_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESD(Dd, Dm) EMIT(AESD_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESE_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESE(Dd, Dm) EMIT(AESE_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESIMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESIMC(Dd, Dm) EMIT(AESIMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESMC(Dd, Dm) EMIT(AESMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#endif //__ARM_EMITTER_H__
+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}
+5 -3
View File
@@ -335,9 +335,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
@@ -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>
+104 -10
View File
@@ -16,7 +16,14 @@
.global arm_lock_xchg
.global arm_lock_storeifnull
.global arm_lock_storeifref
.global arm_lock_storeifref2
.global arm_lock_decifnot0b
.global arm_lock_incb
.global arm_lock_incif0b
.global arm_lock_stored
.global arm_lock_storeb
.global arm_lock_storeif0b
.global arm_lock_readb
arm_lock_read_b:
// address is r0, return is r0
@@ -83,33 +90,120 @@ arm_lock_xchg:
bx lr
arm_lock_storeifnull:
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return old [r0] value
// r0 needs to be aligned
dmb ish
ldrex r2, [r0]
cmp r2, #0
bne arm_lock_storeifnull_exit
mov r2, r1
strex r3, r2, [r0]
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifnull
arm_lock_storeifnull_exit:
mov r0, r2
dmb ish
bx lr
arm_lock_storeifref2:
dmb ish
arm_lock_storeifref2_loop:
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return old [r0] value (so r2 or old value)
ldrex r3, [r0]
cmp r3, r2
movne r0, r3
bne arm_lock_storeifref2_exit
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifref_loop
mov r0, r2
arm_lock_storeifref2_exit:
dmb ish
bx lr
arm_lock_storeifref:
push {r4}
dmb ish
arm_lock_storeifref_loop:
// address is r0, value is r1, r1 store to r0 only if [r0] is r2. return new [r0] value (so r1 or old value)
ldrex r3, [r0]
cmp r3, r2
movne r0, r3
bne arm_lock_storeifref_exit
mov r3, r1
strex r4, r3, [r0]
cmp r4, #1
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeifref_loop
mov r0, r1
arm_lock_storeifref_exit:
mov r0, r3
pop {r4}
dmb ish
bx lr
arm_lock_decifnot0b:
dmb ish
arm_lock_decifnot0b_0:
ldrexb r1, [r0]
cmp r1, #0
subne r3, r1, #1
moveq r3, r1
strexb r2, r3, [r0]
cmp r2, #1
beq arm_lock_decifnot0b_0
dmb ish
mov r0, r1
bx lr
arm_lock_incb:
dmb ish
arm_lock_incb_0:
ldrexb r1, [r0]
add r1, r1, #1
strexb r2, r1, [r0]
cmp r2, #1
beq arm_lock_incb_0
arm_lock_incb_exit:
dmb ish
bx lr
arm_lock_incif0b:
dmb ish
arm_lock_incif0b_0:
ldrexb r1, [r0]
cmp r1, #0
addeq r3, r1, #1
movne r3, r1
strexb r2, r3, [r0]
cmp r2, #1
beq arm_lock_incif0b_0
dmb ish
mov r0, r1
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
arm_lock_storeif0b:
dmb ish
arm_lock_storeif0b_0:
ldrexb r2, [r0]
cmp r2, #0
bne arm_lock_storeif0b_exit
strexb r3, r1, [r0]
cmp r3, #1
beq arm_lock_storeif0b_0
mov r2, #0
dmb ish
arm_lock_storeif0b_exit:
mov r0, r2
bx lr
arm_lock_readb:
dmb ish
ldrb r0, [r0]
bx lr
+25 -1
View File
@@ -25,10 +25,34 @@ extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
// Atomically exchange value at [p] with val, return old p
extern uintptr_t arm_lock_xchg(void* p, uintptr_t val);
// Atomically store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
extern void* arm_lock_storeifnull(void* p, void* val);
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
extern void* arm_lock_storeifref(void* p, void* val, void* ref);
// Atomically store value to [p] only if [p] is ref. Return old [p] value
extern void* arm_lock_storeifref2(void* p, void* val, void* ref);
// decrement atomicaly the byte at [p] (but only if p not 0). Return old [p] value
extern int arm_lock_decifnot0b(void*p);
// increment atomicaly the byte at [p]
extern void arm_lock_incb(void*p);
// increment atomicaly the byte at [p] only if it was 0. Return the old value of [p]
extern int arm_lock_incif0b(void*p);
// atomic store (with memory barrier)
extern void arm_lock_stored(void*p, uint32_t d);
// atomic store (with memory barrier)
extern void arm_lock_storeb(void*p, uint8_t b);
// atomic store (with memory barrier) only if it was 0. Return the old value of [p]
extern int arm_lock_storeif0b(void*p, uint8_t b);
// atomic load (with memory barrier)
extern int arm_lock_readb(void*p);
#endif //__ARM_LOCK_HELPER__H__
+1
View File
@@ -9,6 +9,7 @@
.extern LinkNext
.global arm_next
.4byte 0 // NULL pointer before arm64_next, for getDB
arm_next:
// emu is r0
//stm r0, {r4-r12,r14} // don't put put back reg value in emu, faster but more tricky to debug
+16 -4
View File
@@ -159,7 +159,7 @@ const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
@@ -3049,7 +3049,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3064,7 +3064,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3080,7 +3080,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -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
+190 -304
View File
@@ -41,21 +41,37 @@ uint32_t X31_hash_code(void* addr, int len)
return (uint32_t)h;
}
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
dynablock_t* InvalidDynablock(dynablock_t* db, int need_lock)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
if(db) {
if(db->gone)
return NULL; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "InvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
// remove jumptable
setJumpTableDefault(db->x86_addr);
db->done = 0;
db->gone = 1;
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
dynablocklist_t* ret = (dynablocklist_t*)box_calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
if(direct && textsz) {
ret->direct = (dynablock_t**)box_calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
return db;
}
void FreeInvalidDynablock(dynablock_t* db, int need_lock)
{
if(db) {
if(!db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeInvalidDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
FreeDynarecMap((uintptr_t)db->actual_block);
customFree(db);
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
return ret;
}
void FreeDynablock(dynablock_t* db, int need_lock)
@@ -63,362 +79,223 @@ void FreeDynablock(dynablock_t* db, int need_lock)
if(db) {
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size-1, db->gone);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x86_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
mutex_lock(&my_context->mutex_dyndump);
// remove jumptable
setJumpTableDefault(db->x86_addr);
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son, 0);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
box_free(db->sons);
box_free(db->instsize);
}
box_free(db);
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
if(db->previous)
FreeInvalidDynablock(db->previous, 0);
FreeDynarecMap((uintptr_t)db->actual_block);
customFree(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
}
box_free((*dynablocks)->direct);
}
(*dynablocks)->direct = NULL;
box_free(*dynablocks);
*dynablocks = NULL;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->need_test)
return; // already done
db->need_test = 1;
setJumpTableDefault(db->x86_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault(db->sons[i]->x86_addr);
dynarec_log(LOG_DEBUG, "MarkDynablock %p %p-%p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1);
if(!setJumpTableIfRef(db->x86_addr, db->jmpnext, db->block)) {
dynablock_t* old = db;
db = getDB((uintptr_t)old->x86_addr);
if(!old->gone && db!=old) {
printf_log(LOG_INFO, "Warning, couldn't mark block as dirty for %p, block=%p, current_block=%p\n", old->x86_addr, old, db);
// the block is lost, need to invalidate it...
old->gone = 1;
old->done = 0;
if(!db || db->previous)
FreeInvalidDynablock(old, 1);
else
db->previous = old;
}
}
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz-1;
return 0;
}
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
static int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
{
if(start1 > end2 || start2 > end1)
return 0;
return 1;
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
static int MarkedDynablock(dynablock_t* db)
{
if(!dynablocks)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz -1;
uintptr_t start = addr;
uintptr_t end = addr+size-1;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
dynablock_t *db;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if((db=dynablocks->direct[i-startdb]))
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
MarkDynablock(db);
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct) {
int need_lock = my_context?1:0;
dynablock_t* db;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db, need_lock);
);
kh_destroy(dynablocks, blocks);
if(db) {
if(getNeedTest((uintptr_t)db->x86_addr))
return 1; // already done
}
return 0;
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
// Mark will try to find *any* blocks that intersect the range to mark
if(!db)
return;
if(dynablocks->direct) {
uintptr_t new_addr = addr - dynablocks->maxsz;
uintptr_t new_size = size + dynablocks->maxsz;
MarkDirectDynablock(dynablocks, new_addr, new_size);
// the blocks check before
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x86_addr, (void*)db->x86_size);
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
MarkDynablock(db);
}
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!db)
return 1;
int need_lock = my_context?1:0;
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1)) {
FreeDynablock(db, need_lock);
return 0;
}
return 1;
}
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
dynablock_t *AddNewDynablock(uintptr_t addr)
{
if(!dynablocks)
return NULL;
dynablock_t* db;
kh_foreach_value(dynablocks, db,
const uintptr_t s = (uintptr_t)db->block;
const uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
)
return NULL;
}
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
const int idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
dynablock_t* block;
#if 0
// check if memory as the correct flags
int prot = getProtection(addr);
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if (!*created)
return block;
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
box_free(p); // someone already create the direct array, too late...
}
#endif
// create and add new block
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(tmp != block) {
// a block appeard!
box_free(block);
*created = 0;
return tmp;
}
*created = 1;
block = (dynablock_t*)customCalloc(1, sizeof(dynablock_t));
return block;
}
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
#ifdef ANDROID
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
static __thread JUMPBUFF dynarec_jmpbuf;
#ifdef ANDROID
#define DYN_JMPBUF dynarec_jmpbuf
#else
#define DYN_JMPBUF &dynarec_jmpbuf
#endif
void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
longjmp(DYN_JMPBUF, 1);
}
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
{
if(hasAlternate((void*)addr))
return NULL;
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current && current->done) {
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
}
// nope, lets do the long way
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
dynablock_t* block = getDB(addr);
if(block || !create)
return block;
if(need_lock) {
if(box86_dynarec_wait) {
mutex_lock(&my_context->mutex_dyndump);
} else {
if(mutex_trylock(&my_context->mutex_dyndump)) // FillBlock not available for now
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
block = getDB(addr); // just in case
if(block) {
mutex_unlock(&my_context->mutex_dyndump);
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
}
}
block = AddNewDynablock(addr);
// fill the block
block->x86_addr = (void*)addr;
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
if(sigsetjmp(DYN_JMPBUF, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
FreeDynablock(block, 0);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock(block, filladdr);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
void* old = (void*)arm_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
if(old!=block && old) { // put it back in place, strange things are happening here!
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
// Doing nothing else, the block has not been written
}
box_free(block);
customFree(block);
block = NULL;
}
// check size
if(block && block->x86_size) {
if(block) {
int blocksz = block->x86_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
dblist->maxsz = blocksz;
}
}
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
// but check if it already need test
if(block->need_test || (block->father && block->father->need_test))
return NULL;
if(blocksz>my_context->max_db_size)
my_context->max_db_size = blocksz;
// fill-in jumptable
addJumpTableIfDefault(block->x86_addr, block->block);
for(int i=0; i<block->sons_size; ++i)
addJumpTableIfDefault(block->sons[i]->x86_addr, block->sons[i]->block);
if(!addJumpTableIfDefault(block->x86_addr, block->dirty?block->jmpnext:block->block)) {
FreeDynablock(block, 0);
block = getDB(addr);
MarkDynablock(block); // just in case...
} else {
if(block->x86_size)
block->done = 1; // don't validate the block if the size is null, but keep the block
}
}
if(need_lock)
mutex_unlock(&my_context->mutex_dyndump);
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
dynarec_log(LOG_DEBUG, "%04d| --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", GetTID(), (void*)addr, (void*)(addr+((block)?block->x86_size:1)-1), (block)?block->block:0, (block)?block->size:0);
return block;
}
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father, 0);
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...
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, 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)
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
db = internalDBGetBlock(emu, addr, addr, create, need_lock);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
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
addJumpTableIfDefault(father->x86_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
}
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
if(!db || !db->block || !db->done)
emu->test.test = 0;
return db;
}
@@ -426,27 +303,36 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father, 0);
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
if(db && db->done && db->block && getNeedTest(filladdr)) {
if(db->always_test)
sched_yield(); // just calm down...
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
dynablock_t* old = InvalidDynablock(db, need_lock);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
db = internalDBGetBlock(emu, addr, filladdr, create, need_lock);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
protectDB((uintptr_t)db->x86_addr, db->x86_size);
// fill back jumptable
addJumpTableIfDefault(father->x86_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
}
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
if(!db || !db->block || !db->done)
emu->test.test = 0;
return db;
}
+6 -16
View File
@@ -1,36 +1,26 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct instsize_s {
unsigned char x86:4;
unsigned char nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
void* block;
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
struct dynablock_s* previous; // a previous block that might need to be freed
int size;
void* x86_addr;
uintptr_t x86_size;
uint32_t hash;
uint8_t need_test;
uint8_t done;
uint8_t gone;
uint8_t dummy;
uint8_t always_test;
uint8_t dirty; // if need to be tested as soon as it's created
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
instsize_t* instsize;
void* jmpnext; // a branch jmpnext code when block is marked
} dynablock_t;
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
int maxsz; // maxblock size (for this block or previous block)
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+112 -146
View File
@@ -20,6 +20,8 @@
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#include "custommem.h"
void x86test_check(x86emu_t* ref, uintptr_t ip);
#endif
#ifdef ARM
@@ -44,26 +46,31 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
}
#endif
dynablock_t* current = NULL;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
dynablock_t* block = NULL;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1);
} else
block = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
}
if(!block) {
#ifdef HAVE_TRACE
dynablock_t* db = FindDynablockFromNativeAddress(x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
#ifdef HAVE_TRACE
if(LOG_INFO<=box86_dynarec_log) {
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);
return arm_epilog;
}
if(!block->done) {
// not finished yet... leave linker
@@ -79,166 +86,125 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
}
#endif
#ifdef ANDROID
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
void DynaCall(x86emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
int a;
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
addr = R_EIP; // not sure if it should still be inside DynaCall!
if(a==2)
Run(emu, 1); // "single step" next instruction that is doing auto-smc
}
}
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
// save defered flags
defered_flags_t old_df = emu->df;
uint32_t old_op1 = emu->op1;
uint32_t old_op2 = emu->op2;
uint32_t old_res = emu->res;
// uc_link
i386_ucontext_t* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
// restore defered flags
emu->df = old_df;
emu->op1 = old_op1;
emu->op2 = old_op2;
emu->res = old_res;
// and the old registers
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
EmuCall(emu, addr);
#ifdef DYNAREC
else {
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = block;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,block->father, emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP;
}
}
}
}
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
emu->longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
}
#endif
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
}
int my_setcontext(x86emu_t* emu, void* ucp);
int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
#ifdef DYNAREC
int jmpbuf_reset = 1;
#endif
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
int a;
#ifdef DYNAREC
jmpbuf_reset = 1;
#endif
if((a=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", a, ejb->emu->segs[_FS]);
if(a==2)
Run(emu, 1); // "single step" next instruction that is doing auto-smc
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)))
#else
if((skip=sigsetjmp(emu->jmpbuf, 1)))
#endif
{
printf_log(LOG_DEBUG, "Setjmp DynaRun\n");
#ifdef DYNAREC
if(box86_dynarec_test) {
if(emu->test.clean)
x86test_check(emu, R_EIP);
emu->test.clean = 0;
}
#endif
}
}
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = block;
if(emu->flags.need_jmpbuf)
emu->flags.need_jmpbuf = 0;
#ifndef DYNAREC
Run(emu, 0);
#else
if(!box86_dynarec)
Run(emu, 0);
else {
dynablock_t* block = (skip || ACCESS_FLAG(F_TF))?NULL:DBGetBlock(emu, R_EIP, 1);
if(!block || !block->block || !block->done) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
if(box86_dynarec_test)
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->hash, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
else if(emu->quit && emu->uc_link) {
if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
emu->quit = 0;
}
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
return 0;
#endif
emu->jmpbuf = old_jmpbuf;
emu->xSPSave = old_savesp;
}
+292 -189
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 += 16;
dyn->next = (uintptr_t*)box_realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
printf_log(LOG_NONE, "Warning, overallocating next\n");
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -83,16 +82,32 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
uintptr_t best = 0;
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
if(dyn->next[i]) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
}
}
++i;
}
return best;
}
void add_jump(dynarec_arm_t *dyn, int ninst) {
// add slots
if(dyn->jmp_sz == dyn->jmp_cap) {
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 dyn->jmps[i];
return -2;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
@@ -241,54 +256,71 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
return (i==n)?1:0;
}
static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
void addInst(instsize_t* insts, size_t* size, int x86_size, int native_size)
{
// x86 instruction is <16 bytes
int toadd;
if(x86_size>arm_size)
if(x86_size>native_size)
toadd = 1 + x86_size/15;
else
toadd = 1 + arm_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)box_realloc(insts, (*cap)*sizeof(instsize_t));
}
toadd = 1 + native_size/15;
while(toadd) {
if(x86_size>15)
insts[*size].x86 = 15;
else
insts[*size].x86 = x86_size;
x86_size -= insts[*size].x86;
if(arm_size>15)
if(native_size>15)
insts[*size].nat = 15;
else
insts[*size].nat = arm_size;
arm_size -= insts[*size].nat;
insts[*size].nat = native_size;
native_size -= insts[*size].nat;
++(*size);
--toadd;
}
return insts;
}
static void fillPredecessors(dynarec_arm_t* dyn)
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 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 orphan branch
for(int i=0; i<dyn->size-1; ++i) {
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*)box_malloc(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) {
@@ -297,13 +329,14 @@ 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) {
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz))
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)
dyn->insts[dyn->insts[i].x86.jmp_insts].pred[dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && (dyn->insts[i].x86.jmp_insts!=-1)) {
int j = dyn->insts[i].x86.jmp_insts;
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
// updateNeed goes backward, from last intruction to top
@@ -311,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);
}
@@ -327,11 +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
// Consume X_PEND if relevant
if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
need &=~X_PEND;
else if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
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;
@@ -346,158 +375,274 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
else
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
}
if(!ok)
return ninst - 1;
--ninst;
if(!ok)
return ninst;
}
return ninst;
}
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;
if(helper) {
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);
}
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void arm_epilog();
void arm_next();
__thread void* current_helper = NULL;
void CancelBlock()
{
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(!helper)
return;
box_free(helper->next);
box_free(helper->insts);
box_free(helper->predecessor);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
size_t sz = 8*sizeof(void*);
void* actual_p = (void*)AllocDynarecMap(sz);
void* p = actual_p + sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock(0);
return NULL;
}
block->size = sz;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
*(dynablock_t**)actual_p = block;
*(void**)(p+4*sizeof(void*)) = arm_epilog;
CreateJmpNext(block->jmpnext, p+4*sizeof(void*));
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
return block;
}
void* FillBlock(dynablock_t* block, uintptr_t addr) {
/*
A Block must have this layout:
0x0000..0x0003 : dynablock_t* : self
0x0004..4+4*n : actual Native instructions, (n is the total number)
B .. B+3 : dynablock_t* : self (as part of JmpNext, that simulate another block)
B+4 .. B+15 : 3 Native code for jmpnext (or jmp epilog in case of empty block)
B+16 .. B+19 : jmpnext (or jmp_epilog) address
B+20 .. B+31 : empty (in case an architecture needs more than 3 opcodes)
B+32 .. B+32+sz : instsize (compressed array with each instruction lenght on x86 and native side)
*/
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
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);
}
if(current_helper) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
return NULL;
}
if(!isJumpTableDefault((void*)addr)) {
dynarec_log(LOG_DEBUG, "Asked to fill a block at %p, but JumpTable is not default\n", (void*)addr);
return NULL;
}
// protect the 1st page
protectDB(addr, 1);
// init the helper
dynarec_arm_t helper = {0};
current_helper = &helper;
helper.dynablock = block;
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm_t*)box_calloc(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);
// no need for next anymore
box_free(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
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);
CancelBlock();
return (void*)block;
CancelBlock(0);
return CreateEmptyBlock(block, addr);
}
if(!isprotectedDB(addr, 1)) {
dynarec_log(LOG_INFO, "Warning, write on current page on pass0, aborting dynablock creation (%p)\n", (void*)addr);
CancelBlock(0);
return NULL;
}
// already protect the block and compute hash signature
protectDB(addr, end-addr); //end is 1byte after actual end
// protect the block of it goes over the 1st page
if((addr&~box86_pagesize)!=(end&~box86_pagesize)) // need to protect some other pages too
protectDB(addr, end-addr); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end) {
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x86.addr==j)
k=i2;
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.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
int search = ((j>=helper.insts[0].x86.addr) && j<helper.insts[0].x86.addr+helper.isize)?1:0;
int imin = 0;
int imax = helper.size-1;
int i2 = helper.size/2;
// dichotomy search
while(search) {
if(helper.insts[i2].x86.addr == j) {
k = i2;
search = 0;
} else if(helper.insts[i2].x86.addr>j) {
imax = i2;
i2 = (imax+imin)/2;
} else {
imin = i2;
i2 = (imax+imin)/2;
}
if(search && (imax-imin)<2) {
search = 0;
if(helper.insts[imin].x86.addr==j)
k = imin;
else if(helper.insts[imax].x86.addr==j)
k = imax;
}
}
/*for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x86.addr==j)
k=i2;
}*/
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
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
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);
// check for the optionnal barriers now
/*for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].barrier_maybe) {
// out-of-block jump
if(helper.insts[i].x86.jmp_insts == -1) {
// nothing for now
} else {
// inside block jump
int k = helper.insts[i].x86.jmp_insts;
if(k>i) {
// jump in the future
if(helper.insts[k].pred_sz>1) {
// with multiple flow, put a barrier
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
} else {
// jump back
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
}
}
}*/
// check to remove useless barrier, in case of jump when destination doesn't needs flags
/*for(int i=helper.size-1; i>=0; --i) {
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
&& helper.insts[k].x86.barrier&BARRIER_FLAGS) {
//TODO: optimize FPU barrier too
if((!helper.insts[k].x86.need_flags)
||(helper.insts[k].x86.set_flags==X_ALL
&& helper.insts[k].x86.state_flags==SF_SET)
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
helper.insts[k].x86.barrier &= ~BARRIER_FLAGS; // remove flag barrier
}
}
}*/
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
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
CancelBlock();
size_t insts_rsize = (helper.insts_size+2)*sizeof(instsize_t);
insts_rsize = (insts_rsize+7)&~7; // round the size...
size_t arm_size = (helper.arm_size+7)&~7; // round the size...
// ok, now allocate mapped memory, with executable flag on
size_t sz = sizeof(void*) + arm_size + 8*sizeof(void*) + insts_rsize;
// dynablock_t* block (arm insts) jmpnext code instsize
void* actual_p = (void*)AllocDynarecMap(sz);
void* p = (void*)(((uintptr_t)actual_p) + sizeof(void*));
void* next = p + arm_size;
void* instsize = next + 8*sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock(0);
return NULL;
}
helper.block = p;
block->actual_block = actual_p;
helper.arm_start = (uintptr_t)p;
if(helper.sons_size) {
helper.sons_x86 = (uintptr_t*)alloca(helper.sons_size*sizeof(uintptr_t));
helper.sons_arm = (void**)alloca(helper.sons_size*sizeof(void*));
}
// pass 3, emit (log emit arm opcode)
helper.jmp_next = (uintptr_t)next+sizeof(void*);
helper.instsize = (instsize_t*)instsize;
*(dynablock_t**)actual_p = block;
// pass 3, emit (log emit native opcode)
if(box86_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
size_t oldarmsize = helper.arm_size;
size_t oldinstsize = helper.insts_size;
helper.arm_size = 0;
helper.insts_size = 0; // reset
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
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
helper.insts = NULL;
helper.instsize = NULL;
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->jmpnext = next+sizeof(void*);
block->always_test = helper.always_test;
block->dirty = block->always_test;
*(dynablock_t**)next = block;
*(void**)(next+5*sizeof(void*)) = arm_next;
CreateJmpNext(block->jmpnext, next+5*sizeof(void*));
//block->x86_addr = (void*)start;
block->x86_size = end-start;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// 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);
CancelBlock(0);
return NULL;
}
if((oldarmsize!=helper.arm_size)) {
printf_log(LOG_NONE, "BOx86: Warning, size difference in block between pass2 (%zu) & pass3 (%zu)!\n", sz, helper.arm_size);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
for(int i=0; i<helper.size; ++i) {
@@ -507,69 +652,27 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
printf_log(LOG_NONE, "\t%d -> %d\n", helper.insts[i].size2, helper.insts[i].size);
}
printf_log(LOG_NONE, " ------------\n");
}
// all done...
__clear_cache(p, p+sz); // need to clear the cache before execution...
// keep size of instructions for signal handling
{
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
size_t size = 0;
block->instsize = (instsize_t*)box_calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
}
// ok, free the helper now
box_free(helper.insts);
helper.insts = NULL;
box_free(helper.next);
helper.next = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->need_test = 0;
//block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// Check if something changed, to abbort if it as
if(block->hash != hash) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%d)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
CancelBlock();
CancelBlock(0);
return NULL;
}
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
sons = (dynablock_t**)box_calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
if(created) { // avoid breaking a working block!
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i];
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
box_free(sons);
// 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);
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);
}
box_free(helper.predecessor);
helper.predecessor = NULL;
current_helper = NULL;
block->done = 1;
//block->done = 1;
return (void*)block;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+103 -17
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"
@@ -29,7 +30,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, u8;
uint8_t wback, u8, wb1, wb2;
uint8_t gb1, gb2, eb1, eb2;
int fixedaddress;
MAYUSE(j32);
@@ -46,6 +48,17 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_add32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x20:
INST_NAME("AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGB(x2);
GETEBO(x14);
emit_and8(dyn, ninst, x1, x2, x14, x2);
EBBACK;
break;
case 0x2B:
INST_NAME("SUB Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -86,6 +99,13 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x64:
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x65:
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x67:
// reduced EA size...
opcode = F8;
@@ -95,7 +115,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -103,6 +123,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
SMWRITE2();
}
break;
@@ -111,9 +132,10 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -123,12 +145,13 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x1, x14, 0);
SMWRITE2();
}
break;
@@ -140,6 +163,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
SMREAD();
LDR_IMM9(xEAX, x1, 0);
break;
@@ -152,6 +176,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
SMWRITE2();
break;
case 0xFF:
@@ -160,9 +185,10 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
@@ -176,17 +202,41 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
gd = (nextop&0x38)>>3;
gb2 = ((gd&4)>>2);
gb1 = xEAX+(gd&3);
if(gb2) {
gd = x3;
UXTB(gd, gb1, gb2);
} else {
gd = gb1; // no need to extract
}
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)<<1); // L or H
BFI(eb1, gd, eb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STRB_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
@@ -195,9 +245,10 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -207,14 +258,18 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ed");
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA0:
INST_NAME("MOV AL, FS:Id");
@@ -224,6 +279,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
SMREAD();
LDRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
@@ -235,6 +291,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
SMREAD();
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
@@ -247,6 +304,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
MOV32(x2, i32);
STRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
SMWRITE2();
}
break;
case 0xA3:
@@ -255,9 +313,11 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
if(i32>-4096 && i32<4096) {
STR_IMM9(xEAX, x1, i32);
SMWRITE2();
} else {
MOV32(x2, i32);
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
SMWRITE2();
}
break;
@@ -274,7 +334,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
if(MODREG) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
@@ -283,6 +343,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
@@ -298,29 +359,54 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 2: // CALL Ed
INST_NAME("CALL FS:Ed");
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
PASS2IF((box86_dynarec_safeflags>1) ||
((ninst && dyn->insts[ninst-1].x86.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x86.set_flags)), 1)
{
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((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
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;
case 6: // Push Ed
INST_NAME("PUSH FS:Ed");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+64 -49
View File
@@ -50,7 +50,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x03:
@@ -97,7 +97,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_and32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x23:
@@ -118,7 +118,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
WBACK;
WBACK2;
break;
case 0x2B:
@@ -139,7 +139,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
GETEDO2(x14);
emit_xor32(dyn, ninst, gd, ed, x3, x14);
WBACK;
WBACK2;
break;
case 0x33:
@@ -172,6 +172,13 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x64:
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x65:
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x69:
INST_NAME("IMUL Gd, GS:Ed, Id");
SETFLAGS(X_ALL, SF_PENDING);
@@ -202,7 +209,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 1: //OR
INST_NAME("OR GS:Eb, Ib");
@@ -211,7 +218,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 2: //ADC
INST_NAME("ADC GS:Eb, Ib");
@@ -221,7 +228,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 3: //SBB
INST_NAME("SBB GS:Eb, Ib");
@@ -231,7 +238,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 4: //AND
INST_NAME("AND GS:Eb, Ib");
@@ -240,7 +247,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 5: //SUB
INST_NAME("SUB GS:Eb, Ib");
@@ -249,7 +256,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 6: //XOR
INST_NAME("XOR GS:Eb, Ib");
@@ -258,7 +265,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEBO(x1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
EBBACK2;
break;
case 7: //CMP
INST_NAME("CMP GS:Eb, Ib");
@@ -290,7 +297,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_add32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
@@ -299,7 +306,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_or32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
@@ -309,7 +316,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
@@ -319,7 +326,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
@@ -328,7 +335,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_and32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
@@ -337,7 +344,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
@@ -346,7 +353,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
WBACK;
WBACK2;
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
@@ -369,11 +376,12 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
@@ -382,9 +390,10 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
@@ -394,19 +403,24 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP GS:Ed");
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA1:
INST_NAME("MOV EAX, GS:Id");
grab_tlsdata(dyn, addr, ninst, x1);
i32 = F32S;
SMREAD();
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
} else {
@@ -423,6 +437,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STRB_IMM9(xEAX, x2, 0);
SMWRITE2();
break;
case 0xA3:
@@ -432,13 +447,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
STR_IMM9(xEAX, x2, 0);
SMWRITE2();
break;
case 0xC6:
INST_NAME("MOV GS:Eb, Ib");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= u8
if(MODREG) { // reg <= u8
u8 = F8;
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
@@ -450,13 +466,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = F8;
MOVW(x3, u8);
STRB_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
case 0xC7:
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
if(MODREG) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
@@ -465,6 +482,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
SMWRITE2();
}
break;
@@ -477,37 +495,35 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 2:
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);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
CALL_(rcl32, ed, (1<<x2));
WBACK2;
break;
case 3:
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);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
CALL_(rcr32, ed, (1<<x2));
WBACK2;
break;
case 4:
case 6:
@@ -515,21 +531,21 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shl32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 5:
INST_NAME("SHR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_shr32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
case 7:
INST_NAME("SAR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO2(x14);
emit_sar32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
WBACK2;
break;
}
break;
@@ -546,7 +562,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
RSB_IMM8(x3, x3, 0x20);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 31);
B_MARK(cNE);
@@ -567,7 +583,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK2(cEQ);
GETEDO2(x14);
MOV_REG_ROR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x3, 1);
B_MARK(cNE);
@@ -585,23 +601,21 @@ 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);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcl32, ed, (1<<x14));
SBACK(wb);
CALL_(rcl32, ed, (1<<x2));
WBACK2;
break;
case 3:
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);
wb = ed;
if(ed!=x1) {MOV_REG(x1, ed); wb = x1;}
CALL_(rcr32, ed, (1<<x14));
SBACK(wb);
WBACK2;
break;
case 4:
case 6:
@@ -610,7 +624,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shl32(dyn, ninst, ed, x3, x3, x14);
WBACK;
WBACK2;
break;
case 5:
INST_NAME("SHR Ed, CL");
@@ -618,7 +632,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x3, xECX, 0x1f);
GETEDO2(x14);
emit_shr32(dyn, ninst, ed, x3, x3, x14);
WBACK;
WBACK2;
break;
case 7:
INST_NAME("SAR Ed, CL");
@@ -627,7 +641,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDO2(x14);
UFLAG_OP12(ed, x3);
MOV_REG_ASR_REG(ed, ed, x3);
WBACK;
WBACK2;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar32);
break;
@@ -646,9 +660,10 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH GS:Ed");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+223 -120
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_helper.h"
#include "dynarec_arm_functions.h"
@@ -172,9 +173,9 @@ 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);
i16 = F16;
i32 = F16;
UXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
emit_sbb16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x1E:
@@ -388,13 +389,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("IMUL Gw,Ew,Iw");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETEW(x1);
i16 = F16S;
MOVW(x2, i16);
SMULBB(x2, ed, x2);
UFLAG_RES(x2);
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 0x6A:
INST_NAME("PUSH Ib");
@@ -406,13 +407,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("IMUL Gw,Ew,Ib");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETEW(x1);
i16 = F8S;
MOVW(x2, i16);
SMULBB(x2, ed, x2);
UFLAG_RES(x2);
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 0x81:
@@ -505,9 +506,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x87:
INST_NAME("XCHG Ew, Gw");
INST_NAME("(LOCK) XCHG Ew, Gw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGD;
UXTH(x14, gd, 0);
ed = xEAX + (nextop&7);
@@ -518,6 +519,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETGD;
UXTH(x14, gd, 0);
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
#if 0
MARKLOCK;
@@ -531,6 +533,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRH_IMM8(x1, ed, fixedaddress);
STRH_IMM8(x14, ed, fixedaddress);
#endif
SMDMB();
BFI(gd, x1, 0, 16);
}
break;
@@ -539,7 +542,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -547,21 +550,21 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
STRH_IMM8(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x8B:
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD; // don't need GETGW neither
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
if(lock) {DMB_ISH();}
SMREADLOCK(lock);
LDRH_IMM8(x1, ed, fixedaddress);
BFI(gd, x1, 0, 16);
}
@@ -571,23 +574,25 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
LDRH_REG(x1, xEmu, x2);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
BFI(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
STRH_IMM8(x1, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
@@ -632,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);
@@ -645,6 +650,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV, AX, Od");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDRH_IMM8(x2, x2, 0);
BFI(xEAX, x2, 0, 16);
break;
@@ -652,7 +659,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Od, AX");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
STRH_IMM8(xEAX, x2, 0);
SMWRITELOCK(lock);
break;
case 0xA5:
INST_NAME("MOVSW");
@@ -717,26 +726,34 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
CALL_(rol16, x1, (1<<x3));
EWBACK;
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_rol16c(dyn, ninst, x1, u8&15, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 1:
INST_NAME("ROR Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
CALL_(ror16, x1, (1<<x3));
EWBACK;
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_ror16c(dyn, ninst, x1, u8&15, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
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);
@@ -746,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);
@@ -756,39 +773,42 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_LSL_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
emit_shl16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 5:
INST_NAME("SHR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
emit_shr16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_ASR_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1);
u8 = F8;
emit_sar16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
}
break;
@@ -796,7 +816,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u16 = F16;
MOVW(x1, u16);
@@ -810,101 +830,178 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
if(opcode==0xD1) {
INST_NAME("ROL Ew, 1");
MOVW(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROL Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
CALL_(rol16, x1, (1<<x3));
emit_rol16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
case 1:
if(opcode==0xD1) {
INST_NAME("ROR Ew, 1");
MOVW(x2, 1);
} else {
INST_NAME("ROR Ew, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
CALL_(ror16, x1, (1<<x3));
emit_ror16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
case 2:
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
INST_NAME("RCL Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
EWBACK;
break;
case 3:
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
INST_NAME("RCR Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
SETFLAGS(X_OF|X_CF, SF_SET_DF);
MOVW(x2, 1);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
EWBACK;
break;
case 4:
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SHL Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHL Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_LSL_REG(ed, ed, x14);
emit_shl16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SHR Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_LSR_REG(ed, ed, x14);
emit_shr16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SAR Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SAR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_ASR_REG(ed, ed, x14);
emit_sar16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
}
break;
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x0f);
RSB_IMM8(x2, x2, 16);
GETEW(x1);
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 15);
ADD_REG_LSR_IMM5_COND(cEQ, x3, ed, ed, 15);
BFI_COND(cEQ, xFlags, x3, F_OF, 1);
BFI(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x0f);
GETEW(x1);
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 1);
MOV_REG_LSR_IMM5_COND(cEQ, x2, ed, 14); // x2 = d>>14
XOR_REG_LSR_IMM8_COND(cEQ, x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFI_COND(cEQ, xFlags, x2, F_OF, 1);
MOV_REG_LSR_IMM5(x2, ed, 15);
BFI(xFlags, x2, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 2:
INST_NAME("RCL Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET_DF);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEW(x1);
emit_shl16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
break;
case 5:
INST_NAME("SHR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEW(x1);
emit_shr16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
break;
case 7:
INST_NAME("SAR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETSEW(x1);
emit_sar16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
@@ -1052,19 +1149,20 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5:
INST_NAME("IMUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_imul16);
GETEW(x1);
SMULBB(x2, xEAX, ed);
UFLAG_RES(x2);
BFI(xEAX, x2, 0, 16);
MOV_REG_LSR_IMM5(x2, x2, 16);
BFI(xEDX, x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 6:
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);
@@ -1073,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);
@@ -1083,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);
@@ -1122,6 +1220,11 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
case 6:
INST_NAME("PUSH Ew");
GETEW(x1);
PUSH16(x1, xESP);
break;
default:
DEFAULT;
}
File diff suppressed because it is too large. Load diff
+12 -12
View File
@@ -41,7 +41,6 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -50,8 +49,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = xEAX+(nextop&7);
emit_add16c(dyn, ninst, ed, i16, x3, x14);
@@ -69,9 +67,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -84,24 +82,24 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0); // put the whole value
SMDMB();
}
DMB_ISH();
}
break;
default:
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
case 0xFF:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ew
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEW(x1);
emit_inc16(dyn, ninst, ed, x3, x14);
EWBACK(x1);
@@ -118,9 +116,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -133,13 +131,14 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
SMDMB();
}
}
break;
case 1: //DEC Ew
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEW(x1);
emit_dec32(dyn, ninst, ed, x3, x14);
EWBACK(x1);
@@ -156,9 +155,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -171,6 +170,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
SMDMB();
}
}
break;
@@ -178,7 +178,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
// default to NO LOCK
addr-=2;
}
DMB_ISH();
SMDMB();
break;
default:
DEFAULT;
+10 -4
View File
@@ -50,7 +50,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -58,6 +58,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
SMWRITE2();
}
break;
@@ -66,12 +67,13 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
}
} else { // mem <= reg
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, x14, ed, 0);
}
@@ -81,12 +83,13 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x14, ed, 0);
SMWRITE2();
}
break;
@@ -98,6 +101,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
SMREAD();
LDR_IMM9(xEAX, x1, 0);
break;
@@ -110,6 +114,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
SMWRITE2();
break;
case 0xFF:
@@ -118,9 +123,10 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
+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;
+144 -70
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, 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, 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, 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, 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, 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, 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, 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,44 +327,58 @@ 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, 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));
BFC(x1, 9, 2); //C1 C2 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
} else {
VMOV_i_64(v2, 0b01110000);
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
} else {
VMOV_i_64(v2, 0b01110000);
}
}
break;
case 0xF3:
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:
@@ -346,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:
@@ -445,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
@@ -505,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
@@ -533,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
@@ -568,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
@@ -589,12 +655,16 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0))
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) {
@@ -608,12 +678,16 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0))
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) {
@@ -624,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;
}
}
+116 -98
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,12 +218,12 @@ 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");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -233,10 +233,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
@@ -248,7 +244,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -258,17 +254,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// The FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (denormal and overflow only)
VMOVfrV(ed, s0);
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:
@@ -276,28 +268,98 @@ 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) {
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);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
}
} else {
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
if(ed!=x1) {
MOV_REG(x1, ed);
}
X87_PUSH_OR_FAIL_empty( , dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
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;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
#endif
}
}
break;
case 7:
INST_NAME("FSTP tbyte");
if(box86_x87_no80bits) {
v1 = x87_get_st(dyn, ninst, x1, x2, 0, 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);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
} else {
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
CALL(arm_fstp, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
@@ -308,86 +370,42 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
}
break;
case 7:
INST_NAME("FSTP tbyte");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
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:
+23 -97
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, 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)) {
@@ -175,7 +175,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
@@ -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,21 +197,17 @@ 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:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
@@ -228,16 +224,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
v1 = x87_get_st(dyn, ninst, x1, x2, 0, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
u8 = x87_setround_reset(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
VCVTR_S32_F32(s0, v1);
} else {
@@ -250,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);
@@ -322,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");
@@ -341,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;
@@ -379,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);
}
}
+34 -34
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);
}
}
@@ -923,7 +923,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
SET_DF(s3, d_dec8);
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
SET_DFNONE(s3);
@@ -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);
}
}
+706 -55
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);
}
}
@@ -154,7 +154,17 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
}
IFX(X_ZF|X_CF) {
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_ZF) {
MOVS_REG_LSR_REG(s1, s1, s2);
} else {
MOV_REG_LSR_REG(s1, s1, s2);
@@ -162,27 +172,16 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF|X_CF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
}
IFX(X_ZF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -203,7 +202,21 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
}
return;
}
IFX(X_ZF|X_CF) {
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, F_CF, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, F_CF, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_ZF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
MOV_REG_LSR_IMM5(s1, s1, c);
@@ -211,28 +224,16 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF|X_CF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
}
IFX(X_ZF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -274,8 +275,567 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF | X_OF) {
RSB_IMM8(s4, s2, 8);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
MOV_REG_LSL_REG(s1, s1, s2);
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
} else IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOV32(s4, 1);
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);}
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c<8) {
IFX(X_CF|X_OF) {
MOV_REG_LSR_IMM5(s3, s1, 8-c);
BFI(xFlags, s3, F_CF, 1);
}
MOV_REG_LSL_IMM5(s1, s1, c);
IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 7);}
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
MOV_REG_LSL_IMM5(s3, s1, c-1);
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_CF, 1);
}
MOVW(s1, 0);
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFC(xFlags, F_SF, 1);
}
IFX(X_PF | X_ZF) {
MOVW(s3, 1);
IFX(X_ZF) {
BFI(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFI(xFlags, s3, F_PF, 1);
}
}
}
}
// emit SHR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
MOV_REG_LSR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, 0, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_OF, 1);
}
}
MOV_REG_LSR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_ASR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
MOV_REG_ASR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
MOV_REG_ASR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
MOV_REG_ASR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF | X_OF) {
RSB_IMM8(s4, s2, 16);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
MOV_REG_LSL_REG(s1, s1, s2);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOV32(s4, 1);
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 15);}
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c<16) {
IFX(X_CF|X_OF) {
MOV_REG_LSR_IMM5(s3, s1, 16-c);
BFI(xFlags, s3, F_CF, 1);
}
MOV_REG_LSL_IMM5(s1, s1, c);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 15);}
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
} else {
IFX(X_CF) {
MOV_REG_LSL_IMM5(s3, s1, c-1);
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_CF, 1);
}
MOVW(s1, 0);
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFC(xFlags, F_SF, 1);
}
IFX(X_PF | X_ZF) {
MOVW(s3, 1);
IFX(X_ZF) {
BFI(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFI(xFlags, s3, F_PF, 1);
}
}
}
}
// emit SHR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 16);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
MOV_REG_LSR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SHR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, 0, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_OF, 1);
}
}
MOV_REG_LSR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_ASR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
MOV_REG_ASR_REG(s1, s1, s2);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
MOV_REG_ASR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
MOV_REG_ASR_IMM5(s1, s1, c);
IFX(X_PEND | X_ZF) {
UXTH(s1, s1, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -366,6 +926,12 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
return;
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
}
IFX(X_CF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
@@ -394,13 +960,15 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
MOV_REG_LSR_IMM5(s4, s1, 31);
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -425,6 +993,12 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
return;
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 32-c);
BFI(xFlags, s3, F_CF, 1);
@@ -436,9 +1010,9 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
IFX(X_OF) {
if(c==1) {
UBFX(s3, s1, (31-c), 1);
XOR_IMM8_COND(cCS, s3, s3, 1);
BFI(xFlags, s3, F_OF, 1);
MOV_REG_LSR_IMM5(s4, s1, 31);
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
@@ -461,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);
}
}
@@ -474,7 +1048,7 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shr32
SET_DF(s4, d_shr32);
SET_DF(s4, d_shrd32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
@@ -484,6 +1058,10 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
IFX(X_CF) {
MOVS_REG_LSR_REG(s1, s1, s3);
} else {
@@ -513,12 +1091,12 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
IFX(X_OF) {
CMPS_IMM8(s3, 31); // 32-c
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
emit_pf(dyn, ninst, s1, s4);
}
}
@@ -531,7 +1109,7 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shl32
SET_DF(s4, d_shl32);
SET_DF(s4, d_shld32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
@@ -544,6 +1122,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
IFX(X_CF) {
RSB_IMM8(s4, s3, 32);
MOV_REG_LSR_REG(s4, s1, s4);
@@ -555,13 +1137,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSL_REG(s1, s1, s3);
}
IFX(X_OF) {
MOVW_COND(cCS, s4, 1);
MOVW_COND(cCC, s4, 0);
CMPS_IMM8(s3, 1);
ORR_REG_LSR_IMM5_COND(cEQ, s4, s4, s1, 30);
CMPS_IMM8(s3, 31); // 32-c
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
//else
BFC_COND(cNE, xFlags, F_OF, 1);
}
RSB_IMM8(s3, s3, 32);
IFX(X_ZF) {
@@ -581,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);
}
}
@@ -602,8 +1181,8 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
return;
}
if(c&7) {
BFI(s1, s1, 24, 8); // duplicate the value for rotate left
MOV_REG_ROR_IMM5(s1, s1, 32-(c&7));
BFI(s1, s1, 8, 8);
MOV_REG_LSR_IMM5(s1, s1, 8-(c&7));
}
//AND_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
@@ -614,7 +1193,7 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
IFX(X_OF) {
if(c==1) {
ADD_REG_LSR_IMM5(s3, s1, s1, 7);
XOR_REG_LSR_IMM8(s3, s1, s1, 7);
BFI(xFlags, s3, F_OF, 1);
}
}
@@ -638,7 +1217,7 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
if(c&7) {
BFI(s1, s1, 8, 8); // duplicate the value for Rotate right
MOV_REG_ROR_IMM5(s1, s1, c&7);
MOV_REG_LSR_IMM5(s1, s1, c&7);
}
IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
@@ -656,3 +1235,75 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
}
}
// emit ROL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_rol16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&15) {
BFI(s1, s1, 16, 16);
MOV_REG_LSR_IMM5(s1, s1, 16-(c&15));
}
IFX(X_PEND) {
UBFX(s1, s1, 0, 16);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
BFI(xFlags, s1, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
XOR_REG_LSR_IMM8(s3, s1, s1, 15);
BFI(xFlags, s3, F_OF, 1);
}
}
}
// emit ROR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_ror16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&15) {
BFI(s1, s1, 16, 16); // duplicate the value for Rotate right
MOV_REG_LSR_IMM5(s1, s1, c&15);
}
IFX(X_PEND) {
UBFX(s1, s1, 0, 16);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 15);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 14);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
}
+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);
}
}
+158 -141
View File
@@ -42,8 +42,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -59,15 +58,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -79,14 +77,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x08:
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -104,15 +101,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -124,7 +120,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x10:
INST_NAME("LOCK ADC Eb, Gb");
@@ -132,8 +128,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -149,7 +144,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x11:
INST_NAME("LOCK ADC Ed, Gd");
@@ -157,8 +152,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -170,7 +164,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x18:
INST_NAME("LOCK SBB Eb, Gb");
@@ -178,8 +172,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -195,7 +188,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x19:
INST_NAME("LOCK SBB Ed, Gd");
@@ -203,8 +196,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -216,14 +208,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x20:
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -241,15 +232,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -261,15 +251,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x28:
INST_NAME("LOCK SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -285,15 +274,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -305,14 +293,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x38:
INST_NAME("LOCK XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -330,15 +317,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
DMB_ISH();
SMDMB();
break;
case 0x39:
INST_NAME("LOCK XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -350,7 +336,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0x66:
@@ -368,8 +354,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_add32c(dyn, ninst, ed, i32, x3, x14);
@@ -389,7 +374,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -403,14 +388,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_or32c(dyn, ninst, ed, i32, x3, x14);
@@ -424,14 +408,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
@@ -445,14 +428,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
@@ -466,13 +448,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_and32c(dyn, ninst, ed, i32, x3, x14);
@@ -486,17 +467,16 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(!fixedaddress) {
@@ -512,7 +492,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -526,18 +506,17 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
STR_IMM9(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
@@ -546,13 +525,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
DMB_ISH();
SMDMB();
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -566,7 +544,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed by a locked write)
#define GO(A) \
case A+0x02: \
case A+0x03: \
@@ -582,18 +560,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#undef GO
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
case 0x87:
DMB_ISH();
--addr;
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
DMB_ISH();
SMDMB();
--addr;
break;
@@ -603,9 +570,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xB0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -640,7 +606,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// AL != Eb
BFI(xEAX, ed, 0, 8);
MARK3;
DMB_ISH();
SMDMB();
// done, do the cmp now
UFLAG_IF {emit_cmp8(dyn, ninst, x1, x2, x3, x14);}
break;
@@ -649,8 +615,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
// same as no lock, all in regs...
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
@@ -679,7 +644,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
// EAX == Ed
STREX(x14, gd, wback);
DMB_ISH();
SMDMB();
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
B_MARK(c__);
@@ -695,7 +660,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARK2(cNE);
STR_IMM9(gd, wback, 0);
DMB_ISH();
SMDMB();
} else {
MARKLOCK;
// alignment is good
@@ -706,7 +671,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x14, gd, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
DMB_ISH();
SMDMB();
}
// end of EAX == Ed or EAX != Ed
MARK;
@@ -721,8 +686,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -736,30 +700,26 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
BIC_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
DMB_ISH();
SMDMB();
break;
case 0xBA:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0, LOCK_LOCK);
@@ -778,26 +738,21 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8&0x1f);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
u8 = F8&0x1f;
ed = x1;
MOVW(gd, u8&0x1f);
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cNE); // bit already set, jump to next instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
BFI(ed, x14, u8, 1);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
@@ -809,26 +764,46 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8&0x1f);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
u8 = F8&0x1f;
ed = x1;
MOVW(gd, u8&0x1f);
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to next instruction
//MOVW(x14, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
BFC(ed, u8, 1);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
case 7:
INST_NAME("LOCK BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8&0x1f;
ed = x1;
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
MOV32(x14, 1);
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
@@ -839,7 +814,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
default:
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
case 0xBB:
INST_NAME("LOCK BTC Ed, Gd");
@@ -847,8 +822,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -870,16 +844,16 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
DMB_ISH();
SMDMB();
break;
case 0xC0:
INST_NAME("LOCK XADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
DMB_ISH();
SMDMB();
GETGB(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -902,15 +876,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
BFI(wback, ed, wb2*8, 8);
}
DMB_ISH();
SMDMB();
break;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
@@ -955,7 +928,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
MOV_REG(gd, x1);
}
DMB_ISH();
SMDMB();
break;
case 0xC7:
@@ -964,7 +937,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
@@ -1001,7 +973,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
DMB_ISH();
SMDMB();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
@@ -1010,20 +982,65 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
default:
// dafault to NO LOCK
addr-=2;
DEFAULT;
}
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;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x14);
} else {
@@ -1039,9 +1056,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1054,13 +1071,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0);
SMDMB();
}
}
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x14);
} else {
@@ -1076,9 +1094,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1091,19 +1109,18 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0);
SMDMB();
}
}
break;
default:
// default to NO LOCK
addr-=2;
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
default:
// default to NO LOCK
--addr;
DEFAULT;
}
return addr;
+66 -10
View File
@@ -24,11 +24,12 @@
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
#define GETEX(a, w) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7,w);\
} else { \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
SMREAD(); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL); \
VLDR_64(a, ed, fixedaddress); \
@@ -67,11 +68,12 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0, d0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -85,7 +87,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
VMOVD(d0, v0);
} else {
@@ -93,17 +95,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
SMWRITE2();
}
break;
case 0x12:
INST_NAME("MOVDDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -129,31 +133,53 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
if(!box86_dynarec_fastround) {
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VCVT_S32_F64(s0, d0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
VMSR(x14); // put back values
}
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(!box86_dynarec_fastround)
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
else
u8 = sse_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
VCVTR_S32_F64(s0, d0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
}
x87_restoreround(dyn, ninst, u8);
break;
@@ -302,9 +328,10 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -337,9 +364,10 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -401,15 +429,43 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_64(v0, v1);
break;
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_8(v1, ed);
}
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(v0<16) {
VCVTR_S32_F64(v0*2, v1);
VCVTR_S32_F64(v0*2+1, v1+1);
} else {
d0 = fpu_get_scratch_double(dyn);
VCVTR_S32_F64(d0*2, v1);
VCVTR_S32_F64(d0*2+1, v1+1);
VMOVD(v0, d0);
}
x87_restoreround(dyn, ninst, u8);
VEOR(v0+1, v0+1, v0+1);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
+50 -16
View File
@@ -24,7 +24,7 @@
// Get Ex as a single, not a quad, with b a intermediary double
#define GETEX(a, b) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
b = sse_get_reg(dyn, ninst, x1, nextop&7,0);\
if(b<16) \
a = b; \
@@ -37,6 +37,7 @@
b = fpu_get_scratch_double(dyn); \
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
SMREAD(); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL); \
VLDR_32(a, ed, fixedaddress); \
@@ -80,7 +81,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
@@ -102,6 +103,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
parity = getedparity(dyn, ninst, addr, nextop, 2);
SMREAD();
if(parity && (v0<16)) {
VEORQ(v0, v0, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
@@ -119,7 +121,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
if(v0<16)
d0 = v0;
@@ -147,15 +149,17 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
}
SMWRITE2();
}
break;
case 0x12:
INST_NAME("MOVSLDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
@@ -169,9 +173,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
@@ -218,7 +223,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
@@ -229,6 +234,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_32(s0, d0*2);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
@@ -238,16 +244,31 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoV(s0, x2);
}
}
if(!box86_dynarec_fastround) {
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VCVT_S32_F32(s0, s0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
VMSR(x14); // put back values
}
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
u8 = sse_setround(dyn, ninst, x1, x2, x14);
if(!box86_dynarec_fastround)
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
else
u8 = sse_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
@@ -258,6 +279,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOV_32(s0, d0*2);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
@@ -269,6 +291,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VCVTR_S32_F32(s0, s0);
VMOVfrV(gd, s0);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, gd, 0b10, 1); // 0x80000000
}
x87_restoreround(dyn, ninst, u8);
break;
@@ -393,9 +420,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5B:
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
@@ -495,11 +523,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDQU Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
@@ -514,14 +543,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
u8 = F8;
// only high part need to be shuffled. VTBL only handle 8bits value, so the 16bits shuffles need to be changed in 8bits
u32 = 0;
@@ -549,11 +579,12 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0, ed);
@@ -565,7 +596,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -576,6 +607,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
SMWRITE2();
}
break;
@@ -634,12 +666,13 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX_empty(v0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VEORQ(v0, v0, v0); // usefull?
VMOV_64(v0, v1);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
@@ -655,7 +688,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v1<16)
v0 = v1;
@@ -666,6 +699,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
v0 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
SMREAD();
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
+385 -94
View File
@@ -27,6 +27,8 @@
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
#include "bridge.h"
#include "arm_printer.h"
#include "custommem.h"
void arm_fstp(x86emu_t* emu, void* p)
{
@@ -60,19 +62,41 @@ 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)
{
int64_t tmp64s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
void arm_frndint(x86emu_t* emu)
{
@@ -102,25 +126,10 @@ 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)(int64_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;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = nearbyint(d);
@@ -129,7 +138,7 @@ int64_t arm_fist64_0(double d)
int64_t arm_fist64_1(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = floor(d);
@@ -138,7 +147,7 @@ int64_t arm_fist64_1(double d)
int64_t arm_fist64_2(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = ceil(d);
@@ -147,20 +156,13 @@ int64_t arm_fist64_2(double d)
int64_t arm_fist64_3(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = trunc(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);
@@ -170,9 +172,22 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
void arm_ud(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
}
void arm_priv(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
}
void arm_singlestep(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGTRAP, (void*)R_EIP, 2);
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -199,15 +214,185 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int64_t tmp64s = lrint(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void arm_aesimc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void arm_aesmc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void arm_aesdlast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
void arm_aeselast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void arm_aesd(x86emu_t* emu, int xmm)
{
arm_aesdlast(emu, xmm);
arm_aesimc(emu, xmm);
}
void arm_aese(x86emu_t* emu, int xmm)
{
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8)
{
sse_regs_t *EX = ((uintptr_t)p>8)?((sse_regs_t*)p):&emu->xmm[(uintptr_t)p];
sse_regs_t *GX = &emu->xmm[gx];
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8)
{
int ex = (((uintptr_t)p)<8)?((uintptr_t)p):-1;
sse_regs_t *EX = (ex==-1)?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
uint64_t result[2] = {0};
uint64_t op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i)) {
result[0] ^= (EX->q[e]<<i);
if(i)
result[1] ^= (EX->q[e]>>(64-i));
}
GX->q[0] = result[0];
GX->q[1] = result[1];
}
void arm_clflush(x86emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
@@ -290,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)
@@ -543,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)
@@ -559,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;
@@ -576,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
@@ -608,6 +811,7 @@ void neoncacheUnwind(neoncache_t* cache)
case NEON_CACHE_XMMW:
cache->ssecache[cache->neoncache[i].n].reg = i+FPUFIRST;
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
cache->neoncache[i] = cache->neoncache[i+1];
++cache->fpu_reg;
++i; // next next
break;
@@ -694,6 +898,12 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
}
return addr;
}
// return Ib on a mod/rm opcode without emiting anything
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
addr = fakeed(dyn, addr, ninst, nextop);
return F8;
}
#undef F8
#undef F32
@@ -702,13 +912,13 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
if(!addr)
if(!addr || !getProtection(addr))
return 0;
if(PK(0)==0xff && PK(1)==0x25) { // absolute jump, maybe the GOT
uintptr_t a1 = (PK32(2)); // need to add a check to see if the address is from the GOT !
addr = (uintptr_t)getAlternate(*(void**)a1);
}
if(addr<0x10000) // too low, that is suspicious
if(addr<0x10000 || !getProtection(addr)) // too low, that is suspicious
return 0;
onebridge_t *b = (onebridge_t*)(addr);
if(b->CC==0xCC && b->S=='S' && b->C=='C' && b->w!=(wrapper_t)0 && b->f!=(uintptr_t)PltResolver) {
@@ -737,62 +947,143 @@ const char* getCacheName(int t, int n)
return buff;
}
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst)
{
// check flags cache
if(dyn->insts[ninst].f_entry.dfnone || dyn->insts[ninst].f_entry.pending)
return 0;
if(dyn->insts[ninst].x86.state_flags)
return 0;
// check neoncache
neoncache_t* n = &dyn->insts[ninst].n;
if(n->news || n->stack || n->stack_next)
return 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].v)
return 0;
return 1;
}
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int jmp = dyn->insts[ninst].x86.jmp_insts;
if(jmp<0)
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
return 1;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending==SF_PENDING || dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
return 0;
}
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int ret = 0;
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
return ret;
}
void inst_name_pass3(dynarec_arm_t* dyn, int ninst, const char* name)
{
if(box86_dynarec_dump) {
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name);
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X sm=%d/%d",
(box86_dynarec_dump>1)?"\e[32m":"",
(void*)(dyn->arm_start+dyn->insts[ninst].address),
dyn->insts[ninst].size/4,
ninst,
dyn->insts[ninst].x86.barrier,
dyn->insts[ninst].x86.state_flags,
dyn->f.pending,
dyn->f.dfnone,
dyn->insts[ninst].x86.may_set?"may":"set",
dyn->insts[ninst].x86.set_flags,
dyn->insts[ninst].x86.gen_flags,
dyn->insts[ninst].x86.use_flags,
dyn->insts[ninst].x86.need_before,
dyn->insts[ninst].x86.need_after,
dyn->smread, dyn->smwrite);
if(dyn->insts[ninst].pred_sz) {
dynarec_log(LOG_NONE, ", pred=");
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);
}
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)
dynarec_log(LOG_NONE, ", jmp=out");
for(int ii=0; ii<24; ++ii) {
switch(dyn->insts[ninst].n.neoncache[ii].t) {
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break;
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break;
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break;
case NEON_CACHE_NONE:
default: break;
}
}
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack)
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack);
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
}
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;
}
+22 -5
View File
@@ -16,19 +16,29 @@ 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);
void arm_fprem1(x86emu_t* emu);
void arm_aesd(x86emu_t* emu, int xmm);
void arm_aese(x86emu_t* emu, int xmm);
void arm_aesdlast(x86emu_t* emu, int xmm);
void arm_aeselast(x86emu_t* emu, int xmm);
void arm_aesimc(x86emu_t* emu, int xmm);
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8);
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8);
void arm_clflush(x86emu_t* emu, void* p);
int64_t arm_fist64_0(double d);
int64_t arm_fist64_1(double d);
int64_t arm_fist64_2(double d);
int64_t arm_fist64_3(double d);
void arm_ud(x86emu_t* emu);
void arm_priv(x86emu_t* emu);
void arm_singlestep(x86emu_t* emu);
#define FPUFIRST 8
@@ -71,9 +81,6 @@ int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_arm_t* dyn, int ninst, int pred);
int getNominalPred(dynarec_arm_t* dyn, int ninst);
@@ -82,10 +89,20 @@ int getNominalPred(dynarec_arm_t* dyn, int ninst);
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
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__
File diff suppressed because it is too large. Load diff
+198 -36
View File
@@ -27,6 +27,35 @@
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
#define MODREG ((nextop&0xC0)==0xC0)
// Strong mem emulation helpers
#define SMREAD_MIN 2
#define SMWRITE_MIN 1
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
// Opcode will read
#define SMREAD() if((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
// Opcode might read (depend on nextop)
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
// Opcode has wrote
#define SMWRITE() dyn->smwrite=1
// Opcode has wrote (strongmem>1 only)
#define SMWRITE2() if(box86_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock || (box86_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
// Opcode might have wrote (depend on nextop)
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
// Start of sequence
#define SMSTART() SMEND()
// End of sequence
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -37,6 +66,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(x1, wback, fixedaddress); \
ed = x1; \
@@ -46,6 +76,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(hint, wback, fixedaddress); \
ed = hint; \
@@ -56,19 +87,21 @@
MOV_REG(ret, ed); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0, NULL); \
ed = ret; \
LDR_IMM9(ed, wback, fixedaddress); \
}
// Write back ed in wback (if wback not 0)
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress);}
// Send back wb to either ed or wback
#define SBACK(wb) if(wback) {STR_IMM9(wb, wback, fixedaddress);} else {MOV_REG(ed, wb);}
#define WBACK if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE();}
// Write back ed in wback (if wback not 0) (SMWRITE2 version)
#define WBACK2 if(wback) {STR_IMM9(ed, wback, fixedaddress); SMWRITE2();}
//GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
#define GETEDO(O) if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
ed = x1; \
@@ -78,19 +111,22 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
ed = x1; \
}
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0);}
#define WBACKO(O) if(wback) {STR_REG_LSL_IMM5(ed, wback, O, 0); SMWRITE();}
//FAKEELike GETED, but doesn't get anything
#define FAKEED if((nextop&0xC0)!=0xC0) { \
addr = fakeed(dyn, addr, ninst, nextop); \
}
// GETGW extract x86 register in gd, that is i
#define GETGW(i) gd = xEAX+((nextop&0x38)>>3); UXTH(i, gd, 0); gd = i;
// GETSGW extract x86 signed register in gd, that is i
#define GETSGW(i) gd = xEAX+((nextop&0x38)>>3); SXTH(i, gd, 0); gd = i;
//GETEWW will use i for ed, and can use w for wback.
#define GETEWW(w, i) if((nextop&0xC0)==0xC0) { \
wback = xEAX+(nextop&7);\
@@ -98,6 +134,7 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
@@ -110,6 +147,7 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
@@ -122,15 +160,16 @@
ed = i; \
wb1 = 0; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSH_IMM8(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
}
// Write ed back to original register / memory
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress);} else {BFI(wback, ed, 0, 16);}
#define EWBACK if(wb1) {STRH_IMM8(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, 0, 16);}
// Write w back to original register / memory
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress);} else {BFI(wback, w, 0, 16);}
#define EWBACKW(w) if(wb1) {STRH_IMM8(w, wback, fixedaddress); SMWRITE();} else {BFI(wback, w, 0, 16);}
// Write back gd in correct register
#define GWBACK BFI((xEAX+((nextop&0x38)>>3)), gd, 0, 16);
//GETEB will use i for ed, and can use r3 for wback.
@@ -142,6 +181,7 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
@@ -156,6 +196,7 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL); \
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
if(wback!=x3) wback = x3; \
@@ -172,13 +213,16 @@
wb1 = 0; \
ed = i; \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSB_IMM8(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
}
// Write eb (ed) back to original register / memory
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress);} else {BFI(wback, ed, wb2*8, 8);}
#define EBBACK if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE();} else {BFI(wback, ed, wb2*8, 8);}
// Write eb (ed) back to original register / memory (SMWRITE2 version)
#define EBBACK2 if(wb1) {STRB_IMM9(ed, wback, fixedaddress); SMWRITE2();} else {BFI(wback, ed, wb2*8, 8);}
//GETGB will use i for gd
#define GETGB(i) gd = (nextop&0x38)>>3; \
gb2 = ((gd&4)>>2); \
@@ -218,22 +262,26 @@
#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);
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKF2 if(dyn->insts) {dyn->insts[ninst].markf2 = (uintptr_t)dyn->arm_size;}
#define GETMARKF2 ((dyn->insts)?dyn->insts[ninst].markf2:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
// Branch to MARK if cond (use j32)
@@ -268,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); \
@@ -279,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); \
@@ -287,16 +335,55 @@
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;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
#define SET_DF(S, N) \
if(N) { \
MOVW(S, N);\
STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); \
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x86.need_after && !(dyn->insts[ninst].x86.need_after&X_PEND)) { \
CALL_(UpdateFlags, -1, 0); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone=0;\
} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
@@ -306,7 +393,7 @@
#ifndef READFLAGS
#define READFLAGS(A) \
if((dyn->f.pending!=SF_SET) \
if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \
&& (dyn->f.pending!=SF_SET_PENDING)) { \
if(dyn->f.pending!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
@@ -330,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: \
@@ -338,7 +427,7 @@
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
#define JUMP(A, C) SMEND()
#endif
#ifndef BARRIER
#define BARRIER(A)
@@ -346,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));}
@@ -404,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_)
@@ -473,10 +566,24 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define emit_shr32 STEPNAME(emit_shr32)
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_shl8 STEPNAME(emit_shl8)
#define emit_shl8c STEPNAME(emit_shl8c)
#define emit_shr8 STEPNAME(emit_shr8)
#define emit_shr8c STEPNAME(emit_shr8c)
#define emit_sar8 STEPNAME(emit_sar8)
#define emit_sar8c STEPNAME(emit_sar8c)
#define emit_shl16 STEPNAME(emit_shl16)
#define emit_shl16c STEPNAME(emit_shl16c)
#define emit_shr16 STEPNAME(emit_shr16)
#define emit_shr16c STEPNAME(emit_shr16c)
#define emit_sar16 STEPNAME(emit_sar16)
#define emit_sar16c STEPNAME(emit_sar16c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_rol8c STEPNAME(emit_rol8c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_ror8c STEPNAME(emit_ror8c)
#define emit_rol16c STEPNAME(emit_rol16c)
#define emit_ror16c STEPNAME(emit_ror16c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
@@ -492,28 +599,34 @@ 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)
#define x87_swapreg STEPNAME(x87_swapreg)
#define sse_setround STEPNAME(sse_setround)
#define sse_setround_reset STEPNAME(sse_setround_reset)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
#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)
#define x87_purgecache STEPNAME(x87_purgecache)
#define mmx_purgecache STEPNAME(mmx_purgecache)
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
#define fpu_unreflectcache STEPNAME(fpu_unreflectcache)
// get the single reg that from the double "reg" (so Dx[idx])
#define fpu_get_single_reg STEPNAME(fpu_get_single_reg)
@@ -538,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);
@@ -606,20 +720,36 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
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)
@@ -636,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)
@@ -644,12 +776,16 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int 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);
// Set rounding according to cw flags, return reg to restore flags, also enable exceptions and reset counters
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// swap 2 x87 regs
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b);
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Set rounding according to mxcsr flags, return reg to restore flags, also enable exceptions and reset counters
int sse_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
@@ -694,17 +830,22 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// forget an SSE reg
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
// sync reg with emu for sse reg (return 1 if reflect was done, s1 = &xmm[a] then)
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
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
@@ -751,4 +892,25 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
#define MAYUSE(A)
#endif
#define NOTEST(s1, s2) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
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, s2) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
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); \
MOVW(s1, offsetof(x86emu_t, test.test)); \
STR_REG_LSL_IMM5(s2, xEmu, s1, 0); \
}
#endif //__DYNAREC_ARM_HELPER_H__
+12
View File
@@ -0,0 +1,12 @@
#include <stdint.h>
#include <stdlib.h>
#include "arm_emitter.h"
#define EMIT(A) *block = (A); ++block
void CreateJmpNext(void* addr, void* next)
{
uint32_t* block = (uint32_t*)addr;
LDR_literal(x2, ((intptr_t)next - (intptr_t)addr)-8);
BX(x2);
}
+169 -79
View File
@@ -21,11 +21,18 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
#include "custommem.h"
#include "elfloader.h"
#ifndef STEP
#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;
@@ -35,16 +42,35 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
uintptr_t init_addr = addr;
MAYUSE(init_addr);
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->f.pending = 0;
dyn->f.dfnone = 0;
dyn->forward = 0;
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;
// ok, go now
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");
@@ -52,44 +78,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->f.pending = 0;
fpu_reset(dyn);
} else {
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",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;
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
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=");
for(int i=0; i<24; ++i)
if(dyn->insts[reset_n].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
MESSAGE(LOG_DEBUG, " ==> ");
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
MESSAGE(LOG_DEBUG, " -> ");
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
if(dyn->n.combined1 || dyn->n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
if(dyn->n.stack_push || dyn->n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
fpu_reset_cache(dyn, ninst, reset_n);
dyn->f = dyn->insts[reset_n].f_exit;
if(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT) {
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
@@ -103,28 +92,33 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
reset_n = -1;
}
// propagate ST stack state, especial stack pop that are defered
if(dyn->n.stack_pop) {
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)) {
if(dyn->n.neoncache[j].n<dyn->n.stack_pop)
dyn->n.neoncache[j].v = 0;
else
dyn->n.neoncache[j].n-=dyn->n.stack_pop;
}
dyn->n.stack_pop = 0;
}
dyn->n.stack = dyn->n.stack_next;
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
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);
}
if(dyn->insts[ninst].pred_sz>1) {SMSTART();}
fpu_reset_scratch(dyn);
if((dyn->insts[ninst].x86.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x86.need_before&~X_PEND);
}
if(box86_dynarec_test) {
MESSAGE(LOG_DUMP, "TEST INIT ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
MOV32(x1, ip);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
MOVW(x2, 1);
CALL(x86test_init, -1, 0);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
#ifdef HAVE_TRACE
if(my_context->dec && box86_dynarec_trace) {
else if(my_context->dec && box86_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
@@ -134,6 +128,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
MOVW(x2, 1);
CALL(PrintTrace, -1, 0);
fpu_unreflectcache(dyn, ninst, x1, x2, x3);
MESSAGE(LOG_DUMP, "----------\n");
}
}
@@ -147,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);
@@ -156,13 +150,27 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->f.dfnone = 0;
}
}
#endif
#ifndef PROT_READ
#define PROT_READ 1
#endif
#if STEP != 0
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
++ii;
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;
MESSAGE(LOG_DEBUG, "Skipping unused opcode\n");
INST_NAME("Skipped opcode");
INST_EPILOG;
addr += dyn->insts[ii].x86.size;
++ii;
}
}
if((dyn->insts[ii].x86.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
@@ -174,43 +182,123 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
}
#else
#ifndef PROT_READ
#define PROT_READ 1
#endif
if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
// 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 && ok>=0) {
// we made it!
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<=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;
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
// else just continue
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&~PROT_READ))
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
&& (((box86_dynarec_bigblock<2) && isJumpTableDefault((void*)next)) || (box86_dynarec_bigblock>1))
/*||(((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
reset_n = -2;
for(int ii=0; ii<ninst; ++ii)
if(dyn->insts[ii].x86.jmp == next) {
reset_n = ii;
ii=ninst;
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) {
if(next<dyn->forward_to)
dyn->forward_to = next;
reset_n = -2;
ok = 1;
} else {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
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);
} else if(next && (next-addr)<30) {
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
if(ok<0) {
ok = 0; need_epilog=1;
#if STEP == 0
if(ninst) {
--ninst;
if(!dyn->insts[ninst].x86.barrier) {
BARRIER(BARRIER_FLOAT);
}
dyn->insts[ninst].x86.need_after |= X_PEND;
++ninst;
}
if(dyn->forward) {
// stopping too soon
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst+1;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
#endif
}
if((ok>0) && dyn->insts[ninst].x86.has_callret)
reset_n = -2;
++ninst;
#if STEP == 0
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
(ok && dyn->size >= 2000))
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
if(dyn->forward) {
// stopping too soon
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst+1;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
#endif
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
if(!box86_dynarec_dump && addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
dynarec_log(LOG_INFO, "Stopping block in no-dynarec zone\n");
--ninst;
if(!dyn->insts[ninst].x86.barrier) {
BARRIER(BARRIER_FLOAT);
@@ -219,16 +307,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->insts[ninst].x86.need_after |= X_PEND;
#endif
++ninst;
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(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
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
return addr;
}
+8 -11
View File
@@ -4,6 +4,7 @@
dyn->isize = addr-sav_addr;\
dyn->insts[ninst].x86.addr = addr;\
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
#define MESSAGE(A, ...)
#define MAYSETFLAGS() dyn->insts[ninst].x86.may_set = 1
#define READFLAGS(A) \
@@ -11,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) if((A)>addr) add_next(dyn, (uintptr_t)(A)); 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*)box_realloc(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; \
@@ -34,12 +31,12 @@
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].x86.has_next = ok;
dyn->insts[ninst].x86.has_next = (ok>0)?1:0;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump || box86_dynarec_missing) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped @ %s (%s:%u) because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, __FUNCTION__, __FILE__, __LINE__, PKip(0), \
PKip(1), PKip(2), PKip(3), \
-1
View File
@@ -2,7 +2,6 @@
#define FINI
#define MESSAGE(A, ...)
#define EMIT(A)
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
+7 -4
View File
@@ -1,13 +1,16 @@
#define INIT dyn->arm_size = 0
#define FINI if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define FINI \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
dyn->insts_size += 1+((dyn->insts[ninst].x86.size>dyn->insts[ninst].size)?dyn->insts[ninst].x86.size:dyn->insts[ninst].size)/15; \
}
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
#define EMIT(A) do{dyn->insts[ninst].size+=4; dyn->arm_size+=4;}while(0)
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
if(ninst && isInstClean(dyn, ninst)) \
++dyn->sons_size; \
dyn->insts_size += 1+((dyn->insts[ninst-1].x86.size>dyn->insts[ninst-1].size)?dyn->insts[ninst-1].x86.size:dyn->insts[ninst-1].size)/15; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
+15 -59
View File
@@ -1,64 +1,20 @@
#define INIT
#define FINI
#define EMIT(A) \
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4;\
dyn->insts[ninst].size2 += 4
#define FINI \
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst].x86.size, dyn->insts[ninst].size/4); \
addInst(dyn->instsize, &dyn->insts_size, 0, 0);
#define EMIT(A) \
do{ \
if(box86_dynarec_dump) print_opcode(dyn, ninst, (uint32_t)(A)); \
if((uintptr_t)dyn->block<(uintptr_t)dyn->next-sizeof(void*))\
*(uint32_t*)(dyn->block) = (uint32_t)(A); \
dyn->block += 4; dyn->arm_size += 4; \
dyn->insts[ninst].size2 += 4; \
}while(0)
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst && isInstClean(dyn, ninst)) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block); \
++dyn->sons_size; \
}
if(ninst) \
addInst(dyn->instsize, &dyn->insts_size, dyn->insts[ninst-1].x86.size, dyn->insts[ninst-1].size/4);
#define INST_EPILOG
#define INST_NAME(name) \
if(box86_dynarec_dump) {\
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
ninst, \
dyn->insts[ninst].x86.barrier, \
dyn->insts[ninst].x86.state_flags, \
dyn->f.pending, \
dyn->f.dfnone, \
dyn->insts[ninst].x86.may_set?"may":"set", \
dyn->insts[ninst].x86.set_flags, \
dyn->insts[ninst].x86.gen_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_before, \
dyn->insts[ninst].x86.need_after); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);\
} \
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)\
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);\
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)\
dynarec_log(LOG_NONE, ", jmp=out");\
for(int ii=0; ii<24; ++ii) { \
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_NONE: \
default: break; \
} \
} \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) \
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack); \
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
}
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name)
+23 -4
View File
@@ -5,6 +5,7 @@
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
@@ -40,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
@@ -68,7 +72,7 @@ typedef struct instruction_arm_s {
int pred_sz; // size of predecessor list
int *pred; // predecessor array
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markf, markf2;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
@@ -90,21 +94,36 @@ typedef struct dynarec_arm_s {
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
uintptr_t jmp_next; // address of the jump_next address
flagcache_t f;
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
int* jmps; // variable array of jump instructions
int jmp_sz;
int jmp_cap;
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
size_t insts_size; // size of the instruction size array (calculated)
uint8_t smread; // for strongmem model emulation
uint8_t smwrite; // for strongmem model emulation
uintptr_t forward; // address of the last end of code while testing forward
uintptr_t forward_to; // address of the next jump to (to check if everything is ok)
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);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
void CreateJmpNext(void* addr, void* next);
#endif //__DYNAREC_ARM_PRIVATE_H_
+22 -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
@@ -44,4 +51,17 @@ typedef struct instruction_x86_s {
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
//#define USE_CUSTOM_MEM
#ifdef USE_CUSTOM_MEM
#define dynaMalloc customMalloc
#define dynaCalloc customCalloc
#define dynaRealloc customRealloc
#define dynaFree customFree
#else
#define dynaMalloc box_malloc
#define dynaCalloc box_calloc
#define dynaRealloc box_realloc
#define dynaFree box_free
#endif
#endif //__DYNAREC_PRIVATE_H_
+5 -3
View File
@@ -233,9 +233,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
@@ -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>
+10 -8
View File
@@ -45,7 +45,9 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_GNU_ATTRIBUTES);
GO(SHT_GNU_HASH);
GO(SHT_GNU_LIBLIST);
GO(SHT_CHECKSUM);
#ifndef TERMUX
GO(SHT_CHECKSUM);
#endif
GO(SHT_LOSUNW);
//GO(SHT_SUNW_move);
GO(SHT_SUNW_COMDAT);
@@ -235,12 +237,12 @@ void DumpMainHeader(Elf32_Ehdr *header, elfheader_t *h)
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
printf_dump(LOG_NEVER, "ELF Dump PEntries (%d)\n", h->numSHEntries);
for (int i=0; i<h->numPHEntries; ++i)
for (uint16_t i=0; i<h->numPHEntries; ++i)
printf_dump(LOG_NEVER, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
printf_dump(LOG_NEVER, "ELF Dump Sections (%d)\n", h->numSHEntries);
for (int i=0; i<h->numSHEntries; ++i)
for (uint16_t i=0; i<h->numSHEntries; ++i)
printf_dump(LOG_NEVER, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
}
@@ -251,7 +253,7 @@ void DumpSymTab(elfheader_t *h)
if(box86_dump && h->SymTab) {
const char* name = ElfName(h);
printf_dump(LOG_NEVER, "ELF Dump SymTab(%d)=\n", h->numSymTab);
for (int i=0; i<h->numSymTab; ++i)
for (uint32_t i=0; i<h->numSymTab; ++i)
printf_dump(LOG_NEVER, " %s:SymTab[%d] = \"%s\", value=%p, size=%d, info/other=%d/%d index=%d\n", name,
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
@@ -263,7 +265,7 @@ void DumpDynamicSections(elfheader_t *h)
{
if(box86_dump && h->Dynamic) {
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
printf_dump(LOG_NEVER, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
}
@@ -274,7 +276,7 @@ void DumpDynSym(elfheader_t *h)
if(box86_dump && h->DynSym) {
const char* name = ElfName(h);
printf_dump(LOG_NEVER, "ELF Dump DynSym(%d)=\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i) {
for (uint32_t i=0; i<h->numDynSym; ++i) {
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
printf_dump(LOG_NEVER, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
}
@@ -286,7 +288,7 @@ void DumpDynamicNeeded(elfheader_t *h)
{
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
for (int i=0; i<h->numDynamic; ++i)
for (uint32_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
@@ -298,7 +300,7 @@ void DumpDynamicRPath(elfheader_t *h)
{
if(box86_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
for (uint32_t i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
+613 -384
View File
File diff suppressed because it is too large. Load diff
+39 -19
View File
@@ -1,10 +1,6 @@
#ifndef __ELFLOADER_PRIVATE_H_
#define __ELFLOADER_PRIVATE_H_
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
#endif
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
@@ -12,24 +8,36 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
#include <elf.h>
#include "elfloader.h"
struct elfheader_s {
typedef struct multiblock_s {
void* p;
uintptr_t offs;
uintptr_t paddr;
uintptr_t align;
size_t size;
size_t asize;
uint8_t flags;
} multiblock_t;
typedef struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
char* soname; // soname of the elf
uint16_t numPHEntries;
Elf32_Phdr *PHEntries;
int numSHEntries;
uint16_t numSHEntries;
Elf32_Shdr *SHEntries;
int SHIdx;
int numSST;
char* SHStrTab;
char* StrTab;
Elf32_Sym* SymTab;
int numSymTab;
uint32_t numSymTab;
char* DynStr;
Elf32_Sym* DynSym;
int numDynSym;
uint32_t numDynSym;
Elf32_Dyn* Dynamic;
int numDynamic;
uint32_t numDynamic;
char* DynStrTab;
int szDynStrTab;
Elf32_Half* VerSym;
@@ -38,8 +46,12 @@ struct elfheader_s {
Elf32_Verdef* VerDef;
int szVerDef;
int e_type;
uint32_t flags;
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;
@@ -70,37 +82,45 @@ struct elfheader_s {
int textsz;
uintptr_t bss;
int bsssz;
uintptr_t ehframe;
uintptr_t ehframe_end;
uintptr_t ehframehdr;
uintptr_t paddr;
uintptr_t vaddr;
int align;
uint32_t align;
uint32_t memsz;
uint32_t reserve;
uint32_t stacksz;
int stackalign;
uint32_t stackalign;
uintptr_t tlsaddr;
uint32_t tlssize;
uint32_t tlsfilesize;
int tlsalign;
uint32_t tlsalign;
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
int init_done;
int fini_done;
int refcnt; // ref count for the elf
int malloc_hook_2; // this elf hook malloc, hacking it
char* memory; // char* and not void* to allow math on memory pointer
void** multiblock;
uintptr_t* multiblock_offs;
uint32_t* multiblock_size;
multiblock_t* multiblocks;
int multiblock_n;
library_t *lib;
needed_libs_t *neededlibs;
needed_libs_t *needed;
FILE* file;
int fileno;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
};
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
} elfheader_t;
#define R_386_NONE 0
#define R_386_32 1
@@ -116,4 +136,4 @@ struct elfheader_s {
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
#endif //__ELFLOADER_PRIVATE_H_
#endif //__ELFLOADER_PRIVATE_H_
+93 -5
View File
@@ -43,7 +43,7 @@ int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
return 0;
}
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, uint32_t* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
@@ -136,7 +136,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_dump(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
printf_dump(LOG_DEBUG, "Read %u Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf32_Shdr));
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
@@ -188,7 +188,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
for (uint32_t i=0; i<h->numDynamic; ++i) {
Elf32_Dyn d = h->Dynamic[i];
Elf32_Word val = d.d_un.d_val;
Elf32_Addr ptr = d.d_un.d_ptr;
@@ -242,8 +242,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#ifndef ANDROID
if(val)
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#endif
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
@@ -273,6 +275,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->VerDef = (Elf32_Verdef*)ptr;
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
case DT_FLAGS:
h->flags = val;
printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags);
break;
}
}
if(h->rel) {
@@ -351,6 +357,17 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->bsssz = h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame");
if(ii) {
h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr");
if(ii) {
h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
@@ -399,3 +416,74 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index)
}
return NULL;
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerDef) {
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname))
return ver->vn_cnt;
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return 0;
}
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname)) {
for(int j=0; j<ver->vn_cnt; ++j) {
if(j==idx)
return h->DynStr+aux->vna_name;
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
return NULL; // idx out of bound, return NULL...
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return NULL;
}
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
{
if(!libname || !ver)
return 0;
int n = GetNeededVersionCnt(h, libname);
if(!n)
return 0;
for(int i=0; i<n; ++i) {
const char* vername = GetNeededVersionString(h, libname, i);
if(vername && !strcmp(ver, vername))
return 1;
}
return 0;
}
+104 -9
View File
@@ -1,4 +1,27 @@
#include <string.h>
#define F8 *(uint8_t*)(addr++)
#define F8S *(int8_t*)(addr++)
#define F16 *(uint16_t*)(addr+=2, addr-2)
#define F16S *(int16_t*)(addr+=2, addr-2)
#define F32 *(uint32_t*)(addr+=4, addr-4)
#define F32S *(int32_t*)(addr+=4, addr-4)
#define F32S64 (uint64_t)(int64_t)F32S
#define F64 *(uint64_t*)(addr+=8, addr-8)
#define F64S *(int64_t*)(addr+=8, addr-8)
#define PK(a) *(uint8_t*)(addr+a)
#ifdef DYNAREC
#define STEP if(step) return 0;
#define STEP2 if(step) {R_EIP = addr; return 0;}
#define STEP3 if(*step) (*step)++;
#else
#define STEP
#define STEP2
#define STEP3
#endif
// ModRM utilities macros
#define MODREG ((nextop&0xC0)==0xC0)
#define getecommon(A, T) \
if(!(nextop&0xC0)) { \
if((nextop&7)==4) { \
@@ -85,7 +108,7 @@
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 0: if((m&7)==6) base = F16S; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
@@ -94,47 +117,119 @@
#define geteb(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommon(A, reg32_t)
#define testeb(A, O) \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else { \
reg32_t* ret; \
getecommono(ret, reg32_t, O);\
test->memsize = 1; \
test->memaddr = (uintptr_t)ret;\
test->mem[0] = ret->byte[0];\
A = (reg32_t*)test->mem;\
}
#define getebo(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommono(A, reg32_t, O)
#define geted(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon(A, reg32_t)
#define getedo(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommono(A, reg32_t, O)
#define tested(A, SZ, O) \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else {\
reg32_t* ret; \
getecommono(ret, reg32_t, O);\
test->memsize = SZ; \
test->memaddr = (uintptr_t)ret;\
memcpy(test->mem, ret->dword, SZ);\
A = (reg32_t*)test->mem;\
}
#define getem(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->mmx[(nextop&7)]; \
} else getecommon(A, mmx87_regs_t)
#define testem(A) \
if(MODREG) { \
A = &emu->mmx[(nextop&7)]; \
} else {\
mmx87_regs_t* ret; \
getecommon(ret, mmx87_regs_t) \
test->memsize = 8; \
test->memaddr = (uintptr_t)ret;\
memcpy(test->mem, ret->ub, 8);\
A = (mmx87_regs_t*)test->mem;\
}
#define getex(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
#define testex(A) \
if(MODREG) { \
A = &emu->xmm[(nextop&7)]; \
} else {\
sse_regs_t* ret; \
getecommon(ret, sse_regs_t);\
test->memsize = 16; \
test->memaddr = (uintptr_t)ret;\
memcpy(test->mem, ret->ub, 16);\
A = (sse_regs_t*)test->mem;\
}
#define getew16(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16(A, reg32_t)
#define getew16o(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16o(A, reg32_t, O)
#define testtew16(A, O) \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else { \
reg32_t* ret; \
getecommon16o(A, reg32_t, O); \
test->memsize = 2; \
test->memaddr = (uintptr_t)ret; \
*(uint16_t*)test->mem = ret->word[0];\
A = (reg32_t*)test->mem; \
}
// Macros for ModR/M gets
#ifdef TEST_INTERPRETER
#define GET_EB testeb(oped, 0)
#define GET_ED tested(oped, 4, 0)
#define GET_ED8 tested(oped, 8, 0)
#define GET_EDT tested(oped, 10, 0)
#define GET_ED_OFFS(o) tested(oped, 4, o)
#define GET_EB_OFFS(o) testeb(oped, o)
#define GET_EM testem(opem)
#define GET_EX testex(opex)
#define GET_EW16 testew16(oped, 0)
#define GET_EW16_OFFS(o) testtew16(oped, o)
#else
#define GET_EB geteb(oped)
#define GET_ED geted(oped)
#define GET_ED8 geted(oped)
#define GET_EDT geted(oped)
#define GET_ED_OFFS(o) getedo(oped, o)
#define GET_EB_OFFS(o) getebo(oped, o)
#define GET_EM getem(opem)
#define GET_EX getex(opex)
#define GET_EW16 getew16(oped)
#define GET_EW16_OFFS(o) getew16o(oped, o)
#endif
#define GET_ED_ geted(oped)
#define GET_EW16_ getew16(oped)
#define EB oped
#define ED oped
#define EM opem
-555
View File
@@ -1,555 +0,0 @@
opcode = F8;
goto *opcodes66[opcode];
#define GO(B, OP) \
_66_##B##_0: \
nextop = F8; \
GET_EB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
NEXT; \
_66_##B##_1: \
nextop = F8; \
GET_EW; \
EW->word[0] = OP##16(emu, EW->word[0], GW.word[0]); \
NEXT; \
_66_##B##_2: \
nextop = F8; \
GET_EB; \
GB = OP##8(emu, GB, EB->byte[0]); \
NEXT; \
_66_##B##_3: \
nextop = F8; \
GET_EW; \
GW.word[0] = OP##16(emu, GW.word[0], EW->word[0]); \
NEXT; \
_66_##B##_4: \
R_AL = OP##8(emu, R_AL, F8); \
NEXT; \
_66_##B##_5: \
R_AX = OP##16(emu, R_AX, F16); \
NEXT;
GO(0x00, add) /* ADD 0x01 ~> 0x05 */
GO(0x08, or) /* OR 0x09 ~> 0x0D */
GO(0x10, adc) /* ADC 0x11 ~> 0x15 */
GO(0x18, sbb) /* SBB 0x19 ~> 0x1D */
GO(0x20, and) /* AND 0x21 ~> 0x25 */
GO(0x28, sub) /* SUB 0x29 ~> 0x2D */
GO(0x30, xor) /* XOR 0x31 ~> 0x35 */
//GO(0x38, cmp) /* CMP 0x39 ~> 0x3D */
#undef GO
_66_0x06: /* PUSH ES */
Push16(emu, emu->segs[_ES]);
NEXT;
_66_0x07: /* POP ES */
emu->segs[_ES] = Pop16(emu); // no check, no use....
emu->segs_serial[_ES] = 0;
NEXT;
_66_0x0F: /* 66 0f prefix */
emu->old_ip = R_EIP;
R_EIP = ip-2; // don't count 66 0F yet
Run660F(emu); // implemented in Run660f.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0x1E: /* PUSH DS */
Push16(emu, emu->segs[_DS]);
NEXT;
_66_0x1F: /* POP DS */
emu->segs[_DS] = Pop16(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
NEXT;
_66_0x26: /* ES: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x2E: /* CS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x36: /* SS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x39:
nextop = F8;
GET_EW;
cmp16(emu, EW->word[0], GW.word[0]);
NEXT;
_66_0x3B:
nextop = F8;
GET_EW;
cmp16(emu, GW.word[0], EW->word[0]);
NEXT;
_66_0x3D:
cmp16(emu, R_AX, F16);
NEXT;
_66_0x3E: /* DS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x40:
_66_0x41:
_66_0x42:
_66_0x43:
_66_0x44:
_66_0x45:
_66_0x46:
_66_0x47: /* INC Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = inc16(emu, emu->regs[tmp8u].word[0]);
NEXT;
_66_0x48:
_66_0x49:
_66_0x4A:
_66_0x4B:
_66_0x4C:
_66_0x4D:
_66_0x4E:
_66_0x4F: /* DEC Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = dec16(emu, emu->regs[tmp8u].word[0]);
NEXT;
_66_0x50:
_66_0x51:
_66_0x52:
_66_0x53:
_66_0x54:
_66_0x55:
_66_0x56:
_66_0x57: /* PUSH Reg */
tmp8u = opcode&7;
Push16(emu, emu->regs[tmp8u].word[0]);
NEXT;
_66_0x58:
_66_0x59:
_66_0x5A:
_66_0x5B:
_66_0x5C:
_66_0x5D:
_66_0x5E:
_66_0x5F: /* POP Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = Pop16(emu);
NEXT;
_66_0x60: /* PUSHA */
tmp16u = R_SP;
Push16(emu, R_AX);
Push16(emu, R_CX);
Push16(emu, R_DX);
Push16(emu, R_BX);
Push16(emu, tmp16u);
Push16(emu, R_BP);
Push16(emu, R_SI);
Push16(emu, R_DI);
NEXT;
_66_0x61: /* POPA */
R_DI = Pop16(emu);
R_SI = Pop16(emu);
R_BP = Pop16(emu);
R_ESP+=2; // POP ESP
R_BX = Pop16(emu);
R_DX = Pop16(emu);
R_CX = Pop16(emu);
R_AX = Pop16(emu);
NEXT;
_66_0x64:
R_EIP = ip-2;
RunFS66(emu, GetFSBaseEmu(emu));
ip = R_EIP;
STEP;
NEXT;
_66_0x66:
goto _0x66; // 0x66 0x66 => can remove one 0x66
_66_0x68: /* PUSH u16 */
tmp16u = F16;
Push16(emu, tmp16u);
NEXT;
_66_0x69: /* IMUL Gw,Ew,Iw */
nextop = F8;
GET_EW;
tmp16u = F16;
GW.word[0] = imul16(emu, EW->word[0], tmp16u);
NEXT;
_66_0x6A: /* PUSH Ib (as signed word) */
tmp16s = F8S;
Push16(emu, (uint16_t)tmp16s);
NEXT;
_66_0x6B: /* IMUL Gw,Ew,Ib */
nextop = F8;
GET_EW;
tmp16s = F8S;
GW.word[0] = imul16(emu, EW->word[0], (uint16_t)tmp16s);
NEXT;
_66_0x81: /* GRP3 Ew,Iw */
_66_0x83: /* GRP3 Ew,Ib */
nextop = F8;
GET_EW;
if(opcode==0x81)
tmp16u = F16;
else {
tmp16s = F8S;
tmp16u = (uint16_t)tmp16s;
}
switch((nextop>>3)&7) {
case 0: EW->word[0] = add16(emu, EW->word[0], tmp16u); break;
case 1: EW->word[0] = or16(emu, EW->word[0], tmp16u); break;
case 2: EW->word[0] = adc16(emu, EW->word[0], tmp16u); break;
case 3: EW->word[0] = sbb16(emu, EW->word[0], tmp16u); break;
case 4: EW->word[0] = and16(emu, EW->word[0], tmp16u); break;
case 5: EW->word[0] = sub16(emu, EW->word[0], tmp16u); break;
case 6: EW->word[0] = xor16(emu, EW->word[0], tmp16u); break;
case 7: cmp16(emu, EW->word[0], tmp16u); break;
}
NEXT;
_66_0x85: /* TEST Ew,Gw */
nextop = F8;
GET_EW;
test16(emu, EW->word[0], GW.word[0]);
NEXT;
_66_0x87: /* XCHG Ew,Gw */
nextop = F8;
GET_EW;
tmp16u = GW.word[0];
GW.word[0] = EW->word[0];
EW->word[0] = tmp16u;
NEXT;
_66_0x89: /* MOV Ew,Gw */
nextop = F8;
GET_EW;
EW->word[0] = GW.word[0];
NEXT;
_66_0x8B: /* MOV Gw,Ew */
nextop = F8;
GET_EW;
GW.word[0] = EW->word[0];
NEXT;
_66_0x8C: /* MOV Ew,Seg */
nextop = F8;
GET_EW;
EW->word[0] = emu->segs[(nextop&0x38)>>3];
NEXT;
_66_0x8E: /* MOV Seg,Ew */
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_serial[((nextop&0x38)>>3)] = 0;
NEXT;
_66_0x8F: /* POP Ew */
nextop = F8;
GET_EW;
EW->word[0] = Pop16(emu);
NEXT;
_66_0x90: /* NOP */
NEXT;
_66_0x91:
_66_0x92:
_66_0x93:
_66_0x94:
_66_0x95:
_66_0x96:
_66_0x97: /* XCHG reg,EAX */
tmp16u = R_AX;
R_AX = emu->regs[opcode&7].word[0];
emu->regs[opcode&7].word[0] = tmp16u;
NEXT;
_66_0x98: /* CBW */
emu->regs[_AX].sword[0] = emu->regs[_AX].sbyte[0];
NEXT;
_66_0x99: /* CWD */
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
NEXT;
_66_0x9C: /* PUSHFW */
CHECK_FLAGS(emu);
Push16(emu, (uint16_t)emu->eflags.x32);
NEXT;
_66_0x9D: /* POPFW */
CHECK_FLAGS(emu);
emu->eflags.x32 &=0xffff0000;
emu->eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
NEXT;
_66_0xA1: /* MOV AX,Ow */
R_AX = *(uint16_t*)F32;
NEXT;
_66_0xA3: /* MOV Ow,AX */
*(uint16_t*)F32 = R_AX;
NEXT;
_66_0xA5: /* MOVSW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
*(uint16_t*)R_EDI = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
NEXT;
_66_0xA7: /* CMPSW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp16u = *(uint16_t*)R_EDI;
tmp16u2 = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
cmp16(emu, tmp16u2, tmp16u);
NEXT;
_66_0xA9: /* TEST AX,Iw */
test16(emu, R_AX, F16);
NEXT;
_66_0xAB: /* STOSW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
*(uint16_t*)R_EDI = R_AX;
R_EDI += tmp8s;
NEXT;
_66_0xAD: /* LODSW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
R_AX = *(uint16_t*)R_ESI;
R_ESI += tmp8s;
NEXT;
_66_0xAF: /* SCASW */
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
cmp16(emu, R_AX, *(uint16_t*)R_EDI);
R_EDI += tmp8s;
NEXT;
_66_0xB8: /* MOV AX,Iw */
_66_0xB9: /* MOV CX,Iw */
_66_0xBA: /* MOV DX,Iw */
_66_0xBB: /* MOV BX,Iw */
_66_0xBC: /* ... */
_66_0xBD:
_66_0xBE:
_66_0xBF:
emu->regs[opcode&7].word[0] = F16;
NEXT;
_66_0xC1: /* GRP2 Ew,Ib */
nextop = F8;
GET_EW;
tmp8u = F8 /*& 0x1f*/;
switch((nextop>>3)&7) {
case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;
case 1: EW->word[0] = ror16(emu, EW->word[0], tmp8u); break;
case 2: EW->word[0] = rcl16(emu, EW->word[0], tmp8u); break;
case 3: EW->word[0] = rcr16(emu, EW->word[0], tmp8u); break;
case 4:
case 6: EW->word[0] = shl16(emu, EW->word[0], tmp8u); break;
case 5: EW->word[0] = shr16(emu, EW->word[0], tmp8u); break;
case 7: EW->word[0] = sar16(emu, EW->word[0], tmp8u); break;
}
NEXT;
_66_0xC7: /* MOV Ew,Iw */
nextop = F8;
GET_EW;
EW->word[0] = F16;
NEXT;
_66_0xCB: /* FAR RET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu); // no check, no use....
emu->segs_serial[_CS] = 0;
// need to check status of CS register!
STEP
NEXT;
_66_0xCC: /* INT3 */
emu->old_ip = R_EIP;
R_EIP = ip-1;
if(my_context->signals[SIGTRAP])
raise(SIGTRAP);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xD1: /* GRP2 Ew,1 */
_66_0xD3: /* GRP2 Ew,CL */
nextop = F8;
GET_EW;
tmp8u=(opcode==0xD3)?R_CL:1;
switch((nextop>>3)&7) {
case 0: EW->word[0] = rol16(emu, EW->word[0], tmp8u); break;
case 1: EW->word[0] = ror16(emu, EW->word[0], tmp8u); break;
case 2: EW->word[0] = rcl16(emu, EW->word[0], tmp8u); break;
case 3: EW->word[0] = rcr16(emu, EW->word[0], tmp8u); break;
case 4:
case 6: EW->word[0] = shl16(emu, EW->word[0], tmp8u); break;
case 5: EW->word[0] = shr16(emu, EW->word[0], tmp8u); break;
case 7: EW->word[0] = sar16(emu, EW->word[0], tmp8u); break;
}
NEXT;
_66_0xD9:
emu->old_ip = R_EIP;
R_EIP = ip;
Run66D9(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xDD:
emu->old_ip = R_EIP;
R_EIP = ip;
Run66DD(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF0: /* LOCK prefix */
emu->old_ip = R_EIP;
R_EIP = ip - 2;
RunLock66(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF2: /* REPNZ prefix */
_66_0xF3: /* REPZ prefix */
nextop = F8;
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp32u = R_ECX;
switch(nextop) {
case 0xA4: /* REP MOVSB */
while(tmp32u) {
--tmp32u;
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
}
break;
case 0xA5: /* REP MOVSW */
while(tmp32u) {
--tmp32u;
*(uint16_t*)R_EDI = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
}
break;
case 0xA7: /* REP(N)Z CMPSW */
tmp16u = 0;
tmp16u2 = 0;
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
tmp16u2 = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
if((tmp16u==tmp16u2)==(opcode==0xF2))
break;
}
if(R_ECX) cmp16(emu, tmp16u2, tmp16u);
break;
case 0xAB: /* REP STOSW */
while(tmp32u) {
--tmp32u;
*(uint16_t*)R_EDI = R_AX;
R_EDI += tmp8s;
}
break;
case 0xAD: /* REP LODSW */
while(tmp32u) {
--tmp32u;
R_AX = *(uint16_t*)R_ESI;
R_ESI += tmp8s;
}
break;
case 0xAF: /* REP(N)Z SCASW */
tmp16u = 0;
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
R_EDI += tmp8s;
if((R_AX==tmp16u)==(opcode==0xF2))
break;
}
if(R_ECX) cmp16(emu, R_AX, tmp16u);
break;
default:
goto _default;
}
R_ECX = tmp32u;
NEXT;
_66_0xF5: /* CMC */
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
NEXT;
_66_0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
GET_EW;
switch((nextop>>3)&7) {
case 0:
case 1: /* TEST Ew,Iw */
test16(emu, EW->word[0], F16);
break;
case 2: /* NOT Ew */
EW->word[0] = not16(emu, EW->word[0]);
break;
case 3: /* NEG Ew */
EW->word[0] = neg16(emu, EW->word[0]);
break;
case 4: /* MUL AX,Ew */
mul16(emu, EW->word[0]);
break;
case 5: /* IMUL AX,Ew */
imul16_eax(emu, EW->word[0]);
break;
case 6: /* DIV Ew */
div16(emu, EW->word[0]);
break;
case 7: /* IDIV Ew */
idiv16(emu, EW->word[0]);
break;
}
NEXT;
_66_0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
NEXT;
_66_0xF9: /* STC */
CHECK_FLAGS(emu);
SET_FLAG(F_CF);
NEXT;
_66_0xFF: /* GRP 5 Ew */
nextop = F8;
GET_EW;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
EW->word[0] = inc16(emu, EW->word[0]);
break;
case 1: /* DEC Ed */
EW->word[0] = dec16(emu, EW->word[0]);
break;
case 6:
Push16(emu, EW->word[0]);
break;
default:
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 66 %02X %02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
}
NEXT;
+127
View File
@@ -0,0 +1,127 @@
#include <stdint.h>
#include "box86stack.h"
#include "x86emu.h"
#include "x86run_private.h"
#include "x86emu_private.h"
#include "x86compstrings.h"
static int overrideIfDataInvalid(sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, int j, int i, int imm8)
{
int valid1 = (i<lreg);
int valid2 = (j<lmem);
if(!valid1 && !valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01: return 0;
case 0b10:
case 0b11: return 1;
}
if(!valid1 && valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01:
case 0b10: return 0;
case 0b11: return 1;
}
if(valid1 && !valid2)
return 0;
switch((imm8>>2)&3) {
case 0b01: // range
switch (imm8&3) {
case 0b00: // ub
return (i&1)?((reg->ub[i]>=mem->ub[j])):((reg->ub[i]<=mem->ub[j]));
case 0b01: // uw
return (i&1)?((reg->uw[i]>=mem->uw[j])):((reg->uw[i]<=mem->uw[j]));
case 0b10: // sb
return (i&1)?((reg->sb[i]>=mem->sb[j])):((reg->sb[i]<=mem->sb[j]));
case 0b11: // sw
return (i&1)?((reg->sw[i]>=mem->sw[j])):((reg->sw[i]<=mem->sw[j]));
}
break;
default: // the others
switch (imm8&1) {
case 0: // byte
return (reg->ub[i] == mem->ub[j]);
case 1: // word
return (reg->uw[i] == mem->uw[j]);
}
}
}
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, uint8_t imm8)
{
// get number of packed byte/word
int n_packed = (imm8&1)?8:16;
if(lreg<0) lreg = -lreg;
if(lmem<0) lmem = -lmem;
if(lreg>n_packed) lreg = n_packed;
if(lmem>n_packed) lmem = n_packed;
// aggregate to intres1
uint32_t intres1 = 0;
switch((imm8>>2)&3) {
case 0b00: //Equal any
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8)<<j;
}
break;
case 0b01: // Range
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; i+=2) {
intres1 |= (overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8) & overrideIfDataInvalid(mem, lmem, reg, lreg, j, i+1, imm8))<<j;
}
break;
case 0b10: // Equal each
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, i, i, imm8)<<i;
}
break;
case 0b11: // Equal ordered
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;
}
// build intres2
uint32_t intres2 = intres1;
switch((imm8>>4)&3) {
case 0b01: intres2 ^= ((1<<n_packed)-1); break;
case 0b11: intres2 ^= ((1<<lmem)-1); break;
}
// and now set the flags
RESET_FLAGS(emu);
CONDITIONAL_SET_FLAG(intres2, F_CF);
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
CONDITIONAL_SET_FLAG(((!intres2) && (lmem==n_packed)), F_AF);
CLEAR_FLAG(F_PF);
return intres2;
}
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* mem, sse_regs_t* reg, uint8_t imm8)
{
int lmem = 0;
int lreg = 0;
// get lmem and lreg
if(imm8&1) {
while(lmem<8 && mem->uw[lmem]) ++lmem;
while(lreg<8 && reg->uw[lreg]) ++lreg;
} else {
while(lmem<16 && mem->ub[lmem]) ++lmem;
while(lreg<16 && reg->ub[lreg]) ++lreg;
}
return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8);
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef __X86_CMPSTRINGS_H__
#define __X86_CMPSTRINGS_H__
#include <stdint.h>
#include "regs.h"
typedef struct x86emu_s x86emu_t;
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* a, int la, sse_regs_t* b, int lb, uint8_t imm8);
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8);
#endif //__X86_CMPSTRINGS_H__
+89 -42
View File
@@ -23,6 +23,13 @@
#ifdef DYNAREC
#include "custommem.h"
#endif
// for the applyFlushTo0
#ifdef __i386__
#include <immintrin.h>
#elif defined(__arm__)
#else
#warning Architecture cannot follow SSE Flush to 0 flag
#endif
typedef struct cleanup_s {
void* f;
@@ -42,22 +49,6 @@ static uint32_t x86emu_parity_tab[8] =
0x69969669,
};
uint32_t* GetParityTab()
{
return x86emu_parity_tab;
}
void PushExit(x86emu_t* emu)
{
uintptr_t endMarker = AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
Push(emu, endMarker);
}
void* GetExit()
{
return (void*)AddCheckBridge(my_context->system, NULL, NULL, 0, "(ExitEmulation)");
}
static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
emu->context = context;
@@ -81,13 +72,13 @@ static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t s
emu->segs[_GS] = 0x33;
// setup fpu regs
reset_fpu(emu);
emu->mxcsr = 0x1f80;
emu->mxcsr.x32 = 0x1f80;
}
EXPORTDYN
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
printf_log(LOG_DEBUG, "%04d|Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
x86emu_t *emu = (x86emu_t*)box_calloc(1, sizeof(x86emu_t));
@@ -98,7 +89,7 @@ x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, i
x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
printf_log(LOG_DEBUG, "%04d|New X86 Emu from stack, with EIP=%p and Stack=%p/0x%X\n", GetTID(), (void*)start, (void*)stack, stacksize);
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
@@ -108,6 +99,7 @@ x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t s
EXPORTDYN
void SetupX86Emu(x86emu_t *emu)
{
(void)emu;
printf_log(LOG_DEBUG, "Setup X86 Emu\n");
}
@@ -128,6 +120,7 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
void AddCleanup(x86emu_t *emu, void *p)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -139,6 +132,7 @@ void AddCleanup(x86emu_t *emu, void *p)
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -188,6 +182,11 @@ void FreeX86Emu(x86emu_t **emu)
return;
printf_log(LOG_DEBUG, "%04d|Free a X86 Emu (%p)\n", GetTID(), *emu);
if((*emu)->test.emu) {
internalFreeX86((*emu)->test.emu);
box_free((*emu)->test.emu);
(*emu)->test.emu = NULL;
}
internalFreeX86(*emu);
box_free(*emu);
@@ -215,19 +214,47 @@ 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;
newemu->fpu_stack = emu->fpu_stack;
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
newemu->df = emu->df;
newemu->op1 = emu->op1;
newemu->op2 = emu->op2;
newemu->res = emu->res;
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
newemu->error = emu->error;
}
void CopyEmu(x86emu_t *newemu, const x86emu_t* emu)
{
memcpy(newemu->regs, emu->regs, sizeof(emu->regs));
memcpy(&newemu->ip, &emu->ip, sizeof(emu->ip));
memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags));
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memcpy(newemu->segs_serial, emu->segs_serial, sizeof(emu->segs_serial));
memcpy(newemu->segs_offs, emu->segs_offs, sizeof(emu->segs_offs));
memcpy(newemu->x87, emu->x87, sizeof(emu->x87));
memcpy(newemu->mmx, emu->mmx, sizeof(emu->mmx));
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));
newemu->fpu_tags = emu->fpu_tags;
newemu->cw = emu->cw;
newemu->sw = emu->sw;
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
newemu->df = emu->df;
newemu->op1 = emu->op1;
newemu->op2 = emu->op2;
newemu->res = emu->res;
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);
}
box86context_t* GetEmuContext(x86emu_t* emu)
@@ -301,7 +328,8 @@ void ResetFlags(x86emu_t *emu)
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
{
static char buff[800];
char* regname[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
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) {
@@ -322,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);
@@ -386,8 +420,6 @@ void UnimpOpcode(x86emu_t* emu)
tid, (void*)emu->old_ip, Peek(emu, -1),
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
void EmuCall(x86emu_t* emu, uintptr_t addr)
@@ -404,9 +436,9 @@ void EmuCall(x86emu_t* emu, uintptr_t addr)
Run(emu, 0);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
if(emu->quitonlongjmp==1)
emu->longjmp = 0; // don't change anything because of the longjmp
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
@@ -458,14 +490,15 @@ static inline void init_perfcounters (int32_t do_reset, int32_t enable_divider)
uint64_t ReadTSC(x86emu_t* emu)
{
(void)emu;
// Read the TimeStamp Counter as 64bits.
// this is supposed to be the number of instructions executed since last reset
#if defined(__i386__)
uint64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
#if 0
#elif defined(__ARM_ARCH)
#if 0
#if (__ARM_ARCH >= 6)
static int init = 1;
if(init) {
@@ -497,3 +530,17 @@ void ResetSegmentsCache(x86emu_t *emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
void applyFlushTo0(x86emu_t* emu)
{
#ifdef __i386__
_mm_setcsr(_mm_getcsr() | (emu->mxcsr.x32&0x8040));
#elif defined(__arm__)
uint64_t fpscr = __builtin_arm_get_fpscr();
fpscr &= ~(1<<24); // clear bit FZ (24)
fpscr |= (emu->mxcsr.f.MXCSR_FZ)<<24; // set FZ as mxcsr FZ
__builtin_arm_set_fpscr(fpscr);
#else
(void)emu;
#endif
}
+38 -6
View File
@@ -23,11 +23,38 @@ typedef struct forkpty_s {
void* f; // forkpty function
} forkpty_t;
typedef struct x86emu_s x86emu_t;
typedef struct x86test_s {
x86emu_t* emu;
uintptr_t memaddr;
int memsize;
int test;
int clean;
uint8_t mem[16];
} x86test_t;
typedef struct emu_flags_s {
uint32_t need_jmpbuf:1; // need a new jmpbuff for signal handling
uint32_t quitonlongjmp:2; // quit if longjmp is called
uint32_t quitonexit:2; // quit if exit/_exit is called
uint32_t longjmp:1; // if quit because of longjmp
uint32_t jmpbuf_ready:1; // the jmpbuf in the emu is ok and don't need refresh
} emu_flags_t;
#ifdef ANDROID
#include <setjmp.h>
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
typedef struct x86emu_s {
// cpu
reg32_t regs[8];
x86flags_t eflags;
reg32_t ip;
uintptr_t xSPSave;
// fpu / mmx
x87control_t cw;
x87flags_t sw;
@@ -35,12 +62,12 @@ 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];
uint32_t mxcsr;
mmxcontrol_t mxcsr;
uintptr_t old_ip;
// defered flags
defered_flags_t df;
@@ -52,17 +79,18 @@ typedef struct x86emu_s {
uintptr_t prev2_ip, prev_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uint16_t segs[6];
uint16_t dummy_seg6, dummy_seg7; // to stay aligned
uintptr_t segs_offs[6]; // computed offset associate with segment
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
int fork; // quit because need to fork
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
forkpty_t* forkpty_info;
emu_flags_t flags;
x86test_t test; // used for dynarec testing
// parent context
box86context_t *context;
// cpu helpers
@@ -74,6 +102,8 @@ typedef struct x86emu_s {
void* stack2free; // this is the stack to free (can be NULL)
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
@@ -88,4 +118,6 @@ typedef struct x86emu_s {
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
void applyFlushTo0(x86emu_t* emu);
#endif //__X86EMU_PRIVATE_H_
+98 -79
View File
@@ -10,6 +10,7 @@
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <wait.h>
#include "debug.h"
#include "box86stack.h"
@@ -42,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);
@@ -50,20 +53,19 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
// error...
} else if(v!=0) {
// execute atforks parent functions
for (int i=0; i<my_context->atfork_sz; --i)
for (int i=0; i<my_context->atfork_sz; ++i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<my_context->atfork_sz; --i)
for (int i=0; i<my_context->atfork_sz; ++i)
if(my_context->atforks[i].child)
EmuCall(emu, my_context->atforks[i].child);
}
R_EAX = v;
return emu;
}
void emit_signal(x86emu_t* emu, int sig, void* addr, int code); // in signals.c
extern int errno;
void x86Int3(x86emu_t* emu)
{
@@ -87,6 +89,8 @@ void x86Int3(x86emu_t* emu)
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG || cycle_log) {
int tid = GetTID();
const char *s = NULL;
s = GetNativeName((void*)addr);
char t_buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
@@ -99,210 +103,223 @@ void x86Int3(x86emu_t* emu)
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = NULL;
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", cycle_log?"PltResolver ":" ... ");
} else
if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, "glColor4f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
} else if(strstr(s, "glTexCoord2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex3f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
} else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "opendir")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
perr = 1;
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "my_open64")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "shm_open")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "mkdir")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 2;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
} else if(!strcmp(s, "chdir")) {
pu32=*(uint32_t**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "putenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(!strcmp(s, "read")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "statvfs64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "index")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "__xstat")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "sem_timedwait")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
perr = 1;
} else if(strstr(s, "waitpid")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
post = 1;
pu32 = *(uint32_t**)(R_ESP+8);
} else if(strstr(s, "semop")==s) {
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 3;
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, 255, "%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));
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) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, "strstr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %u, %p(\"%s\")...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(void**)(R_ESP+12), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "__vsprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "__snprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "printf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "wprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
} else if(strstr(s, "__vswprintf")==s) {
if(*(size_t*)(R_ESP+12)<2) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
}
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vfprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
snprintf(buff, 256, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vkGetInstanceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
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, "vkGetDeviceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
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, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
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, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, "XCreateWindow")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
} else if(strstr(s, "XLoadQueryFont")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
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, "pthread_mutex_lock")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(!strcmp(s, "fmodf")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(!strcmp(s, "fmod")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
} else if(strstr(s, "SDL_GetWindowSurface")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
snprintf(buff, 256, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
snprintf(buff, 256, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
snprintf(buff, 256, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else if(strstr(s, "___tls_get_addr")) {
snprintf(buff, 256, "%04d|%p: Calling %s(%p[%d, %d])", tid, *(void**)(R_ESP), s, (void*)(R_EAX), ((int*)(R_EAX))[0], ((int*)(R_EAX))[1]);
} 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 {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
snprintf(buff, 256, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
}
if(!cycle_log) {
pthread_mutex_lock(&emu->context->mutex_trace);
mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
mutex_unlock(&emu->context->mutex_trace);
}
w(emu, addr); // some function never come back, so unlock the mutex first!
if(post)
switch(post) {
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?(int32_t)pu32[0]:-1, pu32?(int32_t)pu32[1]:-1);
break;
case 2: snprintf(buff2, 63, "(%s)", R_EAX?((char*)R_EAX):"nil");
break;
@@ -320,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));
@@ -330,17 +349,17 @@ void x86Int3(x86emu_t* emu)
if(cycle_log)
snprintf(buffret, 127, "0x%X%s%s", R_EAX, buff2, buff3);
else {
pthread_mutex_lock(&emu->context->mutex_trace);
mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
mutex_unlock(&emu->context->mutex_trace);
}
} else
w(emu, addr);
}
return;
}
if(0 && my_context->signals[SIGTRAP])
raise(SIGTRAP);
if(1 && my_context->signals[SIGTRAP])
emit_signal(emu, SIGTRAP, (void*)R_EIP, 128);
else
printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_EIP);
//emu->quit = 1;
@@ -362,4 +381,4 @@ void print_cycle_log(int loglevel) {
}
}
}
}
}
+27 -37
View File
@@ -484,10 +484,8 @@ uint8_t rcl8(x86emu_t *emu, uint8_t d, uint8_t s)
CONDITIONAL_SET_FLAG(cf, F_CF);
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized this expression since it appears to
be causing OF to be misset */
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 7)) & 0x1, F_OF);
}
return (uint8_t)res;
@@ -513,8 +511,8 @@ uint16_t rcl16(x86emu_t *emu, uint16_t d, uint8_t s)
res |= 1 << (cnt - 1);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF);
}
return (uint16_t)res;
}
@@ -539,8 +537,8 @@ uint32_t rcl32(x86emu_t *emu, uint32_t d, uint8_t s)
res |= 1 << (cnt - 1);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 31)) & 0x1, F_OF);
}
return res;
}
@@ -592,6 +590,11 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
(i.e. packed bit array or unpacked.)
*/
ocf = ACCESS_FLAG(F_CF) != 0;
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized... */
CONDITIONAL_SET_FLAG((ocf ^ (d >> 7)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
@@ -620,13 +623,6 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
}
/* set the new carry flag, based on the variable "cf" */
CONDITIONAL_SET_FLAG(cf, F_CF);
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized... */
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
F_OF);
}
}
return (uint8_t)res;
}
@@ -648,6 +644,8 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
if (cnt == 1) {
cf = d & 0x1;
ocf = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG((ocf ^ (d >> 15)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
mask = (1 << (16 - cnt)) - 1;
@@ -657,10 +655,6 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
res |= 1 << (16 - cnt);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
F_OF);
}
}
return (uint16_t)res;
}
@@ -682,6 +676,8 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
if (cnt == 1) {
cf = d & 0x1;
ocf = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG((ocf ^ (d >> 31)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
mask = (1 << (32 - cnt)) - 1;
@@ -692,10 +688,6 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
res |= 1 << (32 - cnt);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
F_OF);
}
}
return res;
}
@@ -885,8 +877,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
(ACCESS_FLAG(F_CF) != 0)), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -927,8 +918,7 @@ uint32_t shld32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
(ACCESS_FLAG(F_CF) != 0)), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -959,7 +949,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -1005,7 +995,7 @@ uint32_t shrd32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -1044,14 +1034,14 @@ Implements the SBB instruction and side effects.
****************************************************************************/
uint16_t sbb16(x86emu_t *emu, uint16_t d, uint16_t s)
{
uint32_t res; /* all operands in native machine order */
uint32_t bc;
uint32_t res; /* all operands in native machine order */
uint32_t bc;
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
res = d - s - 1;
else
res = d - s;
res = d - s - 1;
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
@@ -1075,9 +1065,9 @@ uint32_t sbb32(x86emu_t *emu, uint32_t d, uint32_t s)
CHECK_FLAGS(emu);
if (ACCESS_FLAG(F_CF))
res = d - s - 1;
else
res = d - s;
res = d - s - 1;
else
res = d - s;
CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
+3
View File
@@ -247,6 +247,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint8_t not8(x86emu_t *emu, uint8_t s)
{
(void)emu;
return ~s;
}
@@ -256,6 +257,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint16_t not16(x86emu_t *emu, uint16_t s)
{
(void)emu;
return ~s;
}
@@ -265,6 +267,7 @@ Implements the NOT instruction
****************************************************************************/
static inline uint32_t not32(x86emu_t *emu, uint32_t s)
{
(void)emu;
return ~s;
}
+1031 -1031
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Loaded 100 of 948 files, more files were not shown because too many files have changed in this diff. Show more