138 Commits
Author SHA1 Message Date
ptitSeb 32accd0e77 Hotfix for steam not launching when libudev1 is wrapped 2023-08-19 19:07:30 +02:00
ptitSeb c4b3fc25e0 Bumped to version 0.3.2 2023-08-19 17:17:47 +02:00
ptitSeb 676b02b5aa Added a profile to fix PixelJunk Shooter linux version 2023-08-19 17:15:31 +02:00
ptitSeb 3c8e34f691 Removed a debug leftover 2023-08-19 16:39:06 +02:00
ptitSeb 630f42e9e2 [ELFLOADER] Adjusted fetching of symbol 2023-08-19 16:36:15 +02:00
ptitSeb 58b0338dff Fixed wrapped __gmp_get_memory_functions and added __gmp_set_memory_functions 2023-08-18 21:28:39 +02:00
ptitSeb 80c77bad96 Added 2 structures to vkalign 2023-08-15 18:14:36 +02:00
ptitSeb 771ff1b2e2 Added many wrapped symbols to libgmp (for Steam beta client) 2023-08-15 10:41:06 +02:00
ptitSeb cef87f7f7d Fixed a few warning 2023-08-15 10:37:56 +02:00
ptitSeb e8d4ffc782 [DYNAREC] Fixed 0F 52/53 opcodes (for #848) 2023-07-31 15:37:32 +02:00
ptitSeb 85397e9895 [DYNAREC] Fixed BOX86_NODYNAREC inside an rcfile 2023-07-31 14:28:20 +02:00
Ilya114 8194ad9728 Update README_CN.md 2023-07-27 13:19:08 +02:00
Ilya114 b82f203a9d Update README.md 2023-07-27 13:19:08 +02:00
Ilya114 151e2ae3a4 Update README_UK.md 2023-07-27 13:08:18 +02:00
Ilya114 0072524d5d Update README_UK.md 2023-07-27 13:08:18 +02:00
Ilya114 949417f412 Update README_CN.md 2023-07-27 13:08:18 +02:00
Ilya114 21fea0f195 Update README.md 2023-07-27 13:08:18 +02:00
Ilya114 9c1317f899 Ukrainian translate of README 2023-07-27 13:08:18 +02:00
ptitSeb 127a48f199 [ELFLOADER] Fixed a potential segfault when resizing tlsdata 2023-07-25 17:29:42 +02:00
ptitSeb 66b8c58cc1 Added some more extensions and structure to wrapped vulkan 2023-07-24 20:49:39 +02:00
ptitSeb 39bb606c06 Some improvment to get UPlay a bit more stable 2023-07-24 19:23:49 +02:00
ptitSeb 626826f33e [DYNAREC] Added a profile for TINTIN.exe to disable BOX86_DAYNREC_FORWARD, that tend go crazy on the obfuscated code 2023-07-23 13:01:26 +02:00
ptitSeb a9082f60b6 [DYNAREC] Improvments to BOX86_DYNAREC_FORWARD handling 2023-07-23 13:00:31 +02:00
ptitSeb 3b394b8f0d Hacked wrapped ptrace to avoid crash when wine handle exception (and debug registers in general) 2023-07-22 20:51:44 +02:00
ptitSeb a108a23c56 [TRACE] Fixed crash when tracing a function that is not defined in main at beggining 2023-07-22 20:51:35 +02:00
rajdakin 51baede9c1 [PRINTER] Fixed the ARM printer
(overwritten warning fix)
2023-07-17 22:20:25 +02:00
rajdakin d601b42ddc [WRAPPERS] Version bump 2023-07-17 22:20:25 +02:00
rajdakin d430332c45 [WRAPPERS] Cleaned up the rebuild_wrappers script 2023-07-17 22:20:25 +02:00
ptitSeb 63fae1b6c8 Another try to fix Android build (I'm considering removing this useless port) 2023-07-16 19:40:50 +02:00
ptitSeb c45d3d80ab Another try to fix Android build 2023-07-16 19:23:49 +02:00
ptitSeb 57e9e95411 Improved a bit my_execv wrapped function 2023-07-16 19:17:20 +02:00
ptitSeb 68fb291c83 Try to fix Android build 2023-07-16 18:39:47 +02:00
ptitSeb f3ee727bc4 Fixed a warning 2023-07-16 18:39:32 +02:00
ptitSeb 21ed47c4cb Added some more libgio2 wrapped symbols 2023-07-16 18:30:33 +02:00
ptitSeb 2147d92d9d Added missing docs in USAGE.md 2023-07-16 18:22:47 +02:00
ptitSeb 1465ff8aad Added BOX86_NOSANDBOX handling 2023-07-16 18:20:46 +02:00
ptitSeb ac895e3dad [ELFLOADER] Major refactor of elfloader, now on par with box64 one 2023-07-16 18:10:22 +02:00
ptitSeb 983a3d9926 Removed useless box86context_t parameter to RunFunction and friend 2023-07-16 14:37:29 +02:00
ptitSeb ecec73547f Added a few wrapped function to libgio2 2023-07-16 14:21:50 +02:00
ptitSeb 6ed82e7f7d Improved BOX64_MALLOC_HACK=2 and the glAleternate mecanism 2023-07-16 14:17:20 +02:00
ptitSeb 83a9b2cab5 Better wrapping for __libc_stack_end symbol 2023-07-16 13:51:45 +02:00
ptitSeb 666e41a0cb Improved wrapping of XextAddDisplay libxext function 2023-07-16 13:48:37 +02:00
ptitSeb c78be09d7f Fixed a few gio2 wrapped function signature 2023-07-16 13:41:48 +02:00
ptitSeb 21023e9802 [DYNAREC] Made dynarec use regular malloc memory for now (changeable with a define) 2023-07-16 13:35:59 +02:00
ptitSeb 38c07f2a2f [DYNAREC] Small improvment to dynarec memory handling 2023-07-16 13:35:11 +02:00
ptitSeb e6d124aed4 Fixed some edge case 16bits opcodes ([DYNAREC] too) 2023-07-16 11:09:35 +02:00
ptitSeb 8335a8c2d9 Added workaround for the still unimplemented PR_CreateIOLayerStub function fpr Garry's Mod 2023-07-15 17:44:24 +02:00
ptitSeb 6f7a513051 [DYNAREC] Better handling if wrapped function that return float/double in x87 register 2023-07-14 14:02:00 +02:00
ptitSeb 43189a2914 [DYNAREC] Fixed an issue with forward jump state retreival 2023-07-14 11:04:59 +02:00
ptitSeb 3bf9e4d989 Added 2 more wrapped function to libsdbus 2023-07-06 15:20:27 +02:00
ptitSeb fe3419957e and converted d3dadapter9 to RunFunctionFmt too 2023-07-04 18:09:17 +02:00
ptitSeb f8c8a5d596 Even more RunFunctionFmt conversions 2023-07-04 18:01:49 +02:00
ptitSeb 9ee7f84015 Finsihed converting wrapped lib to RunFunctionFmt 2023-07-04 16:45:52 +02:00
ptitSeb 36b316746b More wrapped lib converted to RunFunctionFmt 2023-07-04 15:13:49 +02:00
ptitSeb 0131572edf Fixed signature for wrapped vkGetPhysicalDeviceQueueFamilyProperties2 function 2023-07-02 19:08:32 +02:00
ptitSeb d74e873a85 Improved libz wrapping (backported from box64) 2023-07-02 18:31:31 +02:00
ptitSeb be53b823d3 More wrappers conversion to RunFunctionFmt 2023-07-02 18:28:56 +02:00
ptitSeb e5b6c8b6e0 Introduced RunFunctionFmt and started migrating wrapper to use it 2023-07-02 18:19:11 +02:00
ptitSeb ecf7bfd848 Added 4 syscalls (for #842) 2023-07-02 10:11:28 +02:00
ptitSeb 2a7b848d0e Reworked handling of privileged instruction, backported from box64 (|DYNAREC] too) 2023-06-27 17:24:58 +02:00
ptitSeb fa5fa7b5c0 Allow winedbg to run with undocumented BOX86_WINDBG (but it will not work, except for the backtrace) 2023-06-24 18:01:05 +02:00
ptitSeb b7283b8d9d Added 1 Vulkan extension 2023-06-24 17:58:56 +02:00
ptitSeb b8d72023c5 Try to improve custom memory allocator 2023-06-24 17:58:15 +02:00
ptitSeb e10a710591 Added another function to wrapped SDL2 (for #836) 2023-06-23 18:25:06 +02:00
ptitSeb 9ee030a566 Added 1 more function to wrapped SDL2 (for #836) 2023-06-23 16:42:10 +02:00
ptitSeb a8e96764b5 Fixed some warnings 2023-06-23 15:22:26 +02:00
ptitSeb c43f1d882c Fixed segment order in x86 emulator 2023-06-23 15:22:09 +02:00
ptitSeb 1e67cefc43 Added 1 wrapped function to recent SDL2 (for #836, but might need a recent native SDL2 lib) 2023-06-23 15:20:45 +02:00
ptitSeb 5cdc1b9fa2 Allow running at NULL, and trigger a segfault (for #830) 2023-06-07 09:49:49 +02:00
ptitSeb ab75a3e2d3 Added a few wrapped function to libgcrypt and libgnutls (for wine) 2023-06-05 10:05:40 +02:00
ptitSeb 21d097853b [ELF_LOAD] Also use SONAME of loaded elf to match loaded libs 2023-06-04 13:01:38 +02:00
ptitSeb 2e3bdbefc7 Added 1 more structure to vkalign 2023-06-04 12:57:36 +02:00
澪 a19773cfb0 fix typo 2023-06-03 16:32:18 +02:00
ptitSeb 1988eb0366 [DYNAREC] Do not track memory that is not accessible (should save some memory) 2023-05-28 14:37:26 +02:00
ptitSeb 54d5aaa11d Added partial support to TF flags ([DYNAREC] too) (Helps #671 and uplay) 2023-05-24 19:33:36 +02:00
ptitSeb 205ec1f4dc [DYNAREC] Free jmptable memory when destroying DB 2023-05-19 18:47:54 +02:00
Ilya114 005367ea3c -noreactlogin deleted from Steam 2023-05-16 13:43:01 +02:00
ptitSeb 8ac9bc30a2 Added memfd_create to wrapped libc 2023-05-15 20:20:02 +02:00
ptitSeb f0691e56fc Added more bits to CPUID, and 0F AE /7 opcode ([DYNAREC] too) (for Burning Paradise) 2023-05-13 18:42:46 +02:00
ptitSeb bc06c277ec This make disblaed code clearer 2023-05-13 18:12:03 +02:00
ptitSeb 1341a4a55f Optimized Exit bridge managment 2023-05-10 17:29:25 +02:00
ptitSeb 82cf77b9d9 Improved custom memory allocator 2023-05-10 17:29:25 +02:00
ptitSeb 10db79df4a Fixed a nasty small memory leak 2023-05-10 17:29:25 +02:00
ptitSeb bce188e217 [DYNAREC] Removed all remaining trace of dynablocklist_t 2023-05-10 17:29:25 +02:00
ptitSeb 220a64af1f Added some more libgstreamer wrapped functions 2023-05-10 17:29:25 +02:00
ptitSeb e73fa8f3fb [DYNAREC] Fixed some remaining issues (PvZ works now) 2023-05-10 17:29:25 +02:00
ptitSeb 053a75f5d5 [DYNAREC] Removed DynablockList, backported from Box64 (PvZ broken for now) 2023-05-10 17:29:25 +02:00
ptitSeb bcb19dbe5d Improved fpu_fxsave/fpu_fxrstor 2023-05-08 13:30:10 +02:00
ptitSeb 039c62f740 [DYNAREC] Removed dynablocks sons handling, it makes things compicated for not enough benefits (fixed GoG Windows installers) 2023-05-04 21:30:07 +02:00
ptitSeb 7663aacd1b Added some Hack for wine int 2d calls 2023-05-04 21:28:41 +02:00
ptitSeb fd5bf804ec [DYNAREC] Slightly better handling of dynablock getting dirty during signal 2023-05-04 17:26:28 +02:00
ptitSeb 70d18cfb7c [DYNAREC] Slightly better signal handling for running dynablock getting dirty durring signal 2023-05-04 17:25:40 +02:00
ptitSeb 1e32ccc9c7 Try to fix a wine error message 2023-05-04 17:24:56 +02:00
ptitSeb 23fa99d148 [DYNAREC_TEST] Fixed 0F AE opcodes handling 2023-05-04 17:23:58 +02:00
josch 0e3ce6d8b1 add NO_LIB_INSTALL and NO_CONF_INSTALL (#822)
This adds commits 6ff68849f88cbec622fe7a485e301111319ab8d6 and
53687387ebca091043cecbfc2d99494865336b94 from box64.

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

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

* Fix

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

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

No files matched your search

+56 -16
View File
@@ -29,6 +29,9 @@ 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})
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 "")
@@ -297,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"
@@ -307,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"
@@ -324,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"
@@ -492,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
@@ -545,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"
@@ -593,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)
@@ -604,6 +635,7 @@ if(ARM_DYNAREC)
$<TARGET_OBJECTS:arm_pass1>
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
$<TARGET_OBJECTS:test_interpreter>
)
endif()
@@ -613,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)
@@ -632,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")
@@ -660,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")
@@ -679,13 +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/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
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)
+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
+13
View File
@@ -1,3 +1,16 @@
v0.3.2
======
* Better syscall handling
* Fixed some wrapped functions, added some others
* Introduced another wrapper helper
* Added some more opcodes
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
* Added support of FASTNAN for some more opcodes
* Reduced memory footprint
* Added BOX86_NOSANDBOX (adds an argument to the command line)
* Added an ukrainian translation
=> Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
v0.3.0
======
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
+3 -3
View File
@@ -6,7 +6,7 @@ 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
```
@@ -117,7 +117,7 @@ Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may hav
#### for Other ARM64 64bits Linux platform
`mkdir build; cd build; cmake .. -DARM64 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
`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
@@ -194,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`.
+2 -2
View File
@@ -2,7 +2,7 @@
Linux Userspace x86 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
@@ -88,7 +88,7 @@ So, your settings in `~/.bashrc` may override the setting from your command line
Notes about Unity game emulation
----
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Running Unity games should generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
+1 -1
View File
@@ -2,7 +2,7 @@
Linux用户空间的x86应用模拟器
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
+143
View File
@@ -0,0 +1,143 @@
![Official logo](img/Box86Logo.png "Official Logo")
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
Box86 дозволяє запускати x86 Linux програми (наприклад, ігри) на системах Linux відмінних від x86, наприклад ARM (хост-система має мати 32-розрядний порядок редагування).
Вам *ПОТРІБНА* 32-розрядна підсистема для запуску та створення Box86. Box86 марний лише на 64-розрядних системах. Крім того, вам *ПОТРІБЕН* 32-розрядний інструментарій для створення Box86. Ланцюжок інструментів, який підтримує лише 64-розрядні версії, не компілює Box86, і ви отримаєте помилки (зазвичай на aarch64 ви отримуєте що «-marm» не розпізнається, і вам знадобиться середовище з мультиархітектурою або chroot).
Оскільки Box86 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/). Це також означає, що вам знадобиться 32-бітний простір користувача на 64-бітній ОС, наприклад `armhf` поверх `aarch64` 64-бітної ОС.
Більшість x86-ігор потребують OpenGL, тому на платформах ARM може знадобитися таке рішення, як [gl4es](https://github.com/ptitSeb/gl4es). (Деякі платформи ARM підтримують лише OpenGL ES і/або їх реалізація OpenGL хитра. (див. OpenGL на Android))
Box86 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 5-10 разів, ніж використання лише інтерпретатора. Деякі високорівневі відомості про те, як працює DynaRec, можна знайти [тут](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Багато ігор просто працюють без особливих налаштувань, наприклад: WorldOfGoo, Airline Tycoon Deluxe і FTL. Багато ігор GameMaker Linux також працюють нормально. (є довгий список, серед них UNDERTALE, A Risk of Rain і Cook Serve Delicious). Ігри Unity3D також працюють добре, але вимога OpenGL може бути проблемою на деяких платформах ARM.
Якщо ви серйозно ставитеся до розробки Box86, вам слід встановити ccache та створити Box86 з ним. (Використовуйте, наприклад, ccmake.)
Щоб увімкнути TRACE (тобто скидання в stdout усіх окремих виконаних інструкцій x86 із дампом регістрів), вам також знадобиться [бібліотека Zydis](https://github.com/zyantific/zydis), доступна у вашій системі.
Деякі внутрішні коди операцій x86 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x86primop.c](../src/emu/x86primop.c) для детальної інформації про авторські права.
----
Компіляція/Встановлення
----
> Інструкцію зі складання Box86 можна знайти [тут](COMPILE.md).\
> Інструкцію з встановлення Wine для Box86 можна знайти [тут](X86WINE.md).
----
Ось 6 відео, перші 2 відео – це відео "Airline Tycoon Deluxe" і "Heretic 2", які працюють на GigaHertz OpenPandora (друге використовує Dynarec), а наступні 2 відео – це відео "Bit.Trip.Runner" і "Neverwinter Night", які працюють на ODroid XU4 (без dynarec), а останні 2 відео на Pi4: Shovel Knight (відео від @ITotalJustice) і Freedom Planet (відео від @djazz), також без Dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
Ви можете знайти багато інших відео про Box86 у YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA).
Список сумісності доступний тут: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
Логотип і піктограма зроблені @grayduck, дякую!
Зауважте, що цей проект не слід плутати з [86box](https://github.com/86Box/86Box), гарним емулятором "повної системи", що спеціалізується на ранньому (до відносно недавньому) апаратному забезпеченні ПК.
----
Використання
----
Є кілька змінних середовища для керування поведінкою Box86.
Дивіться [тут](USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
Примітка: Dynarec від Box86 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
----
Історія версій/Журнал змін
----
Історія версій доступна [тут](docs/CHANGELOG.md).
----
Примітки щодо 64-розрядних платформ
----
Оскільки Box86 працює шляхом прямого перекладу викликів функцій із x86 на хост-систему, хост-система (на якій працює Box86) повинна мати 32-розрядні бібліотеки. Box86 не містить 32-біт <-> 64-біт перекладу. Отже, щоб запустити Box86, наприклад, на платформі ARM64, вам потрібно буде зібрати Box86 для 32-бітної ARM, а також потрібно мати chroot з 32-бітними бібліотеками.
Якщо ви дивитесь на 64-розрядну версію box86, подивіться на [Box64](https://github.com/ptitSeb/box64): він може запускати двійкові файли x86_64 на 64-розрядних платформах. Але зауважте, що вам все одно потрібен Box86 (і 32-розрядний chroot) для запуску бінарних файлів x86 (як це також трапляється в реальному Linux x86_64, для запуску якого потрібні бібліотеки x86 і двійковий файл в multiarch).
----
Примітки щодо конфігурації Box86
----
Box86 тепер має конфігураційні файли. Завантажуються 2 файли: `/etc/box4.box86rc` і `~/.box86rc`. Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться на [використання](docs/USAGE.md), щоб дізнатися, які параметри можна використовувати. Box86 поставляється з файлом за замовчуванням, який слід інсталювати для кращої стабільності. Файл знаходиться в `system/box86.box86rc` і має бути встановлено в `/etc/box86.box86rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box86rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box86.box86rc` > командний рядок
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
----
Примітки щодо емуляції ігор Unity
----
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
----
Примітки щодо Steam
----
Linux версія Steam тепер може працювати з Box86, але вам також потрібен Box64, щоб його можна було повністю використовувати.
Рекомендується запускати Steam у small режимі, оскільки він використовує менше пам’яті, але steamwebhelper (64-бітний процес) усе одно завантажуватиметься, навіть якщо він не використовується.
Екран входу не може працювати без steamwebhelper, і буде показувати лише порожні вікна без належного налаштування box64 у системі.
Зауважте, що Steam використовуватиме багато пам’яті та ледве поміститься в систему з 4 ГБ оперативної пам’яті. Він більше не працюватиме в системі з меншим об’ємом пам’яті (як обхідний шлях, створіть файл підкачки, увійдіть і поставте прапорець «запам’ятати мене», використовуйте box64rc, щоб вимкнути steamwebhelper і запускати лише в малому режимі без підкачки після першого входу в систему)
Останнє зауваження: Steam BigPicture працюватиме, але також потрібен steamwebhelper (і box64) і багато пам’яті. Він не запуститься в системі лише з 4 ГБ оперативної пам’яті без файлу підкачки.
- Якщо у вас виникли проблеми зі встановленням Steam, ви можете знайти `install_steam.sh` у кореневій папці сховища box86. Цей простий скрипт завантажить і встановить Steam у вашу домашню папку, а потім створить ярлик steam у `/usr/local/bin` (для цього він запитає дозвіл sudo). Просто використовуйте `steam` для запуску після встановлення. Зауважте, що інсталяція, яка знаходиться в папці Home, працюватиме лише для одного користувача. Не використовуйте цей скрипт, якщо вам потрібна багатокористувацька інсталяція.
- Щоб уникнути повідомлення «libc.so.6 відсутній», ви можете використовувати `STEAMOS=1` і `STEAM_RUNTIME=1` як змінні середовища (воно автоматично з’являється, якщо ви використовували сценарій `install_steam.sh`)
Щоб вимкнути `steamwebhelper`, коли Box64 встановлений і працює, створіть (або відредагуйте) `~/.box64rc` і додайте у ньому:
```
[steamwebhelper]
BOX64_EXIT=1
```
І тоді `steamwebhelper` буде вимкнено. Прокоментуйте `#` ці 2 рядки, щоб увімкнути його знову.
----
Примітки щодо Wine
----
Wine тепер підтримується. Інтегровани програми Wine працює як і багато програм та ігор для Windows. Не забувайте, що більшість ігор для Windows використовують Direct3D, для цього може знадобитися повний драйвер OpenGL і якомога більш високий профіль (і gl4es з бекендом ES2 наразі мають проблеми з Wine).
Примітка: якщо ви плануєте використовувати box86 з Wine на Raspberry Pi 3 або ранішої версії, ці моделі використовують ОС за замовчуванням, яка має ядро ​​з розділенням 2/2 (тобто 2G місця для програми користувача та 2 Г місця для ядра). Це несумісно з програмами Wine, яким потрібен доступ до пам’яті > 2 Гб адреси. Тож вам потрібно буде переналаштувати ядро ​​для розділення 3G/1G.
----
Примітки щодо Vulkan
----
Box86 вже використовує Vulkan. Якщо у вашій системі є 32-розрядний драйвер Vulkan, Box86 використовуватиме його за потреби. Профіль 1.0, 1.1, 1.2 і 1.3, з деякими розширеннями, має бути в порядку. DXVK, включаючи 2.0, працює. Я знаю, що деякі демонстраційні версії працюють на Pi4 (демонстраційні версії Sascha Willems для x86 працюють так само, як якщо б створювати безпосередньо на armhf). Зауважте, що драйвер Vulkan для Pi4 наразі НЕ підтримує DXVK (обгортка Wine DirectX->Vulkan). Це не проблема Box86, у драйвері відсутні розширення (підтримка апаратного забезпечення) та кілька інших речей, через які DXVK не працює на pi4. З боку Panfrost, PanVK трохи молодий, і я ще не тестував DXVK з ним.
----
Останнє слово
----
Я хочу подякувати всім, хто зробив внесок у розвиток box86.
Є багато способів зробити свій внесок: код, фінанси, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, icecream95, M-HT
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За внесок у апаратне забезпечення: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
* За постійну рекламу Box86: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[Команда TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
І я також дякую багатьом іншим людям, які хоч раз брали участь у проекті.
(Якщо ви використовуєте Box86 у своєму проекті, будь ласка, не забудьте згадати про це!)
+30
View File
@@ -127,6 +127,11 @@ Enables/Disables trace for generated code.
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_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)
@@ -170,11 +175,26 @@ 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_JVM *
Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
#### BOX86_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
@@ -185,6 +205,11 @@ Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX86_LIBCEF *
Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
#### BOX86_LIBGL *
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -281,3 +306,8 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
#### BOX86_NORCFILES
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
#### BOX86_NOSANDBOX
* 0 : Nothing special
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
+1 -1
View File
@@ -42,7 +42,7 @@ rm ~/wine.tgz # clean up
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could also just make a symlink, but box86 only works for 32bit apps at the moment
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
+10 -3
View File
@@ -22,20 +22,27 @@ echo "#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
~/steam/bin/steam 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
# 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
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
@@ -1834,7 +1834,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
+37 -14
View File
@@ -679,12 +679,12 @@ class Clauses:
return isinstance(o, Clauses) and (self.clauses == o.clauses)
JumbledFunctions = CustOrderedDictList[Clause, Function]
FilesSpecific = Dict[Filename, FileSpec]
FileSpecifics = Dict[Filename, FileSpec]
SortedGlobals = CustOrderedDictList[Clauses, FunctionType]
SortedRedirects = CustOrderedDictList[Clauses, FunctionType]
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FilesSpecific]:
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FileSpecifics]:
"""
readFiles
@@ -693,7 +693,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
gbls: JumbledFunctions = CustOrderedDictList()
redirects: JumbledFunctions = CustOrderedDictList()
filespecs: FilesSpecific = {}
filespecs: FileSpecifics = {}
symbols: Dict[str, Filename] = {}
need_halt: bool = False
@@ -880,7 +880,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
return gbls, redirects, filespecs
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FilesSpecific) \
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FileSpecifics) \
-> Tuple[SortedGlobals, SortedRedirects]:
# First sort file specific stuff
for fn in filespecs:
@@ -944,13 +944,13 @@ def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespe
redirects[red_vals[funtype]].append(funtype)
redirects.sort(key=Clauses.splitdef)
def fail(): assert(False)
def fail(): assert False
for clauses in redirects:
redirects[clauses].sort(key=lambda v: fail() if v.redirected is None else v.splitchar() + v.redirected.splitchar())
return gbls, redirects
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filesspec: FilesSpecific) -> Optional[str]:
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filespecs: FileSpecifics) -> Optional[str]:
# Check if there was any new functions compared to last run
functions_list: str = ""
for clauses in gbls:
@@ -960,18 +960,18 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
for v in redirects[clauses]:
assert(v.redirected is not None)
functions_list = functions_list + "#" + str(clauses) + " " + v.orig + " -> " + v.redirected.orig + "\n"
for filename in sorted(filesspec.keys()):
for filename in sorted(filespecs.keys()):
functions_list = functions_list + filename + ":\n"
for st in filesspec[filename].structs:
struct = filesspec[filename].structs[st]
for st in filespecs[filename].structs:
struct = filespecs[filename].structs[st]
functions_list = functions_list + \
"% " + st + " " + struct.name + " " + struct.repl + "\n"
for _bare in filesspec[filename].typedefs:
for _bare in filespecs[filename].typedefs:
functions_list = functions_list + "- " + _bare.orig + ":\n"
for fn in filesspec[filename].typedefs[_bare]:
for fn in filespecs[filename].typedefs[_bare]:
if fn.no_dlsym: continue
functions_list = functions_list + " - " + fn.name + "\n"
for funtype in filesspec[filename].structsuses:
for funtype in filespecs[filename].structsuses:
assert(funtype.redirected is not None)
functions_list = functions_list + "% " + funtype.orig + " -> " + funtype.redirected.orig + "\n"
@@ -992,7 +992,7 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
return functions_list
def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobals, redirects: SortedRedirects, \
filespecs: FilesSpecific) -> None:
filespecs: FileSpecifics) -> None:
# Files header and guard
files_header = {
"wrapper.c": """
@@ -1148,6 +1148,13 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
for fhdr in files_header:
files_guard[fhdr] = trim(files_guard[fhdr])
# TODO: put the informations below in a structure (like in box64, where
# typedefs & co. are stored in an ABI-specific structure)
return_x87: str = "DKdf"
if any(c not in FileSpec.values for c in return_x87):
raise NotImplementedError("Invalid character")
# Typedefs
# E v c w i I C W u U f d D K l L p V O S 2 P G N M s
tdtypes = ["x86emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*", "...", "...", "void*"]
@@ -1309,6 +1316,22 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
if not clauses.empty():
file.write("#endif\n")
# Finally, write predicate functions
# isRetX87Wrapper
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
for clauses in gbls:
empty = True
for funtype in gbls[clauses]:
if funtype.orig[0] in return_x87: # TODO: put this in a function (functions would request the ABI for more info)
if empty and (not clauses.empty()):
file.write("#if " + str(clauses) + "\n")
empty = False
file.write("\tif (fun == &" + funtype.orig + ") return 1;\n")
if not empty:
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
# Rewrite the wrapper.h file:
@@ -1398,6 +1421,6 @@ if __name__ == '__main__':
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.10") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.11") != 0:
exit(2)
exit(0)
+50 -17
View File
@@ -23,6 +23,7 @@
#include "custommem.h"
#include "dictionnary.h"
#include "rcfile.h"
#include "gltools.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
@@ -146,6 +147,7 @@ static void init_mutexes(box86context_t* context)
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);
@@ -210,7 +212,7 @@ box86context_t *NewBox86Context(int argc)
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
context->deferedInit = 1;
context->deferredInit = 1;
#endif
context->sel_serial = 1;
@@ -220,11 +222,12 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
// create exit bridge
context->exit_bridge = AddBridge(context->system, NULL, NULL, 0, NULL);
#ifdef BUILD_LIB
context->box86lib = RTLD_DEFAULT; // not ideal
#else
@@ -246,11 +249,13 @@ box86context_t *NewBox86Context(int argc)
context->canary[/*getrand(4)*/0] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
context->globdata = NewMapSymbols();
initAllHelpers(context);
return context;
}
void freeALProcWrapper(box86context_t* context);
EXPORTDYN
void FreeBox86Context(box86context_t** context)
{
@@ -288,8 +293,8 @@ void FreeBox86Context(box86context_t** context)
if(ctx->zydis)
DeleteX86Trace(ctx);
if(ctx->deferedInitList)
box_free(ctx->deferedInitList);
if(ctx->deferredInitList)
box_free(ctx->deferredInitList);
/*box_free(ctx->argv);*/
@@ -350,16 +355,19 @@ void FreeBox86Context(box86context_t** context)
}
}
free_neededlib(&ctx->neededlibs);
free_neededlib(ctx->neededlibs);
ctx->neededlibs = NULL;
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
FreeMapSymbols(&ctx->globdata);
finiAllHelpers(ctx);
#ifndef DYNAREC
#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);
@@ -375,20 +383,45 @@ void FreeBox86Context(box86context_t** context)
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
int idx = ctx->elfsize;
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
int idx = 0;
while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
if(idx == ctx->elfsize) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
} else {
ctx->elfs[idx] = head;
}
ctx->elfs[idx] = head;
ctx->elfsize++;
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
return idx;
}
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head) {
if(GetTLSBase(head)) {
// should remove the tls info
int tlsbase = GetTLSBase(head);
/*if(tlsbase == -ctx->tlssize) {
// not really correct, but will do for now
ctx->tlssize -= GetTLSSize(head);
if(!(++ctx->sel_serial))
++ctx->sel_serial;
}*/
}
for(int i=0; i<ctx->elfsize; ++i)
if(ctx->elfs[i] == head) {
ctx->elfs[i] = NULL;
return;
}
}
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
// should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
context->tlssize += tlssize;
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 3
#define BOX86_REVISION 0
#define BOX86_REVISION 2
#endif //__BOX86_VERSION_H_
+578 -500
View File
File diff suppressed because it is too large. Load diff
+2
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) )
+3 -3
View File
@@ -335,9 +335,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
+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
+4 -4
View File
@@ -159,7 +159,7 @@ const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
@@ -3049,7 +3049,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3064,7 +3064,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3080,7 +3080,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
+187 -300
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,237 +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)
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;
}
// 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)
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;
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)box_calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm_lock_storeifnull(&dynablocks->direct, p)!=NULL)
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_storeifref(&dynablocks->direct[addr-dynablocks->text], block, NULL);
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;
}
@@ -309,121 +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]))
return block;
int created = create;
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
block = AddNewDynablock(dynablocks, addr, &created);
if(!created) {
if(need_lock)
block = getDB(addr); // just in case
if(block) {
mutex_unlock(&my_context->mutex_dyndump);
return block; // existing block...
return block;
}
}
block = AddNewDynablock(addr);
// fill the block
block->x86_addr = (void*)addr;
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)
mutex_unlock(&my_context->mutex_dyndump);
return NULL;
}
void* ret = FillBlock(block, filladdr);
if(need_lock)
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))) {
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)) {
dynarec_log(LOG_DEBUG, "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;
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;
}
}
if(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);
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, *current, 0);
db = internalDBGetBlock(emu, addr, addr, create, need_lock);
if(db) {
if(db->previous)
FreeInvalidDynablock(db->previous, need_lock);
db->previous = old;
} else
FreeInvalidDynablock(old, need_lock);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) 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
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);
}
}
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;
}
@@ -431,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(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);
}
}
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_
+51 -29
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,26 +45,27 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
}
#endif
dynablock_t* current = NULL;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
dynablock_t* block = NULL;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1);
} else
block = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
}
if(!block) {
#ifdef HAVE_TRACE
#ifdef HAVE_TRACE
if(LOG_INFO<=box86_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x86addr=%p)\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
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;
}
if(!block->done) {
// not finished yet... leave linker
@@ -84,18 +86,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 +126,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 +185,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 +198,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 +221,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);
+144 -126
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*)dynaRealloc(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
@@ -281,6 +279,13 @@ static void fillPredecessors(dynarec_arm_t* dyn)
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
}
}
// remove "has_next" from orphean branch
for(int i=0; i<dyn->size-1; ++i) {
if(!dyn->insts[i].x86.has_next) {
if(dyn->insts[i+1].x86.has_next && !dyn->insts[i+1].pred_sz)
dyn->insts[i+1].x86.has_next = 0;
}
}
// second the "has_next"
for(int i=0; i<dyn->size-1; ++i) {
if(dyn->insts[i].x86.has_next) {
@@ -288,7 +293,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*)dynaMalloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -305,8 +310,6 @@ static void fillPredecessors(dynarec_arm_t* dyn)
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
// updateNeed goes backward, from last intruction to top
@@ -349,43 +352,77 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
else
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
}
if(!ok)
return ninst - 1;
--ninst;
if(!ok)
return ninst;
}
return ninst;
}
void* current_helper = NULL;
void CancelBlock(int need_lock)
{
if(need_lock)
mutex_lock(&my_context->mutex_dyndump);
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(helper) {
dynaFree(helper->next);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = NULL;
}
}
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* 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 arm_epilog();
void arm_next();
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
block->size = 0;
block->block = NULL;
block->need_test = 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);
@@ -395,10 +432,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
return CreateEmptyBlock(block, addr);
}
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;
}
if(current_helper) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock at %p as anothor one is going on\n", (void*)addr);
return NULL;
@@ -412,23 +445,23 @@ 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*)dynaCalloc(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);
dynaFree(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();
CancelBlock(0);
return NULL;
}
// already protect the block and compute hash signature
@@ -441,6 +474,8 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
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 {
@@ -468,29 +503,69 @@ 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.instsize = (instsize_t*)instsize;
*(dynablock_t**)actual_p = block;
// pass 3, emit (log emit native opcode)
if(box86_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
size_t oldarmsize = helper.arm_size;
size_t oldinstsize = helper.insts_size;
helper.arm_size = 0;
helper.insts_size = 0; // reset
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
dynaFree(helper.insts);
helper.insts = NULL;
helper.instsize = NULL;
dynaFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->jmpnext = next+sizeof(void*);
block->always_test = helper.always_test;
block->dirty = block->always_test;
*(dynablock_t**)next = block;
*(void**)(next+5*sizeof(void*)) = arm_next;
CreateJmpNext(block->jmpnext, next+5*sizeof(void*));
//block->x86_addr = (void*)start;
block->x86_size = end-start;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// Check if something changed, to abbort if it as
if((block->hash != hash)) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%zu)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
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) {
@@ -500,76 +575,19 @@ 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();
AddHotPage(addr);
CancelBlock(0);
return NULL;
}
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "BOX86: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
}
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while beeing processed %p:%zd, cancelling\n", block->x86_addr, block->x86_size);
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%zu, marking as need_test\n", block->x86_addr, block->x86_size);
AddHotPage(addr);
block->need_test = 1;
block->dirty = 1;
//protectDB(addr, end-addr);
}
// 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);
}
box_free(helper.predecessor);
helper.predecessor = NULL;
current_helper = NULL;
block->done = 1;
//block->done = 1;
return (void*)block;
}
+68 -24
View File
@@ -27,6 +27,8 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
int isRetX87Wrapper(wrapper_t fun);
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
@@ -1245,6 +1247,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
ORR_IMM8(xFlags, xFlags, 2, 0);
SET_DFNONE(x1);
if(box86_wine) { // should this be done all the time?
TSTS_IMM8_ROR(xFlags, 0x1, 12); // 0x100 == F_TF
B_NEXT(cEQ);
MOV32(x1, addr);
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));
CALL(arm_singlestep, -1, 0);
BFC(xFlags, F_TF, 1); // should not be needed
}
break;
case 0x9E:
INST_NAME("SAHF");
@@ -1663,6 +1674,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));
@@ -1672,6 +1684,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!!!
@@ -1715,10 +1728,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...)
SKIPTEST(x14);
SMEND();
if(PK(0)==0x80) {
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));
@@ -1734,7 +1748,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;
@@ -2158,8 +2176,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
@@ -2169,18 +2187,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);
@@ -2188,7 +2207,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
x87_forget(dyn, ninst, x3, x14, 0);
if(isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
// return value will be on the stack, so the stack depth needs to be updated
x87_purgecache(dyn, ninst, 0, x3, x14, x1);
}
if((box86_log<2) && !cycle_log && dyn->insts[ninst].natcall) { // call the wrapper directly
uintptr_t ncall[2];
memcpy(ncall, (void*)(dyn->insts[ninst].natcall+2), 2*sizeof(void*)); // the wrapper + function
@@ -2219,16 +2241,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);
@@ -2252,11 +2280,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("JMP Ib");
i32 = F8S;
}
JUMP(addr+i32, 0);
JUMP((uintptr_t)getAlternate((void*)(addr+i32)), 0);
if(dyn->insts[ninst].x86.jmp_insts==-1) {
// out of the block
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
jump_to_next(dyn, addr+i32, 0, ninst);
jump_to_next(dyn, (uintptr_t)getAlternate((void*)(addr+i32)), 0, ninst);
} else {
// inside the block
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
@@ -2271,9 +2299,19 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*ok = 0;
break;
case 0xEE:
INST_NAME("OUT dx, al");
//ignored!
case 0xEC: /* IN AL, DX */
case 0xED: /* IN EAX, DX */
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, EAX */
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_priv, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0xF0:
@@ -2764,13 +2802,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORRS_IMM8(xFlags, xFlags, 1, 0);
break;
case 0xFA:
INST_NAME("CLI");
BFC(xFlags, F_IF, 1);
break;
case 0xFB:
INST_NAME("STI");
MOVW(x1, 1);
BFI(xFlags, x1, F_IF, 1);
INST_NAME(opcode==0xFA?"STI":"CLI");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_priv, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0xFC:
INST_NAME("CLD");
@@ -2823,10 +2864,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);
+73 -2
View File
@@ -90,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;
@@ -421,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;
@@ -656,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;
@@ -695,19 +698,42 @@ 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;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
v0 = fpu_get_scratch_quad(dyn);
if(q1==q0 || !box86_dynarec_fastnan)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = q1;
VRSQRTEQ_F32(v0, q0);
VMULQ_F32(v1, v0, q0);
VRSQRTSQ_F32(v1, v1, v0);
VMULQ_F32(q1, v1, v0);
if(!box86_dynarec_fastnan) {
VCEQQ_F32(v1, q1, q1); // 00 is nan
VANDQ(q1, q1, v1); // if nan, remove
VBICQ(v0, v0, v1); // if nan, keep
VORRQ(q1, q1, v0);
}
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
SKIPTEST(x1);
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(q0 == q1)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = q1;
v0 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v0, q0);
VRECPSQ_F32(v1, v0, q0);
VMULQ_F32(q1, v0, v1);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
@@ -791,7 +817,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");
@@ -815,7 +857,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");
@@ -1640,7 +1698,20 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("XRSTOR Ed (not implemented");
FAKEED;
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_ud, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL_(arm_clflush, -1, 0);
break;
default:
DEFAULT;
+4 -1
View File
@@ -313,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
+19 -3
View File
@@ -230,7 +230,7 @@ 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;
@@ -244,7 +244,23 @@ 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;
@@ -2295,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);
+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 {
+4 -4
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,7 +202,7 @@ 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);
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;
@@ -224,7 +224,7 @@ 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);
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;
+82 -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,9 +172,22 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
void arm_ud(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
}
void arm_priv(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
}
void arm_singlestep(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGTRAP, (void*)R_EIP, 1);
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -208,6 +223,10 @@ void arm_fprem1(x86emu_t* emu)
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
}
void arm_clflush(x86emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
@@ -608,6 +627,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 +722,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 +757,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 +797,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));
}
+7 -3
View File
@@ -23,12 +23,16 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
void arm_clflush(x86emu_t* emu, void* p);
int64_t arm_fist64_0(double d);
int64_t arm_fist64_1(double d);
int64_t arm_fist64_2(double d);
int64_t arm_fist64_3(double d);
void arm_ud(x86emu_t* emu);
void arm_priv(x86emu_t* emu);
void arm_singlestep(x86emu_t* emu);
#define FPUFIRST 8
@@ -71,9 +75,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 +89,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__
+135 -24
View File
@@ -4,6 +4,7 @@
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include "debug.h"
#include "box86context.h"
@@ -176,8 +177,8 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
uint32_t m = nextop&0xC7;
uint32_t n = (m>>6)&3;
int32_t offset = 0;
if(!n && m==6) {
offset = F16;
if(!n && (m&7)==6) {
offset = F16S;
MOVW(ret, offset);
} else {
switch(n) {
@@ -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;
}
@@ -861,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)
@@ -872,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));
@@ -887,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)
{
@@ -1223,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;
@@ -1241,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
@@ -1321,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;
@@ -1345,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)
{
@@ -1446,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);
@@ -1717,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];
@@ -1825,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
}
@@ -1841,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)
{
@@ -1887,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;
}
+38 -15
View File
@@ -260,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)
@@ -547,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)
@@ -741,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);
@@ -794,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);
}
+97 -78
View File
@@ -36,7 +36,6 @@ 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;
@@ -57,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");
@@ -108,29 +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");
@@ -140,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");
}
}
@@ -162,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 {
@@ -180,20 +156,18 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
}
#else
#ifndef PROT_READ
#define PROT_READ 1
#endif
if(dyn->forward) {
if(dyn->forward_to == addr) {
if(dyn->forward_to == addr && !need_epilog) {
// we made it!
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Forward extend block %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
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 %p -> %p\n", (void*)dyn->forward, (void*)dyn->forward_to);
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;
@@ -204,12 +178,12 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->forward_ninst = 0;
}
// else just continue
} else if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
} 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*/))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
@@ -220,30 +194,73 @@ 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<box86_dynarec_forward)
&& (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=forwardblock*/) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
if(dyn->forward) {
if(next<dyn->forward_to)
dyn->forward_to = next;
reset_n = -2;
ok = 1;
} else {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
}
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
if(ok<0) {
ok = 0; need_epilog=1;
#if STEP == 0
if(ninst) {
--ninst;
if(!dyn->insts[ninst].x86.barrier) {
BARRIER(BARRIER_FLOAT);
}
dyn->insts[ninst].x86.need_after |= X_PEND;
++ninst;
}
if(dyn->forward) {
// stopping too soon
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst+1;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
#endif
}
++ninst;
#if STEP == 0
if(ok && (((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)addr))
|| (addr>=box86_nodynarec_start && addr<box86_nodynarec_end)
/*|| (dyn->size >= 2000)*/)) // is this still needed? maybe it should be a parameter?
|| (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);
@@ -252,16 +269,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;
}
+3 -2
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*)dynaRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
-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 -60
View File
@@ -1,65 +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 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":""); \
}
#define INST_NAME(name) inst_name_pass3(dyn, ninst, name)
+8 -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,22 +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);
@@ -113,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_
+13
View File
@@ -44,4 +44,17 @@ typedef struct instruction_x86_s {
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
//#define USE_CUSTOM_MEM
#ifdef USE_CUSTOM_MEM
#define dynaMalloc customMalloc
#define dynaCalloc customCalloc
#define dynaRealloc customRealloc
#define dynaFree customFree
#else
#define dynaMalloc box_malloc
#define dynaCalloc box_calloc
#define dynaRealloc box_realloc
#define dynaFree box_free
#endif
#endif //__DYNAREC_PRIVATE_H_
+3 -3
View File
@@ -233,9 +233,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
+326 -162
View File
@@ -60,11 +60,14 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
h->path = (char*)box_malloc(1);
h->path[0] = '\0';
}
h->mapsymbols = NewMapSymbols();
h->weaksymbols = NewMapSymbols();
h->localsymbols = NewMapSymbols();
h->globaldefver = NewDefaultVersion();
h->weakdefver = NewDefaultVersion();
h->refcnt = 1;
return h;
}
@@ -73,14 +76,9 @@ void FreeElfHeader(elfheader_t** head)
if(!head || !*head)
return;
elfheader_t *h = *head;
#ifdef DYNAREC
/*if(h->text) {
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
}*/ // will be free at the end, no need to free it now
#endif
box_free(h->name);
box_free(h->path);
if(my_context)
RemoveElfHeader(my_context, h);
box_free(h->PHEntries);
box_free(h->SHEntries);
box_free(h->SHStrTab);
@@ -93,8 +91,13 @@ void FreeElfHeader(elfheader_t** head)
FreeMapSymbols(&h->mapsymbols);
FreeMapSymbols(&h->weaksymbols);
FreeMapSymbols(&h->localsymbols);
FreeDefaultVersion(&h->globaldefver);
FreeDefaultVersion(&h->weakdefver);
FreeElfMemory(h);
box_free(h->name);
box_free(h->path);
box_free(h);
*head = NULL;
@@ -158,12 +161,17 @@ const char* ElfName(elfheader_t* head)
return "(noelf)";
return head->name;
}
const char* ElfPath(elfheader_t* head)
{
if(!head)
return NULL;
return head->path;
}
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
if(!head->vaddr && box86_load_addr) {
offs = box86_load_addr;
offs = (uintptr_t)findBlockNearHint((void*)box86_load_addr, head->memsz);
box86_load_addr += head->memsz*(1+mainbin);
box86_load_addr = (box86_load_addr+0xffffffLL)&~0xffffffLL;
}
@@ -296,6 +304,13 @@ void FreeElfMemory(elfheader_t* head)
else
for(int i=0; i<head->multiblock_n; ++i)
munmap(head->multiblock[i], head->multiblock_size[i]);
#ifdef DYNAREC
for(int i=0; i<head->multiblock_n; ++i) {
dynarec_log(LOG_INFO, "Free DynaBlocks for %s\n", head->path);
cleanDBFromAddressRange((uintptr_t)head->multiblock[i], head->multiblock_size[i], 1);
freeProtection((uintptr_t)head->multiblock[i], head->multiblock_size[i]);
}
#endif
box_free(head->multiblock);
box_free(head->multiblock_size);
box_free(head->multiblock_offs);
@@ -353,6 +368,23 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
return 0;
}
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded)
{
if(!verneeded || !head)
return 1;
if(!head->VerDef || !verneeded->VerNeed)
return 1;
int cnt = GetNeededVersionCnt(verneeded, libname);
for (int i=0; i<cnt; ++i) {
const char* vername = GetNeededVersionString(verneeded, libname, i);
if(vername && !GetVersionIndice(head, vername)) {
printf_log(/*LOG_DEBUG*/LOG_INFO, "Discarding %s for missing version %s\n", head->path, vername);
return 0; // missing version
}
}
return 1;
}
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
{
(void)context;
@@ -402,7 +434,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
*offs = sym->st_value + h->delta;
*p = (uint32_t*)(rel[i].r_offset + h->delta);
return 1;
@@ -422,7 +454,7 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
if(version2!=-1) version2 &= 0x7fff;
if(version && !version2) version2=-1; // match a versionned symbol against a global "local" symbol
const char* vername2 = GetSymbolVersion(h, version2);
if(SameVersionnedSymbol(name, version, vername, symname, version2, vername2)) {
if(SameVersionedSymbol(name, version, vername, symname, version2, vername2)) {
*offs = sym->st_value + h->delta;
*p = (uint32_t*)(rela[i].r_offset + h->delta + rela[i].r_addend);
return 1;
@@ -436,6 +468,13 @@ int FindR386COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint32_t*
int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf32_Rel *rel, int* need_resolv)
{
int ret_ok = 0;
const char* old_globdefver = NULL;
const char* old_weakdefver = NULL;
int old_bind = -1;
const char* old_symname = NULL;
uintptr_t old_offs = 0;
uintptr_t old_end = 0;
int old_version = -1;
for (int i=0; i<cnt; ++i) {
int t = ELF32_R_TYPE(rel[i].r_info);
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rel[i].r_info)];
@@ -450,32 +489,62 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
const char* globdefver = NULL;
const char* weakdefver = NULL;
if(old_bind==bind && old_symname==symname) {
globdefver = old_globdefver;
weakdefver = old_weakdefver;
} else {
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
}
if(bind==STB_LOCAL) {
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);
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
if(local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
// this is probably very very wrong. A proprer way to get reloc need to be written, but this hack seems ok for now
// at least it work for half-life, unreal, ut99, zsnes, Undertale, ColinMcRae Remake, FTL, ShovelKnight...
/*if(bind==STB_GLOBAL && (ndx==10 || ndx==19) && t!=R_386_GLOB_DAT) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
}*/
// so weak symbol are the one left
if(!offs && !end) {
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
if(bind==STB_WEAK) {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
}
old_bind = bind;
old_symname = symname;
old_offs = offs;
old_end = end;
uintptr_t globoffs, globend;
uint32_t* globp;
uintptr_t tmp = 0;
@@ -503,23 +572,23 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
globoffs = offs;
globend = end;
offs = end = 0;
GetSizedSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, size, version, vername, 1, defver); // try globaldata symbols first
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
printf_dump(LOG_NEVER, "Apply R_386_COPY @%p with sym=%s (ver=%d/%s), @%p size=%zd\n", p, symname, version, vername?vername:"(none)", (void*)offs, sym->st_size);
if(p!=(void*)(offs))
memmove(p, (void*)(offs), sym->st_size);
if(p!=(void*)offs)
memmove(p, (void*)offs, sym->st_size);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_386_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
break;
case R_386_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -528,7 +597,8 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
@@ -537,7 +607,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername)) {
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
offs = globoffs;
end = globend;
}
@@ -687,6 +757,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head, int cnt, Elf32_Rela *rela, int* need_resolv)
{
int ret_ok = 0;
const char* old_globdefver = NULL;
const char* old_weakdefver = NULL;
int old_bind = -1;
const char* old_symname = NULL;
uintptr_t old_offs = 0;
uintptr_t old_end = 0;
int old_version = -1;
for (int i=0; i<cnt; ++i) {
int t = ELF32_R_TYPE(rela[i].r_info);
Elf32_Sym *sym = &head->DynSym[ELF32_R_SYM(rela[i].r_info)];
@@ -701,16 +778,29 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
const char* globdefver = NULL;
const char* weakdefver = NULL;
if(old_bind==bind && old_symname==symname) {
globdefver = old_globdefver;
weakdefver = old_weakdefver;
} else {
old_globdefver = globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(maplib, local_maplib, 0, symname);
old_weakdefver = weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(maplib, local_maplib, 1, symname):NULL;
}
if(bind==STB_LOCAL) {
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);
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
if(local_maplib)
GetLocalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end)
GetLocalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
} else {
// this is probably very very wrong. A proprer way to get reloc need to be writen, but this hack seems ok for now
@@ -720,18 +810,35 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
end = offs + sym->st_size;
}*/
// so weak symbol are the one left
if(!offs && !end) {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end && local_maplib) {
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(bind==STB_WEAK) {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
GetGlobalWeakSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
GetGlobalWeakSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
} else {
if(old_version==version && old_bind==bind && old_symname==symname) {
offs = old_offs;
end = old_end;
} else {
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername, globdefver, weakdefver);
}
}
}
old_bind = bind;
old_symname = symname;
old_offs = offs;
old_end = end;
uintptr_t globoffs, globend;
uint32_t* globp;
uintptr_t tmp = 0;
intptr_t delta;
switch(ELF32_R_TYPE(rela[i].r_info)) {
switch(t) {
case R_386_NONE:
// can be ignored
printf_dump(LOG_NEVER, "Ignoring [%d] %s %p (%p)\n", i, DumpRelType(t), p, (void*)(p?(*p):0));
@@ -753,11 +860,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
globoffs = offs;
globend = end;
offs = end = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1, defver); // try globaldata symbols first
GetSizedSymbolStartEnd(my_context->globdata, symname, &offs, &end, size, version, vername, 1, globdefver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername);
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
if(!offs)
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername);
GetNoSelfSymbolStartEnd(maplib, symname, &offs, &end, head, size, version, vername, globdefver, weakdefver);
if(!offs) {offs = globoffs; end = globend;}
if(offs) {
// add r_addend to p?
@@ -769,7 +876,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
break;
case R_386_GLOB_DAT:
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
if(head!=my_context->elfs[0] && !IsGlobalNoWeakSymbolInNative(maplib, symname, version, vername, globdefver) && FindR386COPYRel(my_context->elfs[0], symname, &globoffs, &globp, size, version, vername)) {
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -778,7 +885,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, globoffs, sym->st_size, version, vername);
AddUniqueSymbol(my_context->globdata, symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
@@ -787,7 +895,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
*p = globoffs;
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername)) {
if (GetGlobalNoWeakSymbolStartEnd(local_maplib?local_maplib:maplib, symname, &globoffs, &globend, version, vername, globdefver)) {
offs = globoffs;
end = globend;
}
@@ -932,9 +1040,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
return bindnow?ret_ok:0;
}
void checkHookedSymbols(lib_t *maplib, elfheader_t* h); // in mallochook.c
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
bindnow = 1;
printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
}
if(head->rel) {
int cnt = head->relsz / head->relent;
DumpRelTable(head, cnt, (Elf32_Rel *)(head->rel + head->delta), "Rel");
@@ -949,13 +1061,16 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* he
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf32_Rela *)(head->rela + head->delta), NULL))
return -1;
}
checkHookedSymbols(maplib, head);
return 0;
}
int RelocateElfPlt(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
int need_resolver = 0;
if(0 && (head->flags&DF_BIND_NOW) && !bindnow) { // disable for now, needs more symbol in a fow libs like gtk and nss3
bindnow = 1;
printf_log(LOG_DEBUG, "Forcing %s to Bind Now\n", head->name);
}
if(head->pltrel) {
int cnt = head->pltsz / head->pltent;
if(head->pltrel==DT_REL) {
@@ -1058,6 +1173,7 @@ uintptr_t GetLastByte(elfheader_t* h)
#define STB_GNU_UNIQUE 10
#endif
void checkHookedSymbols(elfheader_t* h); // in mallochook.c
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
{
if(box86_dump && h->DynSym) DumpDynSym(h);
@@ -1068,41 +1184,29 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
int type = ELF32_ST_TYPE(h->SymTab[i].st_info);
int vis = h->SymTab[i].st_other&0x3;
size_t sz = h->SymTab[i].st_size;
// check "@@" default version symbol to add that information, regardless of size or type
if(symname && strstr(symname, "@@")) {
char symnameversionned[strlen(symname)+1];
strcpy(symnameversionned, symname);
// extract symname@@vername
char* p = strchr(symnameversionned, '@');
*p=0;
p+=2;
symname = AddDictionnary(my_context->versym, symnameversionned);
const char* vername = AddDictionnary(my_context->versym, p);
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
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 || (vis==STV_HIDDEN && bind==STB_LOCAL)) && (h->SymTab[i].st_shndx!=0)) {
if(strstr(symname, "@@")) {
char symnameversionned[strlen(symname)+1];
strcpy(symnameversionned, symname);
// extract symname@@vername
char* p = strchr(symnameversionned, '@');
if(sz && strstr(symname, "@@")) {
char symnameversioned[strlen(symname)+1];
strcpy(symnameversioned, symname);
// extact symname@@vername
char* p = strchr(symnameversioned, '@');
*p=0;
p+=2;
symname = AddDictionnary(my_context->versym, symnameversionned);
symname = AddDictionnary(my_context->versym, symnameversioned);
const char* vername = AddDictionnary(my_context->versym, p);
if(!sz || ((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p)))
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
if((bind==STB_GNU_UNIQUE /*|| (bind==STB_GLOBAL && type==STT_FUNC)*/) && FindGlobalSymbol(maplib, symname, 2, p))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
printf_dump(LOG_NEVER, "Adding Default Versionned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
printf_dump(LOG_NEVER, "Adding Default Versioned Symbol(bind=%s) \"%s@%s\" with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, vername, (void*)offs, sz);
if(bind==STB_LOCAL)
AddSymbol(localsymbols, symname, offs, sz, 0, vername);
AddSymbol(localsymbols, symname, offs, sz, 2, vername);
else // add in local and global map
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, 0, vername);
AddSymbol(weaksymbols, symname, offs, sz, 2, vername);
} else {
AddSymbol(mapsymbols, symname, offs, sz, 0, vername);
AddSymbol(mapsymbols, symname, offs, sz, 2, vername);
}
} else {
int to_add = 1;
@@ -1133,17 +1237,17 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
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;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname))?1:0;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetMaplibDefaultVersion(my_context->maplib, (maplib==my_context->maplib)?NULL:maplib, (bind==STB_WEAK)?1:0, symname))?1:0;
if(version!=-1) version &= 0x7fff;
const char* vername = GetSymbolVersion(h, version);
if(add_default) {
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
AddDefaultVersion((bind==STB_WEAK)?h->weakdefver:h->globaldefver, symname, vername);
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
}
int to_add = 1;
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername)))
continue;
printf_dump(LOG_NEVER, "Adding Versionned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
printf_dump(LOG_NEVER, "Adding Versioned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
if(bind==STB_LOCAL)
AddSymbol(localsymbols, symname, offs, sz, version, vername);
else // add in local and global map
@@ -1154,7 +1258,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
}
}
}
checkHookedSymbols(h);
}
/*
@@ -1171,8 +1275,10 @@ $PLATFORM – Expands to the processor type of the current machine (see the
uname(1) man page description of the -i option). For more details of this token
expansion, see “System Specific Shared Objects”
*/
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu)
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box86context_t *box86, x86emu_t* emu)
{
if(h->needed) // already done
return 0;
DumpDynamicRPath(h);
// update RPATH first
for (uint32_t i=0; i<h->numDynamic; ++i)
@@ -1210,39 +1316,49 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
box_free(origin);
is_origin = 1;
}
while(strstr(rpath, "${PLATFORM}")) {
char* platform = box_strdup("i686");
char* p = strrchr(platform, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${PLATFORM}")+strlen(platform)+1);
p = strstr(rpath, "${PLATFORM}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, platform);
strcat(tmp, p+strlen("${PLATFORM}"));
if(rpath!=rpathref)
box_free(rpath);
rpath = tmp;
box_free(platform);
}
if(strchr(rpath, '$')) {
printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
} else {
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
if(is_origin) {
// also add rpath/i686
char tmp[strlen(rpath)+strlen("/i686")+1];
strcpy(tmp, rpath);
strcat(tmp, "/i686");
PrependList(&box86->box86_ld_lib, tmp, 1);
}
PrependList(&box86->box86_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
box_free(rpath);
}
if(!h->neededlibs && neededlibs)
h->neededlibs = neededlibs;
DumpDynamicNeeded(h);
int cnt = 0;
for (uint32_t i=0; i<h->numDynamic; ++i)
// count the number of needed libs, and also grab soname
for (uint32_t i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_NEEDED)
++cnt;
const char* nlibs[cnt];
if(h->Dynamic[i].d_tag==DT_SONAME)
h->soname = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
}
h->needed = new_neededlib(cnt);
if(h == my_context->elfs[0])
my_context->neededlibs = h->needed;
int j=0;
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;
h->needed->names[j++] = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
// TODO: Add LD_LIBRARY_PATH and RPATH handling
if(AddNeededLib(maplib, neededlibs, deplib, local, bindnow, nlibs, cnt, box86, emu)) {
if(AddNeededLib(maplib, local, bindnow, h->needed, h, box86, emu)) {
printf_log(LOG_INFO, "Error loading one of needed lib\n");
if(!allow_missing_libs)
return 1; //error...
@@ -1289,30 +1405,35 @@ void MarkElfInitDone(elfheader_t* h)
if(h)
h->init_done = 1;
}
void startMallocHook();
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];
for(int i=0; i<h->needed->size; ++i) {
library_t *lib = h->needed->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);
RunSafeFunction(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);
if(addr[i]) {
printf_log(LOG_DEBUG, "Calling Init[%d] for %s %p\n", i, ElfName(h), (void*)addr[i]);
RunSafeFunction((uintptr_t)addr[i], 3, my_context->argc, my_context->argv, my_context->envv);
}
}
if(h->malloc_hook_2)
startMallocHook();
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;
@@ -1328,44 +1449,55 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
// Refresh no-file part of TLS in case default value changed
RefreshElfTLS(h);
// check if in deferedInit
if(context->deferedInit) {
if(context->deferedInitSz==context->deferedInitCap) {
context->deferedInitCap += 4;
context->deferedInitList = (elfheader_t**)box_realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
if(context->deferredInit) {
if(context->deferredInitSz==context->deferredInitCap) {
context->deferredInitCap += 4;
context->deferredInitList = (elfheader_t**)box_realloc(context->deferredInitList, context->deferredInitCap*sizeof(elfheader_t*));
}
context->deferedInitList[context->deferedInitSz++] = h;
context->deferredInitList[context->deferredInitSz++] = h;
return;
}
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
h->init_done = 1;
for(int i=0; i<h->needed->size; ++i) {
library_t *lib = h->needed->libs[i];
elfheader_t *lib_elf = GetElf(lib);
if(lib_elf)
RunElfInit(lib_elf, emu);
}
printf_dump(LOG_DEBUG, "Calling Init for %s @%p\n", ElfName(h), (void*)p);
if(h->initentry)
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
printf_dump(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]);
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
for (size_t i=0; i<h->initarray_sz; ++i) {
if(addr[i]) {
printf_dump(LOG_DEBUG, "Calling Init[%zu] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
}
}
if(h->malloc_hook_2)
startMallocHook();
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));
printf_dump(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
return;
}
EXPORTDYN
void RunDeferedElfInit(x86emu_t *emu)
void RunDeferredElfInit(x86emu_t *emu)
{
box86context_t* context = GetEmuContext(emu);
if(!context->deferedInit)
if(!context->deferredInit)
return;
context->deferedInit = 0;
if(!context->deferedInitList)
context->deferredInit = 0;
if(!context->deferredInitList)
return;
int Sz = context->deferedInitSz;
elfheader_t** List = context->deferedInitList;
context->deferedInitList = NULL;
context->deferedInitCap = context->deferedInitSz = 0;
int Sz = context->deferredInitSz;
elfheader_t** List = context->deferredInitList;
context->deferredInitList = NULL;
context->deferredInitCap = context->deferredInitSz = 0;
for (int i=0; i<Sz; ++i)
RunElfInit(List[i], emu);
box_free(List);
@@ -1373,7 +1505,7 @@ void RunDeferedElfInit(x86emu_t *emu)
void RunElfFini(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->fini_done)
if(!h || h->fini_done || !h->init_done)
return;
h->fini_done = 1;
#ifdef ANDROID
@@ -1420,7 +1552,7 @@ uint32_t GetBaseSize(elfheader_t* h)
return h->memsz;
}
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr)
int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr)
{
if(!h)
return 0;
@@ -1450,7 +1582,23 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
const char* ret = NULL;
uintptr_t s = 0;
uint32_t size = 0;
if(!h)
#ifdef HAVE_TRACE
if(!h) {
if(getProtection((uintptr_t)p)&(PROT_READ)) {
if(*(uint8_t*)(p)==0xCC && *(uint8_t*)(p+1)=='S' && *(uint8_t*)(p+2)=='C') {
ret = getBridgeName(*(void**)(p+3+4));
if(ret) {
if(start)
*start = (uintptr_t)p;
if(sz)
*sz = 32;
}
}
}
return ret;
}
#endif
if(!h || h->fini_done)
return ret;
for (uint32_t i=0; (i<h->numSymTab) && (distance!=0); ++i) {
@@ -1488,7 +1636,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
return ret;
}
const char* VersionnedName(const char* name, int ver, const char* vername)
const char* VersionedName(const char* name, int ver, const char* vername)
{
if(ver<0)
return name;
@@ -1508,7 +1656,7 @@ const char* VersionnedName(const char* name, int ver, const char* vername)
return AddDictionnary(my_context->versym, buf);
}
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2)
{
if(strcmp(name1, name2)) //name are different, no need to go further
return 0;
@@ -1532,12 +1680,12 @@ void* GetDTatOffset(box86context_t* context, int index, int offset)
int32_t GetTLSBase(elfheader_t* h)
{
return h->tlsbase;
return h?h->tlsbase:0;
}
uint32_t GetTLSSize(elfheader_t* h)
{
return h->tlssize;
return h?h->tlssize:0;
}
void* GetTLSPointer(box86context_t* context, elfheader_t* h)
@@ -1607,8 +1755,9 @@ void* ElfSetBrk(void* newbrk)
}
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
{
(void)context;
// if we are here, the there is not block in standard "space"
/*dynablocklist_t* ret = getDBFromAddress(addr);
if(ret) {
@@ -1616,7 +1765,7 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
}*/
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;
@@ -1629,26 +1778,6 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
}
#endif
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->mapsymbols;
}
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->weaksymbols;
}
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->localsymbols;
}
typedef struct my_dl_phdr_info_s {
void* dlpi_addr;
const char* dlpi_name;
@@ -1671,14 +1800,14 @@ GO(4)
// dl_iterate_phdr ...
#define GO(A) \
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c)\
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
return 0; \
return RunFunction(my_context, my_dl_iterate_phdr_fct_##A, 3, a, b, c); \
static uintptr_t my_dl_iterate_phdr_fct_##A = 0; \
static int my_dl_iterate_phdr_##A(struct dl_phdr_info* a, size_t b, void* c) \
{ \
if(!a->dlpi_name) \
return 0; \
if(!a->dlpi_name[0]) /*don't send informations about box86 itself*/ \
return 0; \
return RunFunctionFmt(my_dl_iterate_phdr_fct_##A, "pLp", a, b, c); \
}
SUPER()
#undef GO
@@ -1801,6 +1930,25 @@ void ElfAttachLib(elfheader_t* head, library_t* lib)
head->lib = lib;
}
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->mapsymbols;
}
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->weaksymbols;
}
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->localsymbols;
}
typedef struct search_symbol_s{
const char* name;
void* addr;
@@ -1858,7 +2006,7 @@ int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* dat
return 0;
}
void* GetNativeSymbolUnversionned(void* lib, const char* name)
void* GetNativeSymbolUnversioned(void* lib, const char* name)
{
// try to find "name" in loaded elf, whithout checking for the symbol version (like dlsym, but no version check)
search_symbol_t s;
@@ -1873,6 +2021,16 @@ void* GetNativeSymbolUnversionned(void* lib, const char* name)
return s.addr;
}
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h)
{
return h?h->globaldefver:NULL;
}
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h)
{
return h?h->weakdefver:NULL;
}
uintptr_t pltResolver = ~(uintptr_t)0;
EXPORT void PltResolver(x86emu_t* emu)
{
@@ -1880,6 +2038,7 @@ EXPORT void PltResolver(x86emu_t* emu)
int slot = (int)Pop32(emu);
elfheader_t *h = (elfheader_t*)addr;
printf_dump(LOG_DEBUG, "PltResolver: Addr=%p, Slot=%d Return=%p: elf is %s (VerSym=%p)\n", (void*)addr, slot, *(void**)(R_ESP), h->name, h->VerSym);
Elf32_Rel * rel = (Elf32_Rel *)(h->jmprel + h->delta + slot);
Elf32_Sym *sym = &h->DynSym[ELF32_R_SYM(rel->r_info)];
@@ -1894,11 +2053,15 @@ EXPORT void PltResolver(x86emu_t* emu)
library_t* lib = h->lib;
lib_t* local_maplib = GetMaplib(lib);
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername);
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername);
const char* globdefver = (bind==STB_WEAK)?NULL:GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 0, symname);
const char* weakdefver = (bind==STB_WEAK)?GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==local_maplib)?NULL:local_maplib, 1, symname):NULL;
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
if(!offs && !end && local_maplib) {
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, h, version, vername, globdefver, weakdefver);
}
if(!offs && !end && !version)
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL);
GetGlobalSymbolStartEnd(my_context->maplib, symname, &offs, &end, h, -1, NULL, globdefver, weakdefver);
if (!offs) {
printf_log(LOG_NONE, "Error: PltResolver: Symbol %s(ver %d: %s%s%s) not found, cannot apply R_386_JMP_SLOT %p (%p) in %s\n", symname, version, symname, vername?"@":"", vername?vername:"", p, *(void**)p, h->name);
@@ -1910,6 +2073,7 @@ EXPORT void PltResolver(x86emu_t* emu)
printf_dump(LOG_DEBUG, "symbol %s from %s but elf not initialized yet, run Init now (from %s)\n", symname, ElfName(sym_elf), ElfName(h));
RunElfInitPltResolver(sym_elf, emu);
}
offs = (uintptr_t)getAlternate((void*)offs);
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)));
+10 -5
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,6 +11,7 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
struct elfheader_s {
char* name;
char* path; // Resolved path to file
char* soname; // soname of the elf
uint16_t numPHEntries;
Elf32_Phdr *PHEntries;
uint16_t numSHEntries;
@@ -38,6 +35,7 @@ struct elfheader_s {
Elf32_Verdef* VerDef;
int szVerDef;
int e_type;
uint32_t flags;
intptr_t delta; // should be 0
@@ -70,6 +68,9 @@ struct elfheader_s {
int textsz;
uintptr_t bss;
int bsssz;
uintptr_t ehframe;
uintptr_t ehframe_end;
uintptr_t ehframehdr;
uintptr_t paddr;
uintptr_t vaddr;
@@ -87,6 +88,8 @@ struct elfheader_s {
int init_done;
int fini_done;
int refcnt; // ref count for the elf
int malloc_hook_2; // this elf hook malloc, hacking it
char* memory; // char* and not void* to allow math on memory pointer
void** multiblock;
@@ -95,11 +98,13 @@ struct elfheader_s {
int multiblock_n;
library_t *lib;
needed_libs_t *neededlibs;
needed_libs_t *needed;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
};
#define R_386_NONE 0
+71
View File
@@ -273,6 +273,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->VerDef = (Elf32_Verdef*)ptr;
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
case DT_FLAGS:
h->flags = val;
printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags);
break;
}
}
if(h->rel) {
@@ -351,6 +355,17 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->bsssz = h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame");
if(ii) {
h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr");
if(ii) {
h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
@@ -399,3 +414,59 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index)
}
return NULL;
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerDef) {
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname))
return ver->vn_cnt;
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return 0;
}
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname)) {
for(int j=0; j<ver->vn_cnt; ++j) {
if(j==idx)
return h->DynStr+aux->vna_name;
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
return NULL; // idx out of bound, return NULL...
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return NULL;
}
+95 -1
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)) { \
@@ -85,7 +107,7 @@
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 0: if(m&7==6) base = F16S; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
@@ -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;
+39 -13
View File
@@ -54,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;
@@ -198,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);
@@ -231,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;
@@ -240,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;
@@ -311,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) {
@@ -475,8 +501,8 @@ uint64_t ReadTSC(x86emu_t* emu)
uint64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
#if 0
#elif defined(__ARM_ARCH)
#if 0
#if (__ARM_ARCH >= 6)
static int init = 1;
if(init) {
+12
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];
@@ -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
+970 -1037
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;
}
+520 -1634
View File
File diff suppressed because it is too large. Load diff
+119 -102
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,16 +216,20 @@ 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;
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
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(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
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];
@@ -237,7 +238,7 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
for(int i=0; i<2; ++i)
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
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) {
@@ -347,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;
@@ -513,8 +541,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
@@ -528,28 +555,28 @@ void Run660F(x86emu_t *emu)
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;
@@ -584,16 +611,16 @@ void Run660F(x86emu_t *emu)
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;
@@ -634,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
@@ -696,8 +700,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
@@ -782,23 +785,24 @@ void Run660F(x86emu_t *emu)
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
// 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;
}
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;
@@ -1016,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 */
@@ -1043,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 */
@@ -1096,8 +1098,7 @@ void Run660F(x86emu_t *emu)
}
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0x74: /* PCMPEQB Gx,Ex */
@@ -1190,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);
@@ -1217,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);
@@ -1263,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);
@@ -1332,8 +1348,7 @@ void Run660F(x86emu_t *emu)
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
return 0;
}
break;
case 0xBB: /* BTC Ew,Gw */
@@ -1345,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);
@@ -1512,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 */
@@ -1617,11 +1636,11 @@ void Run660F(x86emu_t *emu)
case 0xE6: /* CVTTPD2DQ Gx, Ex */
nextop = F8;
GET_EX;
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
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]>0x7fffffff)
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];
@@ -1799,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;
}
+1 -1
View File
@@ -890,7 +890,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
const uint8_t pk1 = PK(1);
if(((pk1>>3)&7)==2 || ((pk1>>3)&7)==4) { // jmp/call near
uintptr_t nextaddr = (uintptr_t)getAlternate((void*)evalED(emu, ip+1));
printf_log(LOG_NONE, " => %p", nextaddr);
printf_log(LOG_NONE, " => %p", (void*)nextaddr);
printFunctionAddr(nextaddr, " / ");
}
}
+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;
}
+54 -6
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,7 +77,7 @@
case 0x2C: /* CVTTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
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];
@@ -38,7 +85,7 @@
case 0x2D: /* CVTSD2SI Gd, Ex */
nextop = F8;
GET_EX;
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
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) {
@@ -255,7 +302,7 @@
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, ip += tmp32s;
, addr += tmp32s; STEP3;
) /* 0x80 -> 0x8F Jxx */
case 0xC2: /* CMPSD Gx, Ex, Ib */
@@ -295,7 +342,7 @@
nextop = F8;
GET_EX;
for(int i=0; i<2; ++i)
if(isnan(EX->d[i]) || isinf(EX->d[i]) || EX->d[i]>0x7fffffff)
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) {
@@ -322,6 +369,7 @@
break;
default:
goto _default;
return 0;
}
return addr;
}
+53 -6
View File
@@ -1,4 +1,49 @@
#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 TestF30F(x86test_t *test, uintptr_t addr)
#else
uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
#endif
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u;
uint32_t tmp32u;
int64_t tmp64s;
uint64_t tmp64u;
reg32_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem;
#ifdef TEST_INTERPRETER
x86emu_t*emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
case 0x10: /* MOVSS Gx Ex */
@@ -47,7 +92,7 @@
case 0x2C: /* CVTTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[0]<-(float)0x80000000U)
GD.dword[0] = 0x80000000;
else
GD.sdword[0] = EX->f[0];
@@ -55,7 +100,7 @@
case 0x2D: /* CVTSS2SI Gd, Ex */
nextop = F8;
GET_EX;
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>0x7fffffff)
if(isnanf(EX->f[0]) || isinff(EX->f[0]) || EX->f[0]>=(float)0x80000000U || EX->f[0]<-(float)0x80000000U)
GD.dword[0] = 0x80000000;
else
switch(emu->mxcsr.f.MXCSR_RC) {
@@ -109,7 +154,7 @@
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>0x7fffffff)
if(isnanf(EX->f[i]) || isinff(EX->f[i]) || EX->f[i]>=(float)0x80000000U || EX->f[i]<-(float)0x80000000U)
GX.ud[i] = 0x80000000;
else
GX.sd[i] = EX->f[i];
@@ -123,7 +168,7 @@
case 0x5D: /* MINSS Gx, Ex */
nextop = F8;
GET_EX;
if(isnan(GX.f[0]) || isnan(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
if(isnanf(GX.f[0]) || isnanf(EX->f[0]) || islessequal(EX->f[0], GX.f[0]))
GX.f[0] = EX->f[0];
break;
case 0x5E: /* DIVSS Gx, Ex */
@@ -134,7 +179,7 @@
case 0x5F: /* MAXSS Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.f[0]) || isnan(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
if (isnanf(GX.f[0]) || isnanf(EX->f[0]) || isgreaterequal(EX->f[0], GX.f[0]))
GX.f[0] = EX->f[0];
break;
@@ -240,5 +285,7 @@
break;
default:
goto _default;
return 0;
}
return addr;
}
+67 -34
View File
@@ -51,6 +51,7 @@ int32_t my___sendmmsg(x86emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, ui
#endif
#endif
typedef struct x86_sigaction_s x86_sigaction_t;
typedef struct x86_sigaction_restorer_s x86_sigaction_restorer_t;
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
@@ -67,6 +68,7 @@ int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void*
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
#endif
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
int my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize);
int32_t my_execve(x86emu_t* emu, const char* path, char* const argv[], char* const envp[]);
void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
@@ -75,6 +77,39 @@ int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot);
void* ElfSetBrk(void* newbrk);
int my_vfork(x86emu_t* emu);
#ifndef __NR_socketcall
int my_socketcall(x86emu_t* emu, int n, unsigned long *args) {
int ret = 0;
switch(n) {
case SYS_SOCKET: ret = socket(args[0], args[1], args[2]); break;
case SYS_BIND: ret = bind(args[0], (void*)args[1], args[2]); break;
case SYS_CONNECT: ret = connect(args[0], (void*)args[1], args[2]); break;
case SYS_LISTEN: ret = listen(args[0], args[1]); break;
case SYS_ACCEPT: ret = accept(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETSOCKNAME: ret = getsockname(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETPEERNAME: ret = getpeername(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_SOCKETPAIR: ret = socketpair(args[0], args[1], args[2], (int*)args[3]); break;
case SYS_SEND: ret = send(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_RECV: ret = recv(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_SENDTO: ret = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break;
case SYS_RECVFROM: ret = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break;
case SYS_SHUTDOWN: ret = shutdown(args[0], args[1]); break;
case SYS_SETSOCKOPT: ret = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break;
case SYS_GETSOCKOPT: ret = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break;
case SYS_SENDMSG: ret = sendmsg(args[0], (void*)args[1], args[2]); break;
case SYS_RECVMSG: ret = recvmsg(args[0], (void*)args[1], args[2]); break;
case SYS_ACCEPT4: ret = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break;
#ifdef SYS_RECVMMSG
case SYS_RECVMMSG: ret = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break;
case SYS_SENDMMSG: ret = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break;
#endif
default:
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", n);
ret = -EINVAL;
}
};
#endif
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
#define O_NONBLOCK 04000
@@ -106,6 +141,9 @@ scwrap_t syscallwrap[] = {
{ 19, __NR_lseek, 3 },
{ 20, __NR_getpid, 0 },
{ 24, __NR_getuid, 0 },
#ifdef __NR_alarm
{ 27, __NR_alarm, 1 },
#endif
{ 33, __NR_access, 2 },
{ 37, __NR_kill, 2 },
{ 38, __NR_rename, 2 },
@@ -123,12 +161,14 @@ scwrap_t syscallwrap[] = {
{ 63, __NR_dup2, 2 },
{ 64, __NR_getppid, 0 },
{ 66, __NR_setsid, 0 },
//{ 67, __NR_sigaction, 3 },
{ 75, __NR_setrlimit, 2 },
#ifdef __NR_getrlimit
{ 76, __NR_getrlimit, 2 },
#endif
{ 77, __NR_getrusage, 2 },
{ 78, __NR_gettimeofday, 2 },
{ 80, __NR_getgroups, 2 },
{ 83, __NR_symlink, 2 },
#ifdef __NR_select
{ 82, __NR_select, 5 },
@@ -172,6 +212,7 @@ scwrap_t syscallwrap[] = {
//{ 122, __NR_uname, 1 },
//{ 123, __NR_modify_ldt },
//{ 125, __NR_mprotect, 3 },
{ 126, __NR_sigprocmask, 3 },
{ 136, __NR_personality, 1 },
{ 140, __NR__llseek, 5 },
{ 141, __NR_getdents, 3 },
@@ -447,6 +488,13 @@ void EXPORT x86Syscall(x86emu_t *emu)
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
#ifndef __NR_alarm
case 27:
R_EAX = alarm(R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#endif
case 45: // sys_brk
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
@@ -463,6 +511,11 @@ void EXPORT x86Syscall(x86emu_t *emu)
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
case 67: // sys_sigaction
R_EAX = (uint32_t)my_syscall_sigaction(emu, R_EBX, (x86_sigaction_restorer_t*)R_ECX, (x86_sigaction_restorer_t*)R_EDX, R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_getrlimit
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
@@ -491,39 +544,10 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = (uint32_t)-errno;
break;
#ifndef __NR_socketcall
case 102: {
unsigned long *args = (unsigned long *)R_ECX;
// need to do all call "by hand"
switch(R_EBX) {
case SYS_SOCKET: R_EAX = socket(args[0], args[1], args[2]); break;
case SYS_BIND: R_EAX = bind(args[0], (void*)args[1], args[2]); break;
case SYS_CONNECT: R_EAX = connect(args[0], (void*)args[1], args[2]); break;
case SYS_LISTEN: R_EAX = listen(args[0], args[1]); break;
case SYS_ACCEPT: R_EAX = accept(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETSOCKNAME: R_EAX = getsockname(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_GETPEERNAME: R_EAX = getpeername(args[0], (void*)args[1], (void*)args[2]); break;
case SYS_SOCKETPAIR: R_EAX = socketpair(args[0], args[1], args[2], (int*)args[3]); break;
case SYS_SEND: R_EAX = send(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_RECV: R_EAX = recv(args[0], (void*)args[1], args[2], args[3]); break;
case SYS_SENDTO: R_EAX = sendto(args[0], (void*)args[1], args[2], args[3], (void*)args[4], args[5]); break;
case SYS_RECVFROM: R_EAX = recvfrom(args[0], (void*)args[1], args[2], args[3], (void*)args[4], (void*)args[5]); break;
case SYS_SHUTDOWN: R_EAX = shutdown(args[0], args[1]); break;
case SYS_SETSOCKOPT: R_EAX = setsockopt(args[0], args[1], args[2], (void*)args[3], args[4]); break;
case SYS_GETSOCKOPT: R_EAX = getsockopt(args[0], args[1], args[2], (void*)args[3], (void*)args[4]); break;
case SYS_SENDMSG: R_EAX = sendmsg(args[0], (void*)args[1], args[2]); break;
case SYS_RECVMSG: R_EAX = recvmsg(args[0], (void*)args[1], args[2]); break;
case SYS_ACCEPT4: R_EAX = my_accept4(emu, args[0], (void*)args[1], (void*)args[2], args[3]); break;
#ifdef SYS_RECVMMSG
case SYS_RECVMMSG: R_EAX = my_recvmmsg(emu, args[0], (void*)args[1], args[2], args[3], (void*)args[4]); break;
case SYS_SENDMMSG: R_EAX = my___sendmmsg(emu, args[0], (void*)args[1], args[2], args[3]); break;
#endif
default:
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", R_EBX);
R_EAX = -EINVAL;
}
case 102:
R_EAX = my_socketcall(emu, R_EBX, (unsigned long *)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
}
break;
#endif
#ifndef __NR_olduname
@@ -748,9 +772,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
printf_log(LOG_INFO, "Warning: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
R_EAX = (uint32_t)-ENOSYS;
return;
}
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
@@ -800,10 +823,20 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return (uint32_t)close(i32(4));
case 11: // execve
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
#ifndef __NR_alarm
case 27:
return alarm(R_EBX);
#endif
case 45: // brk
return (uintptr_t)ElfSetBrk(p(4));
case 67: // sys_sigaction
return my_syscall_sigaction(emu, u32(4), (x86_sigaction_restorer_t*)p(8), (x86_sigaction_restorer_t*)p(12), u32(16));
case 91: // munmap
return (uint32_t)my_munmap(emu, p(4), u32(8));
#ifndef __NR_socketcall
case 102:
return my_socketcall(emu, i32(4), (unsigned long *)p(8));
#endif
#ifndef __NR_ipc
case 117: // ipc
return (uint32_t)my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
+159
View File
@@ -0,0 +1,159 @@
#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 <stddef.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 "signals.h"
void print_banner(x86emu_t* ref)
{
printf_log(LOG_NONE, "Warning, difference between Interpreter and Dynarec in %p (%02x %02x %02x %02x %02x %02x %02x %02x)\n"\
"=======================================\n",
(void*)ref->old_ip,
((uint8_t*)ref->old_ip)[0], ((uint8_t*)ref->old_ip)[1], ((uint8_t*)ref->old_ip)[2], ((uint8_t*)ref->old_ip)[3],
((uint8_t*)ref->old_ip)[4], ((uint8_t*)ref->old_ip)[5], ((uint8_t*)ref->old_ip)[6], ((uint8_t*)ref->old_ip)[7]
);
printf_log(LOG_NONE, "DIFF: Dynarec | Interpreter\n----------------------\n");
}
#define BANNER if(!banner) {banner=1; print_banner(ref);}
void x86test_check(x86emu_t* ref, uintptr_t ip)
{
int banner = 0;
x86test_t* test = &ref->test;
x86emu_t* emu = test->emu;
if(memcmp(ref->regs, emu->regs, sizeof(emu->regs))) {
static const char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI"};
BANNER;
for(int i=0; i<8; ++i) {
if(ref->regs[i].dword[0]!=emu->regs[i].dword[0]) {
printf_log(LOG_NONE, "%s: %08x | %08x\n", regname[i], ref->regs[i].dword[0], emu->regs[i].dword[0]);
}
}
}
if(ip!=emu->ip.dword[0]) {
BANNER;
printf_log(LOG_NONE, "RIP: %08x | %08x\n", ip, emu->ip.dword[0]);
}
// flags are volatile, so don't test them
//memcpy(&ref->eflags, &emu->eflags, sizeof(emu->eflags));
if(memcmp(ref->segs, emu->segs, sizeof(emu->segs))) {
static const char* segname[] = {"CS", "DS", "ES", "SS", "FS", "GS"};
BANNER;
for(int i=0; i<6; ++i) {
if(ref->segs[i]!=emu->segs[i]) {
printf_log(LOG_NONE, "%s: %04x | %04x\n", segname[i], ref->segs[i], emu->segs[i]);
}
}
}
if(ref->top != emu->top) {
BANNER;
printf_log(LOG_NONE, "X87 TOP: %d | %d\n", ref->top, emu->top);
}
if(ref->fpu_stack != emu->fpu_stack) {
BANNER;
printf_log(LOG_NONE, "X87 STACK: %d | %d\n", ref->fpu_stack, emu->fpu_stack);
}
if(ref->fpu_stack && memcmp(ref->x87, emu->x87, sizeof(emu->x87))) {
// need to check each regs, unused one might have different left over value
for(int i=0; i<ref->fpu_stack; ++i) {
if(ref->x87[(ref->top+i)&7].d != emu->x87[(emu->top+i)&7].d) {
BANNER;
printf_log(LOG_NONE, "ST%d: %g | %g\n", i, ref->x87[(ref->top+i)&7].d, emu->x87[(emu->top+i)&7].d);
}
}
}
//memcpy(ref->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
//memcpy(ref->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
/*if(ref->p_regs != emu->p_regs) {
BANNER;
printf_log(LOG_NONE, "X87 PREG: %x | %x\n", ref->p_regs, emu->p_regs);
}*/
if(ref->cw.x16 != emu->cw.x16) {
BANNER;
printf_log(LOG_NONE, "X87 CW: %x | %x\n", ref->cw.x16, emu->cw.x16);
}
if(ref->sw.x16 != emu->sw.x16) {
BANNER;
printf_log(LOG_NONE, "X87 SW: %x | %x\n", ref->sw.x16, emu->sw.x16);
}
if(memcmp(ref->mmx, emu->mmx, sizeof(emu->mmx))) {
BANNER;
for(int i=0; i<8; ++i) {
if(ref->mmx[i].q!=emu->mmx[i].q) {
printf_log(LOG_NONE, "EMM[%d]: %016llx | %016llx\n", i, ref->mmx[i].q, emu->mmx[i].q);
}
}
}
if(ref->mxcsr.x32 != emu->mxcsr.x32) {
BANNER;
printf_log(LOG_NONE, "MXCSR: %x | %x\n", ref->mxcsr.x32, emu->mxcsr.x32);
}
if(memcmp(ref->xmm, emu->xmm, sizeof(emu->xmm))) {
BANNER;
for(int i=0; i<8; ++i) {
if(ref->xmm[i].q[0]!=emu->xmm[i].q[0] || ref->xmm[i].q[1]!=emu->xmm[i].q[1] ) {
printf_log(LOG_NONE, "XMM[%02d]: %016llx-%016llx | %016llx-%016llx\n", i, ref->xmm[i].q[1], ref->xmm[i].q[0], emu->xmm[i].q[1], emu->xmm[i].q[0]);
}
}
}
if(test->memsize) {
if(memcmp(test->mem, (void*)test->memaddr, test->memsize)) {
BANNER;
printf_log(LOG_NONE, "MEM: @%p :", (void*)test->memaddr);
for(int i=0; i<test->memsize; ++i)
printf_log(LOG_NONE, " %02x", test->mem[i]);
printf_log(LOG_NONE, " |");
for(int i=0; i<test->memsize; ++i)
printf_log(LOG_NONE, " %02x", ((uint8_t*)test->memaddr)[i]);
printf_log(LOG_NONE, "\n");
}
}
if(banner) // there was an error, re-sync!
CopyEmu(emu, ref);
}
#undef BANNER
void x86test_init(x86emu_t* ref, uintptr_t ip)
{
x86test_t* test = &ref->test;
if(!test->test) {
test->clean = 0;
return;
}
// check if test as a valid emu struct
if(!test->emu) {
test->emu = NewX86Emu(my_context, ip, (uintptr_t)ref->init_stack, ref->size_stack, 0);
CopyEmu(test->emu, ref);
} else {
// check if IP is same, else, sync
uintptr_t prev_ip = test->emu->ip.dword[0];
if(test->clean)
x86test_check(ref, ip);
if(ip != prev_ip || !test->test || !test->clean) {
CopyEmu(test->emu, ref);
}
}
// Do a Dry single Step
test->memsize = 0;
test->clean = 1;
ref->old_ip = ip;
RunTest(test);
// this will be anakyzed next step
}
+3 -2
View File
@@ -304,6 +304,8 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
emu->sw.f.F87_TOP = top;
p->ControlWord = emu->cw.x16;
p->StatusWord = emu->sw.x16;
p->MxCsr = emu->mxcsr.x32;
p->MxCsr_Mask = 0;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
@@ -313,8 +315,6 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
p->ErrorSelector = 0;
p->DataOffset = 0;
p->DataSelector = 0;
p->MxCsr = 0;
p->MxCsr_Mask = 0;
// copy MMX regs...
for(int i=0; i<8; ++i)
memcpy(&p->FloatRegisters[i].q[0], (i<stack)?&ST(i):&emu->mmx[i], sizeof(mmx87_regs_t));
@@ -327,6 +327,7 @@ void fpu_fxrstor(x86emu_t* emu, void* ed)
xsave_t *p = (xsave_t*)ed;
emu->cw.x16 = p->ControlWord;
emu->sw.x16 = p->StatusWord;
emu->mxcsr.x32 = p->MxCsr;
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = p->TagWord;
for(int i=0; i<8; ++i)
-4
View File
@@ -14,10 +14,6 @@ typedef struct x86emu_s x86emu_t;
#define LN2 0.69314718055994531
#define LG2 0.3010299956639812
void Run66D9(x86emu_t *emu);
void Run66DD(x86emu_t *emu);
void RunDF(x86emu_t *emu);
#define ST0 emu->x87[emu->top]
#define ST1 emu->x87[(emu->top+1)&7]
#define ST(a) emu->x87[(emu->top+(a))&7]
-193
View File
@@ -1,193 +0,0 @@
#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 "x86run.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 Run66D9(x86emu_t *emu)
{
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch (nextop) {
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:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
// warning, incomplete
GET_EW;
fpu_loadenv(emu, (char*)ED, 1);
break;
case 6: /* FNSTENV m */
// warning, incomplete
GET_EW;
fpu_savenv(emu, (char*)ED, 1);
break;
default:
ip = R_EIP-2;
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
void Run66DD(x86emu_t *emu)
{
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch(nextop) {
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:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
GET_EW;
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;
}
}
break;
case 6: /* FNSAVE m94byte */
GET_EW;
// ENV first...
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;
}
}
reset_fpu(emu);
break;
default:
ip = R_EIP-2; // unfetch
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
+30 -21
View File
@@ -17,6 +17,7 @@ typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct kh_defaultversion_s kh_defaultversion_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct library_s library_t;
typedef struct linkmap_s linkmap_t;
typedef struct kh_fts_s kh_fts_t;
@@ -30,7 +31,6 @@ typedef struct atfork_fnc_s {
} atfork_fnc_t;
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
#endif
@@ -38,9 +38,10 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
#define DYNAMAP_SIZE (1<<(32-DYNAMAP_SHIFT))
#define JMPTABL_SHIFT 16
#define JMPTABL_SIZE (1<<(32-JMPTABL_SHIFT))
#define JMPTABLE_MASK ((1<<JMPTABL_SHIFT)-1)
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
typedef void* (*procaddress_t)(const char* name);
typedef void* (*vkprocaddress_t)(void* instance, const char* name);
#define MAX_SIGNAL 64
@@ -56,9 +57,15 @@ void free_tlsdatasize(void* p);
typedef struct needed_libs_s {
int cap;
int size;
library_t **libs;
char** names;
library_t** libs;
} needed_libs_t;
void free_neededlib(needed_libs_t* needed); // defined in library.c
void free_neededlib(needed_libs_t* needed);
needed_libs_t* new_neededlib(int n);
needed_libs_t* copy_neededlib(needed_libs_t* needed);
void add1_neededlib(needed_libs_t* needed);
void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name);
typedef struct base_segment_s {
uintptr_t base;
@@ -100,7 +107,8 @@ typedef struct box86context_s {
int elfcap;
int elfsize; // number of elf loaded
needed_libs_t neededlibs; // needed libs for main elf
needed_libs_t *neededlibs; // needed libs for main elf
needed_libs_t *preload;
uintptr_t ep; // entry point
@@ -109,22 +117,19 @@ typedef struct box86context_s {
lib_t *maplib; // lib and symbols handling
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
dic_t *versym; // dictionnary of versionned symbols
dic_t *versym; // dictionnary of versioned symbols
kh_mapsymbols_t *globdata; // GLOBAL_DAT relocation for COPY mapping in main elf
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
bridge_t *system; // other bridges
uintptr_t exit_bridge; // exit bridge value
uintptr_t vsyscall; // vsyscall bridge value
dlprivate_t *dlprivate; // dlopen library map
kh_symbolmap_t *glwrappers; // the map of wrapper for glProcs (for GLX or SDL1/2)
kh_symbolmap_t *glmymap; // link to the mysymbolmap of libGL
procaddess_t glxprocaddress;
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
vkprocaddess_t vkprocaddress;
vkprocaddress_t vkprocaddress;
#ifndef DYNAREC
pthread_mutex_t mutex_once;
@@ -142,7 +147,9 @@ typedef struct box86context_s {
uint32_t mutex_thread;
uint32_t mutex_bridge;
uint32_t mutex_dyndump;
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
int trace_dynarec;
pthread_mutex_t mutex_lock; // this is for the Test interpreter
#endif
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
@@ -157,10 +164,10 @@ typedef struct box86context_s {
void* sdl2allocrw; // AllocRW/FreeRW functions from SDL2
void* sdl2freerw;
int deferedInit;
elfheader_t **deferedInitList;
int deferedInitSz;
int deferedInitCap;
int deferredInit;
elfheader_t **deferredInitList;
int deferredInitSz;
int deferredInitCap;
pthread_key_t tlskey; // then tls key to have actual tlsdata
void* tlsdata; // the initial global tlsdata
@@ -169,9 +176,9 @@ typedef struct box86context_s {
uintptr_t *auxval_start;
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
#ifndef NOALIGN
kh_fts_t *ftsmap;
#endif
@@ -208,7 +215,7 @@ typedef struct box86context_s {
#else
int GetTID();
#define mutex_lock(A) {int tid = GetTID(); while(arm_lock_storeifnull(A, (void*)tid)) sched_yield();}
#define mutex_trylock(A) arm_lock_storeifnull(A, (void*)GetTID())
#define mutex_trylock(A) (uintptr_t)arm_lock_storeifnull(A, (void*)GetTID())
#define mutex_unlock(A) arm_lock_storeifref(A, NULL, (void*)GetTID())
#endif
@@ -224,6 +231,8 @@ void print_cycle_log(int loglevel);
// return the index of the added header
int AddElfHeader(box86context_t* ctx, elfheader_t* head);
// remove an elf from list (but list is never reduced, so there can be holes)
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head);
// return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
int AddTLSPartition(box86context_t* context, int tlssize);
+1 -1
View File
@@ -14,7 +14,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
int IsBridge(void* func);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
+7 -3
View File
@@ -5,11 +5,15 @@
typedef struct x86emu_s x86emu_t;
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint32_t RunFunction(uintptr_t fnc, int nargs, ...);
// using a fmt description
uint32_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...);
// use thread local emu to run the function (context is unused now)
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint64_t RunFunction64(uintptr_t fnc, int nargs, ...);
// using a fmt description and returning a 64bit value
uint64_t RunFunctionFmt64(uintptr_t fnc, const char* fmt, ...);
// use emu state to run function
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint32_t RunSafeFunction(uintptr_t fnc, int nargs, ...);
#endif //__CALLBACK_H__
Loaded 100 of 758 files, more files were not shown because too many files have changed in this diff. Show more