Author SHA1 Message Date
ptitSeb 157d368939 Optimized Exit bridge managment 2023-05-10 17:27:31 +02:00
ptitSeb ea7eb6f866 Improved custom memory allocator 2023-05-10 16:23:28 +02:00
ptitSeb c6cdde4b53 Fixed a nasty small memory leak 2023-05-10 16:22:56 +02:00
ptitSeb df71c7da43 [DYNAREC] Removed all remaining trace of dynablocklist_t 2023-05-09 14:53:13 +02:00
ptitSeb ec8f7a6179 Added some more libgstreamer wrapped functions 2023-05-09 14:45:08 +02:00
ptitSeb cbbe23606d [DYNAREC] Fixed some remaining issues (PvZ works now) 2023-05-08 13:30:43 +02:00
ptitSeb 1c4898754f [DYNAREC] Removed DynablockList, backported from Box64 (PvZ broken for now) 2023-05-08 13:30:43 +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
308 changed files with 23107 additions and 10570 deletions

No files matched your search

+6 -6
View File
@@ -34,21 +34,21 @@ jobs:
include:
- platform: TEGRAX1
type: Release
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1
type: Trace
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1ARM32
type: Release
os: ubuntu-18.04
os: ubuntu-20.04
- platform: TEGRAX1ARM32
type: Trace
os: ubuntu-18.04
os: ubuntu-20.04
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Environment preparation"
run: |
@@ -111,7 +111,7 @@ jobs:
ctest -j$(nproc)
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
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
+96 -18
View File
@@ -5,10 +5,12 @@ 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(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})
@@ -18,6 +20,8 @@ option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
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(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(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
@@ -25,10 +29,16 @@ option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${
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 ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 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(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
@@ -61,7 +71,7 @@ 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))
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR RK3588 OR ARM64))
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
@@ -81,6 +91,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,6 +115,11 @@ 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)
@@ -133,6 +149,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)
@@ -160,6 +185,10 @@ elseif(ARM_DYNAREC)
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
if(POWER9)
add_definitions(-mcpu=power9 -mtune=power9)
endif()
@@ -260,6 +289,7 @@ 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/wine_tools.c"
"${BOX86_ROOT}/src/elfs/elfloader.c"
"${BOX86_ROOT}/src/elfs/elfparser.c"
@@ -270,9 +300,6 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/librarian/symbols.c"
"${BOX86_ROOT}/src/librarian/globalsymbols.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,7 +307,6 @@ 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"
@@ -297,6 +323,33 @@ 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/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"
@@ -327,6 +380,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"
@@ -408,6 +462,7 @@ 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"
@@ -418,6 +473,7 @@ set(WRAPPEDS
"${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 +518,7 @@ 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"
)
if(ANDROID)
list(APPEND WRAPPEDS
@@ -515,7 +572,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 +622,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 +635,7 @@ if(ARM_DYNAREC)
$<TARGET_OBJECTS:arm_pass1>
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
$<TARGET_OBJECTS:test_interpreter>
)
endif()
@@ -583,16 +645,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 +666,9 @@ else()
endif()
if(ARM_DYNAREC)
if(ANDROID)
target_link_libraries(${BOX86} dynarec m dl)
target_link_libraries(${BOX86} dynarec interpreter m dl)
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")
@@ -630,7 +694,9 @@ else()
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")
@@ -649,12 +715,17 @@ endif()
if(NOT _x86 AND NOT _x86_64)
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/)
if(NOT NO_CONF_INSTALL)
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}/system/box86.box86rc DESTINATION /etc/)
endif()
if(NOT NO_LIB_INSTALL)
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/)
endif()
endif()
if(NOT TARGET uninstall)
@@ -784,7 +855,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
@@ -810,4 +881,11 @@ foreach(file ${extension_tests})
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
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")
endif(BOX86LIB)
+61
View File
@@ -1,3 +1,64 @@
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
+2 -1
View File
@@ -6,7 +6,8 @@
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
+18
View File
@@ -1,3 +1,21 @@
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
+34 -3
View File
@@ -6,10 +6,12 @@ You can use [@Itai-Nelken](https://github.com/Itai-Nelken)'s apt repository to i
```
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 -
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/box86-debs-archive-keyring.gpg
sudo apt update && sudo apt install box86 -y
```
**Note:** On a 64bit OS, install the `box86:armhf` package.
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
#### for Pandora
@@ -52,7 +54,7 @@ _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
@@ -70,6 +72,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`
@@ -94,12 +112,25 @@ 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 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`
@@ -163,5 +194,5 @@ NVIDIA doesn't provide armhf libraries for their GPU drivers at this time. There
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`.
+22 -8
View File
@@ -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/).
@@ -76,6 +76,15 @@ 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: `~/.bashrc` > `/etc/box86.box86rc` > command line
So, your settings in `~/.bashrc` may override the setting from your command line...
----
Notes about Unity game emulation
----
@@ -87,15 +96,20 @@ 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.
to disable `steamwebhelper` when box64 installed and running, create (or edit) `~/.box64rc` and add:
```
[steamwebhelper]
BOX64_EXIT=1
```
in it and it will be disable. Comment with a `#` those 2 lines to enable it again
----
+98 -43
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,173 +28,223 @@ 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.
#### 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
#### 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 like on x86
* 1 : Don't do anything special with edge case Rounding, to go as fast as possible (no INF/NAN/Overflow -> MIN_INT conversion) (faster, Default)
#### 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_HOTPAGE *
Handling of HotPage (Page beeing both executed and writen)
* 0 : Don't track hotpage
* 1-255 : Trak HotPage, and disable execution of a page beeing writen for N attempts (default is 16)
#### BOX86_DYNAREC_FASTPAGE *
Will use a faster handling of HotPage (Page being both executed and written)
* 0 : use regular hotpage (Default)
* 1 : Use faster hotpage, taking the risk of running obsolete JIT code (might be faster, but more prone to crash)
#### BOX86_DYNAREC_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_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_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_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.)
@@ -206,22 +257,22 @@ 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_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.
@@ -230,7 +281,8 @@ Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a va
Define where to find box64 binary
* yyyy
Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
#### BOX86_JITGDB
#### 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 +293,6 @@ 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)
#### BOX86_NORCFILES
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
+11 -2
View File
@@ -21,19 +21,28 @@ cd ../ && rm -rf ./tmp/
echo "#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > 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 libncurses5: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
# 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
}
+50
View File
@@ -0,0 +1,50 @@
# 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')
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:
+1 -1
View File
@@ -1249,7 +1249,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'
+35 -13
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();
@@ -82,11 +85,20 @@ int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#ifdef DYNAREC
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 +112,6 @@ int unlockMutex()
GO(my_context->mutex_thread, 10)
GO(my_context->mutex_bridge, 11)
#undef GO
return ret;
}
@@ -108,7 +119,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 +138,30 @@ void relockMutex(int locks)
static void init_mutexes(box86context_t* context)
{
#ifdef DYNAREC
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);
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)
@@ -205,9 +224,12 @@ box86context_t *NewBox86Context(int argc)
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
@@ -233,7 +255,7 @@ box86context_t *NewBox86Context(int argc)
return context;
}
void freeALProcWrapper(box86context_t* context);
EXPORTDYN
void FreeBox86Context(box86context_t** context)
{
@@ -342,17 +364,17 @@ void FreeBox86Context(box86context_t** context)
finiAllHelpers(ctx);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#else
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);
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
freeCycleLog(ctx);
+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 1
#endif //__BOX86_VERSION_H_
+592 -379
View File
File diff suppressed because it is too large. Load diff
+6
View File
@@ -390,6 +390,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) )
@@ -820,6 +822,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 +845,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
+101 -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,117 @@ 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
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:
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}
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
+196 -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,239 +79,100 @@ 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;
}
@@ -311,114 +188,120 @@ void cancelFillBlock()
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)) {
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);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->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);
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
if(db && db->done && db->block && getNeedTest(addr)) {
if(db->always_test)
sched_yield(); // just calm down...
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
emu->test.test = 0;
if(box86_dynarec_fastpage) {
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
if(hash==db->hash) { // seems ok, run it without reprotecting it
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
return db;
}
db->done = 0; // invalidating the block, it's already not good
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 1);
return NULL; // not building a new one, it's still a hotpage
} else {
dynarec_log(LOG_INFO, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
return NULL;
}
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
int need_lock = mutex_trylock(&my_context->mutex_dyndump);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
// 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, need_lock);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
protectDB((uintptr_t)db->x86_addr, db->x86_size);
// fill back jumptable
if(isprotectedDB((uintptr_t)db->x86_addr, db->x86_size) && !db->always_test) {
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
}
}
if(!need_lock)
mutex_unlock(&my_context->mutex_dyndump);
}
if(!db || !db->block || !db->done)
emu->test.test = 0;
return db;
}
@@ -426,27 +309,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_
+42 -19
View File
@@ -20,6 +20,7 @@
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
void x86test_check(x86emu_t* ref, uintptr_t ip);
#endif
#ifdef ARM
@@ -44,9 +45,8 @@ 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 = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
@@ -54,12 +54,15 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
block = DBGetBlock(emu, addr, 1);
}
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);
if(LOG_INFO<=box86_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
}
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
@@ -84,18 +87,25 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
int skip = 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]);
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", skip, 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
#ifdef DYNAREC
if(box86_dynarec_test) {
if(emu->test.clean)
x86test_check(emu, R_EIP);
emu->test.clean = 0;
}
#endif
if(skip!=2)
skip = 0;
}
}
}
@@ -117,15 +127,18 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
current = block;
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|Calling Interpretor @%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|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);
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
@@ -173,6 +186,7 @@ int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int skip = 0;
#ifdef DYNAREC
int jmpbuf_reset = 1;
#endif
@@ -185,11 +199,17 @@ int DynaRun(x86emu_t* emu)
#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
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", skip, ejb->emu->segs[_FS]);
#ifdef DYNAREC
if(box86_dynarec_test) {
if(emu->test.clean)
x86test_check(emu, R_EIP);
emu->test.clean = 0;
}
#endif
if(skip!=2)
skip = 0;
}
}
}
@@ -202,15 +222,18 @@ int DynaRun(x86emu_t* emu)
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
current = block;
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);
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 emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
+164 -155
View File
@@ -73,8 +73,8 @@ 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));
dyn->next_cap += 64;
dyn->next = (uintptr_t*)customRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -83,11 +83,13 @@ 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;
}
@@ -241,35 +243,31 @@ 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)
{
int pred_sz = 1; // to be safe
@@ -288,7 +286,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
++dyn->insts[i+1].pred_sz;
}
}
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
dyn->predecessor = (int*)customMalloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -298,12 +296,15 @@ static void fillPredecessors(dynarec_arm_t* dyn)
}
// 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))
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
@@ -353,36 +354,85 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
return ninst;
}
void* current_helper = NULL;
void CancelBlock(int need_lock)
{
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(helper) {
customFree(helper->next);
customFree(helper->insts);
customFree(helper->predecessor);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = 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(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
return CreateEmptyBlock(block, addr);
}
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;
@@ -390,27 +440,37 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
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.insts = (instruction_arm_t*)customCalloc(helper.cap, sizeof(instruction_arm_t));
// 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);
customFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = 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);
AddHotPage(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) {
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
@@ -427,44 +487,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
// fill predecessors with the jump address
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);
@@ -475,29 +498,68 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
// pass 2, instruction size
arm_pass2(&helper, addr);
// 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.insts_size = 0; // reset
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;
helper.arm_size = 0;
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);
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
customFree(helper.insts);
helper.insts = NULL;
helper.instsize = NULL;
customFree(helper.predecessor);
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:%ld)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
AddHotPage(addr);
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 +569,16 @@ 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);
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x86_addr, block->x86_size);
AddHotPage(addr);
block->dirty = 1;
//protectDB(addr, end-addr);
}
box_free(helper.predecessor);
helper.predecessor = NULL;
current_helper = NULL;
block->done = 1;
//block->done = 1;
return (void*)block;
}
+54 -38
View File
@@ -581,16 +581,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x57:
INST_NAME("PUSH reg");
gd = xEAX+(opcode&0x07);
#ifdef RPI2
if(gd==xESP) {
MOV_REG(x1, gd);
PUSH1(x1);
} else {
PUSH1(gd);
}
#else
PUSH1(gd);
#endif
break;
case 0x58:
case 0x59:
@@ -665,7 +661,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
if(PK(0)==0xC3) {
MESSAGE(LOG_DUMP, "PUSH then RET, using indirect\n");
MOV32(x3, ip+1);
MOV32(x3, addr-4);
LDR_IMM9(x1, x3, 0);
PUSH1(x1);
} else {
@@ -1015,7 +1011,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(eb1, x14, eb2*8, 8);
} else {
GETGB(x14);
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
// do the swap with exclusive locking
@@ -1025,7 +1021,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
BFI(gb1, x1, gb2*8, 8);
DMB_ISH();
SMDMB();
}
break;
case 0x87:
@@ -1041,7 +1037,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
} else {
GETGD;
DMB_ISH();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(ed, 3);
@@ -1065,7 +1061,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(!fixedaddress) {
MARK2;
}
DMB_ISH();
SMDMB();
MOV_REG(gd, x1);
}
break;
@@ -1089,7 +1085,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STRB_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x89:
@@ -1101,7 +1097,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STR_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0x8A:
@@ -1123,10 +1119,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
if(box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
DMB_ISH();
SMDMB();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
if(lock) {DMB_ISH();}
SMREADLOCK(lock);
LDRB_IMM9(x14, wback, fixedaddress);
ed = x14;
}
@@ -1140,10 +1136,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
if(lock || (box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier)))) {
DMB_ISH();
}
SMREADLOCK(lock);
LDR_IMM9(gd, ed, fixedaddress);
}
break;
@@ -1157,6 +1150,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDRH_REG(x3, xEmu, x3);
STRH_IMM8(x3, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x8D:
@@ -1284,12 +1278,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u32 = F32;
MOV32(x2, u32);
STRB_IMM9(xEAX, x2, 0);
SMWRITE();
break;
case 0xA3:
INST_NAME("MOV Od, EAX");
u32 = F32;
MOV32(x2, u32);
STR_IMM9(xEAX, x2, 0);
SMWRITE();
break;
case 0xA4:
INST_NAME("MOVSB");
@@ -1522,7 +1518,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = F8;
MOVW(x2, u8);
CALL_(rcl32, ed, (1<<x14));
WBACK; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, Ib");
@@ -1553,13 +1549,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFC_COND(cCC, xFlags, F_CF, 1);
}
WBACK; // no SBACK here because ed has been used all along and not x1
WBACK;
} else if(u8>1) {
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, u8);
CALL_(rcr32, ed, (1<<x14));
WBACK; // no SBACK here because ret value is ed directly
WBACK;
}
break;
case 4:
@@ -1633,7 +1629,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = F8;
MOVW(x3, u8);
STRB_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
case 0xC7:
@@ -1648,7 +1644,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F32S;
MOV32(x3, i32);
STR_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
SMWRITELOCK(lock);
}
break;
@@ -1667,6 +1663,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
{
addr+=4;
SKIPTEST(x14);
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
MOV32(x14, ip+1+2);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
@@ -1676,6 +1673,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*need_epilog = 1;
} else {
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
SKIPTEST(x14);
x87_forget(dyn, ninst, x3, x14, 0);
if((box86_log<2) && !cycle_log) { // call the wrapper directly
uintptr_t ncall[2]; // to avoid BUSERROR!!!
@@ -1719,9 +1717,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xCD:
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
if(PK(0)==0x80) {
SKIPTEST(x14);
SMEND();
u8 = F8;
if(u8==0x80) {
INST_NAME("Syscall");
u8 = F8;
BARRIER(BARRIER_FLOAT);
MOV32(xEIP, ip+2);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
@@ -1737,7 +1737,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
jump_to_epilog(dyn, 0, xEIP, ninst);
} else {
INST_NAME("INT Ib");
DEFAULT;
if(box86_wine && u8==0x2D) {
MESSAGE(LOG_DEBUG, "Hack for wine/int 2d\n");
} else {
DEFAULT;
}
}
break;
@@ -1884,7 +1888,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x2, 1);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
WBACK; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, 1");
@@ -1994,7 +1998,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
WBACK; // no SBACK here because ret value is ed directly
WBACK;
break;
case 3:
INST_NAME("RCR Ed, CL");
@@ -2004,7 +2008,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcr32, ed, (1<<x14));
WBACK; // no SBACK here because ret value is ed directly
WBACK;
break;
case 4:
case 6:
@@ -2065,6 +2069,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD7:
INST_NAME("XLAT");
UBFX(x1, xEAX, 0, 8); // x1 = AL
SMREAD();
LDRB_REG_LSL_IMM5(x1, xEBX, x1, 0); //x1 = byte ptr[EBX+AL]
BFI(xEAX, x1, 0, 8);
break;
@@ -2160,8 +2165,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
tmp = dyn->insts[ninst].pass2choice = 1;
else if ((getProtection(u32)&PROT_READ) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
tmp = dyn->insts[ninst].pass2choice = 2;
/*else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;*/
else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;
else
tmp = dyn->insts[ninst].pass2choice = 0;
#else
@@ -2171,18 +2176,19 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call 0\n");
SKIPTEST(x14);
MOV32(xEIP, addr);
PUSH1(xEIP);
break;
case 2:
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
MESSAGE(LOG_DUMP, "Hack for Call x86.get_pc_thunk.reg\n");
SKIPTEST(x14);
u8 = PK(i32+1);
gd = xEAX+((u8&0x38)>>3);
MOV32(gd, addr);
break;
// disabling this to avoid fetching data outside current block (in case this part changed, this block will not been marck as dirty)
/*case 3:
case 3:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
@@ -2221,16 +2227,22 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_NEXT(cNE); // not quitting, so lets continue
MARK;
jump_to_epilog(dyn, 0, xEIP, ninst);
break;*/
break;
default:
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
READFLAGS(X_PEND); // that's suspicious
} else {
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
// regular call
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
if(/*box86_dynarec_callret &&*/ box86_dynarec_bigblock>1) {
BARRIER(BARRIER_FULL);
} else {
BARRIER(BARRIER_FLOAT);
*need_epilog = 0;
*ok = 0;
}
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
@@ -2825,10 +2837,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF((box86_dynarec_safeflags>1) || (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); //Hack to put flag in "don't care" state
}
GETEDH(xEIP);
BARRIER(BARRIER_FLOAT);
@@ -2841,7 +2856,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
BARRIER(BARRIER_FULL);
READFLAGS(X_PEND);
BARRIER(BARRIER_FLOAT);
GETEDH(xEIP);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
+106 -10
View File
@@ -31,6 +31,7 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_64(a, ed); \
@@ -42,6 +43,7 @@
if((nextop&0xC0)==0xC0) { \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_double(dyn); \
VLD1_64(a, ed); \
@@ -49,6 +51,7 @@
#define PUTEM(a) \
if((nextop&0xC0)!=0xC0) { \
VST1_64(a, ed); \
SMWRITE2(); \
}
uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -87,6 +90,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
//CALL(arm_ud, -1, 0);
SKIPTEST(x14);
UDF(0);
break;
@@ -112,6 +116,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
//LDRD also have alignment requirements
@@ -140,6 +145,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVfrV_D(x2, x3, v0+1);
STR_IMM9(x2, ed, fixedaddress+8);
STR_IMM9(x3, ed, fixedaddress+12);
SMWRITE2();
}
break;
case 0x12:
@@ -152,6 +158,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("MOVLPS Gx,Ex");
GETGX(v0, 1);
SMREAD();
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);
@@ -170,12 +177,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1_32(v0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
SMWRITE2();
}
}
break;
@@ -212,6 +220,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("MOVHPS Gx,Ex");
GETGX(v0, 1);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0+1, ed);
}
@@ -228,12 +237,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1_64(v0+1, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0+1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
SMWRITE2();
}
}
break;
@@ -278,6 +288,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
}
@@ -293,6 +304,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
SMWRITE2();
}
break;
case 0x2A:
@@ -303,6 +315,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
@@ -330,6 +343,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
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_double(dyn);
VLD1_32(v1, ed);
@@ -344,6 +358,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
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_double(dyn);
VLD1_32(v1, ed);
@@ -383,6 +398,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = d0*2;
} else {
SMREAD();
parity = getedparity(dyn, ninst, addr, nextop, 2);
s0 = fpu_get_scratch_single(dyn);
if(parity) {
@@ -406,6 +422,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x31:
INST_NAME("RDTSC");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SKIPTEST(x14);
CALL(ReadTSC, xEAX, 0); // will return the u64 in x1:xEAX
MOV_REG(xEDX, x1);
break;
@@ -452,6 +469,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
REV(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(gd, ed, fixedaddress);
REV(gd, gd);
@@ -467,6 +485,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
REV(x1, gd);
STR_IMM9(gd, ed, fixedaddress);
SMWRITE();
}
break;
@@ -508,6 +527,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7); \
MOV_REG_COND(YES, gd, ed); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9_COND(YES, gd, ed, fixedaddress); \
}
@@ -620,6 +640,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gd, x3, 3, 1);
} else {
// EX is memory
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4096-16, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
UBFX(x3, x2, 31, 1);
@@ -637,6 +658,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x51:
INST_NAME("SQRTPS Gx, Ex");
SKIPTEST(x1);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -676,6 +698,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
SKIPTEST(x1);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -684,6 +707,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
SKIPTEST(x1);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
@@ -772,7 +796,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0);
// VMIN/VMAX wll put default NaN if any input is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box86_dynarec_fastnan) {
if(v0==v1) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
}
VMINQ_F32(v0, v0, v1);
if(!box86_dynarec_fastnan) {
q0 = fpu_get_scratch_quad(dyn);
VCEQQ_F32(q0, v0, v0); // 0 is NaN, -1 is not NaN
VANDQ(v0, v0, q0);
VBICQ(q0, q1, q0);
VORRQ(v0, v0, q0);
}
break;
case 0x5E:
INST_NAME("DIVPS Gx, Ex");
@@ -796,7 +836,23 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0);
// VMIN/VMAX wll put default NaN if any input is NaN
// but x86 will copy if either v0[x] or v1[x] is NaN, so lets force a copy if source is NaN
if(!box86_dynarec_fastnan) {
if(v0==v1) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
}
VMAXQ_F32(v0, v0, v1);
if(!box86_dynarec_fastnan) {
q0 = fpu_get_scratch_quad(dyn);
VCEQQ_F32(q0, v0, v0); // 0 is NaN, -1 is not NaN
VANDQ(v0, v0, q0);
VBICQ(q0, q1, q0);
VORRQ(v0, v0, q0);
}
break;
case 0x60:
INST_NAME("PUNPCKLBW Gm,Em");
@@ -1005,6 +1061,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1018,6 +1075,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
}
break;
@@ -1026,6 +1084,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1036,6 +1095,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1043,6 +1103,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
@@ -1056,6 +1117,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
if((nextop&0xC0)!=0xC0) {
VST1_16(d0, ed);
SMWRITE2();
}
}
break;
@@ -1065,6 +1127,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x72:
nextop = F8;
SMREAD();
GETEM(v0);
switch((nextop>>3)&7) {
case 2:
@@ -1106,6 +1169,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x73:
nextop = F8;
GETEM(v0);
SMREAD();
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLQ Em, Ib");
@@ -1171,6 +1235,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVfrDx_32(x2, v0, 0); // there can be some bus error is storing the VFPU reg directly
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x7F:
@@ -1185,11 +1250,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v0, ed, fixedaddress);
SMWRITE2();
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
SMWRITE2();
}
}
break;
@@ -1307,6 +1374,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
, cNE, cEQ, X_SF|X_OF|X_ZF)
break;
#undef GO
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
@@ -1321,8 +1389,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);\
STRB_IMM9(x3, ed, fixedaddress); \
SMWRITE(); \
}
case 0x90:
INST_NAME("SETO Eb");
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
@@ -1443,6 +1511,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x1, ed, x1, 2); //(&ed)+=r1*4;
@@ -1499,6 +1568,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
@@ -1517,6 +1587,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
@@ -1544,15 +1615,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// xFENCE -> DMB is approximative, but should be good enough
if((nextop&0xF8)==0xE8) {
INST_NAME("LFENCE");
DMB_ISH();
SMDMB();
} else
if((nextop&0xF8)==0xF0) {
INST_NAME("MFENCE");
DMB_ISH();
SMDMB();
} else
if((nextop&0xF8)==0xF8) {
INST_NAME("SFENCE");
DMB_ISH();
SMDMB();
} else {
switch((nextop>>3)&7) {
case 0:
@@ -1584,6 +1655,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LDMXCSR Md");
GETED;
STR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
if(box86_sse_flushto0) {
VMRS(x14); // get fpscr
MOV_REG_LSR_IMM5(x3, ed, 15); // get FZ bit
BFI(x14, x3, 24, 1); // inject FZ bit
VMSR(x14); // put new fpscr
}
break;
case 3:
INST_NAME("STMXCSR Md");
@@ -1674,6 +1751,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
@@ -1692,6 +1770,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1706,6 +1785,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = (ed&4)>>2; // L or H
UXTB(gd, eb1, eb2);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(gd, ed, fixedaddress);
}
@@ -1718,6 +1798,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
UXTH(gd, ed, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(gd, ed, fixedaddress);
}
@@ -1734,6 +1815,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1754,6 +1836,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1774,6 +1857,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 6:
@@ -1784,6 +1868,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1804,6 +1889,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 7:
@@ -1814,6 +1900,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
@@ -1835,6 +1922,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1852,6 +1940,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
@@ -1868,6 +1957,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xBC:
@@ -1924,6 +2014,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = (ed&4)>>2; // L or H
SXTB(gd, eb1, eb2);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(gd, ed, fixedaddress);
}
@@ -1936,6 +2027,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
SXTH(gd, ed, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSH_IMM8(gd, ed, fixedaddress);
}
@@ -1956,12 +2048,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGD;
GETED;
MOV_REG(x1, gd);
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
MOV_REG(gd, ed);
}
emit_add32(dyn, ninst, ed, gd, x3, x14);
emit_add32(dyn, ninst, ed, x1, x3, x14);
WBACK;
break;
case 0xC2:
@@ -2016,6 +2107,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
VMOVtoDx_16(d0, u8, ed);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&3;
VLD1LANE_16(d0, wback, u8);
@@ -2030,6 +2122,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = (F8)&3;
VMOVfrDx_U16(gd, d0, u8);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0, NULL);
u8 = (F8)&3;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
@@ -2043,6 +2136,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGX(v0, 1);
v2 = fpu_get_scratch_double(dyn);
if((nextop&0xC0)!=0xC0) {
SMREAD();
// from memory
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
@@ -2194,6 +2288,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress+0);
LDR_IMM9(x2, wback, fixedaddress+4);
@@ -2211,6 +2306,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
SMWRITE();
break;
default:
DEFAULT;
+20 -1
View File
@@ -103,6 +103,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;
@@ -114,6 +115,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
}
@@ -129,6 +131,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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 +143,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 +156,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:
@@ -163,6 +168,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
@@ -187,6 +193,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} 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;
@@ -198,6 +205,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
}
@@ -213,6 +221,7 @@ uintptr_t dynarecFS(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);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
@@ -224,6 +233,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 +245,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 +258,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 +267,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;
@@ -283,6 +297,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,7 +313,10 @@ 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
@@ -321,6 +339,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
+44 -39
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:
@@ -202,7 +202,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 +211,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 +221,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 +231,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 +240,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 +249,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 +258,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 +290,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 +299,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 +309,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 +319,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 +328,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 +337,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 +346,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");}
@@ -374,6 +374,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} 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;
@@ -385,6 +386,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
}
@@ -400,6 +402,7 @@ uintptr_t dynarecGS(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);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
SMWRITE2();
}
break;
@@ -407,6 +410,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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 +427,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,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);
STR_IMM9(xEAX, x2, 0);
SMWRITE2();
break;
case 0xC6:
@@ -450,6 +456,7 @@ 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:
@@ -465,6 +472,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,14 +485,14 @@ 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");
@@ -493,10 +501,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_OF|X_CF, SF_SET);
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");
@@ -504,10 +511,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
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 +521,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 +552,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 +573,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);
@@ -587,10 +593,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
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");
@@ -598,10 +603,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
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 +614,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 +622,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 +631,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;
@@ -649,6 +653,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
+9 -3
View File
@@ -505,7 +505,7 @@ 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) {
GETGD;
@@ -518,6 +518,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 +532,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;
@@ -547,7 +549,7 @@ 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:
@@ -561,7 +563,7 @@ 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);
if(lock) {DMB_ISH();}
SMREADLOCK(lock);
LDRH_IMM8(x1, ed, fixedaddress);
BFI(gd, x1, 0, 16);
}
@@ -577,6 +579,7 @@ 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, NULL);
STRH_IMM8(x1, ed, fixedaddress);
SMWRITE2();
}
break;
@@ -588,6 +591,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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]));
@@ -645,6 +649,7 @@ 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);
SMREAD();
LDRH_IMM8(x2, x2, 0);
BFI(xEAX, x2, 0, 16);
break;
@@ -653,6 +658,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u32 = F32;
MOV32(x2, u32);
STRH_IMM8(xEAX, x2, 0);
SMWRITE();
break;
case 0xA5:
INST_NAME("MOVSW");
+136 -42
View File
@@ -27,9 +27,10 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_8(a, ed); \
VLD1Q_8(a, ed); \
}
#define GETGX(a, w) \
gd = (nextop&0x38)>>3; \
@@ -70,6 +71,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
@@ -96,6 +98,7 @@ uintptr_t dynarec660F(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;
case 0x12:
@@ -108,6 +111,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
return addr;
}
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);
@@ -137,6 +141,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
break;
case 0x14:
INST_NAME("UNPCKLPD Gx, Ex");
@@ -146,6 +151,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
@@ -159,6 +165,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1+1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress+4);
}
@@ -173,6 +180,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
return addr;
}
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+1, ed, fixedaddress); // vfpu opcode here
@@ -202,6 +210,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
break;
case 0x1F:
@@ -221,7 +230,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
VLD1Q_64(v0, ed);
SMWRITE2();
}
break;
case 0x29:
@@ -234,7 +244,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
VST1Q_64(v0, ed);
SMWRITE2();
}
break;
case 0x2B:
INST_NAME("MOVNTPD Ex, Gx");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_64(v0, ed);
SMWRITE2();
}
break;
@@ -262,6 +289,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_64(q1, ed);
v0 = q1;
@@ -469,6 +497,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
} else { \
SMREAD(); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);\
LDRH_IMM8_COND(YES, x1, ed, fixedaddress); \
ed = x1; \
@@ -687,8 +716,26 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(v0, 1);
GETEX(v1, 0);
// need rounding?
VCVTQ_S32_F32(v0, v1);
if(v0>15)
q0 = fpu_get_scratch_quad(dyn);
else
q0 = v0;
if(v1>15) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
// need rounding!
//VCVTQ_S32_F32(v0, v1);
u8 = sse_setround(dyn, ninst, x1, x2, x14);
VCVTR_S32_F32(q0*2+0, q1*2+0);
VCVTR_S32_F32(q0*2+1, q1*2+1);
VCVTR_S32_F32(q0*2+2, q1*2+2);
VCVTR_S32_F32(q0*2+3, q1*2+3);
if(q0!=v0) {
VMOVQ(v0, q0);
}
x87_restoreround(dyn, ninst, u8);
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
@@ -893,6 +940,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
@@ -906,6 +954,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(q0+1, q1+1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0, NULL);
VLDR_64(q0+1, ed, fixedaddress+8);
}
@@ -928,6 +977,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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, 0, 0, 0, NULL);
VLD1Q_64(v0, ed);
@@ -1043,6 +1093,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, q0);
}
} else {
SMREAD();
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
@@ -1071,6 +1122,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1084,6 +1136,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
}
break;
@@ -1092,6 +1145,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1102,6 +1156,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1109,6 +1164,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
@@ -1122,6 +1178,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_16(q0, ed);
SMWRITE2();
}
}
break;
@@ -1138,6 +1195,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1151,6 +1209,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
}
break;
@@ -1159,6 +1218,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1169,6 +1229,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
break;
case 6:
@@ -1176,6 +1237,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
@@ -1189,6 +1251,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_32(q0, ed);
SMWRITE2();
}
}
break;
@@ -1204,6 +1267,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1217,6 +1281,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1225,6 +1290,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1240,6 +1306,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1248,6 +1315,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1261,6 +1329,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1269,6 +1338,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
@@ -1284,6 +1354,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
if((nextop&0xC0)!=0xC0) {
VST1Q_64(q0, ed);
SMWRITE2();
}
}
break;
@@ -1325,6 +1396,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrDx_32(x2, v0, 0); // to avoid Bus Error, using regular store
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
SMWRITE2();
}
break;
case 0x7F:
@@ -1337,6 +1409,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
SMWRITE2();
}
break;
@@ -1349,6 +1422,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7); // no need for extract
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x1, gd, 4, 12); // r1 = (gw>>4);
ADD_REG_LSL_IMM5(x1, ed, x1, 1); //(&ed)+=r1*2;
@@ -1391,6 +1465,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
@@ -1407,6 +1482,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ORR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xAC:
@@ -1459,6 +1535,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
@@ -1475,6 +1552,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
@@ -1488,6 +1566,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
eb2 = (ed&4)>>2; // L or H
UXTB(x1, eb1, eb2);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(x1, ed, fixedaddress);
}
@@ -1501,6 +1580,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX + (nextop&7);
UXTH(x1, ed, 0);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
}
@@ -1517,6 +1597,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1537,6 +1618,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1555,6 +1637,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1566,6 +1649,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1584,6 +1668,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1595,6 +1680,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
@@ -1612,6 +1698,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
MARK3;
break;
@@ -1629,6 +1716,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
@@ -1643,6 +1731,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
XOR_REG_LSL_REG(ed, ed, x1, x2);
if(wback) {
STRH_IMM8(ed, wback, fixedaddress);
SMWRITE();
}
break;
case 0xBC:
@@ -1688,6 +1777,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
eb2 = (ed&4)>>2; // L or H
SXTB(x1, eb1, eb2);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(x1, ed, fixedaddress);
}
@@ -1759,6 +1849,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
VMOVtoDx_16(v0+(u8/4), u8&3, ed);
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&7;
VLD1LANE_16(v0+(u8/4), wback, u8&3);
@@ -1773,6 +1864,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
u8 = (F8)&7;
VMOVfrDx_U16(gd, v0+(u8/4), (u8&3));
} else {
SMREAD();
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0, NULL);
u8 = (F8)&7;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
@@ -1830,8 +1922,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VDUPQ_16(v0, q1, 0);
VNEGNQ_16(v0, v0); // because we want SHR and not SHL
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U16(q0, q0, v0);
break;
case 0xD2:
@@ -1840,11 +1935,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U32(q0, q0, v0);
break;
case 0xD3:
@@ -1853,11 +1948,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVL_S32(v0, v0); // 2*q1 in 64 bits now
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_U64(q0, q0, v0);
break;
case 0xD4:
@@ -1894,6 +1989,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
}
SMWRITE2();
}
break;
case 0xD7:
@@ -1999,13 +2095,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VNEGN_16(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_S16(q0, q0, v0);
break;
case 0xE2:
@@ -2014,11 +2108,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VNEGNQ_8(v0, v0); // because we want SHR and not SHL
VSHLQ_S32(q0, q0, v0);
break;
case 0xE3:
@@ -2148,12 +2242,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U16(q0, q0, v0);
break;
case 0xF2:
@@ -2162,10 +2254,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U32(q0, q0, v0);
break;
case 0xF3:
@@ -2174,8 +2266,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, q1);
VQMOVN_S32(v0, v0);
VQMOVN_S16(v0, v0);
VDUPQ_8(v0, v0, 0); // only 8 bits are taken
VSHLQ_U64(q0, q0, v0);
break;
case 0xF4:
@@ -2217,7 +2311,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VPADDLQ_U32(q0, q0);
break;
case 0xF7:
INST_NAME("MASKMOVDQU Gx, Ex")
INST_NAME("MASKMOVDQU Gx, Ex");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0);
+9 -9
View File
@@ -41,7 +41,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -50,7 +50,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = xEAX+(nextop&7);
@@ -71,7 +71,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -85,17 +85,17 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARK(cNE);
STRH_IMM8(x1, wback, 0); // put the whole value
}
DMB_ISH();
SMDMB();
}
break;
default:
DEFAULT;
}
DMB_ISH();
SMDMB();
break;
case 0xFF:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ew
@@ -120,7 +120,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -158,7 +158,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -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;
+6
View File
@@ -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;
@@ -72,6 +73,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
}
@@ -87,6 +89,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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:
@@ -121,6 +126,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // 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);
+10 -10
View File
@@ -194,7 +194,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);
v1 = x87_do_push(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 +204,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);
v1 = x87_do_push(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 +216,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);
v1 = x87_do_push(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 +228,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);
v1 = x87_do_push(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 +240,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);
v1 = x87_do_push(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 +252,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);
v1 = x87_do_push(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 +264,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);
v1 = x87_do_push(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 {
@@ -309,7 +309,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xF2:
INST_NAME("FPTAN");
v2 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
v2 = x87_do_push(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);
VMOV_64(0, v1); // prepare call to tan
CALL_1D(tan, 0);
@@ -589,7 +589,7 @@ 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 {
@@ -608,7 +608,7 @@ 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 {
+108 -88
View File
@@ -223,7 +223,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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,10 +254,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();
// 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);
@@ -287,17 +279,89 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
STRH_IMM8(x14, ed, 8);
} else {
if(box86_x87_no80bits) {
v1 = x87_do_push(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_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
v1 = x87_do_push(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,85 +372,41 @@ 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);
break;
default:
+6 -14
View File
@@ -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);
v1 = x87_do_push(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);
@@ -202,16 +202,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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 {
+69 -69
View File
@@ -42,7 +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();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -59,14 +59,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x14);
@@ -79,13 +79,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -104,14 +104,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x14);
@@ -124,7 +124,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,7 +132,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -149,7 +149,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,7 +157,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
@@ -170,7 +170,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,7 +178,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -195,7 +195,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,7 +203,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
@@ -216,13 +216,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -241,14 +241,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x14);
@@ -261,14 +261,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
@@ -285,14 +285,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
@@ -305,13 +305,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
GETGB(x2);
wback = (nextop&7);
@@ -330,14 +330,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
@@ -350,7 +350,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,7 +368,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -389,7 +389,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,13 +403,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -424,13 +424,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -445,13 +445,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -466,12 +466,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
@@ -486,7 +486,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 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
@@ -496,7 +496,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
SMDMB();
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 +512,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,7 +526,7 @@ 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
@@ -537,7 +537,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
SMDMB();
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 +546,13 @@ 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();
SMDMB();
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -582,7 +582,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();
SMDMB();
--addr;
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
@@ -593,7 +593,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x95:
case 0x96:
case 0x97:
DMB_ISH();
SMDMB();
--addr;
break;
@@ -603,7 +603,7 @@ 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();
SMDMB();
nextop = F8;
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
@@ -640,7 +640,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,7 +649,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
// same as no lock, all in regs...
@@ -679,7 +679,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 +695,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 +706,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,7 +721,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -747,12 +747,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARKLOCK(cNE);
}
MARK3;
DMB_ISH();
SMDMB();
break;
case 0xBA:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
@@ -839,7 +839,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,7 +847,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
DMB_ISH();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -870,14 +870,14 @@ 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) {
wback = (nextop&7);
@@ -902,14 +902,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();
SMDMB();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(gd!=ed) {
@@ -955,7 +955,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 +964,7 @@ 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();
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
@@ -1001,7 +1001,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:
@@ -1017,7 +1017,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
DMB_ISH();
SMDMB();
switch((nextop>>3)&7)
{
case 0: // INC Ed
@@ -1041,7 +1041,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))) {
@@ -1078,7 +1078,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))) {
@@ -1098,7 +1098,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// default to NO LOCK
addr-=2;
}
DMB_ISH();
SMDMB();
break;
default:
+57 -1
View File
@@ -29,6 +29,7 @@
} 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); \
@@ -72,6 +73,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
@@ -93,6 +95,7 @@ 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:
@@ -104,6 +107,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
@@ -132,28 +136,50 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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) {
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;
@@ -305,6 +331,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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);
@@ -340,6 +367,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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,6 +429,33 @@ 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((nextop&0xC0)==0xC0) {
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;
@@ -410,6 +465,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
+36 -2
View File
@@ -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); \
@@ -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);
@@ -147,6 +149,7 @@ 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:
@@ -156,6 +159,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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);
@@ -172,6 +176,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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);
@@ -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,12 +244,27 @@ 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);
@@ -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;
@@ -396,6 +423,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
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);
@@ -500,6 +528,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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) {
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;
@@ -554,6 +584,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
@@ -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;
@@ -640,6 +672,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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
@@ -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
+66 -26
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)
{
@@ -109,7 +111,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
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))
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(uint64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = fpu_round(emu, ST0.d);
@@ -120,7 +122,7 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
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 +131,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 +140,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,7 +149,7 @@ 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);
@@ -170,6 +172,7 @@ 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);
}
@@ -608,6 +611,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;
@@ -702,13 +706,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,24 +741,6 @@ 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)
@@ -795,4 +781,58 @@ int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
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));
}
+3 -3
View File
@@ -71,9 +71,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);
@@ -88,4 +85,7 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
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);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+178 -34
View File
@@ -4,6 +4,7 @@
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "debug.h"
#include "box86context.h"
@@ -185,7 +186,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
case 1: offset = F8S; break;
case 2: offset = F16S; break;
}
if(offset && (abs(offset)>absmax || (offset&mask))) {
if(offset && (abs(offset)<=absmax && !(offset&mask))) {
*fixaddress = offset;
offset = 0;
}
@@ -251,6 +252,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
}
PASS3(void* epilog = arm_epilog);
MOV32_(2, (uintptr_t)epilog);
SMEND();
BX(2);
}
@@ -277,6 +279,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -293,6 +296,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -315,6 +319,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
#ifdef HAVE_TRACE
MOV_REG(x2, 15); // move current PC to x2, for tracing
#endif
SMEND();
BX(x3);
}
@@ -337,6 +342,7 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
SET_DFNONE(x1);
// Ret....
MOV32_(x2, (uintptr_t)arm_epilog); // epilog on purpose, CS might have changed!
SMEND();
BX(x2);
}
@@ -478,7 +484,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
if(s1!=xFlags) mask=1<<xFlags; else mask=1<<x3;
}
PUSH(xSP, (1<<xEmu) | mask);
fpu_pushcache(dyn, ninst, reg);
fpu_pushcache(dyn, ninst, s1);
if(saveflags) {
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
@@ -490,7 +496,7 @@ void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t
#ifdef ARM_SOFTFP
VMOVtoV_64(0, 0, 1); // load r0:r1 to D0 to simulate hardfo
#endif
fpu_popcache(dyn, ninst, reg);
fpu_popcache(dyn, ninst, s1);
POP(xSP, (1<<xEmu) | mask);
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
@@ -856,10 +862,29 @@ void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int
MESSAGE(LOG_DUMP, "\t---Purge x87 Cache and Synch Stackcount\n");
}
#ifdef HAVE_TRACE
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_stackcount(dyn, ninst, s1);
// Synch top & stack counter
int a = dyn->n.x87stack;
if(a) {
// Add x87stack to emu fpu_stack
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
if(a>0) {
ADD_IMM8(s2, s2, a);
} else {
SUB_IMM8(s2, s2, -a);
}
STR_IMM9(s2, xEmu, offsetof(x86emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
if(a>0) {
SUB_IMM8(s2, s2, a);
} else {
ADD_IMM8(s2, s2, -a);
}
AND_IMM8(s2, s2, 7);
STR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
}
int ret = 0;
for (int i=0; (i<8) && (!ret); ++i)
if(dyn->n.x87cache[i] != -1)
@@ -867,13 +892,20 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
if(!ret) // nothing to do
return;
// Get top
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
if(!a) {
// already there
LDR_IMM9(s2, xEmu, offsetof(x86emu_t, top));
}
// loop all cache entries
for (int i=0; i<8; ++i)
if(dyn->n.x87cache[i]!=-1) {
ADD_IMM8(s3, s2, dyn->n.x87cache[i]);
AND_IMM8(s3, s3, 7); // (emu->top + i)&7
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
if(dyn->n.x87cache[i]) {
ADD_IMM8(s3, s2, dyn->n.x87cache[i]);
AND_IMM8(s3, s3, 7); // (emu->top + i)&7
ADD_REG_LSL_IMM5(s3, xEmu, s3, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
} else {
ADD_REG_LSL_IMM5(s3, xEmu, s2, 3);
}
if(ST_IS_F(dyn->n.x87cache[i])) {
VCVT_F64_F32(0, dyn->n.x87reg[i]*2); // use D0 as scratch...
VSTR_64(0, s3, offsetof(x86emu_t, x87));
@@ -882,7 +914,31 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
}
}
}
#endif
static void x87_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
// go back with the top & stack counter
int a = dyn->n.x87stack;
if(a) {
// Add x87stack to emu fpu_stack
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
if(a>0) {
SUB_IMM8(s1, s1, a);
} else {
ADD_IMM8(s1, s1, -a);
}
STR_IMM9(s1, xEmu, offsetof(x86emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
if(a>0) {
ADD_IMM8(s1, s1, a);
} else {
SUB_IMM8(s1, s1, -a);
}
AND_IMM8(s1, s1, 7);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, top));
}
}
int x87_get_current_cache(dynarec_arm_t* dyn, int ninst, int st, int t)
{
@@ -1066,15 +1122,13 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
}
static int round_map[] = {0, 2, 1, 3}; // map x86 -> arm round flag
// 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)
{
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(s2, s1, 10, 2); // extract round...
MOV32(s1, round_map);
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
UBFX(s1, s1, 10, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s1); // get fpscr
MOV_REG(s3, s1);
BFI(s1, s2, 22, 2); // inject new round
@@ -1082,6 +1136,21 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
return s3;
}
// Set rounding according to cw flags, also enable exception and reset counter, return reg to restore flags
int x87_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(s1, s1, 10, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s3); // get fpscr
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
BFI(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
{
int i1, i2, i3;
@@ -1106,9 +1175,9 @@ void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b)
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
UBFX(s2, s1, 13, 2); // extract round...
MOV32(s1, round_map);
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
UBFX(s1, s1, 13, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s1); // get fpscr
MOV_REG(s3, s1);
BFI(s1, s2, 22, 2); // inject new round
@@ -1116,6 +1185,21 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
return s3;
}
// Set rounding according to mxcsr flags, also enable exception and reset counter, return reg to restore flags
int sse_setround_reset(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
UBFX(s1, s1, 13, 2); // extract round...
UBFX(s2, s1, 1, 1); // swap bits 0 and 1
BFI(s2, s1, 1, 1);
VMRS(s3); // get fpscr
ORR_IMM8(s1, s3, 0b010, 9); // enable exceptions
BIC_IMM8(s1, s1, 0b10011111, 0); // reset counters
BFI(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
return s3;
}
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
{
@@ -1190,7 +1274,6 @@ void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
}
}
#ifdef HAVE_TRACE
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
int old = -1;
@@ -1208,7 +1291,6 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
VST1_32_W(dyn->n.mmxcache[i], s1);
}
}
#endif
// SSE / SSE2 helpers
@@ -1288,7 +1370,6 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
}
}
#ifdef HAVE_TRACE
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
int old = -1;
@@ -1312,7 +1393,6 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
VST1Q_32_W(dyn->n.ssecache[i].reg, s1);
}
}
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
{
@@ -1333,7 +1413,7 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
MOV_REG(s1, xSP);
for (int i=16; i<32; ++i) { // should use VSTM?
if(dyn->n.fpuused[i-8]) {
VST1_32_W(i, s1);
VST1_64_W(i, s1);
}
}
MESSAGE(LOG_DUMP, "\t------- Push FPU Cache (%d)\n", n);
@@ -1352,7 +1432,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
MOV_REG(s1, xSP);
for (int i=16; i<32; ++i) {
if(dyn->n.fpuused[i-8]) {
VLD1_32_W(i, s1);
VLD1_64_W(i, s1);
}
}
if(n>=8) {
@@ -1413,8 +1493,10 @@ static void swapCache(dynarec_arm_t* dyn, int ninst, int i, int j, neoncache_t *
quad =1;
if(cache->neoncache[j].t==NEON_CACHE_XMMR || cache->neoncache[j].t==NEON_CACHE_XMMW)
quad =1;
if(quad) // if quad, we need to swap the whole quad!
if(quad) { // if quad, we need to swap the whole quad!
i&=~1;
j&=~1;
}
if(!cache->neoncache[i].v && ((quad && !cache->neoncache[i+1].v) || !quad)) {
// a mov is enough, no need to swap
MESSAGE(LOG_DUMP, "\t - Moving %d <- %d\n", i, j);
@@ -1684,7 +1766,7 @@ static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
stack_cnt = cache_i2.stack;
}
neoncache_t cache = dyn->n;
// sanitize XMM regs alocation
// sanitize XMM regs alocation, cache_i2 has been sanitized in neoncacheUnwind already
for(int i=0; i<24; i+=2) {
if(cache.neoncache[i].t == NEON_CACHE_XMMR || cache.neoncache[i].t == NEON_CACHE_XMMW)
cache.neoncache[i+1] = cache.neoncache[i];
@@ -1792,11 +1874,11 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->f.pending!=SF_PENDING) {
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
TSTS_REG_LSL_IMM5(s1, s1, 0);
j32 = (GETMARK3)-(dyn->arm_size+8);
j32 = (GETMARKF2)-(dyn->arm_size+8);
Bcond(cEQ, j32);
}
CALL_(UpdateFlags, -1, 0);
MARK3;
MARKF2;
}
#endif
}
@@ -1808,16 +1890,17 @@ void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2,
flagsCacheTransform(dyn, ninst, s1);
}
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_reflectcache(dyn, ninst, s1, s2, s3);
if(trace_emm)
mmx_reflectcache(dyn, ninst, s1);
if(trace_xmm)
sse_reflectcache(dyn, ninst, s1);
mmx_reflectcache(dyn, ninst, s1);
sse_reflectcache(dyn, ninst, s1);
}
void fpu_unreflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
x87_unreflectcache(dyn, ninst, s1, s2, s3);
}
#endif
void fpu_reset(dynarec_arm_t* dyn)
{
@@ -1854,3 +1937,64 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n)
{
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
}
// propagate ST stack state, especial stack pop that are deferred
void fpu_propagate_stack(dynarec_arm_t* dyn, int ninst)
{
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;
}
+89 -23
View File
@@ -27,6 +27,30 @@
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
// Strong mem emulation helpers
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
// Opcode will read
#define SMREAD() if(!dyn->smread && box86_dynarec_strongmem>1) {SMDMB();}
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box86_dynarec_strongmem>1)) {SMDMB();}
// Opcode migh 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>1) dyn->smwrite=1
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
// Opcode migh 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) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -37,6 +61,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 +71,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 +82,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,13 +106,14 @@
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); \
@@ -98,6 +127,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 +140,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 +153,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 +174,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 +189,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 +206,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); \
@@ -223,17 +260,19 @@
// 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)
@@ -306,7 +345,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)); \
@@ -497,9 +536,11 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define x87_reget_st STEPNAME(x87_reget_st)
#define x87_stackcount STEPNAME(x87_stackcount)
#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)
@@ -508,12 +549,13 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_reset_cache STEPNAME(fpu_reset_cache)
#define fpu_propagate_stack STEPNAME(fpu_propagate_stack)
#define fpu_purgecache STEPNAME(fpu_purgecache)
#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)
@@ -644,12 +686,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);
@@ -698,13 +744,16 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// 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 +800,21 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
#define MAYUSE(A)
#endif
#define NOTEST(s1) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.test)); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
}
#define SKIPTEST(s1) \
if(box86_dynarec_test) { \
MOVW(s1, 0); \
STR_IMM9(s1, xEmu, offsetof(x86emu_t, test.clean)); \
}
#define GOTEST(s1, s2) \
if(box86_dynarec_test) { \
MOVW(s2, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, test.test)); \
}
#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);
}
+105 -70
View File
@@ -21,6 +21,7 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
#include "custommem.h"
#include "elfloader.h"
#ifndef STEP
#error No STEP defined
@@ -35,13 +36,16 @@ 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;
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;
while(ok) {
ip = addr;
@@ -52,44 +56,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 +70,29 @@ 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;
fpu_propagate_stack(dyn, ninst);
NEW_INST;
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 +102,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");
}
}
@@ -156,13 +125,26 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->f.dfnone = 0;
}
}
#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].pred_sz) {
while(ii<dyn->size && (!dyn->insts[ii].pred_sz || (dyn->insts[ii].pred_sz==1 && dyn->insts[ii].pred[0]==ii-1))) {
// 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,15 +156,33 @@ 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))
if(dyn->forward) {
if(dyn->forward_to == addr && !need_epilog) {
// we made it!
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block for %d bytes %p -> %p\n", dyn->forward_to-dyn->forward, (void*)dyn->forward, (void*)dyn->forward_to);
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) {
// 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;
@@ -194,23 +194,56 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
ii=ninst;
}
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));
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
}
}
#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;
}
#endif
}
++ninst;
#if STEP == 0
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
(ok && dyn->size >= 2000))
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)))
#else
if(ok && (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 +252,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->insts[ninst].x86.need_after |= X_PEND;
#endif
++ninst;
NOTEST(x3);
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
NOTEST(x3);
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;
}
+4 -3
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) \
@@ -15,13 +16,13 @@
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?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_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#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 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); \
dyn->insts = (instruction_arm_t*)customRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
@@ -34,7 +35,7 @@
#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; \
-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)
+14 -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
@@ -68,7 +69,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,16 +91,23 @@ 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* 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;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
@@ -107,4 +115,6 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
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_
+7 -7
View File
@@ -235,12 +235,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 +251,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 +263,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 +274,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 +286,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 +298,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);
}
+88 -38
View File
@@ -1,4 +1,4 @@
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -355,6 +355,7 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
{
(void)context;
for (int i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
Elf32_Phdr * e = &head->PHEntries[i];
@@ -451,8 +452,15 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(!offs && !end && local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
@@ -576,8 +584,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
break;
case R_386_32:
if (!offs) {
printf_log(LOG_NONE, "Error: Symbol sym=%s(%s%s%s/version %d) not found, cannot apply R_386_32 %p (%p) in %s\n", symname, symname, vername?"@":"", vername?vername:"", version, p, *(void**)p, head->name);
ret_ok = 1;
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start")) {
printf_log(LOG_NONE, "Error: Symbol sym=%s(%s%s%s/version %d) not found, cannot apply R_386_32 %p (%p) in %s\n", symname, symname, vername?"@":"", vername?vername:"", version, p, *(void**)p, head->name);
ret_ok = 1;
}
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
*p += offs;
@@ -586,7 +596,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
case R_386_TLS_TPOFF:
// Negated offset in static TLS block
{
if(!symname || !symname[0]) {
if(!symname || !symname[0] || bind==STB_LOCAL) {
h_tls = head;
offs = sym->st_value;
} else {
@@ -656,12 +666,12 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
} else {
if(h_tls)
offs = sym->st_value;
if(!symname || !symname[0]) {
offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset
}
if(p) {
int tlsoffset = offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (ver=%d/%s) (%zd -> %zd)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", (intptr_t)*p, (intptr_t)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
}
@@ -693,8 +703,15 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
if(!symname || !symname[0]) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
} else {
if(!offs && !end && local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
@@ -827,7 +844,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
case R_386_TLS_TPOFF:
// Negated offset in static TLS block
{
if(!symname || !symname[0]) {
if(!symname || !symname[0] || bind==STB_LOCAL) {
h_tls = head;
offs = sym->st_value;
} else {
@@ -897,8 +914,9 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_TLS_DTPOFF32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
} else {
if(h_tls)
offs = sym->st_value;
if(!symname || !symname[0]) {
offs = (uintptr_t)((intptr_t)(head->tlsaddr + head->delta) - (intptr_t)offs); // negative offset
}
if(p) {
int tlsoffset = offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
@@ -952,7 +970,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
return -1;
}
if(need_resolver) {
if(pltResolver==~0) {
if(pltResolver==~(uintptr_t)0) {
pltResolver = AddBridge(my_context->system, vFEv, PltResolver, 0, "(PltResolver)");
}
if(head->pltgot) {
@@ -970,7 +988,7 @@ int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
return 0;
}
void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
void CalcStack(elfheader_t* elf, uint32_t* stacksz, uint32_t* stackalign)
{
if(*stacksz < elf->stacksz)
*stacksz = elf->stacksz;
@@ -981,7 +999,7 @@ void CalcStack(elfheader_t* elf, uint32_t* stacksz, int* stackalign)
Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
{
// TODO: create a hash on named to avoid this loop
for (int i=0; i<h->numSymTab; ++i) {
for (uint32_t i=0; i<h->numSymTab; ++i) {
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(type==STT_FUNC) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -995,7 +1013,7 @@ Elf32_Sym* GetFunction(elfheader_t* h, const char* name)
Elf32_Sym* GetElfObject(elfheader_t* h, const char* name)
{
for (int i=0; i<h->numSymTab; ++i) {
for (uint32_t i=0; i<h->numSymTab; ++i) {
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
if(type==STT_OBJECT) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -1017,6 +1035,7 @@ uintptr_t GetFunctionAddress(elfheader_t* h, const char* name)
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h)
{
(void)maplib;
uintptr_t ep = h->entrypoint + h->delta;
printf_log(LOG_DEBUG, "Entry Point is %p\n", (void*)ep);
if(box86_dump) {
@@ -1063,7 +1082,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
printf_dump(LOG_NEVER, "Adding %s Default Version \"%s\" for Symbol\"%s\"\n", (bind==STB_WEAK)?"Weak":"Global", vername, symname);
}
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
if(strstr(symname, "@@")) {
char symnameversionned[strlen(symname)+1];
strcpy(symnameversionned, symname);
@@ -1110,7 +1129,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
int type = ELF32_ST_TYPE(h->DynSym[i].st_info);
int vis = h->DynSym[i].st_other&0x3;
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
&& (vis==STV_DEFAULT || vis==STV_PROTECTED || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->DynSym[i].st_shndx!=0 && h->DynSym[i].st_shndx<=65521)) {
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
size_t sz = h->DynSym[i].st_size;
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
@@ -1156,7 +1175,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
{
DumpDynamicRPath(h);
// update RPATH first
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 || h->Dynamic[i].d_tag==DT_RUNPATH) {
char *rpathref = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
char* rpath = rpathref;
@@ -1213,12 +1232,12 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
DumpDynamicNeeded(h);
int cnt = 0;
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)
++cnt;
const char* nlibs[cnt];
int j=0;
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)
nlibs[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
@@ -1235,7 +1254,7 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
{
if(!h)
return 0;
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) {
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
if(!strcmp(needed, "libtcmalloc_minimal.so.4")) // tcmalloc needs to be the 1st lib loaded
@@ -1270,6 +1289,34 @@ void MarkElfInitDone(elfheader_t* h)
if(h)
h->init_done = 1;
}
void RunElfInitPltResolver(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
return;
uintptr_t p = h->initentry + h->delta;
h->init_done = 1;
for(int i=0; i<h->neededlibs->size; ++i) {
library_t *lib = h->neededlibs->libs[i];
elfheader_t *lib_elf = GetElf(lib);
if(lib_elf)
RunElfInitPltResolver(lib_elf, emu);
}
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
if(h->initentry)
RunSafeFunction(my_context, p, 3, my_context->argc, my_context->argv, my_context->envv);
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
// and check init array now
Elf32_Addr *addr = (Elf32_Addr*)(h->initarray + h->delta);
for (int i=0; i<h->initarray_sz; ++i) {
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
RunSafeFunction(my_context, (uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
}
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
return;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
@@ -1406,7 +1453,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
if(!h)
return ret;
for (int i=0; (i<h->numSymTab) && (distance!=0); ++i) {
for (uint32_t i=0; (i<h->numSymTab) && (distance!=0); ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
uintptr_t offs = h->SymTab[i].st_value + h->delta;
@@ -1419,7 +1466,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
}
}
}
for (int i=0; (i<h->numDynSym) && (distance!=0); ++i) {
for (uint32_t i=0; (i<h->numDynSym) && (distance!=0); ++i) {
const char * symname = h->DynStr+h->DynSym[i].st_name;
uintptr_t offs = h->DynSym[i].st_value + h->delta;
@@ -1540,7 +1587,7 @@ void* ElfSetBrk(void* newbrk)
printf_log(LOG_NONE, "Error, using brk on multi-part memory elf is not allowed for now");
} else {
printf_log(LOG_DEBUG, "brk change, start=%p with reserve=0x%x, was 0x%x long, will be 0x%x now => %p\n", my_context->brk, h->reserve, my_context->brksz, added, my_context->brk+added);
if(added>0 && added<h->reserve) {
if(added>0 && (uint32_t)added<h->reserve) {
my_context->brksz = added;
return newbrk;
}
@@ -1560,16 +1607,12 @@ void* ElfSetBrk(void* newbrk)
}
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
{
// if we are here, the there is not block in standard "space"
/*dynablocklist_t* ret = getDBFromAddress(addr);
if(ret) {
return ret;
}*/
(void)context;
if(box86_dynarec_forced) {
addDBFromAddressRange(addr, 1);
return getDB(addr>>DYNAMAP_SHIFT);
return getDB(addr);
}
//check if address is in an elf... if yes, grant a block (should I warn)
Dl_info info;
@@ -1673,7 +1716,7 @@ EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
void ResetSpecialCaseMainElf(elfheader_t* h)
{
Elf32_Sym *sym = NULL;
for (int i=0; i<h->numDynSym; ++i) {
for (uint32_t i=0; i<h->numDynSym; ++i) {
if(h->DynSym[i].st_info == 17) {
sym = h->DynSym+i;
const char * symname = h->DynStr+sym->st_name;
@@ -1761,6 +1804,7 @@ typedef struct search_symbol_s{
} search_symbol_t;
int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* data)
{
(void)size;
search_symbol_t* s = (search_symbol_t*)data;
for(int j = 0; j<info->dlpi_phnum; ++j) {
@@ -1825,7 +1869,7 @@ void* GetNativeSymbolUnversionned(void* lib, const char* name)
return s.addr;
}
uintptr_t pltResolver = ~0;
uintptr_t pltResolver = ~(uintptr_t)0;
EXPORT void PltResolver(x86emu_t* emu)
{
uintptr_t addr = Pop32(emu);
@@ -1857,6 +1901,12 @@ EXPORT void PltResolver(x86emu_t* emu)
emu->quit = 1;
return;
} else {
elfheader_t* sym_elf = FindElfAddress(my_context, offs);
if(sym_elf && sym_elf!=my_context->elfs[0] && !sym_elf->init_done) {
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
RunElfInitPltResolver(sym_elf, emu);
}
if(p) {
printf_dump(LOG_DEBUG, " Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
*p = offs;
+9 -13
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;
@@ -15,21 +11,21 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
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;
@@ -73,15 +69,15 @@ struct elfheader_s {
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)
@@ -116,4 +112,4 @@ struct elfheader_s {
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
#endif //__ELFLOADER_PRIVATE_H_
#endif //__ELFLOADER_PRIVATE_H_
+3 -3
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;
+94
View File
@@ -1,3 +1,25 @@
#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 getecommon(A, T) \
if(!(nextop&0xC0)) { \
@@ -97,6 +119,17 @@
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommon(A, reg32_t)
#define testeb(A, O) \
if((nextop&0xC0)==0xC0) { \
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) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
@@ -109,14 +142,47 @@
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommono(A, reg32_t, O)
#define tested(A, SZ, O) \
if((nextop&0xC0)==0xC0) { \
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) { \
A = &emu->mmx[(nextop&7)]; \
} else getecommon(A, mmx87_regs_t)
#define testem(A) \
if((nextop&0xC0)==0xC0) { \
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) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
#define testex(A) \
if((nextop&0xC0)==0xC0) { \
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) { \
A = &emu->regs[(nextop&7)]; \
@@ -125,16 +191,44 @@
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16o(A, reg32_t, O)
#define testtew16(A, O) \
if((nextop&0xC0)==0xC0) { \
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;
+66 -15
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;
@@ -47,17 +54,6 @@ 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 +77,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 +94,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 +104,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 +125,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 +137,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 +187,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);
@@ -221,6 +225,10 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
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;
@@ -230,6 +238,34 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
}
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));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
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;
}
box86context_t* GetEmuContext(x86emu_t* emu)
{
return emu->context;
@@ -301,7 +337,7 @@ 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"};
char tmp[80];
buff[0] = '\0';
if(trace_emm) {
@@ -458,6 +494,7 @@ 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__)
@@ -497,3 +534,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
}
+15 -1
View File
@@ -23,6 +23,17 @@ 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 x86emu_s {
// cpu
reg32_t regs[8];
@@ -40,7 +51,7 @@ typedef struct x86emu_s {
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;
@@ -63,6 +74,7 @@ typedef struct x86emu_s {
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
x86test_t test; // used for dynarec testing
// parent context
box86context_t *context;
// cpu helpers
@@ -88,4 +100,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_
+84 -73
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"
@@ -53,7 +54,10 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
if(forktype==3) {
// vfork, the parent wait the end or execve of the son
waitpid(v, NULL, WEXITED);
}
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<my_context->atfork_sz; --i)
@@ -87,6 +91,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 +105,215 @@ 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, "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(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, "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;
@@ -330,9 +341,9 @@ 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);
@@ -362,4 +373,4 @@ void print_cycle_log(int loglevel) {
}
}
}
}
}
+8 -8
View File
@@ -1044,14 +1044,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 +1075,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;
}
+971 -999
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+459
View File
@@ -0,0 +1,459 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr)
#else
uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
#endif
{
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uintptr_t tlsdata = (seg==_FS)?GetFSBaseEmu(emu):GetGSBaseEmu(emu);
switch(opcode) {
case 0x01: /* ADD GS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x03: /* ADD Gd, GS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x06: /* PUSH ES */
Push(emu, emu->segs[_ES]);
break;
case 0x07: /* POP ES */
emu->segs[_ES] = Pop(emu);
emu->segs_serial[_ES] = 0;
break;
case 0x0f:
#ifdef TEST_INTERPRETER
return Test640F(test, tlsdata, addr);
#else
return Run640F(emu, tlsdata, addr);
#endif
case 0x11: /* ADC GS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x13: /* ADC Gd, GS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = adc32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x21: /* AND Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = and32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x23: /* AND Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = and32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x29: /* SUB GS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = sub32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x2B: /* SUB Gd, GS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x31: /* XOR Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = xor32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x39: /* CMP Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x3B: /* CMP Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47: /* INC Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].dword[0] = inc32(emu, emu->regs[tmp8u].dword[0]);
break;
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F: /* DEC Reg */
tmp8u = opcode&7;
emu->regs[tmp8u].dword[0] = dec32(emu, emu->regs[tmp8u].dword[0]);
break;
case 0x50: /* PUSH Reg */
case 0x51:
case 0x52:
case 0x53:
case 0x54: /* PUSH ESP */
case 0x55:
case 0x56:
case 0x57:
case 0x58: /* POP Reg */
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C: /* POP ESP */
case 0x5D:
case 0x5E:
case 0x5F:
// Segment override if for memory loc, no stack segment
return addr-1;
case 0x64: /* FS: */
// so just ignore that GS: prefix then
#ifdef TEST_INTERPRETER
return Test64(test, _FS, addr-1); // put FS back
#else
return Run64(emu, _FS, addr-1); // put FS back
#endif
case 0x66:
#ifdef TEST_INTERPRETER
return Test6466(test, tlsdata, addr);
#else
return Run6466(emu, tlsdata, addr);
#endif
case 0x67:
#ifdef TEST_INTERPRETER
return Test6467(test, tlsdata, addr);
#else
return Run6467(emu, tlsdata, addr);
#endif
case 0x69: /* IMUL Gd,Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
tmp32u = F32;
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F:
// just ignore the prefix
return addr-1;
case 0x80: /* GRP Eb,Ib */
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_ED_OFFS(tlsdata);
if(opcode==0x83) {
tmp32s = F8S;
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
break;
case 0x87:
nextop = F8;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)==0xC0) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
} else {
if(((uintptr_t)ED)&3)
{
// not aligned, dont't try to "LOCK"
tmp32u = ED->dword[0];
ED->dword[0] = GD.dword[0];
GD.dword[0] = tmp32u;
} else {
// XCHG is supposed to automaticaly LOCK memory bus
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
}
}
#else
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8A: /* MOV Gb,GS:Eb */
nextop = F8;
GET_EB_OFFS(tlsdata);
GB = EB->byte[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8C: /* MOV Seg:Ed, Seg */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8E: /* MOV Seg,Seg:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
emu->segs[((nextop&0x38)>>3)] = ED->word[0];
emu->segs_serial[((nextop&0x38)>>3)] = 0;
break;
case 0x8F: /* POP Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0x9C: /* PUSHFD */
// Segment override if for memory loc, no stack segment
return addr-1; // so ignore prefix and continue
case 0xA0: /* MOV AL,Ob */
tmp32s = F32S;
R_AL = *(uint8_t*)((tlsdata) + tmp32s);
break;
case 0xA1: /* MOV EAX,Ov */
tmp32s = F32S;
R_EAX = *(uint32_t*)((tlsdata) + tmp32s);
break;
case 0xA2: /* MOV Ob,AL */
tmp32s = F32S;
*(uint8_t*)((tlsdata) + tmp32s) = R_AL;
break;
case 0xA3: /* MOV Od,EAX */
tmp32s = F32S;
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
break;
case 0xA8: /* TEST AL, Ib */
test8(emu, R_AL, F8);
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = F8/* & 0x1f*/; // masking done in each functions
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xC6: /* MOV Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
EB->byte[0] = F8;
break;
case 0xC7: /* MOV Ed,Id */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = F32;
break;
case 0xD0: /* GRP2 Eb,1 */
case 0xD2: /* GRP2 Eb,CL */
nextop = F8;
GET_EB_OFFS(tlsdata);
tmp8u = (opcode==0xD0)?1:R_CL;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = rol8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = ror8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = rcl8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = rcr8(emu, EB->byte[0], tmp8u); break;
case 4:
case 6: EB->byte[0] = shl8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = shr8(emu, EB->byte[0], tmp8u); break;
case 7: EB->byte[0] = sar8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0xD1: /* GRP2 Ed,1 */
case 0xD3: /* GRP2 Ed,CL */
nextop = F8;
GET_ED_OFFS(tlsdata);
tmp8u = (opcode==0xD1)?1:R_CL;
switch((nextop>>3)&7) {
case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
case 4:
case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
}
break;
case 0xE9:
case 0xEB:
return addr-1; // ignore FS: to execute regular opcode
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
ED->dword[0] = inc32(emu, ED->dword[0]);
break;
case 1: /* DEC Ed */
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
R_EIP = (uintptr_t)getAlternate((void*)ED->dword[0]);
Push(emu, addr);
addr = R_EIP;
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
} else {
Push16(emu, R_CS);
Push(emu, addr);
addr = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 4: /* JMP NEAR Ed */
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
} else {
addr = ED->dword[0];
R_CS = (ED+1)->word[0];
}
break;
case 6: /* Push Ed */
Push(emu, ED->dword[0]);
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
default:
return 0;
}
return addr;
}
+55
View File
@@ -0,0 +1,55 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
#else
uintptr_t Run640F(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
case 0xAF: /* IMUL Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = imul32(emu, GD.dword[0], ED->dword[0]);
break;
case 0xB6: /* MOVZX Gd,GS:Eb */
nextop = F8;
GET_EB_OFFS(tlsdata);
GD.dword[0] = EB->byte[0];
break;
default:
return 0;
}
return addr;
}
+55
View File
@@ -0,0 +1,55 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
#else
uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
case 0x03: /* ADD Gw, FS:Ew */
nextop = F8;
GET_EW_OFFS(tlsdata);
GW.word[0] = add16(emu, GW.word[0], EW->word[0]);
break;
case 0x8B: /* MOV Gw,FS:Ew */
nextop = F8;
GET_EW_OFFS(tlsdata);
GW.word[0] = EW->word[0];
break;
default:
return 0;
}
return addr;
}
+92
View File
@@ -0,0 +1,92 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr)
#else
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
case 0x3B: /* CMP GD, FS:Ed16 */
nextop = F8;
GET_EW16_OFFS(tlsdata);
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x89: /* MOV ED16,Gd */
nextop = F8;
GET_EW16_OFFS(tlsdata);
ED->dword[0] = GD.dword[0];
break;
case 0x8B: /* MOV Gd,Ed16 */
nextop = F8;
GET_EW16_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8F: /* POP FS:Ed */
nextop = F8;
GET_EW16_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0xA1: /* MOV EAX,Ov16 */
tmp32u = F16;
R_EAX = *(uint32_t*)(tlsdata + tmp32u);
break;
case 0xA3: /* MOV Ov16,EAX */
tmp32u = F16;
#ifdef TEST_INTERPRETER
test->memaddr = tlsdata + tmp32u;
test->memsize = 4;
*(uint32_t*)(test->mem) = R_EAX;
#else
*(uint32_t*)(tlsdata + tmp32u) = R_EAX;
#endif
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 6: /* Push Ed */
GET_EW16_OFFS(tlsdata);
Push(emu, ED->dword[0]);
break;
default:
return 0;
}
break;
default:
return 0;
}
return addr;
}
+519 -1599
View File
File diff suppressed because it is too large. Load diff
+155 -134
View File
@@ -14,19 +14,14 @@
#include "x86trace.h"
#include "box86context.h"
#define F8 *(uint8_t*)(ip++)
#define F8S *(int8_t*)(ip++)
#define F16 *(uint16_t*)(ip+=2, ip-2)
#define F16S *(int16_t*)(ip+=2, ip-2)
#define F32 *(uint32_t*)(ip+=4, ip-4)
#define F32S *(int32_t*)(ip+=4, ip-4)
#define PK(a) *(uint8_t*)(ip+a)
#include "modrm.h"
void Run660F(x86emu_t *emu)
#ifdef TEST_INTERPRETER
uintptr_t Test660F(x86test_t *test, uintptr_t addr)
#else
uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
#endif
{
uintptr_t ip = R_EIP+2; //skip 66 0F
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
@@ -43,6 +38,9 @@ void Run660F(x86emu_t *emu)
#endif
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
@@ -144,8 +142,7 @@ void Run660F(x86emu_t *emu)
EW->word[0] = 0; // dummy operation. Should be CR0 -> Ew
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0x10: /* MOVUPD Gx, Ex */
@@ -160,7 +157,7 @@ void Run660F(x86emu_t *emu)
break;
case 0x12: /* MOVLPD Gx, Eq */
nextop = F8;
GET_ED;
GET_ED8;
if((uintptr_t)ED & 7)
memcpy(&GX.q[0], ED, 8);
else
@@ -168,7 +165,7 @@ void Run660F(x86emu_t *emu)
break;
case 0x13: /* MOVLPD Eq, Gx */
nextop = F8;
GET_ED;
GET_ED8;
if((uintptr_t)ED & 7)
memcpy(ED, &GX.q[0], 8);
else
@@ -187,18 +184,18 @@ void Run660F(x86emu_t *emu)
break;
case 0x16: /* MOVHPD Gx, Ed */
nextop = F8;
GET_ED;
GET_ED8;
GX.q[1] = *(uint64_t*)ED;
break;
case 0x17: /* MOVHPD Ed, Gx */
nextop = F8;
GET_ED;
GET_ED8;
*(uint64_t*)ED = GX.q[1];
break;
case 0x1F: /* NOP (multi-byte) */
nextop = F8;
GET_ED;
GET_ED_;
break;
case 0x28: /* MOVAPD Gx, Ex */
@@ -219,35 +216,45 @@ void Run660F(x86emu_t *emu)
GX.d[0] = EM->sd[0];
GX.d[1] = EM->sd[1];
break;
case 0x2B: /* MOVNTPD Ex, Gx */
nextop = F8;
GET_EX;
EX->q[0] = GX.q[0]; // Address needs to ba aligned for MOVNTPD
EX->q[1] = GX.q[1];
break;
case 0x2C: /* CVTTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
GM.ud[0] = 0x80000000;
else
GM.sd[0] = EX->d[0];
if(!isfinite(EX->d[1]) || EX->d[1]>(double)0x7fffffff || EX->d[1]<-(double)0x80000000U)
GM.ud[1] = 0x80000000;
else
GM.sd[1] = EX->d[1];
break;
case 0x2D: /* CVTPD2PI Gm, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GM.sd[0] = floor(EX->d[0]+0.5);
GM.sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GM.sd[0] = floor(EX->d[0]);
GM.sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GM.sd[0] = ceil(EX->d[0]);
GM.sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GM.sd[0] = EX->d[0];
GM.sd[1] = EX->d[1];
break;
}
for(int i=0; i<2; ++i)
if(!isfinite(EX->d[i]) || EX->d[i]>(double)0x7fffffff || EX->d[i]<-(double)0x80000000U)
GM.ud[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GM.sd[i] = nearbyint(EX->d[i]);
break;
case ROUND_Down:
GM.sd[i] = floor(EX->d[i]);
break;
case ROUND_Up:
GM.sd[i] = ceil(EX->d[i]);
break;
case ROUND_Chop:
GM.sd[i] = EX->d[i];
break;
}
break;
case 0x2E: /* UCOMISD Gx, Ex */
// no special check...
@@ -341,7 +348,34 @@ void Run660F(x86emu_t *emu)
GX.sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
}
break;
case 0x06: /* PHSUBD Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<2; ++i)
GX.sd[i] = GX.sd[i*2+0] - GX.sd[i*2+1];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<2; ++i)
GX.sd[2+i] = EX->sd[i*2+0] - EX->sd[i*2+1];
}
break;
case 0x07: /* PHSUBSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
tmp32s = GX.sw[i*2+0]-GX.sw[i*2+1];
GX.sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] - EX->sw[i*2+1];
GX.sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x08: /* PSIGNB Gx, Ex */
nextop = F8;
GET_EX;
@@ -507,8 +541,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
@@ -519,31 +552,31 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
GX.f[1] = nearbyint(EX->f[1]);
GX.f[2] = nearbyint(EX->f[2]);
GX.f[3] = nearbyint(EX->f[3]);
GX.f[0] = nearbyintf(EX->f[0]);
GX.f[1] = nearbyintf(EX->f[1]);
GX.f[2] = nearbyintf(EX->f[2]);
GX.f[3] = nearbyintf(EX->f[3]);
break;
case ROUND_Down:
GX.f[0] = floor(EX->f[0]);
GX.f[1] = floor(EX->f[1]);
GX.f[2] = floor(EX->f[2]);
GX.f[3] = floor(EX->f[3]);
GX.f[0] = floorf(EX->f[0]);
GX.f[1] = floorf(EX->f[1]);
GX.f[2] = floorf(EX->f[2]);
GX.f[3] = floorf(EX->f[3]);
break;
case ROUND_Up:
GX.f[0] = ceil(EX->f[0]);
GX.f[1] = ceil(EX->f[1]);
GX.f[2] = ceil(EX->f[2]);
GX.f[3] = ceil(EX->f[3]);
GX.f[0] = ceilf(EX->f[0]);
GX.f[1] = ceilf(EX->f[1]);
GX.f[2] = ceilf(EX->f[2]);
GX.f[3] = ceilf(EX->f[3]);
break;
case ROUND_Chop:
GX.f[0] = trunc(EX->f[0]);
GX.f[1] = trunc(EX->f[1]);
GX.f[2] = trunc(EX->f[2]);
GX.f[3] = trunc(EX->f[3]);
GX.f[0] = truncf(EX->f[0]);
GX.f[1] = truncf(EX->f[1]);
GX.f[2] = truncf(EX->f[2]);
GX.f[3] = truncf(EX->f[3]);
break;
}
break;
@@ -551,7 +584,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
@@ -575,19 +608,19 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
GX.f[0] = nearbyintf(EX->f[0]);
break;
case ROUND_Down:
GX.f[0] = floor(EX->f[0]);
GX.f[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GX.f[0] = ceil(EX->f[0]);
GX.f[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GX.f[0] = trunc(EX->f[0]);
GX.f[0] = truncf(EX->f[0]);
break;
}
break;
@@ -595,7 +628,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
switch((tmp8u & 4) ? (emu->mxcsr.f.MXCSR_RC) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
@@ -628,35 +661,12 @@ void Run660F(x86emu_t *emu)
if(tmp8u>31)
{GX.q[0] = GX.q[1] = 0;}
else
#if 0
if(tmp8u>15) {
tmp8u=(tmp8u-16)*8;
if (tmp8u < 64) {
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u);
} else {
GX.q[0] = GX.q[1] >> (tmp8u - 64);
GX.q[1] = 0;
}
} else {
tmp8u*=8;
if (tmp8u < 64) {
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64-tmp8u));
} else {
tmp8u -= 64;
GX.q[0] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64 - tmp8u));
GX.q[1] = (GX.q[0] >> tmp8u) | (GX.q[1] >> (64 - tmp8u));
}
}
#else
{
for (int i=0; i<16; ++i, ++tmp8u)
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX.ub[tmp8u-16]):EX->ub[tmp8u];
GX.q[0] = eax1.q[0];
GX.q[1] = eax1.q[1];
}
#endif
break;
case 0x16: // PEXTRD ED, GX, u8
@@ -690,8 +700,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
@@ -775,32 +784,25 @@ void Run660F(x86emu_t *emu)
case 0x5B: /* CVTPS2DQ Gx, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GX.sd[0] = floorf(EX->f[0]+0.5f);
GX.sd[1] = floorf(EX->f[1]+0.5f);
GX.sd[2] = floorf(EX->f[2]+0.5f);
GX.sd[3] = floorf(EX->f[3]+0.5f);
break;
case ROUND_Down:
GX.sd[0] = floorf(EX->f[0]);
GX.sd[1] = floorf(EX->f[1]);
GX.sd[2] = floorf(EX->f[2]);
GX.sd[3] = floorf(EX->f[3]);
break;
case ROUND_Up:
GX.sd[0] = ceilf(EX->f[0]);
GX.sd[1] = ceilf(EX->f[1]);
GX.sd[2] = ceilf(EX->f[2]);
GX.sd[3] = ceilf(EX->f[3]);
break;
case ROUND_Chop:
GX.sd[0] = EX->f[0];
GX.sd[1] = EX->f[1];
GX.sd[2] = EX->f[2];
GX.sd[3] = EX->f[3];
break;
}
for(int i=0; i<4; ++i)
// note, converting 0x7fffffff to float gives 0x80000000 basicaly, because of the loss or precision in the mantice. So uing >= here...
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>=(float)0x80000000U || EX->f[i]<-(float)0x80000000U)
GX.sd[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GX.sd[i] = nearbyintf(EX->f[i]);
break;
case ROUND_Down:
GX.sd[i] = floorf(EX->f[i]);
break;
case ROUND_Up:
GX.sd[i] = ceilf(EX->f[i]);
break;
case ROUND_Chop:
GX.sd[i] = EX->f[i];
break;
}
break;
case 0x5C: /* SUBPD Gx, Ex */
nextop = F8;
@@ -1018,8 +1020,7 @@ void Run660F(x86emu_t *emu)
for (int i=0; i<8; ++i) EX->uw[i] <<= tmp8u;
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0x72: /* GRP */
@@ -1045,8 +1046,7 @@ void Run660F(x86emu_t *emu)
for (int i=0; i<4; ++i) EX->ud[i] <<= tmp8u;
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0x73: /* GRP */
@@ -1098,8 +1098,7 @@ void Run660F(x86emu_t *emu)
}
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0x74: /* PCMPEQB Gx,Ex */
@@ -1192,7 +1191,12 @@ void Run660F(x86emu_t *emu)
GET_EW;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+tmp32s*2);
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
#else
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
#endif
}
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
@@ -1219,7 +1223,12 @@ void Run660F(x86emu_t *emu)
GET_EW;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+tmp32s*2);
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
#else
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
#endif
}
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
@@ -1265,7 +1274,12 @@ void Run660F(x86emu_t *emu)
GET_EW;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+tmp32s*2);
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
#else
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
#endif
}
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
@@ -1334,8 +1348,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0xBB: /* BTC Ew,Gw */
@@ -1347,7 +1360,12 @@ void Run660F(x86emu_t *emu)
GET_EW;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+tmp32s*2);
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
#else
EW=(reg32_t*)(((uintptr_t)(EW))+(tmp32s*2));
#endif
}
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
@@ -1514,8 +1532,7 @@ void Run660F(x86emu_t *emu)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
} else {
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0xD8: /* PSUBUSB Gx,Ex */
@@ -1590,7 +1607,7 @@ void Run660F(x86emu_t *emu)
case 0xE2: /* PSRAD Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
tmp8u=(EX->q[0]>31)?31:EX->ub[0];
for (int i=0; i<4; ++i)
GX.sd[i] >>= tmp8u;
break;
@@ -1619,8 +1636,14 @@ void Run660F(x86emu_t *emu)
case 0xE6: /* CVTTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
GX.sd[0] = EX->d[0];
GX.sd[1] = EX->d[1];
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
GX.sd[0] = 0x80000000;
else
GX.sd[0] = EX->d[0];
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>(double)0x7fffffff || EX->d[1]<-(double)0x80000000U)
GX.sd[1] = 0x80000000;
else
GX.sd[1] = EX->d[1];
GX.q[1] = 0;
break;
case 0xE7: /* MOVNTDQ Ex, Gx */
@@ -1795,10 +1818,8 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
R_EIP = ip;
return;
return addr;
}
+103
View File
@@ -0,0 +1,103 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test66D9(x86test_t *test, uintptr_t addr)
#else
uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xE0:
case 0xE5:
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xFC:
case 0xE1:
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFD:
case 0xFE:
case 0xFF:
return 0;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
// warning, incomplete
GET_EW;
#ifndef TEST_INTERPRETER
fpu_loadenv(emu, (char*)ED, 1);
#endif
break;
case 6: /* FNSTENV m */
// warning, incomplete
GET_EW;
#ifndef TEST_INTERPRETER
fpu_savenv(emu, (char*)ED, 1);
#endif
break;
default:
return 0;
}
}
return addr;
}
+122
View File
@@ -0,0 +1,122 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test66DD(x86test_t *test, uintptr_t addr)
#else
uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xE0:
case 0xE5:
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xFC:
case 0xE1:
case 0xE4:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFD:
case 0xFE:
case 0xFF:
return 0;
break;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
GET_EW;
#ifndef TEST_INTERPRETER
fpu_loadenv(emu, (char*)ED, 1);
// get the STx
{
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
#endif
break;
case 6: /* FNSAVE m94byte */
GET_EW;
// ENV first...
#ifndef TEST_INTERPRETER
fpu_savenv(emu, (char*)ED, 1);
// save the STx
{
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
#endif
reset_fpu(emu);
break;
default:
return 0;
}
}
return addr;
}
+147
View File
@@ -0,0 +1,147 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test67(x86test_t *test, int rep, uintptr_t addr)
#else
uintptr_t Run67(x86emu_t *emu, int rep, uintptr_t addr)
#endif
{
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u, tmp8u2;
int8_t tmp8s;
uint16_t tmp16u, tmp16u2;
int16_t tmp16s;
uint32_t tmp32u, tmp32u2, tmp32u3;
int32_t tmp32s, tmp32s2;
uint64_t tmp64u;
int64_t tmp64s;
double d;
float f;
int64_t ll;
sse_regs_t *opex, eax1;
mmx87_regs_t *opem, eam1;
uintptr_t tlsdata;
#ifdef TEST_INTERPRETER
x86emu_t *emu = test->emu;
#endif
opcode = F8;
while(opcode==0x67)
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x64:
tlsdata = GetFSBaseEmu(emu);
#ifdef TEST_INTERPRETER
return Test6467(test, tlsdata, addr);
#else
return Run6467(emu, tlsdata, addr);
#endif
case 0x66: /* MoooRE opcodes */
#ifdef TEST_INTERPRETER
return Test6766(test, rep, addr);
#else
return Run6766(emu, rep, addr);
#endif
case 0x6C: /* INSB */
tmp32u = rep?R_CX:1;
while(tmp32u--) {
#ifdef TEST_INTERPRETER
*(int8_t*)(R_DI+GetESBaseEmu(emu)) = 0; // faking port read, using actual segment ES, just in case
#endif
if(ACCESS_FLAG(F_DF))
R_DI-=1;
else
R_DI+=1;
}
if(rep) R_CX = 0;
break;
case 0xAC: /* LODSB */
tmp32u = rep?R_CX:1;
while(tmp32u--) {
R_AL = *(int8_t*)(R_SI+GetDSBaseEmu(emu));
if(ACCESS_FLAG(F_DF))
R_SI-=1;
else
R_SI+=1;
}
if(rep) R_CX = 0;
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && !ACCESS_FLAG(F_ZF))
addr += tmp8s;
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX && ACCESS_FLAG(F_ZF))
addr += tmp8s;
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_CX; // don't update flags
if(R_CX)
addr += tmp8s;
break;
case 0xE3: /* JCXZ */
tmp8s = F8S;
if(!R_CX)
addr += tmp8s;
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, addr);
addr += tmp32s;
break;
default:
return 0;
}
return addr;
}
+58
View File
@@ -0,0 +1,58 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t Test6766(x86test_t *test, int rep, uintptr_t addr)
#else
uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr)
#endif
{
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
uint32_t tmp32u;
int32_t tmp32s;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x8D: /* LEA Gw,Ew */
nextop = F8;
GET_EW16_;
GW.word[0] = (uint16_t)(uintptr_t)ED;
break;
default:
return 0;
}
return addr;
}
+4 -3
View File
@@ -50,6 +50,7 @@ void EXPORT my___libc_init(x86emu_t* emu, void* raw_args __unused, void (*onexit
#else
int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
Push(emu, (uint32_t)my_context->envv);
Push(emu, (uint32_t)my_context->argv);
@@ -818,7 +819,7 @@ uintptr_t evalED(x86emu_t* emu, uintptr_t ip) {
if((nextop&7)==4) {
uint8_t sib = PK(0);
++ip;
uintptr_t base = ((sib&0x7)==5)?(PK32(0)):(emu->regs[(sib&0x7)].dword[0]);
uintptr_t base = ((sib&0x7)==5)?(uint32_t)(PK32(0)):(emu->regs[(sib&0x7)].dword[0]);
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
return *(uintptr_t*)base;
} else if((nextop&7)==5) {
@@ -852,7 +853,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) ) {
int tid = syscall(SYS_gettid);
pthread_mutex_lock(&my_context->mutex_trace);
mutex_lock(&my_context->mutex_trace);
#ifdef DYNAREC
if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
@@ -895,7 +896,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
}
printf_log(LOG_NONE, "\n");
}
pthread_mutex_unlock(&my_context->mutex_trace);
mutex_unlock(&my_context->mutex_trace);
}
}
+70 -13
View File
@@ -4,6 +4,7 @@
#include <stdint.h>
#include "regs.h"
#include "x86emu_private.h"
#include "box86context.h"
typedef struct x86emu_s x86emu_t;
static inline uint8_t Fetch8(x86emu_t *emu) {return *(uint8_t*)(R_EIP++);}
@@ -41,15 +42,25 @@ static inline uint32_t Pop(x86emu_t *emu)
return *st;
}
#ifdef TEST_INTERPRETER
#define Push(E, V) do{E->regs[_SP].dword[0] -=4; test->memsize = 4; *(uint64_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
#define Push16(E, V) do{E->regs[_SP].dword[0] -=2; test->memsize = 2; *(uint16_t*)test->mem = (V); test->memaddr = E->regs[_SP].dword[0];}while(0)
#else
static inline void Push(x86emu_t *emu, uint32_t v)
{
R_ESP -= 4;
*((uint32_t*)R_ESP) = v;
}
#endif
static inline void PushExit(x86emu_t* emu)
{
R_ESP -= 4;
*((uint32_t*)R_ESP) = my_context->exit_bridge;
}
#if 0
// the op code definition can be found here: http://ref.x86asm.net/geek32.html
static inline reg32_t* GetECommon(x86emu_t* emu, uint32_t m)
{
if (m<=7) {
@@ -188,23 +199,69 @@ static inline sse_regs_t* GetGx(x86emu_t *emu, uint32_t v)
uint8_t m = (v&0x38)>>3;
return &emu->xmm[m&7];
}
#endif
void UpdateFlags(x86emu_t *emu);
#define CHECK_FLAGS(emu) if(emu->df) UpdateFlags(emu)
#define RESET_FLAGS(emu) emu->df = d_none
void Run67(x86emu_t *emu);
void Run0F(x86emu_t *emu);
void Run660F(x86emu_t *emu);
void Run66D9(x86emu_t *emu); // x87
void Run6766(x86emu_t *emu);
void RunGS(x86emu_t *emu);
void RunGS0F(x86emu_t *emu, uintptr_t tlsdata);
void RunFS(x86emu_t *emu);
void RunFS66(x86emu_t *emu, uintptr_t tlsdata);
void RunLock(x86emu_t *emu);
void RunLock66(x86emu_t *emu);
uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step);
uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr);
uintptr_t Run640F(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr);
uintptr_t Run660F(x86emu_t *emu, uintptr_t addr);
uintptr_t Run6664(x86emu_t *emu, int seg, uintptr_t addr);
uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr);
uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr);
uintptr_t Run66F0(x86emu_t *emu, uintptr_t addr);
uintptr_t Run67(x86emu_t *emu, int rep, uintptr_t addr);
uintptr_t Run670F(x86emu_t *emu, int rep, uintptr_t addr);
uintptr_t Run6766(x86emu_t *emu, int rep, uintptr_t addr);
uintptr_t Run67660F(x86emu_t *emu, uintptr_t addr);
uintptr_t RunD8(x86emu_t *emu, uintptr_t addr);
uintptr_t RunD9(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDA(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDB(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDC(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDD(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDE(x86emu_t *emu, uintptr_t addr);
uintptr_t RunDF(x86emu_t *emu, uintptr_t addr);
uintptr_t RunF0(x86emu_t *emu, uintptr_t addr);
uintptr_t RunF066(x86emu_t *emu, uintptr_t addr);
uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step);
uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr);
#ifdef DYNAREC
uintptr_t Test0F(x86test_t *test, uintptr_t addr, int *step);
uintptr_t Test64(x86test_t *test, int seg, uintptr_t addr);
uintptr_t Test640F(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Test66(x86test_t *test, int rep, uintptr_t addr);
uintptr_t Test660F(x86test_t *test, uintptr_t addr);
uintptr_t Test6664(x86test_t *test, int seg, uintptr_t addr);
uintptr_t Test66D9(x86test_t *test, uintptr_t addr);
uintptr_t Test66DD(x86test_t *test, uintptr_t addr);
uintptr_t Test66F0(x86test_t *test, uintptr_t addr);
uintptr_t Test67(x86test_t *test, int rep, uintptr_t addr);
uintptr_t Test670F(x86test_t *test, int rep, uintptr_t addr);
uintptr_t Test6766(x86test_t *test, int rep, uintptr_t addr);
uintptr_t Test67660F(x86test_t *test, uintptr_t addr);
uintptr_t TestD8(x86test_t *test, uintptr_t addr);
uintptr_t TestD9(x86test_t *test, uintptr_t addr);
uintptr_t TestDA(x86test_t *test, uintptr_t addr);
uintptr_t TestDB(x86test_t *test, uintptr_t addr);
uintptr_t TestDC(x86test_t *test, uintptr_t addr);
uintptr_t TestDD(x86test_t *test, uintptr_t addr);
uintptr_t TestDE(x86test_t *test, uintptr_t addr);
uintptr_t TestDF(x86test_t *test, uintptr_t addr);
uintptr_t TestF0(x86test_t *test, uintptr_t addr);
uintptr_t TestF066(x86test_t *test, uintptr_t addr);
uintptr_t TestF20F(x86test_t *test, uintptr_t addr, int *step);
uintptr_t TestF30F(x86test_t *test, uintptr_t addr);
#endif
void x86Syscall(x86emu_t *emu);
void x86Int3(x86emu_t* emu);
+37 -2
View File
@@ -1,7 +1,40 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#ifdef TEST_INTERPRETER
uintptr_t TestD8(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunD8(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
float f;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch(nextop) {
switch (nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
@@ -159,7 +192,9 @@
}
break;
default:
goto _default;
return 0;
}
}
return addr;
}
#pragma GCC diagnostic pop
+43 -2
View File
@@ -1,3 +1,38 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestD9(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunD9(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
float f;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch (nextop) {
case 0xC0:
@@ -206,7 +241,7 @@
case 0xE6:
case 0xE7:
case 0xEF:
goto _default;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FLD ST0, Ed float */
@@ -241,7 +276,9 @@
case 4: /* FLDENV m */
// warning, incomplete
GET_ED;
#ifndef TEST_INTERPRETER
fpu_loadenv(emu, (char*)ED, 0);
#endif
break;
case 5: /* FLDCW Ew */
GET_EW;
@@ -251,7 +288,9 @@
case 6: /* FNSTENV m */
// warning, incomplete
GET_ED;
#ifndef TEST_INTERPRETER
fpu_savenv(emu, (char*)ED, 0);
#endif
// intruction pointer: 48bits
// data (operand) pointer: 48bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
@@ -261,6 +300,8 @@
EW->word[0] = emu->cw.x16;
break;
default:
goto _default;
return 0;
}
}
return addr;
}
+37 -2
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDA(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDA(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
float f;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch(nextop) {
@@ -66,8 +100,7 @@
case 0xF8:
case 0xF9:
case 0xFD:
UnimpOpcode(emu);
break;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
@@ -105,3 +138,5 @@
break;
}
}
return addr;
}
+45 -8
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDB(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDB(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
float f;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch(nextop) {
case 0xC0: /* FCMOVNB ST(0), ST(i) */
@@ -93,7 +127,7 @@
case 0xE5:
case 0xE6:
case 0xE7:
goto _default;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Ed */
@@ -103,15 +137,16 @@
break;
case 1: /* FISTTP Ed, ST0 */
GET_ED;
tmp32s = ST0.d; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
tmp32s = 0x80000000;
else
tmp32s = ST0.d; // TODO: Handling of FPU Exception
fpu_do_pop(emu);
ED->sdword[0] = tmp32s;
break;
case 2: /* FIST Ed, ST0 */
GET_ED;
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
@@ -120,7 +155,7 @@
break;
case 3: /* FISTP Ed, ST0 */
GET_ED;
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)0x7fffffff) || isless(ST0.d, -(double)0x80000000U) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
@@ -129,14 +164,14 @@
fpu_do_pop(emu);
break;
case 5: /* FLD ST0, Et */
GET_ED;
GET_EDT;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
break;
case 7: /* FSTP tbyte */
GET_ED;
GET_EDT;
if(ST0.q!=STld(0).uref)
D2LD(&ST0.d, ED);
else
@@ -144,6 +179,8 @@
fpu_do_pop(emu);
break;
default:
goto _default;
return 0;
}
}
return addr;
}
+38 -3
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDC(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDC(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
double d;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -82,7 +116,7 @@
ST(nextop&7).d /= ST0.d;
break;
default:
GET_ED;
GET_ED8;
switch((nextop>>3)&7) {
case 0: /* FADD ST0, double */
if(!(((uintptr_t)ED)&7))
@@ -150,7 +184,8 @@
}
break;
default:
goto _default;
return 0;
}
}
#pragma GCC diagnostic pop
return addr;
}
+67 -12
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDD(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDD(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
double d;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch(nextop) {
@@ -79,12 +113,12 @@
case 0xFD:
case 0xFE:
case 0xFF:
goto _default;
return 0;
default:
switch((nextop>>3)&7) {
case 0: /* FLD double */
GET_ED;
GET_ED8;
fpu_do_push(emu);
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED;
@@ -93,17 +127,32 @@
}
break;
case 1: /* FISTTP ED qword */
GET_ED;
if(!(((uintptr_t)ED)&7))
*(int64_t*)ED = ST0.d;
else {
int64_t i64 = ST0.d;
GET_ED8;
if(!(((uintptr_t)ED)&7)) {
if(STll(0).sref==ST(0).sq)
*(int64_t*)ED = STll(0).sq;
else {
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
*(uint64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = ST0.d;
}
} else {
int64_t i64;
if(STll(0).sref==ST(0).sq)
i64 = STll(0).sq;
else {
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
i64 = 0x8000000000000000LL;
else
i64 = ST0.d;
}
memcpy(ED, &i64, sizeof(int64_t));
}
fpu_do_pop(emu);
break;
case 2: /* FST double */
GET_ED;
GET_ED8;
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
@@ -111,7 +160,7 @@
}
break;
case 3: /* FSTP double */
GET_ED;
GET_ED8;
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
@@ -120,8 +169,10 @@
fpu_do_pop(emu);
break;
case 4: /* FRSTOR m108byte */
GET_ED;
GET_ED_;
#ifndef TEST_INTERPRETER
fpu_loadenv(emu, (char*)ED, 0);
#endif
// get the STx
{
char* p =(char*)ED;
@@ -133,9 +184,10 @@
}
break;
case 6: /* FNSAVE m108byte */
GET_ED;
GET_ED_;
// ENV first...
// warning, incomplete
#ifndef TEST_INTERPRETER
fpu_savenv(emu, (char*)ED, 0);
// save the STx
{
@@ -146,6 +198,7 @@
p+=10;
}
}
#endif
reset_fpu(emu);
break;
case 7: /* FNSTSW m2byte */
@@ -154,6 +207,8 @@
*(uint16_t*)ED = emu->sw.x16;
break;
default:
goto _default;
return 0;
}
}
return addr;
}
+38 -2
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDE(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDE(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int32_t tmp32s;
int64_t ll;
double d;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch (nextop) {
case 0xC0: /* FADDP STx, ST0 */
@@ -95,7 +129,7 @@
case 0xDD:
case 0xDE:
case 0xDF:
goto _default;
return 0;
default:
switch((nextop>>3)&7) {
@@ -124,6 +158,8 @@
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
goto _default;
return 0;
}
}
return addr;
}
+55 -13
View File
@@ -1,3 +1,37 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x87emu_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestDF(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunDF(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t nextop;
int16_t tmp16s;
int64_t tmp64s;
double d;
reg32_t *oped;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
nextop = F8;
switch (nextop) {
case 0xC0: /* FFREEP STx */
@@ -25,8 +59,11 @@
break;
case 0xE0: /* FNSTSW AX */
emu->sw.f.F87_TOP = emu->top&7;
R_AX = emu->sw.x16;
{
x87flags_t sw = emu->sw;
sw.f.F87_TOP = emu->top&7;
R_AX = sw.x16;
}
break;
case 0xE8: /* FUCOMIP ST0, STx */
@@ -84,7 +121,7 @@
case 0xFD:
case 0xFE:
case 0xFF:
goto _default;
return 0;
default:
switch((nextop>>3)&7) {
@@ -96,32 +133,35 @@
break;
case 1: /* FISTTP Ew, ST0 */
GET_EW;
tmp16s = ST0.d;
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
tmp16s = 0x8000;
else
tmp16s = ST0.d;
EW->sword[0] = tmp16s;
fpu_do_pop(emu);
break;
case 2: /* FIST Ew, ST0 */
GET_EW;
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else
EW->sword[0] = fpu_round(emu, ST0.d);
break;
case 3: /* FISTP Ew, ST0 */
GET_EW;
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x8000) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else
EW->sword[0] = fpu_round(emu, ST0.d);
fpu_do_pop(emu);
break;
case 4: /* FBLD ST0, tbytes */
GET_ED;
GET_EDT;
fpu_do_push(emu);
fpu_fbld(emu, (uint8_t*)ED);
break;
case 5: /* FILD ST0, Gq */
GET_ED;
GET_ED8;
tmp64s = *(int64_t*)ED;
fpu_do_push(emu);
ST0.d = tmp64s;
@@ -129,19 +169,19 @@
STll(0).sref = ST0.sq;
break;
case 6: /* FBSTP tbytes, ST0 */
GET_ED;
GET_EDT;
fpu_fbst(emu, (uint8_t*)ED);
fpu_do_pop(emu);
break;
case 7: /* FISTP i64 */
GET_ED;
GET_ED8;
if((uintptr_t)ED & 0x7) {
// un-aligned!
if(STll(0).sref==ST(0).sq)
memcpy(ED, &STll(0).sq, sizeof(int64_t));
else {
int64_t i64;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
i64 = 0x8000000000000000LL;
else
i64 = fpu_round(emu, ST0.d);
@@ -151,7 +191,7 @@
if(STll(0).sref==ST(0).sq)
*(int64_t*)ED = STll(0).sq;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
if(isgreater(ST0.d, (double)0x7fffffffffffffffLL) || isless(ST0.d, -(double)0x8000000000000000LL) || !isfinite(ST0.d))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = fpu_round(emu, ST0.d);
@@ -160,6 +200,8 @@
fpu_do_pop(emu);
break;
default:
goto _default;
return 0;
}
}
return addr;
}
+625
View File
@@ -0,0 +1,625 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#include "signals.h"
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestF0(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u, tmp8u2;
int8_t tmp8s;
uint16_t tmp16u, tmp16u2;
int16_t tmp16s;
uint32_t tmp32u, tmp32u2, tmp32u3;
int32_t tmp32s, tmp32s2;
uint64_t tmp64u;
int64_t tmp64s;
double d;
float f;
int64_t ll;
sse_regs_t *opex, eax1;
mmx87_regs_t *opem, eam1;
#ifdef TEST_INTERPRETER
x86emu_t *emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GET_EB; \
do { \
tmp8u = arm_lock_read_b(EB); \
tmp8u = OP##8(emu, tmp8u, GB); \
} while (arm_lock_write_b(EB, tmp8u)); \
break; \
case B+1: \
nextop = F8; \
GET_ED; \
do { \
tmp32u = arm_lock_read_d(ED); \
tmp32u = OP##32(emu, tmp32u, GD.dword[0]); \
} while (arm_lock_write_d(ED, tmp32u)); \
break; \
case B+2: \
nextop = F8; \
GET_EB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GET_ED; \
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
R_EAX = OP##32(emu, R_EAX, F32); \
break;
#else
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GET_EB; \
pthread_mutex_lock(&emu->context->mutex_lock);\
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+1: \
nextop = F8; \
GET_ED; \
pthread_mutex_lock(&emu->context->mutex_lock);\
ED->dword[0] = OP##32(emu, ED->dword[0], GD.dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+2: \
nextop = F8; \
GET_EB; \
pthread_mutex_lock(&emu->context->mutex_lock);\
GB = OP##8(emu, GB, EB->byte[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+3: \
nextop = F8; \
GET_ED; \
pthread_mutex_lock(&emu->context->mutex_lock);\
GD.dword[0] = OP##32(emu, GD.dword[0], ED->dword[0]); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+4: \
pthread_mutex_lock(&emu->context->mutex_lock);\
R_AL = OP##8(emu, R_AL, F8); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break; \
case B+5: \
pthread_mutex_lock(&emu->context->mutex_lock);\
R_EAX = OP##32(emu, R_EAX, F32); \
pthread_mutex_unlock(&emu->context->mutex_lock);\
break;
#endif
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x0f:
opcode = F8;
switch (opcode) {
case 0xB0: /* CMPXCHG Eb,Gb */
CHECK_FLAGS(emu);
nextop = F8;
GET_EB;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp8u = arm_lock_read_b(EB);
cmp8(emu, R_AL, tmp8u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_b(EB, GB);
} else {
R_AL = tmp8u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp8(emu, R_AL, EB->byte[0]);
if(ACCESS_FLAG(F_ZF)) {
EB->byte[0] = GB;
} else {
R_AL = EB->byte[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB1: /* CMPXCHG Ed,Gd */
nextop = F8;
GET_ED;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if(((uintptr_t)ED)&3) {
do {
tmp32u = ED->dword[0] & ~0xff;
tmp32u |= arm_lock_read_b(ED);
cmp32(emu, R_EAX, tmp32u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_b(ED, GD.dword[0] & 0xff);
if(!tmp32s)
ED->dword[0] = GD.dword[0];
} else {
R_EAX = tmp32u;
tmp32s = 0;
}
} while(tmp32s);
} else {
do {
tmp32u = arm_lock_read_d(ED);
cmp32(emu, R_EAX, tmp32u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_d(ED, GD.dword[0]);
} else {
R_EAX = tmp32u;
tmp32s = 0;
}
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp32(emu, R_EAX, ED->dword[0]);
if(ACCESS_FLAG(F_ZF)) {
ED->dword[0] = GD.dword[0];
} else {
R_EAX = ED->dword[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB3: /* BTR Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp8u>>5));
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
#else
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
#endif
}
tmp8u&=31;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ed,Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp8u>>5));
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
#else
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
#endif
}
tmp8u&=31;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if(arm_lock_read_d(ED) & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 5: /* BTS Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp8u>>5));
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
#else
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
#endif
}
tmp8u&=31;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32s = 0;
} else {
CLEAR_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm_lock_write_d(ED, tmp32u);
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp8u>>5));
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
#else
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
#endif
}
tmp8u&=31;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return addr-3; //unfetchall 0F BA nextop but not F0, continue normal without LOCK
}
break;
case 0xBB: /* BTC Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp8u = GD.byte[0];
if((nextop&0xC0)!=0xC0)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp8u>>5));
*(uint32_t*)test->mem = *(uint32_t*)test->memaddr;
#else
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
#endif
}
tmp8u&=31;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp32u = arm_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
CLEAR_FLAG(F_CF);
}
tmp32u ^= (1<<tmp8u);
} while(arm_lock_write_d(ED, tmp32u));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC0: /* XADD Gb,Eb */
nextop = F8;
GET_EB;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
do {
tmp8u = arm_lock_read_b(EB);
tmp8u2 = add8(emu, tmp8u, GB);
} while (arm_lock_write_b(EB, tmp8u2));
GB = tmp8u;
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp8u = add8(emu, EB->byte[0], GB);
GB = EB->byte[0];
EB->byte[0] = tmp8u;
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GET_ED;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if(((uintptr_t)ED)&3) {
do {
tmp32u = ED->dword[0] & ~0xff;
tmp32u |= arm_lock_read_b(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_b(ED, tmp32u2&0xff));
ED->dword[0] = tmp32u2;
} else {
do {
tmp32u = arm_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_d(ED, tmp32u2));
}
GD.dword[0] = tmp32u;
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = add32(emu, ED->dword[0], GD.dword[0]);
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC7: /* CMPXCHG8B Gq */
nextop = F8;
GET_ED8;
switch((nextop>>3)&7) {
case 1:
CHECK_FLAGS(emu);
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if(((uintptr_t)ED)&7) {
// unaligned!!!
uint64_t ref = R_EDX;
ref = ref<<32 | R_EAX;
void* p = (void*)(((uintptr_t)ED + 3)&~3);
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
do {
uint64_t m = *(uint64_t*)ED;
m&=~((0xffffffffLL)<<d);
tmp32u = arm_lock_read_d(p);
m|=((uint64_t)tmp32u)<<d;
if(ref == m) {
SET_FLAG(F_ZF);
m = ((uint64_t)R_ECX)<<32 | R_EBX;
tmp32u2 = m>>d;
tmp32s = arm_lock_write_d(p, tmp32u2);
if(!tmp32s)
*(uint64_t*)ED = m;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = m&0xffffffff;
R_EDX = m>>32;
tmp32s = 0;
}
} while(tmp32s);
} else
do {
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xC7 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
default:
// trigger invalid lock?
return addr-2; // unfetch 0F and nextop but not F0
}
break;
case 0x66:
#ifdef TEST_INTERPRETER
return TestF066(test, addr);
#else
return RunF066(emu, addr);
#endif
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_ED;
if(opcode==0x83) {
tmp32s = F8S;
tmp32u = (uint32_t)tmp32s;
} else
tmp32u = F32;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
switch((nextop>>3)&7) {
case 0: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, add32(emu, tmp32u2, tmp32u))); break;
case 1: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, or32(emu, tmp32u2, tmp32u))); break;
case 2: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, adc32(emu, tmp32u2, tmp32u))); break;
case 3: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sbb32(emu, tmp32u2, tmp32u))); break;
case 4: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, and32(emu, tmp32u2, tmp32u))); break;
case 5: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, sub32(emu, tmp32u2, tmp32u))); break;
case 6: do { tmp32u2 = arm_lock_read_d(ED);} while(arm_lock_write_d(ED, xor32(emu, tmp32u2, tmp32u))); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
switch((nextop>>3)&7) {
case 0: ED->dword[0] = add32(emu, ED->dword[0], tmp32u); break;
case 1: ED->dword[0] = or32(emu, ED->dword[0], tmp32u); break;
case 2: ED->dword[0] = adc32(emu, ED->dword[0], tmp32u); break;
case 3: ED->dword[0] = sbb32(emu, ED->dword[0], tmp32u); break;
case 4: ED->dword[0] = and32(emu, ED->dword[0], tmp32u); break;
case 5: ED->dword[0] = sub32(emu, ED->dword[0], tmp32u); break;
case 6: ED->dword[0] = xor32(emu, ED->dword[0], tmp32u); break;
case 7: cmp32(emu, ED->dword[0], tmp32u); break;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x86: /* XCHG Eb,Gb */
case 0x87: /* XCHG Ed,Gd */
return addr-1; // let the normal XCHG execute, it have integrated LOCK
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:
return addr-1;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if((uintptr_t)ED&3) {
//meh.
do {
tmp32u = ED->dword[0];
tmp32u &=~0xff;
tmp32u |= arm_lock_read_b(ED);
tmp32u = inc32(emu, tmp32u);
} while(arm_lock_write_b(ED, tmp32u&0xff));
ED->dword[0] = tmp32u;
} else
do {
tmp32u = arm_lock_read_d(ED);
} while(arm_lock_write_d(ED, inc32(emu, tmp32u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = inc32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if((uintptr_t)ED&3) {
//meh.
do {
tmp32u = ED->dword[0];
tmp32u &=~0xff;
tmp32u |= arm_lock_read_b(ED);
tmp32u = dec32(emu, tmp32u);
} while(arm_lock_write_b(ED, tmp32u&0xff));
ED->dword[0] = tmp32u;
} else
do {
tmp32u = arm_lock_read_d(ED);
} while(arm_lock_write_d(ED, dec32(emu, tmp32u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = dec32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
return 0;
}
break;
default:
return 0;
}
return addr;
}
+184
View File
@@ -0,0 +1,184 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#include "signals.h"
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
#include "../dynarec/arm_lock_helper.h"
#endif
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestF066(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunF066(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u, tmp8u2;
int8_t tmp8s;
uint16_t tmp16u, tmp16u2;
int16_t tmp16s;
uint32_t tmp32u, tmp32u2, tmp32u3;
int32_t tmp32s, tmp32s2;
uint64_t tmp64u;
int64_t tmp64s;
double d;
float f;
int64_t ll;
sse_regs_t *opex, eax1;
mmx87_regs_t *opem, eam1;
#ifdef TEST_INTERPRETER
x86emu_t *emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
case 0x0f:
opcode = F8;
switch (opcode) {
case 0xB1: /* CMPXCHG Ew,Gw */
nextop = F8;
GET_EW;
#ifdef DYNAREC
do {
tmp16u = arm_lock_read_h(ED);
cmp16(emu, R_AX, tmp16u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm_lock_write_h(ED, GW.word[0]);
} else {
R_AX = tmp16u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
GET_EW;
cmp16(emu, R_AX, EW->word[0]);
if(ACCESS_FLAG(F_ZF)) {
EW->word[0] = GW.word[0];
} else {
R_AX = EW->word[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 0;
}
break;
case 0x81: /* GRP Ed,Iw */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
GET_EW;
if(opcode==0x83) {
tmp16s = F8S;
tmp16u = (uint32_t)tmp16s;
} else
tmp16u = F16;
#ifdef DYNAREC
switch((nextop>>3)&7) {
case 0: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, add16(emu, tmp16u2, tmp16u))); break;
case 1: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, or16(emu, tmp16u2, tmp16u))); break;
case 2: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, adc16(emu, tmp16u2, tmp16u))); break;
case 3: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, sbb16(emu, tmp16u2, tmp16u))); break;
case 4: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, and16(emu, tmp16u2, tmp16u))); break;
case 5: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, sub16(emu, tmp16u2, tmp16u))); break;
case 6: do { tmp16u2 = arm_lock_read_h(EW);} while(arm_lock_write_h(EW, xor16(emu, tmp16u2, tmp16u))); break;
case 7: cmp16(emu, ED->dword[0], tmp16u); break;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
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;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xFF:
nextop = F8;
GET_EW;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#ifdef DYNAREC
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = inc16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, inc16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = inc32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#ifdef DYNAREC
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = dec16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, dec16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = dec32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 0;
}
break;
default:
return 0;
}
return addr;
}
+104 -37
View File
@@ -1,4 +1,51 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "bridge.h"
#include "modrm.h"
#ifdef TEST_INTERPRETER
uintptr_t TestF20F(x86test_t *test, uintptr_t addr, int *step)
#else
uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step)
#endif
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u;
int32_t tmp32s;
int64_t tmp64s0, tmp64s1;
reg32_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opgm;
#ifndef NOALIGN
int is_nan;
#endif
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
case 0x10: /* MOVSD Gx, Ex */
@@ -30,25 +77,31 @@
case 0x2C: /* CVTTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
GD.sdword[0] = EX->d[0];
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
GD.dword[0] = 0x80000000;
else
GD.sdword[0] = EX->d[0];
break;
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GD.sdword[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->d[0];
break;
}
if(!isfinite(EX->d[0]) || EX->d[0]>(double)0x7fffffff || EX->d[0]<-(double)0x80000000U)
GD.dword[0] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GD.sdword[0] = nearbyint(EX->d[0]);
break;
case ROUND_Down:
GD.sdword[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GD.sdword[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GD.sdword[0] = EX->d[0];
break;
}
break;
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
@@ -119,7 +172,7 @@
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreater(EX->d[0], GX.d[0]))
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isgreaterequal(EX->d[0], GX.d[0]))
GX.d[0] = EX->d[0];
break;
@@ -151,6 +204,19 @@
GX.f[3] = EX->f[2] + EX->f[3];
}
break;
case 0x7D: /* HSUBPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] -= GX.f[1];
GX.f[1] = GX.f[2] - GX.f[3];
if(EX==&GX) {
GX.f[2] = GX.f[0];
GX.f[3] = GX.f[1];
} else {
GX.f[2] = EX->f[0] - EX->f[1];
GX.f[3] = EX->f[2] - EX->f[3];
}
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
case BASE+0: \
@@ -236,7 +302,7 @@
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, ip += tmp32s;
, addr += tmp32s; STEP3;
) /* 0x80 -> 0x8F Jxx */
case 0xC2: /* CMPSD Gx, Ex, Ib */
@@ -275,24 +341,24 @@
case 0xE6: /* CVTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
switch((emu->mxcsr>>13)&3) {
case ROUND_Nearest:
GX.sd[0] = floor(EX->d[0]+0.5);
GX.sd[1] = floor(EX->d[1]+0.5);
break;
case ROUND_Down:
GX.sd[0] = floor(EX->d[0]);
GX.sd[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GX.sd[0] = ceil(EX->d[0]);
GX.sd[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GX.sd[0] = EX->d[0];
GX.sd[1] = EX->d[1];
break;
}
for(int i=0; i<2; ++i)
if(!isfinite(EX->d[i]) || EX->d[i]>(double)0x7fffffff || EX->d[i]<-(double)0x80000000U)
GX.ud[i] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest:
GX.sd[i] = nearbyint(EX->d[i]);
break;
case ROUND_Down:
GX.sd[i] = floor(EX->d[i]);
break;
case ROUND_Up:
GX.sd[i] = ceil(EX->d[i]);
break;
case ROUND_Chop:
GX.sd[i] = EX->d[i];
break;
}
GX.q[1] = 0;
break;
@@ -303,6 +369,7 @@
break;
default:
goto _default;
return 0;
}
return addr;
}
Loaded 100 of 308 files, more files were not shown because too many files have changed in this diff. Show more