398 Commits
Author SHA1 Message Date
ptitSeb b2d5587ea1 Bumped to v0.2.0 2021-01-12 19:44:14 +01:00
ptitSeb 4b020ab4f5 Merge pull request #309 from heavygabriel/master
Simplified code
2021-01-11 19:43:05 +01:00
heavygabriel 088a85c125 Update COMPILE.md 2021-01-11 11:45:54 -05:00
heavygabriel 2bf60dc00d Removed some typos. 2021-01-11 11:39:04 -05:00
unknown b5ffa0e92a Simplified a bunch of ifs and elses 2021-01-11 10:21:01 -05:00
ptitSeb 258f7f9b50 Added BOX86_NOVULKAN to disable loading of vulkan libs 2021-01-10 11:24:55 +01:00
ptitSeb 07c403243d Added 66 CB opcode 2021-01-10 11:03:19 +01:00
ptitSeb 709de6a858 Fix compilation for build without Dynarec 2021-01-09 19:35:41 +01:00
ptitSeb dfed557f61 [DYNAREC] Fixed SAKF opcode, and improved a but flag handling (fixing regression on GIG Installer from Dec. 30th commit) 2021-01-09 17:36:27 +01:00
ptitSeb f143771be8 Merge pull request #303 from heavygabriel/master
Remove the //TODO: in USAGE.md
2021-01-08 19:20:00 +01:00
heavygabriel fc20c410c0 Delete TROUBLESHOOTING.md 2021-01-08 10:23:37 -05:00
heavygabriel 677205a288 Update USAGE.md
removed //TODO:
2021-01-08 09:17:37 -05:00
heavygabriel abb9acfd42 Create TROUBLESHOOTING.md
Information on how to solve specific problems.
2021-01-08 09:16:29 -05:00
ptitSeb 75dca68db0 Fixed custom allocator for memory block >= 256k (should help old 32bits Factorio, and maybe #274) 2021-01-08 09:53:03 +01:00
ptitSeb 5c1a8ad128 Fixed USAGE.md, default log is now 0 2021-01-08 09:51:44 +01:00
ptitSeb e4cf8f8c94 Merge pull request #302 from heavygabriel/master
Updated documentation
2021-01-08 07:49:19 +01:00
heavygabriel 30968917a4 Merge pull request #7 from heavygabriel/patch-7
Update USAGE.md
2021-01-07 18:59:11 -05:00
heavygabriel 84ea9e3301 Merge branch 'master' into patch-7 2021-01-07 18:59:02 -05:00
heavygabriel 1f9c046919 Merge pull request #6 from heavygabriel/patch-8
Update USAGE.md
2021-01-07 18:48:28 -05:00
heavygabriel cefe210184 Merge pull request #5 from heavygabriel/patch-9
Update USAGE.md
2021-01-07 18:47:29 -05:00
heavygabriel 02aa791fd9 Merge pull request #4 from heavygabriel/patch-10
Update COMPILE.md
2021-01-07 18:45:58 -05:00
heavygabriel d8c1341068 Merge pull request #2 from heavygabriel/patch-2
Patch 2
2021-01-07 18:45:14 -05:00
heavygabriel ca648ea128 Merge pull request #3 from heavygabriel/patch-3
Patch 3
2021-01-07 18:43:43 -05:00
heavygabriel daf5a9d91d Merge pull request #1 from heavygabriel/patch-1
Patch 1
2021-01-07 18:43:02 -05:00
heavygabriel 16b95f2088 Update COMPILE.md
Added further clarifications, fixed typos ,etc.
2021-01-07 18:38:26 -05:00
heavygabriel 41dfcb559a Update USAGE.md
Added a bit of documentation, fixed things, etc. (This really needs some love, can anyone better suited for the task contribute? thanks.
2021-01-07 18:32:11 -05:00
heavygabriel 37c871ec2e Update USAGE.md
Added a bit of documentation, fixed things, etc. (This really needs some love, can anyone better suited for the task contribute? thanks.
2021-01-07 18:31:18 -05:00
heavygabriel 34bd1ff42f Update USAGE.md
Added a bit of documentation, fixed things, etc. (This really needs some love, can anyone better suited for the task contribute? thanks.
2021-01-07 18:30:34 -05:00
heavygabriel e0f1d4fecf Update README.md
Changed how things are worded (again again+3 ) . Added some new clarification in the documentation (Need to see how to reword the box86 discord mentionning thingy) etc.
2021-01-07 18:16:37 -05:00
heavygabriel c94d992ef6 Update README.md
Changed how things are worded (again again+3 ) . Added some new clarification in the documentation (Need to see how to reword the box86 discord mentionning thingy) etc.
2021-01-07 18:16:34 -05:00
ptitSeb bfe83d827d Fixed a potential BUSERROR on 66 0F 12 opcode 2021-01-07 19:44:06 +01:00
ptitSeb 1c45795828 Merge pull request #298 from heavygabriel/patch-1
Update README.md
2021-01-07 16:09:30 +01:00
heavygabriel 8dc5c164d8 Update README.md
again, updated typos.
2021-01-07 09:34:47 -05:00
heavygabriel 326032aa23 Update README.md
Changed the notes for raspberry pi a bit, changed how the unity section is worded and generally changed small little typos and things.
2021-01-07 09:24:25 -05:00
ptitSeb b79e234da2 Merge pull request #297 from kalashnikovdmitryv/patch-1
Add flag for RPI4 with arm64+armhf multiatch
2021-01-06 20:32:50 +01:00
kalashnikovdmitryv 5bc6962a9d Update CMakeLists.txt 2021-01-06 22:23:21 +03:00
ptitSeb 168717a90a Added some more functions t wrapped libxslt 2021-01-06 20:02:56 +01:00
ptitSeb dd6b0f6c9a [DYNAREC] Tiny optim on dynablock creation 2021-01-05 22:04:27 +01:00
ptitSeb 0a3c678877 Fixed compilation on non Dynarec build 2021-01-04 18:57:26 +01:00
ptitSeb e2df6f6ce0 Added 66 F0 81/83 opcodes 2021-01-04 08:35:25 +01:00
ptitSeb e58ebdac18 [TRACE] Fix build when trace is enabled 2021-01-03 18:16:10 +01:00
ptitSeb 537312a91f Use Custom allocator for all hash map 2021-01-03 16:39:58 +01:00
ptitSeb 11c08acd6c [DYNAREC] Need to improve this optimization, reverting for now (help Unity3D games) 2021-01-03 15:40:48 +01:00
ptitSeb cf9a38fb02 [DYNBAREC] Try to make dynarec more resiliant on heavily multi-threaded program 2021-01-03 11:20:56 +01:00
ptitSeb 83dff2bf25 Merge branch 'master' of https://github.com/ptitSeb/box86 2021-01-03 10:43:03 +01:00
ptitSeb 49694f300a Fixed a warning on wrapped libdl 2021-01-03 10:21:10 +01:00
ptitSeb daddc8246e Small fixes in xcb wrapped functions signature 2021-01-03 10:20:14 +01:00
ptitSeb 9f92377edc Small change to some pthread wrapped functions 2021-01-02 16:18:21 +01:00
ptitSeb 1ce392d968 Fixed the added flags in O_* converters 2021-01-02 15:03:46 +01:00
ptitSeb bf730b43e2 Add a few more flags in O_* converters 2021-01-02 14:57:38 +01:00
ptitSeb a4adb47caf Various small changes in some libc functions signature 2021-01-02 14:47:19 +01:00
ptitSeb 9317572874 Minor changes to O_* flags handling and conversion 2021-01-02 13:13:58 +01:00
ptitSeb eca39e6a8f Improve Signal and Memory protection Handling on multi-thread program, and added BOX86_JITGDB=2 (Should help #273, KSP old linux32 version now works, should also help .net programs) 2021-01-01 18:32:18 +01:00
ptitSeb 4639dc8ffd Minor signature changes for some libpulse functions 2021-01-01 18:32:18 +01:00
ptitSeb 5a9b34f54b Added log for waitpid 2021-01-01 18:32:18 +01:00
ptitSeb dc07d477de Added syscall 318 getcpu (should help #217) 2021-01-01 18:09:53 +01:00
ptitSeb db5efa8908 Fix compile on non-Dynarec build 2021-01-01 11:12:38 +01:00
ptitSeb 7d462dd837 Try to detect Excution error on Signal handling, to help .net programs 2021-01-01 10:37:56 +01:00
ptitSeb 76010f63c0 Fixed BOX86_LOG=2 on some wrapped libc functions 2021-01-01 09:40:17 +01:00
ptitSeb be7f72808b Merge pull request #292 from Hacker1245/patch-1
Fix a typo
2020-12-31 16:27:01 +01:00
ptitSeb 25f1e8e6fa Fixed some lib pulse callback (should help both #193 and #293 and maybe other pulseaudio apps) 2020-12-31 16:25:10 +01:00
ptitSeb 047df311f0 Added xcb_send_request_with_fds64 to wrapped lib xcb 2020-12-31 16:23:24 +01:00
ptitSeb bcdd99328c [DYNAREC] Fixed a samll issue with Logs 2020-12-31 16:22:40 +01:00
ptitSeb 5cc76a0071 [DYNAREC] Another small optim on flags handling 2020-12-31 12:53:55 +01:00
ptitSeb dee55a9ac2 [DYNAREC] Fixed a potential segfault 2020-12-31 08:59:04 +01:00
ptitSeb 9ff20da9bb Added more slots for pulse audio callback (should help #293) 2020-12-30 22:56:42 +01:00
Hacker1245 0520f5abcd Fix a typo 2020-12-30 22:07:19 +01:00
ptitSeb e1201ff0de [DYNAREC] Optimize test emiter to avoid BFI/UBFX when possible 2020-12-30 18:13:32 +01:00
ptitSeb bc2d7e7396 [DYNAREC] Optimize shift emiter to avoid BFI/UBFX when possible 2020-12-30 17:50:58 +01:00
ptitSeb 9a058a2416 [DYNAREC] Optimize logic emiter to avoid BFI/UBFX when possible 2020-12-30 17:29:51 +01:00
ptitSeb 49fea86b28 [DYNAREC] Optimized math emiter to avoid UBFX/BFI when possible 2020-12-30 16:52:34 +01:00
ptitSeb 1617439d37 Flags are only handled in packed form now, removed Unpacked array 2020-12-30 15:58:07 +01:00
ptitSeb 540459cb78 [DYNAREC] Now used r14 (so lr) instead of r12 for EIP/scratch register 2020-12-29 20:02:12 +01:00
ptitSeb 54b8522df6 [DYNAREC] Added SHLD32c emiter 2020-12-29 16:27:27 +01:00
ptitSeb bf65e606d3 [DYNAREC] Minor reordering of operation in DB E2 opcode 2020-12-29 16:27:01 +01:00
ptitSeb 5335a641df [DYNAREC] Fixed 66 99 CWD opcode 2020-12-29 16:26:16 +01:00
ptitSeb 323ece7417 [DYNAREC] Added amiter for SHRD32c 2020-12-29 13:37:57 +01:00
ptitSeb ca1fc0ffad [DYNAREC] Fix a potential memory corruption on exit 2020-12-29 11:18:30 +01:00
ptitSeb c0706e227e [DYNAREC] Removed a warning 2020-12-29 09:40:48 +01:00
ptitSeb 995e4a9b68 [DYNAREC] Switch POP/PUSH from STM/LDM to LDR/STR, so there is no alignment constraint anymore 2020-12-29 08:43:56 +01:00
ptitSeb 7f53379552 Don't printf Segfault handler message if custom handler is setuped on LOG_NONE level 2020-12-28 16:12:26 +01:00
ptitSeb 3e17299a34 Made 8F opcode consistant on segfault ([DYNAREC] too) 2020-12-28 16:11:06 +01:00
ptitSeb c63cdc9506 Added 66 CC opcode, and handling of CC by using raise(SIGTRAP) if SIGTRAP is handled ([DYNAREC] too) 2020-12-28 10:26:09 +01:00
ptitSeb 7965186817 Added TSC flag to CPUID cpu capabilities 2020-12-28 07:57:35 +01:00
ptitSeb f107612753 Force PROT_REAT when PROT_WRITE is set, as it's implicit on i386 2020-12-28 07:40:45 +01:00
ptitSeb 2295f7bb8b Added 66 0F D0 opcode ([DYNAREC] too) 2020-12-28 05:48:57 +01:00
ptitSeb cc0845a9d3 Added wrapped function glib_check_version 2020-12-27 15:22:31 +01:00
ptitSeb e9019461b7 [DYNAREC] Added 0F E1/E2/E3 opcodes 2020-12-27 15:22:07 +01:00
ptitSeb a19e3ed3dd [DYNAREC] Small optim on new memory protection tracker 2020-12-27 16:11:37 +01:00
ptitSeb 10ec424e96 More separation between POWERPC and ARM 2020-12-27 15:58:15 +01:00
ptitSeb b838c8a7d0 [DYNAREC] Fixed new memory protection tracking 2020-12-27 15:15:24 +01:00
ptitSeb 0331af0643 Track memory protection also on mmap/munmap/mprotect syscall 2020-12-27 12:38:24 +01:00
ptitSeb 24561fc37c [WINE] Removed wine_prereserve handling, it seems to be working better without it 2020-12-27 11:41:35 +01:00
ptitSeb d4ad5334b8 [DYNAREC] Some fixes to new memory protection tracking 2020-12-26 18:30:34 +01:00
ptitSeb 7fe3299282 Refined POWERPC support to less impact ARM 2020-12-26 18:27:21 +01:00
ptitSeb 23fef75ed5 [DYNAREC] Fixed FISTTP opcode 2020-12-26 09:55:10 +01:00
ptitSeb 62722b0618 Merge pull request #279 from eerykitty/master
Basic support for little-endian PowerPC and POWER9.
2020-12-25 09:29:10 +01:00
Joseph Allen e810dba2c9 Fixes semctl and a number of variadic functions. 2020-12-24 22:47:23 -06:00
Joseph Allen 7dfe545161 Basic support for little-endian PowerPC and POWER9. 2020-12-24 15:14:50 -06:00
ptitSeb a5f3966b44 Merge pull request #275 from SpacingBat3/master
Updated the PKGBUILDS
2020-12-24 09:38:53 +01:00
ptitSeb 886573ed8b Merge pull request #276 from RickAndTired/patch-1
Typo fix
2020-12-24 09:38:27 +01:00
RickAndTired 2758c1c955 Typo fix
Line 105 typo: kernle
2020-12-23 21:56:13 -08:00
ptitSeb 591bafe8c3 [DYNAREC] Try to improve the marking mecanism to include blocks that are shadowed by others 2020-12-23 09:21:50 +01:00
ptitSeb 211a8f42db Small cosmetic changes to wrapped libsdl2 2020-12-22 22:01:44 +01:00
ptitSeb fbc9029a8e [DYNAREC] Removed unused fiel in dynablocklist structure 2020-12-22 20:01:57 +01:00
ptitSeb ceb4b8b06d Removed a debug leftover 2020-12-22 15:13:29 +01:00
ptitSeb b88dda442f [DYNAREC] Improved block extender mecanism 2020-12-22 14:42:57 +01:00
ptitSeb 6e8163bded [DYNAREC] Moved fakeed function for helper to functions 2020-12-22 13:32:36 +01:00
ptitSeb 9b253abb53 More jpeg62 compress function wrapping (should help #271) 2020-12-22 11:31:09 +01:00
ptitSeb e5e51e3ea3 [DYNAREC] Fix a potential SIGBUS on 66 0F 12 opcode 2020-12-21 17:37:29 +01:00
ptitSeb 6a2d9d7663 Try to avoid a segfault on quit with libpulse 2020-12-21 17:36:51 +01:00
ptitSeb 0546b1e212 Try to fix wrapped Compress functions of libjpeg62 (for #271) 2020-12-21 11:17:03 +01:00
ptitSeb 320e6dae72 [DYNAREC] Reworked a bit the unaligned stack handling workaround to limit console spam 2020-12-21 10:47:16 +01:00
ptitSeb 96f944c804 More fixes to build new memory tracking whithout dynarec 2020-12-20 23:53:40 +01:00
ptitSeb fd0e2195f7 Fix build of memory tracking whithout dynarec 2020-12-20 23:49:31 +01:00
ptitSeb d2f130a834 Memory protection tracking is not only with Dynarec ON now 2020-12-20 23:38:32 +01:00
ptitSeb a3459712ce Fix 66 F0 0F B1 opcode 2020-12-20 23:37:57 +01:00
ptitSeb 8bf2e49164 Reorganised 8F POP Ed opcode to better handle Ed referencing ESP ([DYNAREC] too) 2020-12-20 15:35:57 +01:00
ptitSeb 0f5cd39a64 [DYNAREC] Refined the SIGBUS recovery to limit to push/pop/call/ret opcode (as FPU/SIMD regs are not saved/restored from Signal for now) 2020-12-20 14:13:24 +01:00
ptitSeb e0ed0076f2 [DYNAREC] When a SIGBUS occurs in a dynablock, invalidate the block at that address and try again with interpretor (fix MapleLegends Setup with its strangely aligned stack) 2020-12-20 12:09:51 +01:00
ptitSeb bfd4ad39af [DYNAREC] Fixed some issue with the memory protection mecanism 2020-12-20 11:06:31 +01:00
ptitSeb a8ff7d8769 [DYNAREC] Improved Memory Protection Tracking 2020-12-20 10:30:37 +01:00
ptitSeb 39c77beb1c Fixed Signal handling for PAGEFAULT with Write Error (helps Wine) 2020-12-20 10:11:59 +01:00
ptitSeb d576f7af39 Cleaner version of TEST Eb, Ib and TEST Ed, Id opcodes 2020-12-20 10:10:10 +01:00
ptitSeb 74c3f43f75 [DYNAREC] Better hanling of memory protection for elf memory 2020-12-20 10:09:12 +01:00
ptitSeb ecacace01d [DYNAREC] Added some handlng of protection for malloc'd memory 2020-12-20 10:08:21 +01:00
ptitSeb a3b0149a84 Added 66 1F opcode 2020-12-19 18:18:04 +01:00
ptitSeb 63111577ec Added 64 66 8B opcode 2020-12-19 17:45:55 +01:00
ptitSeb eb68520709 [DYNAREC] Some fixes to improved Memory protection tracker 2020-12-19 17:09:35 +01:00
ptitSeb a7bf2c6cc3 Fixed a potential SIGBUS on 66 0F 13 ocpode 2020-12-19 14:46:57 +01:00
ptitSeb 190788efd9 Added gss_wrap_iov function to wraped libgssapi_krb5 (still for wine) 2020-12-19 13:42:47 +01:00
ptitSeb 2592a6a342 Added gss_wrap function to wraped libgssapi_krb5 (still for wine) 2020-12-19 12:17:01 +01:00
ptitSeb 16ee4c348d [RK3399] Fixed a warning 2020-12-19 12:02:37 +01:00
ptitSeb 8389097cd3 [DYNAREC] Improved memory protection tractick 2020-12-19 11:44:02 +01:00
ptitSeb 79a885c15e Set theme jekyll-theme-hacker 2020-12-19 10:24:18 +01:00
ptitSeb eb7c683a6d Also added gss_verify_mic to libgssapi_krb5 2020-12-18 16:42:26 +01:00
ptitSeb 95b2b314f6 Wrapped libkrb5 and libgssapi_krb5 (minimum functions for wine) 2020-12-18 15:55:34 +01:00
ptitSeb 07eb0aa5cd [DYNAREC] Don't free dynarec elf memory durring elf unloading, it will be free later anyway 2020-12-18 13:56:09 +01:00
ptitSeb fdce28590a Added alternate way to handle some vaarg wrapped functions 2020-12-18 12:24:10 +01:00
ptitSeb 572613e377 Fixed wrapping of Compress structure on libjpeg62 (for #271) 2020-12-18 11:14:42 +01:00
ptitSeb 29e597b4ed Fixed another potential SIGBUS, in CMPXCHG this time 2020-12-17 21:39:23 +01:00
ptitSeb 981c464c36 Fixed a potential SIGBUS with XADD Gd, Ed opcode 2020-12-17 20:52:48 +01:00
ptitSeb d406c5717c Wrapping Compress functions callbacks for libjpeg.so.62 (shoudl help #271) 2020-12-17 10:44:37 +01:00
ptitSeb 92208efd24 Start of a new dev. cycle 2020-12-17 10:43:31 +01:00
ptitSeb 3c98cbccbe Bumped to v0.1.8 2020-12-16 07:58:23 +01:00
ptitSeb 3a5c6751e2 Many fixes to Double->Int x87 opcodes ([DYNAREC] too) 2020-12-15 15:53:38 +01:00
ptitSeb 002d3d7b9b This also fixes 66 D9 and 66 DD opcodes 2020-12-15 15:52:53 +01:00
ptitSeb e57a66da04 [DYNAREC] Fixed AAD opcode 2020-12-15 15:51:13 +01:00
ptitSeb b1ecad2d49 Fixed 66 D9 and 66 DD opcodes 2020-12-15 15:50:18 +01:00
ptitSeb 658a107f60 Better log for FE xx and FF xx Illegal Instructions on interpretor 2020-12-15 15:49:39 +01:00
ptitSeb 7b419ce5f1 Fix a callback for pulse audio (help #268, seems to be working now) 2020-12-15 15:40:58 +01:00
ptitSeb 367df08989 Fix Zoom hack for libturbojpeg.so (for #268) 2020-12-15 07:59:04 +01:00
ptitSeb 2004006a9d Added Zoom detection and hack to first try to use system libturbojpeg.so if loaded (still for #268) 2020-12-14 21:45:57 +01:00
ptitSeb bed0f24f2b Wrapped libturbojpeg.so.0 with a small set of functions (should help #268) 2020-12-14 20:48:56 +01:00
ptitSeb 7995dfc70a Fixed a potential SIGBUS on DF /7 FISTP opcode 2020-12-14 14:12:43 +01:00
ptitSeb b29d569f6b Reworked libpulse wrappers (should be more stable and little tad faster) 2020-12-14 12:22:39 +01:00
ptitSeb 3c166c438a [DYNAREC] Added BOX86_DYNAREC_SAFEMMAP (can be usefull to speedup Wine progs, but may also introduce crash) 2020-12-13 20:25:55 +01:00
ptitSeb 03dac0ef6a [DYNAREC] Use a table read that is not thread safe in linker (I don't think thread safe is a must-have in this case) 2020-12-13 19:26:31 +01:00
ptitSeb 27cb5219ae [DYNAREC] Various simplifications 2020-12-13 19:24:27 +01:00
ptitSeb 97a7459f5d [DYNAREC] Small optims 2020-12-13 16:12:17 +01:00
ptitSeb 1eac337e59 [DYNAREC] Don't flush dynarec_log 2020-12-13 16:11:59 +01:00
ptitSeb 1613358927 [DYNAREC] Fixed a type is FS: Cache handling (should give back some speed on Wine stuff) 2020-12-13 15:38:32 +01:00
ptitSeb 2f0da26f14 [DYNAREC] Presize dblists 2020-12-13 14:21:05 +01:00
ptitSeb 45fa32cb9d [DYNAREC] Small fixes for cancelled dynablock 2020-12-13 14:19:56 +01:00
ptitSeb 9e9f2a37be [DYNAREC] Precalc exact instsize array size 2020-12-13 14:19:04 +01:00
ptitSeb 7b37bb6825 [DYNAREC] simplify this structure 2020-12-13 14:18:36 +01:00
ptitSeb 081378a178 Added empty wrapped libnsl.so 2020-12-13 10:05:28 +01:00
ptitSeb ff72343429 [DYNAREC] Removed a debug leftover 2020-12-13 10:04:57 +01:00
ptitSeb b0b8a2ca1c Fixed a warning 2020-12-13 09:09:35 +01:00
ptitSeb 55be6835b8 Removed a debug leftover (should help #227 and box-compatibility-list/#46) 2020-12-13 08:38:43 +01:00
ptitSeb c465e1de21 [VULKAN] fixed SDL2 wrapping of SDL_Vulkan_GetVkGetInstanceProcAddr 2020-12-12 19:50:04 +01:00
ptitSeb 0f255de201 Made box86context_t lighter for easier debugging (also reorganised member order) 2020-12-12 19:50:04 +01:00
ptitSeb deb04610b5 Revert commit 31a108b685, previous method seems better 2020-12-12 19:25:53 +01:00
ptitSeb a9887fe471 Fixed an old type on Bridge handling 2020-12-12 17:09:35 +01:00
ptitSeb 4b3c5a7f6f [DYNAREC] Reworked Dynablock memory manager 2020-12-12 15:24:05 +01:00
ptitSeb 0058d3563d Added 66 F0 0F B1 opcode 2020-12-12 10:18:13 +01:00
ptitSeb 52a4808f2c Added a few more function to wrapped libfontconfig 2020-12-12 10:09:17 +01:00
ptitSeb 7a0874165f Added 1 wrapped function to libfontconfig 2020-12-12 09:37:44 +01:00
ptitSeb 7c7acd134b Small wrapped libmpg123 and pulse change 2020-12-11 22:27:43 +01:00
ptitSeb ddd4874baa [DYNAREC] Some small optim on support function for the Dynarec 2020-12-11 21:04:11 +01:00
ptitSeb 23f91b1a0d [DYNAREC] All Interpretor to switch back to Dynarec on more opcodes 2020-12-11 20:47:23 +01:00
ptitSeb b8c32d580b [DYNAREC] If a block wasn't created because executable memory was not allocated, delete the whole dynablocks to try again later 2020-12-11 20:35:39 +01:00
ptitSeb c0e67004d5 [DYNAREC] Reworked the dynarec signal handling, to improve its performances 2020-12-11 20:25:24 +01:00
ptitSeb 38a557b7e9 [DYNAREC] Don't try to create 0 sized Map block 2020-12-11 17:28:32 +01:00
ptitSeb 7d6d5d673d [DYNAREC] added 64 A2 opcode 2020-12-11 17:27:23 +01:00
ptitSeb 2cf067f004 [DYNAREC] Don't try to a free a 0 sized of NULL pos Map 2020-12-11 17:27:08 +01:00
ptitSeb 92d9bc525f [DYNAREC] Try to avoid some deadlock with dynarec that could happens in some specific cases involving signals 2020-12-11 16:43:25 +01:00
ptitSeb dca91b1efc added 64 A0 opcode ([DYNAREC] too) 2020-12-11 16:32:14 +01:00
ptitSeb 6bf1ea7539 [DYNAREC] Remove some old code behind ifdefs 2020-12-11 14:23:18 +01:00
ptitSeb 670b13595b Improved the PltRelocator detection of elfloader 2020-12-10 17:14:17 +01:00
ptitSeb dcbb8b29de Added some X11 wrapped functions 2020-12-10 17:12:40 +01:00
ptitSeb 7284c817b2 And more libxcb* wrapped functions 2020-12-10 17:05:54 +01:00
ptitSeb b16912132f Added some xcb_xrandr wrapped functions 2020-12-10 15:44:53 +01:00
ptitSeb 9805ad7f3a Initialize context as soon as possible in library (should help #265 and #266) 2020-12-10 15:11:26 +01:00
ptitSeb 4e7e0f6aab Added a few libdrm wrapped function 2020-12-10 13:56:24 +01:00
ptitSeb c905ebfdd2 Added wrapped libSDL2_ttf-2.0.so.0 (copy if the sdl1 version) 2020-12-10 13:51:31 +01:00
ptitSeb b5c787938c Fixed commented code, in case it gets uncommented someday 2020-12-10 13:38:59 +01:00
ptitSeb 69ca5351b4 Added a bunch of wrapped xcb* functions 2020-12-10 12:35:52 +01:00
ptitSeb 3f42372603 Added liblcms2 wrapped lib (partial wrapping, just enough for wine) 2020-12-09 15:54:33 +01:00
ptitSeb 595028e9ec Reworked Exit, to avoid segfault and lockup and end of execution 2020-12-09 11:25:14 +01:00
ptitSeb 7358a049ef Huge refactoring (again), completly removed old Callback mecanism (working to have only 1 x86emu_t structure per thread, almost there) 2020-12-08 22:38:51 +01:00
ptitSeb 792aeda72e Be more smart to when to apply PltRelacator or not (fix SuperHexagon's libGLEW loading) 2020-12-08 21:44:21 +01:00
ptitSeb 53bf2d277b Added wrapped libldap_r and liblber 2020-12-08 08:10:02 +01:00
ptitSeb 0cbc55ba24 Fix potential build error on old system (at least with old headers) 2020-12-08 07:56:18 +01:00
ptitSeb 7b0d228972 Added a few XTandr wrapped functions 2020-12-08 07:54:40 +01:00
ptitSeb 8ac0b66836 Improved Segment offset Cache, and enable GS: caching (some speed boost on Linux apps) 2020-12-07 13:56:29 +01:00
ptitSeb 2756b1b9dd [DYNAREC] fixed some warning and a typo from last commit 2020-12-06 22:31:15 +01:00
ptitSeb e3f44bae26 [DYNAREC] Huge refactor to simplify Dynablock handling 2020-12-06 21:52:27 +01:00
ptitSeb 1963589186 Mooore Thread Cancel slots 2020-12-06 21:14:38 +01:00
ptitSeb a5c9675b84 [DYNAREC] Removed Mark mecanism (it needs mutex to run properly, so it's too heavy) 2020-12-06 15:13:40 +01:00
ptitSeb 76747d5c38 [DYNAREC] Immprove log for SMC debugging option 2020-12-06 15:12:36 +01:00
ptitSeb 59bfeb9fb2 [DYNAREC] This barrier optimization seems to break Mono on Linux, so reverting it for now 2020-12-06 13:15:09 +01:00
ptitSeb c40669b429 [DYNAREC] Optimized AddMark function to not redo what is already done 2020-12-05 23:22:09 +01:00
ptitSeb d83cdbfeeb Fixed a potential segfault 2020-12-05 23:21:29 +01:00
ptitSeb d8773e96d6 Not sure if awesomium_process needs or not emulated libpng12. Commenting for now 2020-12-05 20:59:24 +01:00
ptitSeb 78571698c2 Some improvements in wrapped libpng handling 2020-12-05 19:43:52 +01:00
ptitSeb 77282f1ff1 Added one more wrapped function to libglib2 2020-12-05 17:07:57 +01:00
ptitSeb 953fcb7f1b Fixed handling of TLS object with a 0 offset (help Garry's Mod, probably a few other too) 2020-12-05 16:59:08 +01:00
SpacingBat3 edef6d7f99 Updated the PKGBUILDS
Improved old PKGBUILDs and added the PKGBUILD for the RK3399 targets.
2020-12-05 16:43:47 +01:00
ptitSeb 1905e4a7f6 Better handling of libtcmalloc_minimum.so.4 2020-12-05 16:15:35 +01:00
ptitSeb 31e6ae0705 Improved the BOX86_NOBANNER behaviour 2020-12-05 12:49:17 +01:00
ptitSeb 31a108b685 Change method used for Thread Cancel registeration 2020-12-04 21:47:39 +01:00
ptitSeb b122c68b16 Improved a bit XImage handling 2020-12-04 21:47:04 +01:00
ptitSeb 0efae1fdf5 Added BOX86_NOGTK to disable use of wrapped gtk libs (can be used with Steam) 2020-12-04 19:52:10 +01:00
ptitSeb 0850180861 Fixed and improved wrapped libdbus-1 2020-12-04 19:49:25 +01:00
ptitSeb 528478b379 Improved a bit wrapped libusb-1 2020-12-04 17:55:30 +01:00
ptitSeb 65302010db Small remork on cancel tread registration mecanism (should fix memory leaks) 2020-12-03 12:01:07 +01:00
ptitSeb 6b32440347 Small fix (mostly cosmetic) in a pthread wrapped function signature 2020-12-03 12:00:32 +01:00
ptitSeb 5a0b6c419e [DYNAREC] Fixed some memory leak 2020-12-03 11:59:43 +01:00
ptitSeb 94c5d0205b fixed some warning 2020-12-03 11:58:49 +01:00
ptitSeb 0f2998a672 More libxml2 wrapping improvment for wine 2020-12-02 21:39:27 +01:00
ptitSeb 1ba7936ef7 Improve wrapping of libxml2 (especially for wine msxml3.dll.so) 2020-12-02 21:16:19 +01:00
ptitSeb 5192aacb22 [RPI] Added runtime hack to get TokiTori2+ running on Pi 2020-12-01 15:13:22 +01:00
ptitSeb ac2adcaf52 A bit more logs when function name is not found 2020-12-01 15:01:12 +01:00
ptitSeb 1b3e707f62 Added SDL_LogGetOutputFunction to wrapped libsdl2 and refactored remaining callback functions 2020-12-01 08:59:01 +01:00
ptitSeb 925fc67c66 Fixed a typo in wrapped libxml2 2020-12-01 08:33:47 +01:00
ptitSeb 54ce6deb1c Wrapped libxslt (should help #259) 2020-11-30 20:02:57 +01:00
ptitSeb 754859d28a Wrapped libxml2 (should help #259) 2020-11-30 18:42:09 +01:00
ptitSeb 269bc9e289 [DYNAREC] Disable one of the new optim, it breaks some installer 2020-11-29 17:26:54 +01:00
ptitSeb 35c768c040 [DYNAREC] Fixed an issue with an optimisation that was too agressive 2020-11-29 13:51:11 +01:00
ptitSeb ff45cfed83 [DYNAREC] Various fixes on some dynarec optimisation mecanism 2020-11-28 16:07:04 +01:00
ptitSeb 38c5c1c17a [DYNAREC] Added 64 FF /2 CALL FS:Ed opcode 2020-11-28 15:32:22 +01:00
ptitSeb 423b301596 Added syscal 356 (and code to emulate it if not present) 2020-11-28 12:26:40 +01:00
ptitSeb 000c11f9ea [PANDORA] Added basic implementation of renameat2 2020-11-28 12:17:12 +01:00
ptitSeb cea4a02ad9 Fixed RPATH handling when a list of path was set 2020-11-28 11:10:01 +01:00
ptitSeb 4e9bc39381 [DYNAREC] Some rework on dynablock management 2020-11-27 17:40:16 +01:00
ptitSeb ad084da13d Start a new dev. cycle with v0.1.7 2020-11-27 10:18:13 +01:00
ptitSeb 27e5262f1d Bumped to v0.1.6 2020-11-26 09:43:33 +01:00
ptitSeb 363464092e [DYNAREC] Added 66 60/61 16bits PUSHA/POPA opcodes 2020-11-25 12:04:47 +01:00
ptitSeb b2cab70427 [DYNAREC] Improved 16bits immediate PUSH opcodes 2020-11-25 12:04:46 +01:00
ptitSeb 44d5301244 [DYNAREC] Improved 16bits PUSH/POP opcodes 2020-11-25 12:04:46 +01:00
ptitSeb 8e4f4feb3c Updated CHANGELOG 2020-11-25 12:04:46 +01:00
ptitSeb e9f6f8824c [DYNAREC] Fixed a potential SIGBUS with int64->double loading 2020-11-24 12:04:03 +01:00
ptitSeb be6f9870d0 Added 64 01/03/11/2B opcodes 2020-11-23 18:41:20 +01:00
ptitSeb bb086223c7 Update README.md 2020-11-23 13:33:36 +01:00
ptitSeb be6a3bff3f Fixed 2 wrapped functions signature in libappindicator (help Steam) 2020-11-22 20:42:49 +01:00
ptitSeb adfc5fda2e Fixed a SEGBUS on RK339 build 2020-11-22 20:31:33 +01:00
ptitSeb d833f136a0 Enable the 'GOG Linux install hack' also for RK3399 platforms 2020-11-22 18:41:37 +01:00
ptitSeb 1703e9d1b7 Refined CMakeList a bit 2020-11-22 18:41:05 +01:00
ptitSeb 011b9f93e4 [DYNAREC] Fixed 66 0F EA/EE opcodes (should fix #253 this time) 2020-11-22 17:30:30 +01:00
ptitSeb e449a4e247 Launch natively program if elf is not recognised as an i386, or not an elf 2020-11-22 14:08:11 +01:00
ptitSeb fe7f0ff842 Fixed potential BUSERROR with LOCK CMPXCHG8B opcode on interpretor 2020-11-22 13:52:44 +01:00
ptitSeb 2033e5764d Fixed potential segfault when using BOX86_LOG=2 2020-11-22 13:05:28 +01:00
ptitSeb 55175263ac [DYNAREC] Added 0F BA /5 and /7 opcodes 2020-11-22 10:52:40 +01:00
ptitSeb c484221cd6 Remove the 'suspicious segment' left over debug code 2020-11-22 10:21:55 +01:00
ptitSeb e9862cb30d [DYNAREC] Fix potential issue when multiple similar thread are launched at the same time (will help #253) 2020-11-21 20:32:52 +01:00
ptitSeb 0c7b99cbc6 [DYNAREC] Changed how opcodes 66 0F 38 08/09/0A are coded (this fixes the md5 error in #253) 2020-11-21 18:36:55 +01:00
ptitSeb 824f39e4db [DYNAREC] Potential fix for 66 0F 38 1C/1D/1E when Gx==Ex and Gx is not cached yet (help #253, but still some issues) 2020-11-21 15:31:27 +01:00
ptitSeb 66a5ce1e52 [DYNAREC] Fixed 66 0F 38 1C/1D/1E opcode (for #253, still not ok, how many opcodes are borked?) 2020-11-21 15:18:22 +01:00
ptitSeb f39637a652 [DYNAREC] Fixed 66 0F EE opcode (for #253, but still not enough) 2020-11-21 15:10:03 +01:00
ptitSeb eaf7d0a277 [DYNAREC] Fixed 66 0F 38 08/09/0A opcode (should help #253 a bit) 2020-11-21 14:54:25 +01:00
ptitSeb b61bb908a2 Improve handling of signals with threads or functions call 2020-11-21 11:06:16 +01:00
ptitSeb 2e891b807c [DYNAREC] Added 66 0F 38 08/09/0A opcodes (for #253 again) 2020-11-20 21:44:47 +01:00
ptitSeb f0b236df88 [DYNAREC] Added 66 0F 38 1C/1D/1E opcodes (still for #253) 2020-11-20 21:18:42 +01:00
ptitSeb 08904dbe0d [DYNAREC] Added 66 0F E4/E5/EA/EE opcodes (should help #253) 2020-11-20 21:04:45 +01:00
ptitSeb c9c4e226af Added 0F DA PMINUB and 0F DE PMAXUB opcodes ([DYNAREC] too) 2020-11-18 21:21:42 +01:00
ptitSeb ab3dc70145 Added 2 clipboard function to gtk2 wrapped lib 2020-11-18 20:50:06 +01:00
ptitSeb 4d8c841f3f [DYNAREC] Fix potential BUSERROR of F3 0F 2C and F3 0F 2D opcode, and fixed a typo on F3 0F E6 opcode 2020-11-18 20:44:38 +01:00
ptitSeb a8b247cde9 More improvments and fixes to signal handler 2020-11-18 19:29:52 +01:00
ptitSeb 416e161285 Added F2 0F D0 ADDSUBPS Gx, Ex opcode 2020-11-18 15:28:21 +01:00
ptitSeb cc8d1f9bf2 Better handling of signals 2020-11-18 09:58:55 +01:00
ptitSeb ae95f1b0e5 One more wrapped func tion with callback to gtk2 2020-11-17 10:35:29 +01:00
ptitSeb c10441bec4 Added g_timeout_* wrapped functions to libglib2 2020-11-17 10:27:43 +01:00
ptitSeb 6ab334fc34 Fixed a nasty typo in wrapped libgobject2 2020-11-17 10:27:20 +01:00
ptitSeb 10e849ce60 Fixed a warning in generated wrapper.c 2020-11-17 10:03:35 +01:00
ptitSeb c2206f5452 Aligned most of GValue handling in gtk libs 2020-11-17 09:41:18 +01:00
ptitSeb 3b66cd3cee Merge branch 'master' of https://github.com/ptitSeb/box86 2020-11-16 22:20:11 +01:00
ptitSeb 731a083bb7 Merge pull request #251 from daitj/makemkvtest
added few more wrapper for libcrypto (for #250)
2020-11-16 22:18:25 +01:00
Binay Devkota d35c6ab864 added more wrapper function for #250 2020-11-16 22:51:28 +02:00
Binay Devkota e9cade872c fixed previous commit as i am blind 2020-11-16 20:42:46 +02:00
Binay Devkota b2a8146851 added missing wrapped function for libcrypto #250 2020-11-16 20:15:53 +02:00
ptitSeb 6fd3d6c452 Improved handling of 'marshal' function in gobject2 2020-11-16 19:06:25 +01:00
ptitSeb bc3e72a87d Added a few more wrapped function to libcrypto (for #250) 2020-11-16 17:28:18 +01:00
ptitSeb e50e050aa9 Added some AES_* wrapped funciton to libcrypto (for #250) 2020-11-16 16:45:36 +01:00
ptitSeb c1a75607fa Fixed 'Alternate' autobridge on Interpretor 2020-11-16 14:57:37 +01:00
ptitSeb b203cd2af3 Added system 242 and 241 (for #250) 2020-11-16 14:39:39 +01:00
ptitSeb 84063f026f Added gtk_recent_filter_* wrapped function to gtk2 2020-11-16 14:39:12 +01:00
ptitSeb 3ec1ce25d7 [DYNAREC] Remove a leftover of debug trace 2020-11-16 14:35:54 +01:00
ptitSeb 0e70c543ee Added 'Aternate' solution for Gtk Classes functions beeing called in x86 code 2020-11-16 14:19:16 +01:00
ptitSeb e4d522a8d2 Refactored Gtk Class wrapping code 2020-11-16 10:25:32 +01:00
ptitSeb 272ecbd8ff More gtk class wrapping 2020-11-16 09:44:01 +01:00
ptitSeb 369fa03f9b Better handling of gtk signals 2020-11-15 18:28:25 +01:00
ptitSeb 1675ea3ba2 Added 2 functions wrapped libX11 2020-11-15 17:12:43 +01:00
ptitSeb 5b7a1bb9e6 Added phtread_spin handling 2020-11-15 17:07:07 +01:00
ptitSeb ace3effa2d Improved GCallback handling and fixed g_action_group_add_actions 2020-11-15 17:04:07 +01:00
ptitSeb bd0a14b3ce Added g_list_find_custom wrapped function to libglib2 2020-11-15 16:21:55 +01:00
ptitSeb 29a82f83c5 Added g_queue_find_custom to wrapped libglib2 2020-11-15 16:13:17 +01:00
ptitSeb f7232f09de Fixed a warning 2020-11-15 16:12:47 +01:00
ptitSeb f3eeae9edd Implemented gtk_builder_connect_signals to wrapped gtk2 2020-11-15 15:29:44 +01:00
ptitSeb 874468ca07 Added gtk_cell_layout_set_cell_data_func to gtk2 wrapped lib 2020-11-15 13:49:59 +01:00
ptitSeb 7a972af610 Fixed potential issue with gobject2 signal handler 2020-11-15 12:57:37 +01:00
ptitSeb 4ed42c38c9 Added wrapping of GtkLabel class to gtk2/3 libs 2020-11-15 12:55:31 +01:00
ptitSeb 6a73719a6b One more wrapped function to gtk2 2020-11-15 12:29:58 +01:00
ptitSeb 6efcfc6b93 Added 2 more g_list_ function to wrapped libglib2 2020-11-15 12:28:38 +01:00
ptitSeb 25f30c220e Added gtk_viewport_* wrapped function to gtk2 2020-11-15 12:24:42 +01:00
ptitSeb 2e9665f10e One more glib2 wrapped function 2020-11-15 12:22:23 +01:00
ptitSeb 197881b430 Fixed g_build_path wrapped function 2020-11-15 12:20:37 +01:00
ptitSeb 96fe98d71f Added gtk_cell_renderer_* wrapped function to gtk2 2020-11-15 11:54:35 +01:00
ptitSeb d1ecd4c933 Added g_build_path wrapped function to libglib2 2020-11-15 11:44:15 +01:00
ptitSeb fad25caa08 Added g_content_type_* function to wrapped libgio2 2020-11-15 11:34:25 +01:00
ptitSeb 98c481e045 Added gtk_tree_store wrapped functions to gtk2 lib 2020-11-15 11:29:48 +01:00
ptitSeb 6082e655e6 Added g_slist_sort and g_slist_sort_with_data to wrapped libglib2 2020-11-15 11:11:44 +01:00
ptitSeb 6a97367242 Made GetNativeFnc smarter, and should find more native funcs now 2020-11-15 11:05:07 +01:00
ptitSeb bbcfffdab9 Added gtk_container_foreach and fixed gtk_binding_entry_add_signal when n is 0 in wrapped gtk2 2020-11-15 10:28:22 +01:00
ptitSeb 2dfb6c1012 Added g_regex function to wrapped libglib2 2020-11-15 10:11:12 +01:00
ptitSeb 82317343aa Added GtkAction wrapped functions 2020-11-15 09:58:55 +01:00
ptitSeb 0ea0d0ec98 Better handling of custom gtk class, plus a bunch of gtk wrapeed functions 2020-11-15 09:48:10 +01:00
ptitSeb 33aa27c590 Added GtkAction Class handling (gtk2 and gtk3, hopefully it's the same) 2020-11-14 16:17:04 +01:00
ptitSeb c31f990183 Added F3 0F 12 MOVSLDUP Ex, Gx opcode ([DYNAREC] too) 2020-11-14 15:11:52 +01:00
ptitSeb 791956bee0 More wrapped function to gtk2 lib 2020-11-14 15:03:57 +01:00
ptitSeb 6cebf4f6fd Added more wrapped functions to gtk2 lib 2020-11-14 14:46:02 +01:00
ptitSeb 1782136e02 Added F3 0F 16 MOVSHDUP Ex, Gx opcode ([DYNAREC] too) 2020-11-14 14:30:44 +01:00
ptitSeb 2f381192dd Added some queue wrapped function to libglib2 2020-11-14 13:30:51 +01:00
ptitSeb dac2009cab Added the random functions to wrapped libglib2 2020-11-14 12:39:17 +01:00
ptitSeb d592af694f Added some more wrapped functions to libglib2 2020-11-14 12:18:56 +01:00
ptitSeb e5ea3f9e49 Added g_set_print_handler and g_set_printerr_handler to wrapped libglib2 2020-11-14 11:55:01 +01:00
ptitSeb f0af865401 Fix potential crash on exit for app using Pulse (fixes Iconoclash crash on exit) 2020-11-14 11:37:30 +01:00
ptitSeb 1e20a9effe Improved and simplifiex SDL2_mixer wrapped library 2020-11-13 22:33:34 +01:00
ptitSeb ce968f7756 Added some precision on 32bits build over 64bits OS 2020-11-12 17:43:03 +01:00
ptitSeb 00aaf316ef Added RK3399 target and compilation guide (plus some restructuration in CMake project 2020-11-11 18:08:16 +01:00
ptitSeb 3ad9a0ca73 [DYNAREC] Added ability to track exact x86 address in dynablocks for signal handling 2020-11-11 14:08:53 +01:00
ptitSeb 14a2d24fba [DYNAREC] Better way to prevent difference in emited dynablock between pass2 and pass3 2020-11-10 19:13:07 +01:00
ptitSeb e374886fcf AddedF0 90..97 opcode, simply ignoring F0 LOCK prefix ([DYNREC] too) 2020-11-09 15:09:43 +01:00
ptitSeb e25b373f00 Fixed gtk_menu_item_set_use_underline wrapped function signature 2020-11-09 12:06:57 +01:00
ptitSeb 6fbd270d24 [DYNAREC] cosmetic change 2020-11-08 13:40:40 +01:00
ptitSeb 6adb55a9c4 [DYNAREC] Try to fix the randow issue were a block have a different emited size between pass2 and pass3 2020-11-08 13:40:14 +01:00
ptitSeb 16aa5cac04 Fixed a warning with wrapped posix_spawnp 2020-11-08 13:39:06 +01:00
ptitSeb dca0009df5 [DYNAREC] Fix 66 0F 16 MOVHPD opcode and improved 66 0F C6 SHUFPD 2020-11-08 13:32:28 +01:00
ptitSeb 1cae441cbc More glib2 wrapped functions 2020-11-07 11:27:28 +01:00
ptitSeb 8b21d8f74a [DYNAREC] Added some dump of block when incosistancy between pass2 and pass3 is detected 2020-11-07 11:26:40 +01:00
ptitSeb ff141e30ee Added handling of environ instead of envv for box86 called with spawnp 2020-11-07 11:25:54 +01:00
ptitSeb 2c970a1b8d Added wrapped posix_spawnp function 2020-11-07 11:25:12 +01:00
ptitSeb b433f8194e Improved a bit the fork wrapped function 2020-11-06 17:47:53 +01:00
ptitSeb 7b2f5e5de0 Improved some BOX86_LOG=2 traces 2020-11-06 17:47:26 +01:00
ptitSeb 3d1400e347 Added preliminary gtk3/gdk3 wrapped lib (based on gtk2/gdk2 wrapping) 2020-11-06 14:08:10 +01:00
ptitSeb 8b5d68f79b Use std=gnu11 to avoid some warning when using clang 2020-11-05 14:01:32 +01:00
ptitSeb ded4b461b4 Some more check to help build on some Linux on Android env. 2020-11-05 12:48:44 +01:00
ptitSeb 13a7be57f2 Check some define to help build on some Linux on Android env. 2020-11-05 12:21:55 +01:00
ptitSeb e8fdcd5c06 Added a bunch of gtk wrapped functions 2020-11-05 11:34:11 +01:00
ptitSeb b8e263d7e6 Removed a warning in wrapped SDL_mixer 2020-11-05 11:33:50 +01:00
ptitSeb b76d17e7b9 Update ChangeLog 2020-11-04 13:15:57 +01:00
ptitSeb ce3151b256 Fixed some (XX)printf alignement issue when formating have %+ or %- command 2020-11-02 16:19:39 +01:00
ptitSeb dd0c3ac51e [VULKAN] More work on vulkan wrapper 2020-11-02 13:32:38 +01:00
ptitSeb f06c5897db Merge pull request #245 from linkmauve/patch-1
Fix install target after previous change
2020-11-02 12:51:14 +01:00
linkmauve 7dac72f796 Fix install target after previous change
#244 broke the install target because system/box86.conf should
now be taken from the build directory, sorry for that.
2020-11-02 12:10:29 +01:00
ptitSeb e5a55114b7 Merge pull request #239 from SpacingBat3/master
PKGBUILDs for Arch Linux.
2020-11-02 12:02:57 +01:00
ptitSeb a66d0b3d39 Merge pull request #244 from linkmauve/fix-binfmt-path
Generate binfmt so it points to the correct path
2020-11-02 12:00:29 +01:00
Emmanuel Gil Peyrot b01ad69ba1 Generate binfmt so it points to the correct path
CMake’s templating language is suitable for this kind of generation, as
it knows about all of the variables that have been set at configure-
time.
2020-11-02 10:52:25 +00:00
ptitSeb bbe183e8d4 Do not try to run winedbg 2020-11-01 23:29:20 +01:00
ptitSeb f6c9e5079a Small improvement on BOX86_LOG=2 2020-11-01 23:28:54 +01:00
ptitSeb 0b8408d50a [VULKAN] Fixed vkGetPhysicalDeviceImageFormatProperties signature 2020-11-01 22:42:20 +01:00
ptitSeb 51682eac11 [VULKAN] Fixed vkalignStruct/vkunalignStruct (and now Sascha-willems samples start working) 2020-11-01 21:34:23 +01:00
ptitSeb aea38c682c [VULKAN] More vulka wrapping work 2020-11-01 21:12:56 +01:00
ptitSeb 6edbe97290 Added the last function not wrapped in SDL1_mixer, and redid the wrapping of the callback (for #243) 2020-11-01 20:11:23 +01:00
ptitSeb 304eaab4d2 [VULKAN] Fixed a warning 2020-11-01 17:11:53 +01:00
ptitSeb f4e5839931 [VULKAN] Morework on wrapped functions 2020-11-01 15:35:53 +01:00
ptitSeb 4bac9ea9d5 [VULKAN] More work on vulkan wrapper 2020-11-01 10:04:30 +01:00
ptitSeb 64c9b21849 [VULKAN] Alignment of many structures. Now a simple TriangleDrawing windows App works 2020-10-31 22:58:58 +01:00
SpacingBat3 34828b66a2 Added a PKGBUILDs for other platforms. 2020-10-31 17:35:06 +01:00
SpacingBat3 957ba00723 Added a PKGBUILD for other raspberries.
Added a unified PKGBUILD to install box86 on all RPi-based machines (that are fully supported by box86) and did some changes to README.md.
2020-10-31 17:32:45 +01:00
SpacingBat3 d548ee48c1 Added a RPI4B PKGBUILD.
It is possible now to install the `box86` using the PKBUILD providen in the repository.
2020-10-31 16:57:09 +01:00
ptitSeb d0e93a22a2 Better vulkan log 2020-10-31 09:55:49 +01:00
ptitSeb fe6c1e260b Added one more vulkan extension 2020-10-31 09:55:33 +01:00
ptitSeb 1e5add91d3 Fixed many vulkan wrapped function (and now vulkaninfo works) 2020-10-30 22:12:55 +01:00
ptitSeb f4c7329c30 Forgotten in previous commit 2020-10-30 22:12:11 +01:00
ptitSeb b1742ccb8e Added some minimum wrapped libwayland-client 2020-10-30 22:11:37 +01:00
ptitSeb 870a0d8361 [VULKAN] Fixed library not found even if present 2020-10-30 17:52:44 +01:00
ptitSeb 1f0adf92d4 Added 64 8E MOV Seg, FS:Ed opcode (for #241) 2020-10-30 16:15:45 +01:00
ptitSeb 18ce562698 Wrapping of vulkan (untested yet) 2020-10-30 16:08:46 +01:00
ptitSeb 77af926336 Added 64 8C MOV FS:Ed, Seg opcode (for #241) 2020-10-30 10:44:32 +01:00
ptitSeb 33f2269896 [DYNAREC] removes some compile warning 2020-10-30 10:43:52 +01:00
ptitSeb c477e14a04 [DYNAREC] Minor chenges to some 67 xx opcodes 2020-10-30 10:10:36 +01:00
ptitSeb 373494094a [DYNAREC] Forgot that file on previous commit 2020-10-30 10:08:46 +01:00
ptitSeb 72ca666007 [DYNAREC] Added 65 80/82 opcodes 2020-10-30 10:07:47 +01:00
ptitSeb 5be299b897 [DYNAREC] Cosmetic change 2020-10-30 10:06:55 +01:00
ptitSeb 49afd5077b [DYNAREC] Fixed some function that needs flags before CALL (fixed some ESP not properly preserved on some Windows programs) 2020-10-30 10:05:47 +01:00
ptitSeb e7336de8a7 Change COMPILE.md for Pi4: make -j4 is enough 2020-10-30 10:03:10 +01:00
ptitSeb 5b0f4f5b94 Start a new developpement cycle 2020-10-30 10:02:17 +01:00
236 changed files with 26880 additions and 7639 deletions

No files matched your search

+45
View File
@@ -1,3 +1,48 @@
v0.2.0
======
* Improvoment on x86 Flags handling
* A few more opcode added
* A few potential BusError fixed
* Added BOX86_NOVULKAN en. var. disable the wrapping of vulkan libs
* Improvments on libc O_XXXX flags handling
* Now use a custom allocator for Dynarec and Hash tables
* Improvment wrapping of pulse audio
* Optimisation to a few Dynarec opcode (like SHRD/SHLD)
* Improved the tracking of memory protection
* A few more wrapping of libs (like libgssapi_krb5)
* More function wrapping on libturbojpeg
* Preliminary support for POWER9 (ppcle) build
* Many contributed typo and rephrasing of README, COMPILE and USAGE docs
v0.1.8
======
* Fixes on some float to int x87 convertions opcodes
* Reworked all callback mecanisms
* Added libturbojpeg wrapping (and a hack for zoom to force using native one)
* Added BOX86_SAFEMMAP env. var.
* Reworked dynarec memory manager
* Added a few opcodes
* Improve elfloader to not force PltResolver all the time (fixing SuperHexagon and maybe other)
* Reworked Exet and Cancel Thread mecanism
* Added wrapped libldap_r and liblber library (used by wine)
* Reworked Dynarec block handling, and remove the "AddMark" mecanism that wasn't efficient enough
* Added TokiTori 2+ detection and runtime patch on PI
* Fixes on elfloader with TLS object
v0.1.6
======
* Changes in Dynarec to make flags optimizations before CALL and RET opcode less aggressive
* Added Vulkan wrapper
* Improved wrapping of SDL_mixer/ SDL2_mixer lib
* Improved wrapping of some gtk structures
* Added a quick and dirty wrapping of Gtk3 (based on current gtk2)
* Improved the signal handling, should be more stable now (the signal handler from syscall still need some works)
* Added RK3399 profile, and some hints to build the 32bits box86 on 64bits OS
* Fixed some wrapped printf formating not handled correctly
* Fixed some buserror with the new LOCK mecanism handling
* A few more Dynarec opcodes added
* If winedbg is tried to be launched, exit without launching it (it doesn't work anyway)
v0.1.4
======
* Change in Dynarec memory handling, to simplify it (and hopefully optimized it)
+74 -40
View File
@@ -1,25 +1,30 @@
cmake_minimum_required(VERSION 2.6)
project(box86)
enable_testing()
enable_language(C)
cmake_minimum_required(VERSION 3.0)
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
option(RPI2 "Set to ON if targeting an RaspberryPI2 device" ${RPI2})
option(RPI3 "Set to ON if targeting an RaspberryPI3 device" ${RPI3})
option(RPI4 "Set to ON if targeting an RaspberryPI4 device" ${RPI4})
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation (WIP, don't use yet)" ${ARM_DYNAREC})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR RK3399 OR RPI4ARM64)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
option(ARM_DYNAREC "Set to ON to use ARM Dynamic Recompilation (WIP, don't use yet)" ${ARM_DYNAREC})
option(POWERPCLE "Set to ON if targeting a little-endian PowerPC device" ${POWERPCLE})
option(SYSV_VARARG "Set to ON if host device uses SysVR4 vararg calling convention" ${SYSV_VARARG})
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
@@ -37,6 +42,16 @@ else()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
if(RK3399 OR RPI4ARM64)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
endif()
project(box86 C ASM)
enable_testing()
set(default_build_type "RelwithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
@@ -44,66 +59,57 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# Pandora
if(PANDORA)
add_definitions(-DPANDORA)
#add_definitions(-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -fsingle-precision-constant -ffast-math)
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
# Gameshell
if(GAMESHELL)
add_definitions(-DGAMEHELL)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(PYRA)
add_definitions(-DPYRA)
add_definitions(-mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a15 -mfpu=neon -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI2)
add_definitions(-DRPI)
add_definitions(-DRPI2)
add_definitions(-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI3)
add_definitions(-DRPI)
add_definitions(-DRPI3)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RPI4)
add_definitions(-DRPI)
add_definitions(-DRPI3)
add_definitions(-DRPI4)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
endif()
if(RPI4ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI4ARM64)
add_definitions(-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(ODROID)
add_definitions(-DODROID)
add_definitions(-mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard -marm)
set(CMAKE_ASM_FLAGS "-marm -mcpu=cortex-a9 -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
endif()
if(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto")
endif()
if(POWER9)
add_definitions(-mcpu=power9 -mtune=power9)
endif()
if(NOGIT)
@@ -140,6 +146,14 @@ if(ARM_DYNAREC)
enable_language(ASM)
endif()
if(POWERPCLE)
add_definitions(-DPOWERPCLE)
endif()
if(SYSV_VARARG)
add_definitions(-DSYSV_VARARG)
endif()
if(NOGETCLOCK)
add_definitions(-DNOGETCLOCK)
endif()
@@ -158,7 +172,7 @@ else()
endif()
add_definitions(-std=gnu99 -funwind-tables -fvisibility=hidden)
add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
@@ -184,6 +198,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/main.c"
"${BOX86_ROOT}/src/box86context.c"
"${BOX86_ROOT}/src/build_info.c"
"${BOX86_ROOT}/src/custommem.c"
"${BOX86_ROOT}/src/tools/bridge.c"
"${BOX86_ROOT}/src/tools/pathcoll.c"
"${BOX86_ROOT}/src/tools/fileutils.c"
@@ -218,6 +233,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/libtools/sdl2rwops.c"
"${BOX86_ROOT}/src/libtools/signals.c"
"${BOX86_ROOT}/src/libtools/threads.c"
"${BOX86_ROOT}/src/libtools/vkalign.c"
"${BOX86_ROOT}/src/dynarec/dynarec.c"
"${BOX86_ROOT}/src/wrapped/generated/wrapper.c"
)
@@ -239,6 +255,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX86_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX86_ROOT}/src/wrapped/wrappedvorbisfile.c"
@@ -280,6 +297,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibjpeg62.c"
"${BOX86_ROOT}/src/wrapped/wrappedturbojpeg.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
@@ -308,6 +326,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtk3.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdk3.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkpixbuf2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgio2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgmodule2.c"
@@ -332,6 +352,16 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9.c"
"${BOX86_ROOT}/src/wrapped/wrappedvulkan.c"
"${BOX86_ROOT}/src/wrapped/wrappedwaylandclient.c"
"${BOX86_ROOT}/src/wrapped/wrappedxml2.c"
"${BOX86_ROOT}/src/wrapped/wrappedxslt.c"
"${BOX86_ROOT}/src/wrapped/wrappedldapr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlber.c"
"${BOX86_ROOT}/src/wrapped/wrappednsl.c"
"${BOX86_ROOT}/src/wrapped/wrappedlcms2.c"
"${BOX86_ROOT}/src/wrapped/wrappedkrb5.c"
"${BOX86_ROOT}/src/wrapped/wrappedgssapikrb5.c"
"${BOX86_ROOT}/src/wrapped/wrappedldlinux.c"
)
@@ -346,7 +376,10 @@ set(WRAPPER "${BOX86_ROOT}/src/wrapped/generated/wrapper.c" "${BOX86_ROOT}/src/w
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--" ${WRAPPEDS_HEAD}
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
"${BOX86_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
@@ -497,7 +530,8 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
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/)
+12 -6
View File
@@ -20,7 +20,7 @@ Compiling
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j24
make -j4
sudo make install
sudo systemctl restart systemd-binfmt
```
@@ -31,7 +31,13 @@ sudo systemctl restart systemd-binfmt
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Other ARM Linux
#### for RK3399
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Other ARM Linux platforms
`mkdir build; cd build; cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
@@ -51,19 +57,19 @@ Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the so
*have some debug info*
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument make a build that is both optimized for speed, and have debug information embedded. That way, if you have a crash or try to analyse performances, you'll have some symbols.
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
*to have a Trace Enabled build*
To have a trace enabled build (warning, it will be slower), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system lib folders.
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
*to have ARM Dynarec*
The Dynarec is only avaiable on ARM Cpu. Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
*not building from a git clone*
If you are not building from a git clone (for example downloading a release sources Zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box86 print).
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box86 print).
----
+19 -17
View File
@@ -5,11 +5,11 @@ Linux Userspace x86 Emulator with a twist
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux, like ARM (host system needs to be 32bit little-endian).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only support 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environnement).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use, and performance can be surprisingly high in some cases.
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary.
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary(most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android)) .
Box86 now integrates a DynaRec (dynamic recompiler) for the ARM platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
@@ -32,14 +32,14 @@ Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list
Logo and Icon made by @grayduck, thanks!
Note that this project is not to be mystaken with [86box](https://github.com/86Box/86Box), a nice "Full system" emulator specialized in early (to fairly recent) PC hardware.
Note that this project is not to be mistaken with [86box](https://github.com/86Box/86Box), a nice "Full system" emulator specialized in early (to fairly recent) PC hardware.
----
Discord
----
If you want to discuss about box86 on Discord, there is a frendly server there: [PI Lab Discord](https://discord.gg/Fh8sjmu)
If you want to discuss(or have any problems) about box86, there is a Discord friendly server there: [PI Lab Discord](https://discord.gg/Fh8sjmu)
----
@@ -53,11 +53,11 @@ Compilation instructions can be found [here](COMPILE.md)
Usage
----
There are a few environment variables avaiable to control the behaviour of Box86.
There are a few environment variables to control the behaviour of Box86.
See [here](USAGE.md) for all variables and what they do.
See [here](USAGE.md) for all environment variables and what they do.
Note that now the Dynarec of Box86 uses a mecanism with Memory Protection and a SegFault signal handler to handle JIT code. That means if you want to use gdb to debug running a program that use JIT'd code (like mono/Unity3D), you will have many "normal" segfaults triggering. I suggest you use something like `handle SIGSEGV nostop` in gdb to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
Note: Box86's Dynarec uses a mechanism with Memory Protection and a SegFault signal handler to handle JIT code. In simpler terms, if you want to use GDB to debug a running program that use JIT'd code (like mono/Unity3D), you will still have many "normal" segfaults triggering. It is suggested to use something like `handle SIGSEGV nostop` in GDB to not stop at each segfault, and maybe put a breakpoint inside `my_memprotectionhandler` in `signals.c` if you want to trap SegFaults.
----
@@ -68,39 +68,41 @@ The change log is available [here](CHANGELOG.md)
----
A note about 64-bit platforms
Notes about 64-bit platforms
----
Because Box86 works by directly translating function calls from x86 to host system, the host system (the one Box86 is running on) needs to have 32-bit libraries. Box86 doesn't include any 32-bit <-> 64-bit translation. So basically, to run Box86 on, for example, an ARM64 platform, you will need to build Box86 for ARM 32-bit, and also need to have a chroot with 32-bit libraries.
Also note that, even if, on day, there is a Box86_64, this one will only be able to run x86_64 binaries on 64-bit platforms. You will still need Box86 (and see 32-bit chroot) to run x86 binaries (in fact, the same is the case on actual x86_64 Linux).
Also note that, even if, on day, there is a Box86_64, this one will only be able to run x86_64 binaries on 64-bit platforms. You will still need Box86 (and a 32-bit chroot) to run x86 binaries (in fact, the same is the case on actual x86_64 Linux).
----
A note about Unity game emulation
----
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with he new "protected memory" mechanism implemented it is running with correct performance now.
Running Unity games is a hit or miss for now. Unity uses Mono (which uses signals that are not well emulated enough), and a runtime embedded in the main binary. A solution would be to use a native version of the libmono library used by Unity (it can be found here: https://github.com/Unity-Technologies/mono and needs to be built from source). But the wrapping of this lib is tricky, and not done for now, so the only solution is to emulate everything. The tricky part is to emulate the "JIT" code emitted by Mono, however with the new "protected memory" mechanism implemented it should be running with correct performance now.
You should also note that some Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
TL;DR: Not all Unity games work and can require a high OpenGL profile, but the speed, for the ones running, should be correct now.
----
A note about Steam
Notes about Steam
----
Linux Steam can run now with box86. But it's still a bit unstable., and not everything works. First is steam crashes after the Sign in, you may need to add libappindicator. On debian it's `sudo apt install libappindicator1`.
Once open, Steam will only work on "Small mode". So go in the "View" menu and witch to Small view (or Compact view?), else the list will stay empty (this is because some steam component used in the browser view are only 64bits now).
Final word, to avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` export.
(Steam for Windows install fine but doesn't work yet)
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works. First problem is steam crashing after the Sign in window, if you encounter this issue, you may need to add libappindicator. Installing the package on debian `sudo apt install libappindicator1`.
Once open, Steam will only work on "Small Mode" and in "Big Picture", not in the regular "Large Mode"(This is because some steam component used in the browser view are only 64 bits now.). So go in the "View" menu and switch to Small view, else the list will stay empty.
Final words, to avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables.
(Steam for Windows installs fine but doesn't work yet)
Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aformentionned feature, it is safer to add it to your system if you intend to play those game (something like `sudo apt install libtcmalloc-minimal4` to install it on Debian and Debian's deriatives)
----
A note about Wine
Notes about Wine
----
Wine is now partly supported. Wine integreted program all runs, annd some windows program and games now run fine. Don't forget most Windows games use Direct3D, that may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
Wine is now partly supported. Wine integrated program all runs, and some windows programs and games now runs fine. Don't forget most Windows games use Direct3D, this may require a complete OpenGL driver and as high profile as possible (and gl4es with ES2 backend have issue with Wine for now). Also, vulkan is not wrapped on box86, so vk3d is not usable yet, even if supported by the hardware.
Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those models use a default OS that have a kernel with a 2/2 Split (meaning 2G of space for user program, and 2G of space for the Kernel). This is not compatible with Wine programs that needs to access memory > 2Gb address. So you'll need to reconfigure your kernel for a 3G/1G split. Use your favorite search engine for instructions on how to do that.
----
+50 -30
View File
@@ -1,30 +1,31 @@
Usage
----
There are many environment variable to control Box86 behaviour.
There are many environment variables to control Box86 behaviour.
#### BOX86_LOG
Controls the Verbose level of the log
Controls the Verbosity level of the logs
* 0
* NONE : No message (except some fatal error)
* NONE : Current default. No message (except some fatal error)
* 1
* INFO : Current default. Show some log
* INFO : Show some minimum log (like librairies not found)
* 2
* DEBUG : Verbose a lot of stuffs (like relocations or function called)
* DEBUG : Details a lot of stuff (like relocations or function called)
* 3
* DUMP : All DEBUG plus DUMP of all ELF Info
#### BOX86_NOBANNER
Control Box86 printing it's version and build
* 0 : Enabled the printing
* 1 : Diable the printing
Control Box86 printing its version and build
* 0 : Enable printing
* 1 : Disable printing
#### BOX86_LD_LIBRARY_PATH
Controls the folder scanned to look for x86 libs. Default is current folder and `lib` in current folder.
Path to look for x86 libs. Default is current folder and `lib` in current folder.
Also `/usr/lib/i386-linux-gnu` and `/lib/i386-linux-gnu` are added if they exists
#### BOX86_PATH
Controls the folder scanned to look for x86 executable. Default is current folder and `bin` in current folder.
Path to look for x86 executable. Default is current folder and `bin` in current folder.
#### BOX86_DLSYM_ERROR
* 0 : default. Don't log `dlsym` error
@@ -32,17 +33,17 @@ Controls the folder scanned to look for x86 executable. Default is current folde
#### BOX86_TRACE_FILE
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by actual PID of box86 instance
Also, if name contains `%pid` then this is replaced by the actual PID of box86 instance
#### BOX86_TRACE
Only on build with trace enabled. Trace allow the logging of all instruction execute, along with register dump
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
* 0 : No trace
* 1 : Trace enabled. The trace start after the init of all depending libs is done
* 1 : Trace enabled. Trace start after the initialisation of all depending libraries is done
* symbolname : Trace only `symbolname` (trace is disable if the symbol is not found)
* 0xXXXXXXX-0xYYYYYYY : trace only between the 2 addresses
#### BOX86_TRACE_INIT
Use BOX86_TRACE_INIT instead of BOX_TRACE to start trace before init of Libs and main program
Use BOX86_TRACE_INIT instead of BOX_TRACE to start trace before the initialisation of libraries and the running program
* 0 : No trace
* 1 : Trace enabled. The trace start with the init of all depending libs is done
@@ -52,39 +53,40 @@ Only on build with trace enabled.
#### BOX86_TRACE_XMM
Only on build with trace enabled.
* 0 : Default, the XMM (i.e. SSE/SSE2) register will not be logged with the general and x87 registers
* 0 : Default, the XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers
* 1 : Dump the XMM registers
#### BOX86_LOAD_ADDR
Try to load at 0xXXXXXX main binaray (if binary is a PIE)
Try to load at 0xXXXXXX main binary (if binary is a PIE)
* 0xXXXXXXXX the load address (only active on PIE programs)
#### BOX86_NOSIGSEGV
To disable handling of SigSEGV (to ease debugging mainly)
Disable handling of SigSEGV ( Very useful for debugging.)
* 0 : default, let x86 program set sighandler for SEGV
* 1 : disable handling of SigSEGV
#### BOX86_NOSIGILL
To disable handling of SigILL (to ease debugging mainly)
Disable handling of SigILL (to ease debugging mainly)
* 0 : default, let x86 program set sighandler for Illegal Instruction
* 1 : disable handling of SigILL
#### BOX86_X11COLOR16
PANDORA only: to try convert X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows
PANDORA only: Try converting X11 color from 32 bits to 16 bits (to avoid light green on light cyan windows)
* 0 : default, don't touch X11 colors
* 1 : Change colors arguments in XSetForeground, XSetBackground and XCreateGC
#### BOX86_X11THREADS
To call XInitThreads when loading X11 (for old Loki games with Loki_Compat lib)
Call XInitThreads when loading X11 (for old Loki games with Loki_Compat lib)
* 0 : default, don't force call XInitThreads
* 1 : Call XInitThreads as soon as libX11 is loaded
#### BOX86_X11GLX
To Force libX11 GLX extension to be present
Force libX11 GLX extension to be present.
* 0 : Disable the force.
* 1 : default, GLX will always be present when using XQueryExtension
#### BOX86_DYNAREC_DUMP
Enables/disables box86's dynarec dump.
* 0 : Disable Dynarec blocks dump (default)
* 1 : Enable Dynarec blocks dump
* 2 : Enable Dynarec blocks dump with some colors
@@ -108,7 +110,12 @@ Set level of DynaRec log
* 0 : Disable Dynarec Linker (use that on debug, with dynarec log >= 2, to have detail on wich block get executed)
* 1 : Enable Dynarec Linker (default)
#### BOX86_DYNAREC_SAFEMMAP
* 0 : Default. Some mmp/mmap64 are consider unsafe (depending of flags mainly)
* 1 : Consider all mmap/mmap64 safe to use linker (potential speedup, but potential crash for apps using JIT/Dynarec)
#### BOX86_DYNAREC_TRACE
Enables/Disables trace for generated code
* 0 : Disable trace for generated code (default)
* 1 : Enable trace for generated code (like regular Trace, this will slow down a lot and generate huge logs)
@@ -123,26 +130,39 @@ Set level of DynaRec log
#### BOX86_EMULATED_LIBS
* XXXX[:YYYYY] force lib XXXX (and YYYY...) to be emulated (and not wrapped)
Some games use old version of some lib, with an ABI incompatible with native version.
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSINGLIBS
Allow box86 to continue even if a lib is missing
* 0 : default, stop if a lib cannot be loaded
* 1 : continue even if a needed lib cannot be loaded. Unadvised, this will, in most cases, crash later on.
Allow box86 to continue even if a library is missing
* 0 : default, stop if a library cannot be loaded
* 1 : continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_NOPULSE
Disable the load of pulseaudio libs
* 0 : default, load pulseaudio libs if present
* 1 : disable the load of pulse audio libs (libpulse and libpulse-simple), both native and x86 version
Disable the load of pulseaudio libraries
* 0 : default, load pulseaudio libraries if present
* 1 : disable the load of pulse audio libraries (libpulse and libpulse-simple), both native and x86 version
#### BOX86_NOGTK
Disable the load of wrapped GTK libraries
* 0 : default, load wrapped gtk libs if present
* 1 : disable the load of wrapped gtk libs (can be used with Steam, along with STEAM_RUNTIME=1 to use i386 versio of gtk)
#### BOX86_NOVULKAN
Disable the load of vulkan libraries
* 0 : default, load vulkan libraries if present
* 1 : disable the load of vulkan libraries both native and x86 version (can be usefull on Pi4)
#### BOX86_FIX_64BIT_INODES
* 0 : Don't fix 64bit inodes (default)
* 1 : Fix 64bit inodes. Helps when running on filesystems with 64bit inodes, the program uses API functions which don't support it and the program doesn't use inodes information.
* 1 : Fix 64bit inodes. Helps when running on filesystems with 64bit inodes, the program uses API functions which doesn't support it and the program doesn't use inodes information.
#### BOX86_JITGDB
* 0 : Just print the Segfault message on segfault (default)
* 1 : Launch `gdb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
When in gdb, you need to find the correct thread yourself (the one with `my_box86signalhandler` in is stack)
then probably need to `finish` 1 or 2 functions (inside `usleep(..)`) and then you'll be in `my_box86signalhandler`,
just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
just before the printf of the Segfault message. Then simply `set waiting=0` to exit the infinite loop.
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
Use `gdb /PATH/TO/box86` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX86_JITGDB=1`.
This mode can be usefull when program redirect all console output to a file (like Unity3D Games)
+1
View File
@@ -0,0 +1 @@
theme: jekyll-theme-hacker
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=r2798.0edc0374
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%-arm-git}-git" "${_pkgname%-arm-git}")
conflicts=("${pkgname%-git}" "${_pkgname%-arm-git}-git" "${_pkgname%-arm-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-arm-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-gameshell-git
pkgver=r2798.0edc0374
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%-gameshell-git}-git" "${pkgname%-gameshell-git}")
conflicts=("${pkgname%-git}" "${pkgname%-gameshell-git}-git" "${pkgname%-gameshell-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=r2798.0edc0374
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%-odroid-git}-git" "${_pkgname%-odroid-git}")
conflicts=("${pkgname%-git}" "${_pkgname%-odroid-git}-git" "${_pkgname%-odroid-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+45
View File
@@ -0,0 +1,45 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-pandora-git
_pkgname=box86-git
pkgver=r2798.0edc0374
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%-pandora-git}"-git "${pkgname%-pandora-git}")
conflicts=("${pkgname%-git}" "${pkgname%-pandora-git}"-git "${pkgname%-pandora-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pandora-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+45
View File
@@ -0,0 +1,45 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-pyra-git
_pkgname=box86-git
pkgver=r2798.0edc0374
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%-pyra-git}-git" "${pkgname%-pyra-git}")
conflicts=("${pkgname%-git}" "${pkgname%-pyra-git}-git" "${pkgname%-pyra-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+60
View File
@@ -0,0 +1,60 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-rpi-git
_pkgname=box86-git
pkgver=r2798.0edc0374
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%-rpi-git}-git" "${pkgname%--rpi-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rpi-git}-git" "${pkgname%--rpi-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
_pimodel=`tr -d '\0' < /sys/firmware/devicetree/base/model`
pkgver() {
cd "$srcdir/${pkgname%-rpi-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
# Check for Pi version number
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
_piversion=4
elif [[ ${_pimodel} =~ "Raspberry Pi 3" ]]; then
_piversion=3
elif [[ ${_pimodel} =~ "Raspberry Pi 2" ]]; then
_piversion=2
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"
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"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+39
View File
@@ -0,0 +1,39 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
_pkgname=box86-git
pkgver=r2798.0edc0374
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%-rk3399-git}-git" "${pkgname%-rk3399-git}")
conflicts=("${pkgname%-git}" "${pkgname%-rk3399-git}-git" "${pkgname%-rk3399-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
cd "$srcdir/${pkgname%-rk3399-git}"
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make DESTDIR="${pkgdir}/" install
}
+44
View File
@@ -0,0 +1,44 @@
# Maintainer: SpacingBat3 <[email protected]>
# Contributor: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
_pkgname=box86-git
pkgver=r2798.0edc0374
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
url="https://github.com/ptitSeb/box86"
license=('MIT')
makedepends=('git' 'cmake' 'make')
provides=("${pkgname%-x86-git}")
conflicts=("${pkgname%-x86-git}")
source=('git+https://github.com/ptitSeb/box86')
md5sums=('SKIP')
pkgver() {
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}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-x86-git}/build"
make -j$(nproc)
}
package() {
cd "$srcdir/${pkgname%-x86-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
}
+21
View File
@@ -0,0 +1,21 @@
# The directory containing all PKGBUILDs for BOX86
## FAQ
### 1. How to use it?
Just download the `PKGBUILD-<your-platform>` (no need to download the whole repository), go to directory where you downloaded and type:
```sh
mv ./PKGBUILD-<your-platform> ./PKGBUILD
cd ..
makepkg -si
```
This will copy the PKGBUILD for your platform (where you type your platform name instead of `<your-platform>`), build it and install the PKGBUILD on 32-bit Archlinux ARM.
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](../COMPILE.md).
### 3. Any advantages with that sollution?
This might give you some advantages like those:
- automatic updates (with some AUR frontends like [`pamac-aur`](https://aur.archlinux.org/packages/pamac-aur/) or [`yay`](https://aur.archlinux.org/packages/yay));
- easily uninstall with `pacman -R` when no needed (no need other scripts nor Makefile to do this);
- your `box86` installation is recognized as a package (where it wasn't when installing with `make install`).
+126 -62
View File
@@ -3,7 +3,7 @@
import os
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2']
values = ['E', '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']
def splitchar(s):
try:
ret = [len(s), values.index(s[0])]
@@ -252,6 +252,33 @@ static void* io_convert(void* v)
return v;
}
typedef struct my_GValue_s
{
int g_type;
union {
int v_int;
int64_t v_int64;
uint64_t v_uint64;
float v_float;
double v_double;
void* v_pointer;
} data[2];
} my_GValue_t;
static void alignGValue(my_GValue_t* v, void* value)
{
v->g_type = *(int*)value;
memcpy(v->data, value+4, 2*sizeof(double));
}
static void unalignGValue(void* value, my_GValue_t* v)
{
*(int*)value = v->g_type;
memcpy(value+4, v->data, 2*sizeof(double));
}
void* VulkanFromx86(void* src, void** save);
void VulkanTox86(void* src, void* save);
#define ST0val ST0.d
int of_convert(int);
@@ -262,6 +289,7 @@ int of_convert(int);
#ifndef __WRAPPER_H_
#define __WRAPPER_H_
#include <stdint.h>
#include <string.h>
typedef struct x86emu_s x86emu_t;
@@ -282,6 +310,10 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// 2 = struct of 2 uint
// P = Vulkan struture pointer
// G = a single GValue pointer
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
"""
}
@@ -317,8 +349,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
# First part: typedefs
for v in gbl["()"]:
# E e v c w i I C W u U f d D K l L p V O S 2
types = ["x86emu_t*", "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"]
# E 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
types = ["x86emu_t*", "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*", "...", "..."]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -327,8 +359,8 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
# E e v c w i I C W u U f d D K l L p V O S 2
types = ["x86emu_t*", "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"]
# E 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
types = ["x86emu_t*", "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*", "...", "..."]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
@@ -337,8 +369,76 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
file.write("#endif\n")
file.write("\n")
# Next part: function definitions
# Helper variables
arg = [
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # K
"*(intptr_t*)(R_ESP + {p}), ", # l
"*(uintptr_t*)(R_ESP + {p}), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), ", # V
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
"io_convert(*(void**)(R_ESP + {p})), ", # S
"(_2uint_struct_t){{*(uintptr_t*)(R_ESP + {p}),*(uintptr_t*)(R_ESP + {p} + 4)}}, ", # 2
"arg{p}, ", # P
"&arg{p}, ", # G
"*(void**)(R_ESP + {p}), ", # N
"*(void**)(R_ESP + {p}),*(void**)(R_ESP + {p} + 4), ", # M
]
# E 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
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4, 8, 4, 4, 0, 0]
vals = [
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_EAX=fn({0});", # c
"R_EAX=fn({0});", # w
"R_EAX=fn({0});", # i
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
"R_EAX=(unsigned char)fn({0});", # C
"R_EAX=(unsigned short)fn({0});", # W
"R_EAX=(uint32_t)fn({0});", # u
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_EAX=(intptr_t)fn({0});", # l
"R_EAX=(uintptr_t)fn({0});", # L
"R_EAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: _2uint_struct\n", # 2
"\n#error Invalid return type: Vulkan Struct\n", # P
"\n#error Invalid return type: GValue Pointer\n", # G
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
]
# Asserts
if len(values) != len(arg):
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
if len(values) != len(deltas):
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
# Helper functions to write the function definitions
def function_args(args, d=4):
if len(args) == 0:
@@ -351,67 +451,31 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
elif args[0] == "1":
return "1, " + function_args(args[1:], d)
arg = [
"emu, ", # E
"&emu, ", # e
"", # v
"*(int8_t*)(R_ESP + {p}), ", # c
"*(int16_t*)(R_ESP + {p}), ", # w
"*(int32_t*)(R_ESP + {p}), ", # i
"*(int64_t*)(R_ESP + {p}), ", # I
"*(uint8_t*)(R_ESP + {p}), ", # C
"*(uint16_t*)(R_ESP + {p}), ", # W
"*(uint32_t*)(R_ESP + {p}), ", # u
"*(uint64_t*)(R_ESP + {p}), ", # U
"*(float*)(R_ESP + {p}), ", # f
"*(double*)(R_ESP + {p}), ", # d
"*(long double*)(R_ESP + {p}), ", # D
"FromLD((void*)(R_ESP + {p})), ", # K
"*(intptr_t*)(R_ESP + {p}), ", # l
"*(uintptr_t*)(R_ESP + {p}), ", # L
"*(void**)(R_ESP + {p}), ", # p
"(void*)(R_ESP + {p}), ", # V
"of_convert(*(int32_t*)(R_ESP + {p})), ", # O
"io_convert(*(void**)(R_ESP + {p})), ", # S
"(_2uint_struct_t){{*(uintptr_t*)(R_ESP + {p}),*(uintptr_t*)(R_ESP + {p} + 4)}}, ", #2
]
# E e v c w i I C W u U f d D K l L p V O S 2
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4, 8]
if len(values) != len(arg):
raise NotImplementedError("len(values) = {lenval} != len(arg) = {lenarg}".format(lenval=len(values), lenarg=len(arg)))
if len(values) != len(deltas):
raise NotImplementedError("len(values) = {lenval} != len(deltas) = {lendeltas}".format(lenval=len(values), lendeltas=len(deltas)))
return arg[values.index(args[0])].format(p=d) + function_args(args[1:], d + deltas[values.index(args[0])])
def function_writer(f, N, W, rettype, args):
f.write("void {0}(x86emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
vals = [
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_EAX=fn({0});", # c
"R_EAX=fn({0});", # w
"R_EAX=fn({0});", # i
"ui64_t r; r.i=fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # I
"R_EAX=(unsigned char)fn({0});", # C
"R_EAX=(unsigned short)fn({0});", # W
"R_EAX=(uint32_t)fn({0});", # u
"ui64_t r; r.u=(uint64_t)fn({0}); R_EAX=r.d[0]; R_EDX=r.d[1];", # U
"float fl=fn({0}); fpu_do_push(emu); ST0val = fl;", # f
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_EAX=(intptr_t)fn({0});", # l
"R_EAX=(uintptr_t)fn({0});", # L
"R_EAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: _2uint_srtuct\n", # 2
]
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
if any(cc in 'PG' for cc in args):
# Vulkan struct or GValue pointer, need to unwrap functions at the end
delta = 4
for c in args:
if c == 'P':
f.write("void* save{d}=NULL; void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d}), &save{d}); ".format(d=delta))
if c == 'G':
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_ESP + {d})); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " ")
delta = 4
for c in args:
if c == 'P':
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
if c == 'G':
f.write("unalignGValue(*(void**)(R_ESP + {d}), &arg{d}); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write("}\n")
else:
# Generic function
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
for v in gbl["()"]:
function_writer(file, v, v + "_t", v[0], v[2:])
+98 -249
View File
@@ -19,223 +19,80 @@
#include "threads.h"
#include "x86trace.h"
#include "signals.h"
#ifdef DYNAREC
#include <sys/mman.h>
#include "custommem.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
#endif
#define MMAPSIZE (4*1024*1024) // allocate 4Mo sized blocks
#define MMAPBLOCK 256 // minimum size of a block
//#define USE_MMAP
typedef struct mmaplist_s {
void* block;
uint8_t map[MMAPSIZE/(8*MMAPBLOCK)]; // map of allocated sub-block
} mmaplist_t;
// get first subblock free in map, stating at start. return -1 if no block, else first subblock free, filling size (in subblock unit)
static int getFirstBlock(mmaplist_t *map, int start, int maxsize, int* size)
{
#define ISFREE(A) (((map->map[(A)>>3]>>((A)&7))&1)?0:1)
if(start<0) start = 0;
while(start<MMAPSIZE/(8*MMAPBLOCK)) { // still a chance...
if(ISFREE(start)) {
// free, now get size...
int end = start+1;
while(end<MMAPSIZE/(8*MMAPBLOCK)) {
if(!ISFREE(end) || (end-start==maxsize)) {
if(size) *size = end-start;
return start;
}
++end;
}
if(size) *size = end-start;
return start;
}
++start;
}
return -1;
}
static void allocBlock(mmaplist_t *map, int start, int size)
{
for(int i=0; i<size; ++i) {
map->map[start/8]|=(1<<(start&7));
++start;
}
}
static void freeBlock(mmaplist_t *map, int start, int size)
{
for(int i=0; i<size; ++i) {
map->map[start/8]&=~(1<<(start&7));
++start;
}
}
uintptr_t AllocDynarecMap(int size, int nolinker)
{
if(size>MMAPSIZE) {
#ifdef USE_MMAP
void* p = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
#else
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
return (uintptr_t)p;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
for(int i=0; i<my_context->mmapsize; ++i) {
int rsize = 0;
int start = 0;
do {
start = getFirstBlock(my_context->mmaplist+i, start, bsize, &rsize);
if(start!=-1 && rsize>=bsize) {
allocBlock(my_context->mmaplist+i, start, bsize);
uintptr_t ret = (uintptr_t)my_context->mmaplist[i].block + start*MMAPBLOCK;
pthread_mutex_unlock(&my_context->mutex_mmap);
return ret;
}
if(start!=-1)
start += rsize;
} while (start!=-1);
}
// no luck, add a new one !
int i = my_context->mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", my_context->mmapsize);
my_context->mmaplist = (mmaplist_t*)realloc(my_context->mmaplist, my_context->mmapsize*sizeof(mmaplist_t));
#ifdef USE_MMAP
void* p = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(p==MAP_FAILED) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
--my_context->mmapsize;
pthread_mutex_unlock(&my_context->mutex_mmap);
return 0;
}
#else
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
--my_context->mmapsize;
pthread_mutex_unlock(&my_context->mutex_mmap);
return 0;
}
mprotect(p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
my_context->mmaplist[i].block = p;
memset(my_context->mmaplist[i].map, 0, sizeof(my_context->mmaplist[i].map));
allocBlock(my_context->mmaplist+i, 0, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
return (uintptr_t)p;
}
void FreeDynarecMap(uintptr_t addr, uint32_t size)
{
if(size>MMAPSIZE) {
munmap((void*)addr, size);
return;
}
pthread_mutex_lock(&my_context->mutex_mmap);
int bsize = (size+MMAPBLOCK-1)/MMAPBLOCK;
// look for free space
for(int i=0; i<my_context->mmapsize; ++i) {
if(addr>=(uintptr_t)my_context->mmaplist[i].block && ((uintptr_t)my_context->mmaplist[i].block+MMAPSIZE)>=addr+size) {
int start = (addr - (uintptr_t)my_context->mmaplist[i].block) / MMAPBLOCK;
freeBlock(my_context->mmaplist+i, start, bsize);
pthread_mutex_unlock(&my_context->mutex_mmap);
return;
}
}
pthread_mutex_unlock(&my_context->mutex_mmap);
}
// each dynmap is 64k of size
dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
int idx = (addr>>DYNAMAP_SHIFT);
if(!my_context->dynmap[idx]) {
return NULL;
}
return my_context->dynmap[idx]->dynablocks;
}
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!my_context->dynmap[i]) {
my_context->dynmap[i] = (dynmap_t*)calloc(1, sizeof(dynmap_t));
my_context->dynmap[i]->dynablocks = NewDynablockList(i<<DYNAMAP_SHIFT, i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, nolinker, 0);
} else {
ProtectkDynablockList(&my_context->dynmap[i]->dynablocks);
}
}
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>DYNAMAP_SHIFT):(addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynmap_t* dynmap = my_context->dynmap[i];
if(dynmap) {
uintptr_t startdb = StartDynablockList(dynmap->dynablocks);
uintptr_t enddb = EndDynablockList(dynmap->dynablocks);
uintptr_t startaddr = addr;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = addr + size - 1;
if(endaddr>enddb) endaddr = enddb;
if(startaddr==startdb && endaddr==enddb) {
if(destroy) {
my_context->dynmap[i] = NULL;
FreeDynablockList(&dynmap->dynablocks);
free(dynmap);
} else
MarkDynablockList(&dynmap->dynablocks);
} else
if(destroy)
FreeRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
else
MarkRangeDynablock(dynmap->dynablocks, startaddr, endaddr-startaddr+1);
}
}
}
#ifdef DYNAREC
// Remove the Write flag from an adress range, so DB can be executed
// no log, as it can be executed inside a signal handler
void protectDB(uintptr_t addr, uintptr_t size)
{
uintptr_t start = (addr)&~(box86_pagesize-1);
uintptr_t end = (addr+size+(box86_pagesize-1))&~(box86_pagesize-1);
// should get "end" according to last block inside the window
mprotect((void*)start, end-start, PROT_READ|PROT_EXEC);
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot;
do {
prot=arm_lock_read_d(&my_context->memprot[i]);
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
} while(arm_lock_write_d(&my_context->memprot[i], prot|PROT_DYNAREC));
if(!(prot&PROT_DYNAREC))
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
}
}
// Add the Write flag from an adress range, and mark all block as dirty
// no log, as it can be executed inside a signal handler
void unprotectDB(uintptr_t addr, uintptr_t size)
{
uintptr_t start = (addr)&~(box86_pagesize-1);
uintptr_t end = (addr+size+(box86_pagesize-1))&~(box86_pagesize-1);
// should get "end" according to last block inside the window
mprotect((void*)start, end-start, PROT_READ|PROT_WRITE|PROT_EXEC);
cleanDBFromAddressRange(start, end-start, 0);
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot;
do {
prot=arm_lock_read_d(&my_context->memprot[i]);
} while(arm_lock_write_d(&my_context->memprot[i], prot&~PROT_DYNAREC));
if(prot&PROT_DYNAREC) {
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_DYNAREC);
cleanDBFromAddressRange((i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, 0);
}
}
}
#endif
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
const uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
#ifdef DYNAREC
uint32_t dyn;
do {
dyn=arm_lock_read_d(&my_context->memprot[i])&PROT_DYNAREC;
} while(arm_lock_write_d(&my_context->memprot[i], prot|dyn));
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
#else
uint32_t dyn=(my_context->memprot[i]&PROT_DYNAREC);
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
mprotect((void*)(i<<DYNAMAP_SHIFT), 1<<DYNAMAP_SHIFT, prot&~PROT_WRITE);
my_context->memprot[i] = prot|dyn;
#endif
}
}
uint32_t getProtection(uintptr_t addr)
{
const uintptr_t idx = (addr>>DYNAMAP_SHIFT);
return my_context->memprot[idx];
}
EXPORTDYN
void initAllHelpers(box86context_t* context)
{
@@ -245,17 +102,23 @@ void initAllHelpers(box86context_t* context)
my_context = context;
init_pthread_helper();
init_signal_helper(context);
#ifdef DYNAREC
if(box86_dynarec)
DynablockEmuMarker(context);
#endif
inited = 1;
}
EXPORTDYN
void finiAllHelpers()
void finiAllHelpers(box86context_t* context)
{
static int finied = 0;
if(finied)
return;
fini_pthread_helper();
fini_pthread_helper(context);
fini_signal_helper();
cleanAlternate();
fini_custommem_helper(context);
finied = 1;
}
@@ -266,11 +129,11 @@ int getrand(int maxval)
{
if(maxval<1024) {
return ((random()&0x7fff)*maxval)/0x7fff;
} else {
}
uint64_t r = random();
r = (r*maxval) / RAND_MAX;
return r;
}
}
void free_tlsdatasize(void* p)
@@ -292,13 +155,19 @@ box86context_t *NewBox86Context(int argc)
}
#endif
// init and put default values
box86context_t *context = (box86context_t*)calloc(1, sizeof(box86context_t));
box86context_t *context = my_context = (box86context_t*)calloc(1, sizeof(box86context_t));
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
context->deferedInit = 1;
#endif
context->sel_serial = 1;
init_custommem_helper(context);
context->memprot = (uint32_t*)calloc(DYNAMAP_SIZE, sizeof(uint32_t));
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->system = NewBridge();
@@ -311,8 +180,6 @@ box86context_t *NewBox86Context(int argc)
#endif
context->dlprivate = NewDLPrivate();
context->callbacks = NewCallbackList();
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
@@ -321,19 +188,13 @@ box86context_t *NewBox86Context(int argc)
pthread_mutex_init(&context->mutex_trace, NULL);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, NULL);
#else
pthread_mutex_init(&context->mutex_dyndump, NULL);
#endif
pthread_mutex_init(&context->mutex_tls, NULL);
pthread_mutex_init(&context->mutex_thread, NULL);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_dyndump, NULL);
#endif
pthread_key_create(&context->tlskey, free_tlsdatasize);
#ifdef DYNAREC
pthread_mutex_init(&context->mutex_blocks, NULL);
pthread_mutex_init(&context->mutex_mmap, NULL);
context->dynablocks = NewDynablockList(0, 0, 0, 0, 0);
#endif
InitFTSMap(context);
for (int i=0; i<4; ++i) context->canary[i] = 1 + getrand(255);
@@ -390,24 +251,17 @@ void FreeBox86Context(box86context_t** context)
free(ctx->envv[i]);
free(ctx->envv);
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
if(ctx->dynablocks)
FreeDynablockList(&ctx->dynablocks);
for (int i=0; i<ctx->mmapsize; ++i)
if(ctx->mmaplist[i].block)
#ifdef USE_MMAP
munmap(ctx->mmaplist[i].block, MMAPSIZE);
#else
free(ctx->mmaplist[i].block);
#endif
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
cleanDBFromAddressRange(0, 0xffffffff, 1);
pthread_mutex_destroy(&ctx->mutex_blocks);
pthread_mutex_destroy(&ctx->mutex_mmap);
free(ctx->mmaplist);
#endif
if(ctx->atfork_sz) {
free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
for(int i=0; i<MAX_SIGNAL; ++i)
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
*context = NULL; // bye bye my_context
CleanStackSize(ctx);
@@ -429,8 +283,6 @@ void FreeBox86Context(box86context_t** context)
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
FreeCallbackList(&ctx->callbacks);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
@@ -453,30 +305,20 @@ void FreeBox86Context(box86context_t** context)
pthread_mutex_destroy(&ctx->mutex_trace);
#ifndef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#else
pthread_mutex_destroy(&ctx->mutex_dyndump);
#endif
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_dyndump);
#endif
free(ctx->memprot);
ctx->memprot = NULL;
free_neededlib(&ctx->neededlibs);
if(ctx->atfork_sz) {
free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
for(int i=0; i<MAX_SIGNAL; ++i)
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
finiAllHelpers();
finiAllHelpers(ctx);
free(ctx);
}
@@ -500,6 +342,13 @@ int AddTLSPartition(box86context_t* context, int tlssize) {
context->tlsdata = realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
// clean GS segment for current emu
if(my_context) {
ResetSegmentsCache(thread_get_emu());
if(!(++context->sel_serial))
++context->sel_serial;
}
return -context->tlssize; // negative offset
}
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX86_VERSION_H_
#define BOX86_MAJOR 0
#define BOX86_MINOR 1
#define BOX86_REVISION 4
#define BOX86_MINOR 2
#define BOX86_REVISION 0
#endif //__BOX86_VERSION_H_
+530
View File
@@ -0,0 +1,530 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <signal.h>
#include "box86context.h"
#include "elfloader.h"
#include "debug.h"
#include "x86trace.h"
#include "x86emu.h"
#include "librarian.h"
#include "bridge.h"
#include "library.h"
#include "callback.h"
#include "wrapper.h"
#include "myfts.h"
#include "threads.h"
#include "x86trace.h"
#include "signals.h"
#include <sys/mman.h>
#include "custommem.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
#include "khash.h"
// init inside dynablocks.c
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
static dynablocklist_t** dynmap; // 4G of memory mapped by 4K block
static pthread_mutex_t mutex_mmap;
static mmaplist_t *mmaplist;
static int mmapsize;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
#endif
typedef struct blocklist_s {
void* block;
int maxfree;
size_t size;
} blocklist_t;
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
static pthread_mutex_t mutex_blocks = PTHREAD_MUTEX_INITIALIZER;
static int n_blocks = 0; // number of blocks for custom malloc
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
typedef union mark_s {
struct {
unsigned int fill:1;
unsigned int size:31;
};
uint32_t x32;
} mark_t;
typedef struct blockmark_s {
mark_t prev;
mark_t next;
} blockmark_t;
// get first subblock free in block, stating at start (from block). return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, int maxsize, int* size)
{
// get start of block
blockmark_t *m = (blockmark_t*)block;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
*size = m->next.size;
return m;
}
m = (blockmark_t*)((uintptr_t)m + m->next.size);
}
return NULL;
}
static int getMaxFreeBlock(void* block, size_t block_size)
{
// get start of block
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // styart with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return maxsize; // no block large enough left...
}
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
}
return maxsize;
}
static void* allocBlock(void* block, void *sub, int size)
{
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
s->next.fill = 1;
s->next.size = size+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
// new mark
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = (uintptr_t)n - (uintptr_t)m;
n->prev.fill = 0;
n->prev.size = m->next.size;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
static void freeBlock(void *block, void* sub)
{
blockmark_t *m = (blockmark_t*)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
if(block!=sub)
m = (blockmark_t*)((uintptr_t)s - s->prev.size);
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size;
n->prev.size = m->next.size;
s = m;
}
// check if merge with next
if(n->next.x32 && !n->next.fill) {
blockmark_t *n2 = (blockmark_t*)((uintptr_t)n + n->next.size);
//remove n
s->next.size += n->next.size;
n2->prev.size = s->next.size;
}
}
// return 1 if block has been expanded to new size, 0 if not
static int expandBlock(void* block, void* sub, int newsize)
{
newsize = (newsize+3)&~3;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
if(s->next.fill)
return 0; // next block is filled
if(s->next.size + n->next.size < newsize)
return 0; // free space too short
// ok, doing the alloc!
s->next.size = newsize+sizeof(blockmark_t);
blockmark_t *m = (blockmark_t*)((uintptr_t)s + s->next.size); // this is new n
m->prev.fill = 1;
m->prev.size = s->next.size;
if(n!=m) {
// new mark
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = (uintptr_t)n - (uintptr_t)m;
n->prev.fill = 0;
n->prev.size = m->next.size;
}
return 1;
}
// return size of block
static int sizeBlock(void* sub)
{
blockmark_t *s = (blockmark_t*)sub;
return s->next.size;
}
void* customMalloc(size_t size)
{
// look for free space
void* sub = NULL;
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
int rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
if(sub) {
void* ret = allocBlock(p_blocks[i].block, sub, size);
if(rsize==p_blocks[i].maxfree)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
}
}
// add a new block
int i = n_blocks++;
p_blocks = (blocklist_t*)realloc(p_blocks, n_blocks*sizeof(blocklist_t));
size_t allocsize = MMAPSIZE;
if(size+2*sizeof(blockmark_t)>allocsize)
allocsize = size+2*sizeof(blockmark_t);
void* p = calloc(1, allocsize);
p_blocks[i].block = p;
p_blocks[i].size = allocsize;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = allocsize-sizeof(blockmark_t);
m = (blockmark_t*)(p+allocsize-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = allocsize-sizeof(blockmark_t);
// alloc 1st block
void* ret = allocBlock(p_blocks[i].block, p, size);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
void* customCalloc(size_t n, size_t size)
{
size_t newsize = n*size;
void* ret = customMalloc(newsize);
memset(ret, 0, newsize);
return ret;
}
void* customRealloc(void* p, size_t size)
{
if(!p)
return customMalloc(size);
uintptr_t addr = (uintptr_t)p;
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
if(expandBlock(p_blocks[i].block, sub, size)) {
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
pthread_mutex_unlock(&mutex_blocks);
return p;
}
pthread_mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
}
}
pthread_mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
return customMalloc(size);
}
void customFree(void* p)
{
if(!p)
return;
uintptr_t addr = (uintptr_t)p;
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(p_blocks[i].block, sub);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size);
pthread_mutex_unlock(&mutex_blocks);
return;
}
}
pthread_mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Free\n", (void*)addr);
}
#ifdef DYNAREC
typedef struct mmaplist_s {
void* block;
int maxfree;
size_t size;
kh_dynablocks_t* dblist;
} mmaplist_t;
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
{
// look for free space
void* sub = NULL;
for(int i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size) {
int rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
if(rsize==mmaplist[i].maxfree)
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(!blocks) {
blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &r);
kh_value(blocks, k) = db;
return ret;
}
}
}
return 0;
}
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
{
int i = mmapsize++; // yeah, useful post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, MMAPSIZE)) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
--mmapsize;
return 0;
}
mprotect(p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
updateProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
mmaplist[i].block = p;
mmaplist[i].size = MMAPSIZE;
// setup marks
blockmark_t* m = (blockmark_t*)p;
m->prev.x32 = 0;
m->next.fill = 0;
m->next.size = MMAPSIZE-sizeof(blockmark_t);
m = (blockmark_t*)(p+MMAPSIZE-sizeof(blockmark_t));
m->next.x32 = 0;
m->prev.fill = 0;
m->prev.size = MMAPSIZE-sizeof(blockmark_t);
// alloc 1st block
uintptr_t sub = (uintptr_t)allocBlock(mmaplist[i].block, p, size);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
kh_dynablocks_t *blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
khint_t k;
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
return sub;
}
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
{
if(!addr || !size)
return;
for(int i=0; i<mmapsize; ++i) {
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
freeBlock(mmaplist[i].block, sub);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size);
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)db);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
return;
}
}
if(mmapsize)
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
{
// look in actual list
for(int i=0; i<mmapsize; ++i) {
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size))
return FindDynablockDynablocklist(addr, mmaplist[i].dblist);
}
// look in oversized
return FindDynablockDynablocklist(addr, dblist_oversized);
}
uintptr_t AllocDynarecMap(dynablock_t* db, int size)
{
if(!size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
void *p = NULL;
if(posix_memalign(&p, box86_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
return 0;
}
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
updateProtection((uintptr_t)p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
kh_dynablocks_t *blocks = dblist_oversized;
if(!blocks) {
blocks = dblist_oversized = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
return (uintptr_t)p;
}
if(pthread_mutex_trylock(&mutex_mmap)) {
sched_yield(); // give it a chance
if(pthread_mutex_trylock(&mutex_mmap))
return 0; // cannot lock, baillout
}
uintptr_t ret = FindFreeDynarecMap(db, size);
if(!ret)
ret = AddNewDynarecMap(db, size);
pthread_mutex_unlock(&mutex_mmap);
return ret;
}
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
{
if(size>MMAPSIZE) {
munmap((void*)addr, size);
kh_dynablocks_t *blocks = dblist_oversized;
if(blocks) {
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)db);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
return;
}
pthread_mutex_lock(&mutex_mmap);
ActuallyFreeDynarecMap(db, addr, size);
pthread_mutex_unlock(&mutex_mmap);
}
dynablocklist_t* getDB(uintptr_t idx)
{
return dynmap[idx];
}
// each dynmap is 64k of size
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!dynmap[i]) {
dynmap[i] = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, nolinker, 0);
}
}
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>box86_dynarec_largest && !destroy)?((addr-box86_dynarec_largest)>>DYNAMAP_SHIFT):(addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynablocklist_t* dblist = dynmap[i];
if(dblist) {
uintptr_t startdb = StartDynablockList(dblist);
uintptr_t enddb = EndDynablockList(dblist);
uintptr_t startaddr = addr;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = addr + size - 1;
if(endaddr>enddb) endaddr = enddb;
if(destroy)
FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
else
MarkRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
}
}
}
#endif
void init_custommem_helper(box86context_t* ctx)
{
#ifdef DYNAREC
if(dynmap) // already initialized
return;
pthread_mutex_init(&mutex_mmap, NULL);
dynmap = (dynablocklist_t**)calloc(DYNAMAP_SIZE, sizeof(dynablocklist_t*));
#endif
}
void fini_custommem_helper(box86context_t *ctx)
{
#ifdef DYNAREC
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<mmapsize; ++i) {
if(mmaplist[i].block)
free(mmaplist[i].block);
if(mmaplist[i].dblist) {
kh_destroy(dynablocks, mmaplist[i].dblist);
mmaplist[i].dblist = NULL;
}
}
if(dblist_oversized) {
kh_destroy(dynablocks, dblist_oversized);
dblist_oversized = NULL;
}
mmapsize = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
uintptr_t idx = 0;
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynablocklist_t* dblist = dynmap[i];
if(dblist) {
uintptr_t startdb = StartDynablockList(dblist);
uintptr_t enddb = EndDynablockList(dblist);
uintptr_t startaddr = 0;
if(startaddr<startdb) startaddr = startdb;
uintptr_t endaddr = 0xFFFFFFFF;
if(endaddr>enddb) endaddr = enddb;
FreeRangeDynablock(dblist, startaddr, endaddr-startaddr+1);
}
}
pthread_mutex_destroy(&mutex_mmap);
free(mmaplist);
free(dynmap);
dynmap = NULL;
#endif
for(int i=0; i<n_blocks; ++i)
free(p_blocks[i].block);
free(p_blocks);
pthread_mutex_destroy(&mutex_blocks);
}
+85 -9
View File
@@ -21,12 +21,13 @@ Op is 20-27
#define xEBP 9
#define xESI 10
#define xEDI 11
#define xEIP 12
#define xFlags 12
#define xEIP 14
// scratch registers
#define x1 1
#define x2 2
#define x3 3
#define x12 12
#define x14 14
// emu is r0
#define xEmu 0
// ARM SP is r13
@@ -210,6 +211,12 @@ Op is 20-27
// cmp.s dst, src1, src2, lsl #imm
#define CMPS_REG_LSL_IMM5(src1, src2, imm5) \
EMIT(0xe1500000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// cmp.cond.s dst, src1, src2, lsl #imm
#define CMPS_REG_LSL_IMM5_COND(cond, src1, src2, imm5) \
EMIT((cond) | 0x01500000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// cmp.s dst, src, #imm
#define CMPS_IMM8_COND(cond, src, imm8) \
EMIT((cond) | 0x03500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmp.s dst, src, #imm
#define CMPS_IMM8(src, imm8) \
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -228,13 +235,22 @@ Op is 20-27
// orr.s dst, src1, src2, lsl #imm
#define ORRS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.s dst, src1, src2, lsr #imm
#define ORRS_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr dst, src1, #imm8
#define ORR_IMM8(dst, src, imm8, rot) \
EMIT(0xe3800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// orr.s dst, src1, #imm8
#define ORRS_IMM8(dst, src, imm8, rot) \
EMIT(0xe3900000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// orr dst, src1, src2, lsl #rs
// orr.cond dst, src1, #imm8
#define ORR_IMM8_COND(cond, dst, src, imm8, rot) \
EMIT((cond) | 0x03800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// orr dst, src1, src2, lsl rs
#define ORR_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// xor dst, src1, src2, lsl #imm
@@ -265,6 +281,9 @@ Op is 20-27
// bic dst, src, IMM8
#define BIC_IMM8(dst, src, imm8, rot) \
EMIT(0xe3c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// bic.cond dst, src, IMM8
#define BIC_IMM8_COND(cond, dst, src, imm8, rot) \
EMIT((cond) | 0x03c00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// bic.s dst, src1, #imm ror rot*2
#define BICS_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe3d00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
@@ -321,6 +340,8 @@ Op is 20-27
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str with cond reg, [addr, #+/-imm9]
#define STR_IMM9_COND(cond, reg, addr, imm9) EMIT(cond | 0x05000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str reg, [addr, #+/-imm9]!
#define STR_IMM9_W(reg, addr, imm9) EMIT(0xe5200000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// strb reg, [addr, #+/-imm9]
#define STRB_IMM9(reg, addr, imm9) EMIT(0xe5400000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str reg, [addr], #+/-imm9
@@ -358,10 +379,16 @@ Op is 20-27
// all | const |pre-index| subs | no PSR |writeback| store | base |reg list
#define PUSH(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (1<<21) | (0<<20) | ((reg)<<16) | (list))
// push reg to xESP
#define PUSH1(reg) STR_IMM9_W(reg, xESP, -4)
// pop reg!, {list}
// all | const |postindex| add | no PSR |writeback| load | base |reg list
#define POP(reg, list) EMIT(c__ | (0b100<<25) | (0<<24) | (1<<23) | (0<<22) | (1<<21) | (1<<20) | ((reg)<<16) | (list))
// pop reg from xESP
#define POP1(reg) LDRAI_IMM9_W(reg, xESP, 4)
// STMDB reg, {list}
// all | const |pre-index| subs | no PSR | no wb | store | base |reg list
#define STMDB(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (0<<21) | (0<<20) | ((reg)<<16) | (list))
@@ -387,12 +414,14 @@ Op is 20-27
#define LDRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 1, addr, reg, 0, 1, abs(imm8)))
#define LDRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
#define STRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 0, addr, reg, 0, 1, abs(imm8)))
#define STRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
#define LDRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRHAI_REG_LSL_IMM5(reg, addr, rm) EMIT(HWS_REG(c__, 0, 1, 0, 0, addr, reg, 0, 1, rm))
#define LDRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 1, addr, reg, 0, 1, abs(imm8)))
#define LDRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
#define STRHB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 1, 0, addr, reg, 0, 1, abs(imm8)))
#define STRHA_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 0, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
#define PUSH16(reg, addr) EMIT(HWS_OFF(c__, 1, 0, 1, 0, addr, reg, 0, 1, 2))
#define POP16(reg, addr) EMIT(HWS_OFF(c__, 0, 1, 0, 1, addr, reg, 0, 1, 2))
// Mul Long construction
#define MULLONG(Cond, U, A, S, RdHi, RdLo, Rs, Rm) (Cond | 0b00001<<23 | (U)<<22 | (A)<<21 | (S)<<20 | (RdHi)<<16 | (RdLo)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
@@ -425,12 +454,20 @@ Op is 20-27
// BFI_COND: Bit Field Insert with condition: copy any number of low order bit from Rn to any position of Rd
#define BFI_COND(cond, rd, rn, lsb, width) EMIT(cond | (0b0111110<<21) | (((lsb)+(width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b001<<4) | (rn))
// BFC: Bit Field Clear: clear any number of adjacent bit from Rd
#define BFC(rd, lsb, width) EMIT(c__ | (0b0111110<<21) | (((lsb)+(width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b001<<4) | 0b1111)
// BFC_COND: Bit Field Clear with condition: clear any number of adjacent bit from Rd
#define BFC_COND(cond, rd, lsb, width) EMIT(cond | (0b0111110<<21) | (((lsb)+(width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b001<<4) | 0b1111)
// REV: Reverse byte of a 32bits word
#define REV(rd, rm) EMIT(c__ | (0b01101<<23) | (0<<22) | (0b11<<20) | (0b1111<<16) | ((rd)<<12) | (0b1111<<8) | (0b0011<<4) | (rm))
#define SSAT_gen(cond, sat_imm, Rd, imm5, sh, Rn) (cond | 0b0110101<<21 | (sat_imm)<<16 | (Rd)<<12 | (imm5)<<7 | (sh)<<6 | 0b01<<4 | (Rn))
// Signed Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define SSAT_REG_LSL_IMM5(Rd, saturate_to, Rn, shift) EMIT(SSAT_gen(c__, (saturate_to)-1, Rd, shift, 0, Rn))
// Signed Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define SSAT_REG_LSL_IMM5_COND(cond, Rd, saturate_to, Rn, shift) EMIT(SSAT_gen((cond), (saturate_to)-1, Rd, shift, 0, Rn))
#define USAT_gen(cond, sat_imm, Rd, imm5, sh, Rn) (cond | 0b0110111<<21 | (sat_imm)<<16 | (Rd)<<12 | (imm5)<<7 | (sh)<<6 | 0b01<<4 | (Rn))
// Unsigned Staturate Rn to 2^(staturate_to-1) into Rd. Optionnaly shift left Rn before saturate
#define USAT_REG_LSL_IMM5(Rd, saturate_to, Rn, shift) EMIT(SSAT_gen(c__, (saturate_to), Rd, shift, 0, Rn))
@@ -704,6 +741,14 @@ Op is 20-27
#define VMOV_igen(i, D, imm3, Vd, cmode, Q, op, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | (op)<<5 | 1<<4 | (imm4))
#define VMOV_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 0, 0, (imm)&15))
#define VMOVQ_8(Dd, imm) EMIT(VMOV_igen(((imm)>>7)&1, ((Dd)>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1110, 1, 0, (imm)&15))
// Dd <= imm8 in high bits
#define VMOV_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 0, 0, (imm8)&15))
// Dd <= imm8 in high bits
#define VMOV_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 0, 0, (imm8)&15))
// Qd <= imm8 in high bits
#define VMOVQ_H32(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b0110, 1, 0, (imm8)&15))
// Qd <= imm8 in high bits
#define VMOVQ_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 1, 0, (imm8)&15))
#define VLD1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
@@ -768,6 +813,14 @@ Op is 20-27
#define VCEQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b010<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCEQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCGT_I_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCGT_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCGTQ_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -793,6 +846,15 @@ Op is 20-27
#define VCGE_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCGEQ_F32(Dd, Dn, Dm) EMIT(VCGE_F_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b100<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCLT_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLT_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_8(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_16(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCLTQ_0_32(Dd, Dm) EMIT(VCLT_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHR_gen(U, D, imm6, Vd, L, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | (L)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VSHR_U8(Dd, Dm, imm3) EMIT(VSHR_gen(1, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VSHR_S8(Dd, Dm, imm3) EMIT(VSHR_gen(0, ((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -1161,4 +1223,18 @@ Op is 20-27
#define VQRDMULHQ_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULHQ_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_sgen(D, imm4, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (imm4)<<16 | (Vd)<<12 | 0b1100<<8 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= Dup(Dm[x])
#define VDUP_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_vgen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b110<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VABS_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABS_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S16(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
#endif //__ARM_EMITTER_H__
+1 -1
View File
@@ -10,7 +10,7 @@
arm_epilog:
//update register -> emu
//pop {r0}
stm r0, {r4-r12} // put back reg value in emu, including EIP (so r12 must be EIP now)
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (so r14 must be EIP now)
//restore all used register
//vpop {d8-d15}
pop {r4-r11, pc}
+19 -5
View File
@@ -7,19 +7,33 @@
.align 4
.extern UpdateLinkTable
.extern LinkNext
.global arm_linker
arm_linker:
// emu is r0
stm r0, {r4-r12} // put back reg value in emu, including EIP (easier debugging, and safer)
stm r0, {r4-r12,r14} // put back reg value in emu, including EIP (easier debugging, and safer)
// table offset is r1
// IP address is r12
push {r0, r1, r12}
mov r2, r12
// IP address is r14
push {r0, r1, r12, r14}
mov r2, r14
// call the function
bl UpdateLinkTable
// return offset is jump address
mov r3, r0
pop {r0, r1, r12}
pop {r0, r1, r12, r14}
bx r3
.global arm_next
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
// IP address is r1
push {r0, r1, r12, r14}
// call the function
bl LinkNext
// return offset is jump address
mov r3, r0
pop {r0, r1, r12, r14}
bx r3
+39 -1
View File
@@ -7,10 +7,15 @@
.global arm_lock_read_b
.global arm_lock_write_b
.global arm_lock_read_h
.global arm_lock_write_h
.global arm_lock_read_d
.global arm_lock_write_d
.global arm_lock_read_dd
.global arm_lock_write_dd
.global arm_lock_xchg
.global arm_lock_storeifnull
arm_lock_read_b:
// address is r0, return is r0
@@ -23,6 +28,17 @@ arm_lock_write_b:
strexb r0, r1, [r2]
bx lr
arm_lock_read_h:
// address is r0, return is r0
ldrexh r0, [r0]
bx lr
arm_lock_write_h:
// address is r0, value is r1, return is r0
mov r2, r0
strexh r0, r1, [r2]
bx lr
arm_lock_read_d:
// address is r0, return is r0
// r0 needs to be aligned
@@ -48,4 +64,26 @@ arm_lock_write_dd:
// r0 needs to be aligned
strexd r3, r0, r1, [r2]
mov r0, r3
bx lr
bx lr
arm_lock_xchg:
// address is r0, value is r1, return old value in r0
// r0 needs to be aligned
ldrex r2, [r0]
strex r3, r1, [r0]
cmp r3, #1
beq arm_lock_xchg
mov r0, r2
bx lr
arm_lock_storeifnull:
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
// r0 needs to be aligned
ldrex r2, [r0]
cmp r2, #0
moveq r2, r1
strex r3, r2, [r0]
cmp r3, #1
beq arm_lock_storeifnull
mov r0, r2
bx lr
+11
View File
@@ -7,6 +7,11 @@ extern uint8_t arm_lock_read_b(void* addr);
// STREXB of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_b(void* addr, uint8_t val);
// LDREXH of ADDR
extern uint16_t arm_lock_read_h(void* addr);
// STREXH of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_h(void* addr, uint16_t val);
// LDREX of ADDR
extern uint32_t arm_lock_read_d(void* addr);
// STREX of ADDR, return 0 if ok, 1 if not
@@ -17,4 +22,10 @@ extern void arm_lock_read_dd(uint32_t* a, uint32_t* b, void* addr);
// STREX of ADDR, return 0 if ok, 1 if not
extern int arm_lock_write_dd(uint32_t a, uint32_t b, void* addr);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm_lock_xchg(void* p, uintptr_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
extern void* arm_lock_storeifnull(void*p, void* val);
#endif //__ARM_LOCK_HELPER__H__
+1 -1
View File
@@ -13,7 +13,7 @@ arm_prolog:
//vpush {d8-d15}
//setup emu -> register
//push {r0}
ldm r0, {r4-r11} // all 8 register in direct access, no EIP (so r12 can be used as scratch)
ldm r0, {r4-r12} // all 8 register in direct access, plus flags, no EIP (so r14 can be used as scratch)
//TODO
//jump to function
bx r1
+163 -361
View File
@@ -20,16 +20,15 @@
#include "elfloader.h"
#ifdef ARM
#include "dynarec_arm.h"
#include "arm_lock_helper.h"
#else
#error Unsupported architecture!
#endif
#include "custommem.h"
#include "khash.h"
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
KHASH_SET_INIT_INT(mark)
uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
@@ -39,15 +38,16 @@ uint32_t X31_hash_code(void* addr, int len)
return (uint32_t)h;
}
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, int nolinker, int direct)
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int direct)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
}
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->blocks = (nolinker && direct)?NULL:kh_init(dynablocks);
ret->base = base;
ret->text = text;
ret->textsz = textsz;
ret->nolinker = nolinker;
pthread_rwlock_init(&ret->rwlock_blocks, NULL);
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
@@ -58,8 +58,11 @@ dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, in
void FreeDynablock(dynablock_t* db)
{
if(db) {
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, %swith %d son(s)\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->marks?"with marks, ":"", db->sons_size);
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, tablesz=%d, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->tablesz, db->sons_size, db->gone);
if(db->gone)
return; // already in the process of deletion!
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;
@@ -68,53 +71,19 @@ void FreeDynablock(dynablock_t* db)
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
if(db->marks) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
dynarec_log(LOG_DEBUG, " -- resettable(%p)\n", p);
resettable(p);
);
// free mark
kh_destroy(mark, db->marks);
db->marks = NULL;
}
for(int i=0; i<db->tablesz; i+=4) {
dynablock_t* p = (dynablock_t*)db->table[i+3];
dynarec_log(LOG_DEBUG, " -- table[%d+3] = %p ", i, p);
if(p && p!=db && p->marks) {
khint_t kd = kh_get(mark, p->marks, (uintptr_t)(&db->table[i+0]));
if(kd!=kh_end(p->marks)) {
kh_del(mark, p->marks, kd);
dynarec_log(LOG_DEBUG, "cleaned");
}
else {dynarec_log(LOG_DEBUG, "not found");}
}
dynarec_log(LOG_DEBUG, "\n");
}
// remove from hash if there
if (db->parent->blocks) {
pthread_rwlock_wrlock(&db->parent->rwlock_blocks);
khint_t kdb;
kdb = kh_get(dynablocks, db->parent->blocks, (uintptr_t) db->x86_addr - db->parent->base);
if(kdb!=kh_end(db->parent->blocks))
kh_del(dynablocks, db->parent->blocks, kdb);
pthread_rwlock_unlock(&db->parent->rwlock_blocks);
}
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = db->sons[i];
db->sons[i] = NULL;
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap((uintptr_t)db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
}
free(db->sons);
free(db->table);
free(db->instsize);
free(db);
}
}
@@ -125,21 +94,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Free %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %s\n", (*dynablocks)->blocks?kh_size((*dynablocks)->blocks):0, (*dynablocks)->blocks?kh_n_buckets((*dynablocks)->blocks):0, (*dynablocks)->nolinker, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
if((*dynablocks)->blocks) {
// create a list of the parent db to delete (because there are sons in the middle that will be invalid if father is removed)
dynablock_t** list = (dynablock_t**)calloc(kh_size((*dynablocks)->blocks), sizeof(dynablock_t*));
int n = 0;
kh_foreach_value((*dynablocks)->blocks, db,
if(!db->father) list[n++] = db;
);
for (int i=0; i<n; ++i)
FreeDynablock(list[i]);
kh_destroy(dynablocks, (*dynablocks)->blocks);
(*dynablocks)->blocks = NULL;
free(list);
}
dynarec_log(LOG_DEBUG, "Free Direct Blocks %p from Dynablocklist nolinker=%d\n", (*dynablocks)->direct, (*dynablocks)->nolinker);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
@@ -147,8 +102,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks)
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = 0;
pthread_rwlock_destroy(&(*dynablocks)->rwlock_blocks);
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
@@ -159,17 +113,8 @@ void MarkDynablock(dynablock_t* db)
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->marks && !db->need_test) {
// Follow mark and set arm_linker instead
khint_t k;
kh_foreach_key(db->marks, k,
void** p = (void**)(uintptr_t)k;
resettable(p);
);
// free mark
kh_clear(mark, db->marks);
}
db->need_test = 1;
if(db->nolinker)
db->need_test = 1; // test only blocks that can be marked (and so deleted)
}
}
@@ -182,43 +127,6 @@ void ProtectDynablock(dynablock_t* db)
}
}
void RemoveMark(void** table)
{
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
table[3] = NULL;
}
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
void AddMark(dynablock_t* source, dynablock_t* dest, void** table)
{
int ret;
// remove old value if any
dynablock_t *old = (dynablock_t*)table[3];
if(old && old->father)
old = old->father;
if(old && old->marks) {
khint_t kd = kh_get(mark, old->marks, (uintptr_t)table);
if(kd!=kh_end(old->marks))
kh_del(mark, old->marks, kd);
}
// add mark if needed
if(dest->father)
dest = dest->father;
if(dest->marks) {
kh_put(mark, dest->marks, (uintptr_t)table, &ret);
table[3] = (void*)dest;
} else
table[3] = NULL;
}
void MarkDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
@@ -227,36 +135,30 @@ void MarkDynablockList(dynablocklist_t** dynablocks)
return;
if(!(*dynablocks)->nolinker)
return;
dynarec_log(LOG_DEBUG, "Marked %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynarec_log(LOG_DEBUG, "Marked Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
MarkDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
MarkDynablock((*dynablocks)->direct[i]);
db = (*dynablocks)->direct[i];
if(db)
MarkDynablock(db);
}
}
}
void ProtectkDynablockList(dynablocklist_t** dynablocks)
void ProtectDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Protect %d Blocks from Dynablocklist (with %d buckets, nolinker=%d) %p:0x%x %s\n", (*dynablocks)->blocks?(kh_size((*dynablocks)->blocks)):0, (*dynablocks)->blocks?(kh_n_buckets((*dynablocks)->blocks)):0, (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz, ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynarec_log(LOG_DEBUG, "Protect Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
dynablock_t* db;
if((*dynablocks)->blocks) {
kh_foreach_value((*dynablocks)->blocks, db,
ProtectDynablock(db);
);
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
ProtectDynablock((*dynablocks)->direct[i]);
db = (*dynablocks)->direct[i];
if(db)
ProtectDynablock(db);
}
}
}
@@ -270,28 +172,38 @@ uintptr_t StartDynablockList(dynablocklist_t* db)
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz;
return db->text+db->textsz-1;
return 0;
}
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)
{
if(!dynablocks)
return;
if(!dynablocks->nolinker)
if(!dynablocks->nolinker || !dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
uintptr_t enddb = startdb + dynablocks->textsz -1;
int maxsz = dynablocks->maxsz;
uintptr_t start = addr - maxsz;
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(dynablocks->direct[i-startdb]) {
MarkDynablock(dynablocks->direct[i-startdb]);
}
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 ProtectDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
@@ -315,26 +227,12 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
if(!dynablocks)
return;
if(dynablocks->blocks || dynablocks->direct) {
if(dynablocks->direct) {
dynablock_t* db;
uintptr_t s, e;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->blocks) {
kh_foreach_value(dynablocks->blocks, db,
if(db->father)
db =db->father;
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size))) {
//ProtectDynablock(db);
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
);
}
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
@@ -345,14 +243,17 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if(dynablocks->direct[i-startdb]) {
db = dynablocks->direct[i-startdb];
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;
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
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,
@@ -367,156 +268,51 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
return;
if(!dynablocks->nolinker)
return;
if(dynablocks->direct)
if(dynablocks->direct) {
MarkDirectDynablock(dynablocks, addr, size);
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->x86_addr;
e = (uintptr_t)db->x86_addr+db->x86_size-1;
if((s>=addr && s<(addr+size)) || (e>=addr && e<(addr+size)))
MarkDynablock(db);
);
// the blocks check before
for(int idx=(addr-dynablocks->maxsz)>>DYNAMAP_SHIFT; idx<addr>>DYNAMAP_SHIFT; ++idx)
MarkDirectDynablock(getDB(idx), addr, size);
}
}
dynablock_t* FindDynablockDynablocklist(void* addr, dynablocklist_t* dynablocks)
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
{
if(!dynablocks)
return NULL;
if(dynablocks->direct)
for(int i=0; i<dynablocks->textsz; ++i) {
dynablock_t* db;
if((db = dynablocks->direct[i])) {
uintptr_t s = (uintptr_t)db->block;
uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
}
}
if(dynablocks->blocks) {
dynablock_t* db;
uintptr_t s, e;
kh_foreach_value(dynablocks->blocks, db,
s = (uintptr_t)db->block;
e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
);
}
dynablock_t* db;
kh_foreach_value(dynablocks, db,
uintptr_t s = (uintptr_t)db->block;
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;
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
// unoptimized search through all dynablockslist for the dynablock that contains native addr (NULL if not found)
// search "volatile" dynarec first
dynablock_t *ret = NULL;
for(int idx=0; idx<DYNAMAP_SIZE && !ret; ++idx)
if(my_context->dynmap[idx])
ret = FindDynablockDynablocklist(addr, my_context->dynmap[idx]->dynablocks);
if(ret)
return ret;
// last, search context dynablocks
if(my_context->dynablocks)
ret = FindDynablockDynablocklist(addr, my_context->dynablocks);
return ret;
const int idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
void ConvertHash2Direct(dynablocklist_t* dynablocks)
{
if(dynablocks->textsz==0 || dynablocks->text==0 || !dynablocks->blocks)
return; // nothing to do
// create the new set
dynablock_t **direct = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
kh_dynablocks_t *blocks = kh_init(dynablocks);
// transfert
int ret;
khint_t k;
dynablock_t* db;
uintptr_t key;
uintptr_t start = dynablocks->text;
uintptr_t end = start + dynablocks->textsz;
kh_foreach(dynablocks->blocks, key, db,
key += dynablocks->base;
if(key>=start && key<end)
direct[key-start] = db;
else {
k = kh_put(dynablocks, blocks, key-dynablocks->base, &ret);
if(ret) { // don't try to insert if already done...
kh_value(blocks, k) = db;
}
}
);
// destroy old and do the swap (should swap before destroy, but hash access is always behind mutex)
kh_destroy(dynablocks, dynablocks->blocks);
dynablocks->blocks = NULL;
dynablocks->direct = direct;
// unlock
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
// move the one that doesn't fit to other dynablocks
// first check if everything can be moved
int ok = 1;
kh_foreach(blocks, key, db,
key += dynablocks->base;
dynablocklist_t *newdbs = getDBFromAddress(key); // will crash if no dynablocks is found
if(!newdbs)
ok = 0;
else {
if(newdbs->direct) {
if(newdbs->direct[key-newdbs->text])
ok = 0;
} else {
khint_t k;
pthread_rwlock_rdlock(&newdbs->rwlock_blocks);
k = kh_get(dynablocks, newdbs->blocks, key-newdbs->base);
if(k!=kh_end(newdbs->blocks))
ok = 0;
pthread_rwlock_unlock(&newdbs->rwlock_blocks);
}
}
);
if(ok) {
kh_foreach(blocks, key, db,
key += dynablocks->base;
dynablocklist_t *newdbs = getDBFromAddress(key); // will crash if no dynablocks is found
if(newdbs->direct) {
newdbs->direct[key-newdbs->text] = db;
} else {
khint_t k;
int ret;
pthread_rwlock_wrlock(&newdbs->rwlock_blocks);
k = kh_put(dynablocks, newdbs->blocks, key-newdbs->base, &ret);
kh_value(newdbs->blocks, k) = db;
pthread_rwlock_unlock(&newdbs->rwlock_blocks);
}
);
kh_destroy(dynablocks, blocks);
} else {
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
dynablocks->blocks = blocks;
dynarec_log(LOG_DEBUG, "Cannot convert dynablocks(%p) to pure direct\n", (void*)dynablocks->text);
}
}
// a block is 4096 byte, so get a low magic size or no block will get "direct" treatment
#define MAGIC_SIZE 8
#define MAGIC_SIZE2 16
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created)
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynblock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
return NULL;
}
khint_t k;
int ret;
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 && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
@@ -525,65 +321,25 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
}
}
if(dynablocks->blocks) {
pthread_rwlock_rdlock(&dynablocks->rwlock_blocks);
// check again, in case it's been converted to direct in another thread
if(dynablocks->blocks) {
// check if the block exist
khint_t k;
k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
if(k!=kh_end(dynablocks->blocks)) {
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
*created = 0;
return block;
}
}
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
}
if (!*created)
return block;
// Lock as write now!
if(dynablocks->blocks)
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
if(!dynablocks->direct)
dynablocks->direct = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text] = (dynablock_t*)calloc(1, sizeof(dynablock_t));
} else {
if(dynablocks->textsz && ((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz)))) {
if(dynablocks->blocks)
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
//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, with_marks, created);
}
k = kh_put(dynablocks, dynablocks->blocks, addr-dynablocks->base, &ret);
if(!ret) {
// Ooops, block is already there? retreive it and bail out
dynarec_log(LOG_DUMP, "Block already exist in Hash Map\n");
block = kh_value(dynablocks->blocks, k);
if(dynablocks->blocks)
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
*created = 0;
return block;
}
block = kh_value(dynablocks->blocks, k) = (dynablock_t*)calloc(1, sizeof(dynablock_t));
// check if size of hash map == magic size, if yes, convert to direct before unlocking
if(!dynablocks->direct && dynablocks->textsz && kh_size(dynablocks->blocks)>=MAGIC_SIZE && kh_size(dynablocks->blocks)<(MAGIC_SIZE2))
ConvertHash2Direct(dynablocks);
}
block->parent = dynablocks;
// add mark if needed
if(with_marks)
block->marks = kh_init(mark);
// create an empty block first, so if other thread want to execute the same block, they can, but using interpretor path
if(dynablocks->blocks)
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
if(tmp != block) {
// a block appeard!
free(block);
*created = 0;
return tmp;
}
block->parent = dynablocks;
*created = 1;
return block;
@@ -593,68 +349,114 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int wi
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, int create, dynablock_t* current)
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(!(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
else if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))) {
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
}
}
// nope, lets do the long way
if(!dynablocks)
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz)))
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, (dynablocks->nolinker)&&(dynablocks->direct), &created);
if(!created || !create)
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
if(box86_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
// fill the block
block->x86_addr = (void*)addr;
FillBlock(block);
if(!FillBlock(block, filladdr)) {
void* old = (void*)arm_lock_xchg(&dynablocks->direct[addr-dynablocks->text], 0);
if(old!=block) {// put it back in place, strange things are happening here!
dynarec_log(LOG_NONE, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
arm_lock_xchg(&dynablocks->direct[addr-dynablocks->text], (uintptr_t)old);
}
free(block);
block = NULL;
}
if(box86_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
// check 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;
}
}
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, %swith %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+block->x86_size), block->block, block->size, block->marks?"with Marks, ":"", block->sons_size);
if(block->parent->nolinker)
protectDB((uintptr_t)block->x86_addr, block->x86_size);
}
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);
return block;
}
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
{
dynablock_t *db = internalDBGetBlock(emu, addr, create, *current);
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current);
if(db && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = father->nolinker?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)%s with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->marks?" with Mark,":"", father->sons_size);
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size);
// 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);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, create, *current);
db = internalDBGetBlock(emu, addr, addr, create, *current);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
if(father->nolinker)
protectDB((uintptr_t)father->x86_addr, father->x86_size);
}
}
return db;
}
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);
if(db && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *father = db->father?db->father:db;
uint32_t hash = father->nolinker?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)\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size);
// Free father, it's now invalid!
FreeDynablock(father);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL);
} else {
father->need_test = 0;
if(father->nolinker)
protectDB((uintptr_t)father->x86_addr, father->x86_size);
}
}
return db;
+14 -12
View File
@@ -2,36 +2,38 @@
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
typedef struct kh_mark_s kh_mark_t;
typedef struct instsize_s {
unsigned int x86:4;
unsigned int nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
kh_mark_t* marks; // List of blocks that marked this block
void* block;
int size;
void* x86_addr;
int x86_size;
uintptr_t x86_size;
uint32_t hash;
int need_test;
uintptr_t* table;
int tablesz;
int done;
uint8_t need_test;
uint8_t done;
uint8_t gone;
uint8_t nolinker;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
int nolinker;
instsize_t* instsize;
} dynablock_t;
typedef struct dynablocklist_s {
kh_dynablocks_t *blocks;
pthread_rwlock_t rwlock_blocks;
uintptr_t base;
uintptr_t text;
int textsz;
int nolinker; // in case this dynablock can disapear (also, block memory are allocated with a temporary scheme)
dynablock_t **direct; // direct mapping (waste of space, so not always there)
int maxsz; // maxblock size (for this block or previous block)
int nolinker; // in case this dynablock can be deleted
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+43 -18
View File
@@ -56,18 +56,15 @@ void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
dynablock_t* current = (dynablock_t*)table[2];
if(current->father)
current = current->father;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!current) { // current has been invalidated, stop running it...
//dynarec_log(LOG_DEBUG, "--- Current invalidated while linking.\n");
return arm_epilog_fast;
}
if(table[3]) {
//dynarec_log(LOG_DEBUG, "--- Remove mark from %p (%p)\n", current, table[3]);
RemoveMark(table);
}
if(!block) {
// no block, don't try again, ever
tableupdate(arm_epilog, addr, table);
// no block, let link table as is...
//tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
if(!block->done) {
@@ -75,20 +72,40 @@ void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
//tableupdate(arm_linker, addr, table);
return arm_epilog_fast;
}
if(!block->block) {
if(!(jblock=block->block)) {
// null block, but done: go to epilog, no linker here
tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
dynablock_t *father = block->father?block->father:block;
if(!block->parent->nolinker || (current && father->marks)) {
//dynablock_t *father = block->father?block->father:block;
if(!block->parent->nolinker) {
//dynarec_log(LOG_DEBUG, "--- Linking %p/%p to %p (table=%p[%p/%p/%p/%p])\n", block, block->block, current, table, table[0], table[1], table[2], table[3]);
// only update block if linker is allowed or if marks is possibe
if(current && father->marks && current!=father)
AddMark(current, father, table);
tableupdate(block->block, addr, table);
// only update block if linker is allowed
tableupdate(jblock, addr, table);
}
return block->block;
return jblock;
}
void* LinkNext(x86emu_t* emu, uintptr_t addr)
{
dynablock_t* current = NULL;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
}
if(!block->done) {
// not finished yet... leave linker
//tableupdate(arm_linker, addr, table);
return arm_epilog;
}
if(!(jblock=block->block)) {
// null block, but done: go to epilog, no linker here
return arm_epilog;
}
//dynablock_t *father = block->father?block->father:block;
return jblock;
}
#endif
@@ -103,7 +120,10 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
setjmp((struct __jmp_buf_tag*)ejb->jmpbuf);
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP; // not sure if it should still be inside DynaCall!
}
}
}
#ifdef DYNAREC
@@ -149,7 +169,10 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
setjmp((struct __jmp_buf_tag*)ejb->jmpbuf);
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP;
}
}
}
}
@@ -183,7 +206,8 @@ int DynaRun(x86emu_t* emu)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
setjmp((struct __jmp_buf_tag*)ejb->jmpbuf);
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
#ifdef DYNAREC
@@ -219,7 +243,8 @@ int DynaRun(x86emu_t* emu)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
setjmp((struct __jmp_buf_tag*)ejb->jmpbuf);
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
}
+183 -12
View File
@@ -6,6 +6,7 @@
#include "debug.h"
#include "box86context.h"
#include "custommem.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
@@ -19,6 +20,7 @@
#include "dynablock_private.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
#include "elfloader.h"
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name) {
@@ -81,9 +83,9 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
}
return best;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
#define PK(A) (*((uint8_t*)(addr+(A))))
if(!n)
return 1;
if(PK(0)==0x90)
@@ -109,7 +111,122 @@ int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
if(n>7 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x84 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00 && PK(7)==0x00)
return is_nops(dyn, addr+8, n-8);
return 0;
#undef PK
}
// return size of next instuciton, -1 is unknown
// not all instrction are setup
int next_instruction(dynarec_arm_t *dyn, uintptr_t addr)
{
uint8_t opcode = PK(0);
uint8_t nextop;
switch (opcode) {
case 0x66:
opcode = PK(1);
switch(opcode) {
case 0x90:
return 2;
}
break;
case 0x81:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 4;
case 0x83:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr + 1;
case 0x84:
case 0x85:
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
nextop = PK(1);
return fakeed(dyn, addr+2, 0, nextop)-addr;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5A:
case 0x5B:
case 0x5C:
case 0x5D:
case 0x5E:
case 0x5F:
case 0x90:
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9B:
case 0x9C:
case 0x9D:
case 0x9E:
case 0x9F:
return 1;
case 0xA0:
case 0xA1:
case 0xA2:
case 0xA3:
return 5;
case 0xB0:
case 0xB1:
case 0xB2:
case 0xB3:
case 0xB4:
case 0xB5:
case 0xB6:
case 0xB7:
return 2;
case 0xB8:
case 0xB9:
case 0xBA:
case 0xBB:
case 0xBC:
case 0xBD:
case 0xBE:
case 0xBF:
return 5;
case 0xFF:
nextop = PK(1);
switch((nextop>>3)&7) {
case 0: // INC Ed
case 1: //DEC Ed
case 2: // CALL Ed
case 4: // JMP Ed
case 6: // Push Ed
return fakeed(dyn, addr+2, 0, nextop)-addr;
}
break;
default:
break;
}
return -1;
}
#undef PK
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
int i = 0;
while(i<n) {
int j=next_instruction(dyn, addr+i);
if(j<=0) return 0;
i+=j;
}
return (i==n)?1:0;
}
uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
@@ -159,14 +276,42 @@ uint32_t needed_flags(dynarec_arm_t *dyn, int ninst, uint32_t setf, int recurse)
return needed;
}
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
{
// x86 instruction is <16 bytes
int toadd;
if(x86_size>arm_size)
toadd = 1 + x86_size/15;
else
toadd = 1 + arm_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
}
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)
insts[*size].nat = 15;
else
insts[*size].nat = arm_size;
arm_size -= insts[*size].nat;
++(*size);
--toadd;
}
return insts;
}
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void* FillBlock(dynablock_t* block) {
void* FillBlock(dynablock_t* block, uintptr_t addr) {
// init the helper
uintptr_t addr = (uintptr_t)block->x86_addr;
dynarec_arm_t helper = {0};
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
helper.start = addr;
@@ -212,11 +357,12 @@ void* FillBlock(dynablock_t* block) {
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(sz, block->parent->nolinker);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
return (void*)block;
return NULL;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
@@ -235,9 +381,32 @@ void* FillBlock(dynablock_t* block) {
}
helper.arm_size = 0;
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);}
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);
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) {
printf_log(LOG_NONE, "%p:", dump);
for(; dump<(uint8_t*)helper.insts[i+1].x86.addr; ++dump)
printf_log(LOG_NONE, " %02X", *dump);
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*)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
free(helper.insts);
free(helper.next);
block->table = helper.table;
@@ -249,7 +418,7 @@ void* FillBlock(dynablock_t* block) {
block->block = p;
block->nolinker = helper.nolinker;
block->need_test = 0;
block->x86_addr = (void*)start;
//block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
@@ -261,8 +430,8 @@ void* FillBlock(dynablock_t* block) {
sons = (dynablock_t**)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], 0, &created);
if(created) { // avoid breaking a working block! also, block could be outside this parent...
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
if(created || !son->parent) { // avoid breaking a working block! also, block could be outside this parent...
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i];
@@ -270,6 +439,8 @@ void* FillBlock(dynablock_t* block) {
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
@@ -278,8 +449,8 @@ void* FillBlock(dynablock_t* block) {
} else
free(sons);
}
if(block->parent->nolinker)
protectDB((uintptr_t)block->x86_addr, block->x86_size);
free(helper.sons_x86);
free(helper.sons_arm);
block->done = 1;
return (void*)block;
}
File diff suppressed because it is too large. Load diff
+276 -216
View File
@@ -80,6 +80,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#endif
switch(opcode) {
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
@@ -340,7 +341,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d0 = v0;
else
d0 = fpu_get_scratch_double(dyn);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VCVTR_S32_F32(d0*2, d1*2);
VCVTR_S32_F32(d0*2+1, d1*2+1);
if(v0>=16) {
@@ -446,107 +447,93 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x40:
INST_NAME("CMOVO Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cEQ, cNE, X_OF)
break;
case 0x41:
INST_NAME("CMOVNO Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cNE, cEQ, X_OF)
break;
case 0x42:
INST_NAME("CMOVC Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cEQ, cNE, X_CF)
break;
case 0x43:
INST_NAME("CMOVNC Gd, Ed");
GO( LDR_IMM9(2, 0, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(2, 1)
, cEQ, cNE, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cNE, cEQ, X_CF)
break;
case 0x44:
INST_NAME("CMOVZ Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cEQ, cNE, X_ZF)
break;
case 0x45:
INST_NAME("CMOVNZ Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cNE, cEQ, X_ZF)
break;
case 0x46:
INST_NAME("CMOVBE Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cEQ, cNE, X_CF|X_ZF)
break;
case 0x47:
INST_NAME("CMOVNBE Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cNE, cEQ, X_CF|X_ZF)
break;
case 0x48:
INST_NAME("CMOVS Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, x1)
, cNE, cEQ, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cEQ, cNE, X_SF)
break;
case 0x49:
INST_NAME("CMOVNS Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cNE, cEQ, X_SF)
break;
case 0x4A:
INST_NAME("CMOVP Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, x1)
, cNE, cEQ, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cEQ, cNE, X_PF)
break;
case 0x4B:
INST_NAME("CMOVNP Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cNE, cEQ, X_PF)
break;
case 0x4C:
INST_NAME("CMOVL Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cEQ, cNE, X_SF|X_OF)
break;
case 0x4D:
INST_NAME("CMOVGE Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cNE, cEQ, X_SF|X_OF)
break;
case 0x4E:
INST_NAME("CMOVLE Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cEQ, cNE, X_SF|X_OF|X_ZF)
break;
case 0x4F:
INST_NAME("CMOVG Gd, Ed");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cNE, cEQ, X_SF|X_OF|X_ZF)
break;
@@ -1163,107 +1150,93 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x80:
INST_NAME("JO id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cEQ, cNE, X_OF)
break;
case 0x81:
INST_NAME("JNO id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cNE, cEQ, X_OF)
break;
case 0x82:
INST_NAME("JC id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cEQ, cNE, X_CF)
break;
case 0x83:
INST_NAME("JNC id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cNE, cEQ, X_CF)
break;
case 0x84:
INST_NAME("JZ id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cEQ, cNE, X_ZF)
break;
case 0x85:
INST_NAME("JNZ id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cNE, cEQ, X_ZF)
break;
case 0x86:
INST_NAME("JBE id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cEQ, cNE, X_CF|X_ZF)
break;
case 0x87:
INST_NAME("JNBE id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cNE, cEQ, X_CF|X_ZF)
break;
case 0x88:
INST_NAME("JS id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cEQ, cNE, X_SF)
break;
case 0x89:
INST_NAME("JNS id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cNE, cEQ, X_SF)
break;
case 0x8A:
INST_NAME("JP id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cEQ, cNE, X_PF)
break;
case 0x8B:
INST_NAME("JNP id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cNE, cEQ, X_PF)
break;
case 0x8C:
INST_NAME("JL id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cEQ, cNE, X_SF|X_OF)
break;
case 0x8D:
INST_NAME("JGE id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cNE, cEQ, X_SF|X_OF)
break;
case 0x8E:
INST_NAME("JLE id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cEQ, cNE, X_SF|X_OF|X_ZF)
break;
case 0x8F:
INST_NAME("JG id");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cNE, cEQ, X_SF|X_OF|X_ZF)
break;
@@ -1286,107 +1259,93 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x90:
INST_NAME("SETO Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cEQ, cNE, X_OF)
break;
case 0x91:
INST_NAME("SETNO Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cNE, cEQ, X_OF)
break;
case 0x92:
INST_NAME("SETC Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cEQ, cNE, X_CF)
break;
case 0x93:
INST_NAME("SETNC Eb");
GO( LDR_IMM9(2, 0, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(2, 1)
, cEQ, cNE, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cNE, cEQ, X_CF)
break;
case 0x94:
INST_NAME("SETZ Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cEQ, cNE, X_ZF)
break;
case 0x95:
INST_NAME("SETNZ Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cNE, cEQ, X_ZF)
break;
case 0x96:
INST_NAME("SETBE Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cEQ, cNE, X_CF|X_ZF)
break;
case 0x97:
INST_NAME("SETNBE Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cNE, cEQ, X_CF|X_ZF)
break;
case 0x98:
INST_NAME("SETS Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, x1)
, cNE, cEQ, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cEQ, cNE, X_SF)
break;
case 0x99:
INST_NAME("SETNS Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cNE, cEQ, X_SF)
break;
case 0x9A:
INST_NAME("SETP Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, x1)
, cNE, cEQ, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cEQ, cNE, X_PF)
break;
case 0x9B:
INST_NAME("SETNP Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cNE, cEQ, X_PF)
break;
case 0x9C:
INST_NAME("SETL Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cEQ, cNE, X_SF|X_OF)
break;
case 0x9D:
INST_NAME("SETGE Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cNE, cEQ, X_SF|X_OF)
break;
case 0x9E:
INST_NAME("SETLE Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cEQ, cNE, X_SF|X_OF|X_ZF)
break;
case 0x9F:
INST_NAME("SETG Eb");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cNE, cEQ, X_SF|X_OF|X_ZF)
break;
@@ -1396,24 +1355,24 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PUSH FS");
MOVW(x1, offsetof(x86emu_t, segs[_FS]));
LDRH_REG(x2, xEmu, x1);
PUSH(xESP, 1<<x2);
PUSH1(x2);
break;
case 0xA1:
INST_NAME("POP FS");
MOVW(x1, offsetof(x86emu_t, segs[_FS]));
POP(xESP, 1<<x2);
POP1(x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_FS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_FS]));
break;
case 0xA2:
INST_NAME("CPUID");
MOV_REG(x1, xEAX);
MOV32(x12, ip+2); // EIP is useless, but why not...
MOV32(x14, ip+2); // EIP is useless, but why not...
// not purging stuff like x87 here, there is no float math or anything
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
CALL_(my_cpuid, -1, 0);
LDM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|(1<<12));
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
CALL_S(my_cpuid, -1, 0);
LDM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
break;
case 0xA3:
INST_NAME("BT Ed, Gd");
@@ -1431,25 +1390,25 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x1, ed, x2);
AND_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
break;
case 0xA4:
nextop = F8;
INST_NAME("SHLD Ed, Gd, Ib");
SETFLAGS(X_ALL, SF_SET);
GETED;
GETGD;
u8 = F8;
emit_shld32c(dyn, ninst, ed, gd, u8&0x1f, x3, x14);
WBACK;
break;
case 0xA5:
nextop = F8;
if(opcode==0xA4) {
INST_NAME("SHLD Ed, Gd, Ib");
} else {
INST_NAME("SHLD Ed, Gd, CL");
UXTB(x3, xECX, 0);
}
INST_NAME("SHLD Ed, Gd, CL");
UXTB(x3, xECX, 0);
SETFLAGS(X_ALL, SF_SET);
GETEDW(x12, x1);
GETEDW(x14, x1);
GETGD;
if(opcode==0xA4) {
u8 = F8;
MOVW(x3, u8);
}
MOV_REG(x2, gd);
CALL(shld32, ed, (wback?(1<<wback):0));
WBACK;
@@ -1459,15 +1418,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PUSH GS");
MOVW(x1, offsetof(x86emu_t, segs[_GS]));
LDRH_REG(x2, xEmu, x1);
PUSH(xESP, 1<<x2);
PUSH1(x2);
break;
case 0xA9:
INST_NAME("POP GS");
MOVW(x1, offsetof(x86emu_t, segs[_GS]));
POP(xESP, 1<<x2);
POP1(x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_GS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_GS]));
break;
case 0xAB:
@@ -1487,32 +1446,33 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_NEXT(cNE); // bit already set, jump to next instruction
MOVW(x12, 1);
ORR_REG_LSL_REG(ed, ed, x12, x2);
MOVW(x14, 1);
ORR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
break;
case 0xAC:
nextop = F8;
INST_NAME("SHRD Ed, Gd, Ib");
SETFLAGS(X_ALL, SF_SET);
GETED;
GETGD;
u8 = F8;
emit_shrd32c(dyn, ninst, ed, gd, u8, x3, x14);
WBACK;
break;
case 0xAD:
nextop = F8;
if(opcode==0xAC) {
INST_NAME("SHRD Ed, Gd, Ib");
} else {
INST_NAME("SHRD Ed, Gd, CL");
UXTB(x3, xECX, 0);
}
INST_NAME("SHRD Ed, Gd, CL");
SETFLAGS(X_ALL, SF_SET);
GETEDW(x12, x1);
UXTB(x3, xECX, 0);
GETEDW(x14, x1);
GETGD;
if(opcode==0xAC) {
u8 = F8;
MOVW(x3, u8);
}
MOV_REG(x2, gd);
CALL(shrd32, ed, (wback?(1<<wback):0));
WBACK;
@@ -1563,8 +1523,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0);
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, mxcsr));
STR_IMM9(x12, ed, fixedaddress);
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, mxcsr));
STR_IMM9(x14, ed, fixedaddress);
}
break;
default:
@@ -1604,11 +1564,10 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK;
// AL != Eb
BFI(xEAX, ed, 0, 8);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
BFC(xFlags, F_ZF, 1);
MARK3;
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
break;
case 0xB1:
INST_NAME("CMPXCHG Ed, Gd");
@@ -1622,11 +1581,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(x3, ed);
MOV_REG(ed, gd);
WBACK;
emit_cmp32(dyn, ninst, xEAX, x3, x1, x12);
emit_cmp32(dyn, ninst, xEAX, x3, x1, x14);
B_MARK3(c__); // not next, in case its called with a LOCK prefix
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);
MOV_REG(xEAX, ed);
MARK3
break;
@@ -1647,12 +1606,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = x1;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
@@ -1708,8 +1667,38 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG_LSR_IMM5(x1, ed, u8);
ed = x1;
}
AND_IMM8(x1, ed, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, ed, F_CF, 1);
break;
case 5:
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
u8 = F8;
MOVW(gd, u8);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cNE); // bit already set, jump to next instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
MARK3;
break;
case 6:
INST_NAME("BTR Ed, Ib");
@@ -1731,12 +1720,42 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to next instruction
//MOVW(x12, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x12, x2);
//MOVW(x14, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
MARK3;
break;
case 7:
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0);
u8 = F8;
MOVW(gd, u8);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
MOVW_COND(cEQ, x14, 1); // may already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
@@ -1763,11 +1782,10 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
AND_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
MOV_REG_LSR_REG(x14, ed, x2);
BFI(xFlags, x14, F_CF, 1);
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STR_IMM9(ed, wback, fixedaddress);
}
@@ -1785,9 +1803,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CLZ(gd, x1); // x2 gets leading 0 == BSF
MOVW(x1, 0); //ZF not set
MARK;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBD:
INST_NAME("BSR Gd, Ed");
@@ -1802,9 +1819,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
RSB_IMM8(gd, gd, 31); // complement
MOVW(x1, 0); //ZF not set
MARK;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBE:
INST_NAME("MOVSX Gd, Eb");
@@ -1839,8 +1855,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEB(x2);
GETGB(x1);
BFI(gb1, ed, gb2*8, 8); // gb <- eb
emit_add8(dyn, ninst, ed, gd, x12, x3, 1);
ADD_REG_LSL_IMM5(x12, ed, gd, 0);
emit_add8(dyn, ninst, ed, gd, x14, x3, 1);
ADD_REG_LSL_IMM5(x14, ed, gd, 0);
EBBACK;
break;
case 0xC1:
@@ -1854,7 +1870,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
}
emit_add32(dyn, ninst, ed, gd, x3, x12);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0xC2:
@@ -1989,7 +2005,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(xEDX, x2);
MOVW(x1, 0);
MARK3;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
BFI(xFlags, x1, F_ZF, 1);
break;
case 0xC8:
case 0xC9:
@@ -2096,7 +2112,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQSUB_U16(d0, d0, d1);
break;
case 0xDA:
INST_NAME("PMINUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMIN_U8(d0, d0, d1);
break;
case 0xDB:
INST_NAME("PAND Gm, Em");
nextop = F8;
@@ -2118,7 +2140,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQADD_U16(d0, d0, d1);
break;
case 0xDE:
INST_NAME("PMAXUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VMAX_U8(d0, d0, d1);
break;
case 0xDF:
INST_NAME("PANDN Gm, Em");
nextop = F8;
@@ -2133,7 +2161,39 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(v1);
VRHADD_U8(v0, v0, v1);
break;
case 0xE1:
INST_NAME("PSRAW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, d1);
VMOVD(v0+1, d1);
VQMOVN_S64(v0, v0); // 2*d1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*d1 in 16bits now
VNEGN_16(v0, v0); // because we want SHR and not SHL
VSHL_S16(d0, d0, v0);
break;
case 0xE2:
INST_NAME("PSRAD Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, d1);
VMOVD(v0+1, d1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VNEGN_32(v0, v0); // because we want SHR and not SHL
VSHL_S32(d0, d0, v0);
break;
case 0xE3:
INST_NAME("PAVGW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
VRHADD_U16(d0, d0, d1);
break;
case 0xE4:
INST_NAME("PMULHUW Gm,Em");
nextop = F8;
@@ -2210,7 +2270,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VQADD_S16(d0, d0, d1);
break;
case 0xEE:
INST_NAME("PMAXPS Gm, Em");
INST_NAME("PMAXSW Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1);
+85 -37
View File
@@ -34,44 +34,45 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(j32);
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_add32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_add32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x2B:
INST_NAME("SUB Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_sub32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_sub32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_xor32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_xor32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x67:
@@ -81,7 +82,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
@@ -90,33 +91,33 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x12, ed);
STRH_REG(gd, x14, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, x1, x12, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x1, x14, 0);
}
break;
@@ -144,7 +145,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
@@ -152,8 +153,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
@@ -167,43 +168,54 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x12, 0);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ed");
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7))));
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, ed, x12, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
break;
case 0xA0:
INST_NAME("MOV AL, FS:Id");
grab_fsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
LDRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Id");
grab_fsdata(dyn, addr, ninst, x1);
@@ -215,7 +227,17 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDR_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA2:
INST_NAME("MOV FS:Od, AL");
grab_fsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
STRB_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
STRB_REG_LSL_IMM5(xEAX, x1, x2, 0);
}
break;
case 0xA3:
INST_NAME("MOV FS:Od, EAX");
grab_fsdata(dyn, addr, ninst, x1);
@@ -230,7 +252,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
@@ -240,7 +262,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x12, 0);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
@@ -252,16 +274,42 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].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
}
if((nextop&0xC0)==0xC0) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
}
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->nolinker && (!dyn->insts || ninst!=dyn->size-1)) {
PASS2(cstack_push(dyn, ninst, addr, dyn->insts[ninst+1].address, x1, x2);)
} else {
PASS2(cstack_push(dyn, ninst, 0, 0, x1, x2);)
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
}
PUSH1(x2);
jump_to_linker(dyn, 0, xEIP, ninst); // smart linker
break;
case 6: // Push Ed
INST_NAME("PUSH FS:Ed");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
+115 -26
View File
@@ -28,88 +28,177 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
uint8_t wback, wb1, wb2;
uint8_t u8;
int fixedaddress;
MAYUSE(j32);
MAYUSE(wback);
MAYUSE(wb2);
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_add32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_add32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x2B:
INST_NAME("SUB Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_sub32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_sub32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x33:
INST_NAME("XOR Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_xor32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_xor32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
emit_cmp32(dyn, ninst, gd, ed, x3, x12);
GETEDO(x14);
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x80:
case 0x82:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 1: //OR
INST_NAME("OR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 2: //ADC
INST_NAME("ADC GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 3: //SBB
INST_NAME("SBB GS:Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 4: //AND
INST_NAME("AND GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 5: //SUB
INST_NAME("SUB GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 6: //XOR
INST_NAME("XOR GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x14);
EBBACK;
break;
case 7: //CMP
INST_NAME("CMP GS:Eb, Ib");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x1);
GETEBO(x1);
u8 = F8;
if(u8) {
MOVW(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x14);
}
break;
}
break;
case 0x89:
INST_NAME("MOV GS:Ed, Gd");
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STR_REG_LSL_IMM5(gd, ed, x12, 0);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
case 0x8B:
INST_NAME("MOV Gd, GS:Ed");
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
case 0x8F:
INST_NAME("POP GS:Ed");
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7))));
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, ed, x12, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
break;
@@ -137,7 +226,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
@@ -147,7 +236,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x12, 0);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
@@ -159,7 +248,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
grab_tlsdata(dyn, addr, ninst, x12);
grab_tlsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH GS:Ed");
@@ -167,8 +256,8 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
+105 -82
View File
@@ -47,7 +47,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_add16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_add16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x03:
@@ -56,7 +56,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_add16(dyn, ninst, x1, x2, x3, x12, 0);
emit_add16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x05:
@@ -64,7 +64,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_add16c(dyn, ninst, x1, i32, x3, x12);
emit_add16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x06:
@@ -83,7 +83,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRH_IMM8(x2, x1, 0);
ADD_IMM8(xESP, xESP, 2);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_ES]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_ES]));
break;
case 0x09:
@@ -92,7 +92,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_or16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_or16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x0B:
@@ -101,7 +101,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_or16(dyn, ninst, x1, x2, x12, x3, 0);
emit_or16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
case 0x0D:
@@ -109,7 +109,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_or16c(dyn, ninst, x1, i32, x3, x12);
emit_or16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -123,7 +123,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_adc16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_adc16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x13:
@@ -133,7 +133,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_adc16(dyn, ninst, x1, x2, x12, x3, 0);
emit_adc16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
case 0x15:
@@ -142,7 +142,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_adc16c(dyn, ninst, x1, i32, x3, x12);
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -153,7 +153,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_sbb16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x1B:
@@ -163,7 +163,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_sbb16(dyn, ninst, x1, x2, x12, x3, 0);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
case 0x1D:
@@ -172,7 +172,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i16 = F16;
UXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i16, x3, x12);
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -182,7 +182,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_and16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_and16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x23:
@@ -191,7 +191,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_and16(dyn, ninst, x1, x2, x3, x12, 0);
emit_and16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x25:
@@ -199,7 +199,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_and16c(dyn, ninst, x1, i32, x3, x12);
emit_and16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x26:
@@ -213,7 +213,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_sub16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_sub16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x2B:
@@ -222,7 +222,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_sub16(dyn, ninst, x1, x2, x3, x12, 0);
emit_sub16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x2D:
@@ -230,7 +230,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_sub16c(dyn, ninst, x1, i32, x3, x12);
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -240,7 +240,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_xor16(dyn, ninst, x1, x2, x12, x3, (wb1 && (wback==x3))?1:0);
emit_xor16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
case 0x33:
@@ -249,7 +249,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_xor16(dyn, ninst, x1, x2, x3, x12, 0);
emit_xor16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x35:
@@ -257,7 +257,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
i32 = F16;
UXTH(x1, xEAX, 0);
emit_xor16c(dyn, ninst, x1, i32, x3, x12);
emit_xor16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -267,7 +267,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x2);
GETEW(x1);
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
@@ -275,7 +275,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGW(x1);
GETEW(x2);
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
@@ -283,7 +283,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F16;
MOVW(x2, i32);
UXTH(x1, xEAX, 0);
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0x40:
@@ -298,7 +298,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_inc16(dyn, ninst, x1, x3, x12);
emit_inc16(dyn, ninst, x1, x3, x14);
BFI(gd, x1, 0, 16);
break;
case 0x48:
@@ -313,7 +313,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_dec16(dyn, ninst, x1, x3, x12);
emit_dec16(dyn, ninst, x1, x3, x14);
BFI(gd, x1, 0, 16);
break;
case 0x50:
@@ -325,8 +325,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x56:
case 0x57:
INST_NAME("PUSH Reg16");
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(xEAX+(opcode&7), xESP, 0); //TODO: use a single STRH pre-decrement instruction
PUSH16(xEAX+(opcode&7), xESP);
break;
case 0x58:
case 0x59:
@@ -337,17 +336,45 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x5E:
case 0x5F:
INST_NAME("POP Reg16");
LDRH_IMM8(x1, xESP, 0); //TODO: use a single LDRH post-increment instruction
POP16(x1, xESP);
BFI(xEAX+(opcode&7), x1, 0, 16);
ADD_IMM8(xESP, xESP, 2);
break;
case 0x60:
INST_NAME("PUSHA");
MOV_REG(x1, xESP);
PUSH16(xEAX, xESP);
PUSH16(xECX, xESP);
PUSH16(xEDX, xESP);
PUSH16(xEBX, xESP);
PUSH16(x1, xESP);
PUSH16(xEBP, xESP);
PUSH16(xESI, xESP);
PUSH16(xEDI, xESP);
break;
case 0x61:
INST_NAME("POPA");
POP16(x1, xESP);
BFI(xEDI, x1, 0, 16);
POP16(x1, xESP);
BFI(xESI, x1, 0, 16);
POP16(x1, xESP);
BFI(xEBP, x1, 0, 16);
ADD_IMM8(xESP, xESP, 2); //POP16(xESP, xESP);
POP16(x1, xESP);
BFI(xEBX, x1, 0, 16);
POP16(x1, xESP);
BFI(xEDX, x1, 0, 16);
POP16(x1, xESP);
BFI(xECX, x1, 0, 16);
POP16(x1, xESP);
BFI(xEAX, x1, 0, 16);
break;
case 0x68:
INST_NAME("PUSH Iw");
u16 = F16;
MOVW(x2, u16);
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(x2, xESP, 0);
PUSH16(x2, xESP);
break;
case 0x69:
INST_NAME("IMUL Gw,Ew,Iw");
@@ -365,8 +392,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PUSH Ib");
i16 = F8S;
MOVW(x2, i16);
SUB_IMM8(xESP, xESP, 2);
STRH_IMM8(x2, xESP, 0);
PUSH16(x2, xESP);
break;
case 0x6B:
INST_NAME("IMUL Gw,Ew,Ib");
@@ -394,7 +420,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_add16c(dyn, ninst, ed, i16, x2, x12);
emit_add16c(dyn, ninst, ed, i16, x2, x14);
EWBACK;
break;
case 1: //OR
@@ -402,7 +428,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_or16c(dyn, ninst, x1, i16, x2, x12);
emit_or16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 2: //ADC
@@ -411,7 +437,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_adc16c(dyn, ninst, x1, i16, x2, x12);
emit_adc16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 3: //SBB
@@ -420,7 +446,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_sbb16c(dyn, ninst, x1, i16, x2, x12);
emit_sbb16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 4: //AND
@@ -428,7 +454,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_and16c(dyn, ninst, x1, i16, x2, x12);
emit_and16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 5: //SUB
@@ -436,7 +462,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_sub16c(dyn, ninst, x1, i16, x2, x12);
emit_sub16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 6: //XOR
@@ -444,7 +470,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
emit_xor16c(dyn, ninst, x1, i16, x2, x12);
emit_xor16c(dyn, ninst, x1, i16, x2, x14);
EWBACK;
break;
case 7: //CMP
@@ -454,9 +480,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOVW(x2, i16);
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
} else
emit_cmp16_0(dyn, ninst, x1, x3, x12);
emit_cmp16_0(dyn, ninst, x1, x3, x14);
break;
}
break;
@@ -467,7 +493,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETEW(x1);
GETGW(x2);
emit_test16(dyn, ninst, x1, x2, x3, x12);
emit_test16(dyn, ninst, x1, x2, x3, x14);
break;
case 0x89:
@@ -527,7 +553,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRH_REG(x1, xEmu, x2);
}
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[(nextop&0x38)>>3]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[(nextop&0x38)>>3]));
break;
case 0x90:
@@ -554,23 +580,24 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x99:
INST_NAME("CWD");
SXTH(x1, xEAX, 0);
BFI(xEDX, x1, 16, 16);
MOV_REG_LSR_IMM5(x1, x1, 16);
BFI(xEDX, x1, 0, 16);
break;
case 0x9C:
INST_NAME("PUSHF (16b)");
READFLAGS(X_ALL);
CALL(PackFlags, -1, 0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, packed_eflags.x32));
STRHB_IMM8(x1, xESP, -2);
STRHB_IMM8(xFlags, xESP, -2);
break;
case 0x9D:
INST_NAME("POPF (16b)");
SETFLAGS(X_ALL, SF_SET); // lower 16bits is all flags handled in dynarec
LDRHA_IMM8(x1, xESP, 2);
CALL(arm_popf16, -1, 0);
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
LDRHA_IMM8(x2, xESP, 2);
MOV32(x1, 0x7FD7);
AND_REG_LSL_IMM5(x2, x2, x1, 0);
ORR_IMM8(x2, x2, 2, 0);
BFI(xFlags, x2, 0, 16);
SET_DFNONE(x1);
break;
case 0xA1:
@@ -607,7 +634,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u16 = F16;
MOVW(x2, u16);
UBFX(x1, xEAX, 0, 16);
emit_test16(dyn, ninst, x1, x2, x3, x12);
emit_test16(dyn, ninst, x1, x2, x3, x14);
break;
case 0xAB:
@@ -792,15 +819,15 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOVW(x12, 1);
MOVW(x14, 1);
} else {
INST_NAME("SHL Ew, CL");
AND_IMM8(x12, xECX, 0x1f);
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
UFLAG_OP12(ed, x12)
MOV_REG_LSL_REG(ed, ed, x12);
UFLAG_OP12(ed, x14)
MOV_REG_LSL_REG(ed, ed, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
@@ -808,15 +835,15 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOVW(x12, 1);
MOVW(x14, 1);
} else {
INST_NAME("SHR Ew, CL");
AND_IMM8(x12, xECX, 0x1f);
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
UFLAG_OP12(ed, x12)
MOV_REG_LSR_REG(ed, ed, x12);
UFLAG_OP12(ed, x14)
MOV_REG_LSR_REG(ed, ed, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
@@ -824,15 +851,15 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOVW(x12, 1);
MOVW(x14, 1);
} else {
INST_NAME("SAR Ew, CL");
AND_IMM8(x12, xECX, 0x1f);
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1);
UFLAG_OP12(ed, x12)
MOV_REG_ASR_REG(ed, ed, x12);
UFLAG_OP12(ed, x14)
MOV_REG_ASR_REG(ed, ed, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
@@ -890,7 +917,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK2;
SUB_IMM8(xECX, xECX, 1);
MARK3;
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
case 0xAB:
@@ -926,7 +953,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK2;
SUB_IMM8(xECX, xECX, 1);
MARK3;
emit_cmp16(dyn, ninst, x1, x2, x3, x12);
emit_cmp16(dyn, ninst, x1, x2, x3, x14);
break;
default:
DEFAULT;
@@ -943,7 +970,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEW(x1);
u16 = F16;
MOVW(x2, u16);
emit_test16(dyn, ninst, x1, x2, x3, x12);
emit_test16(dyn, ninst, x1, x2, x3, x14);
break;
case 2:
INST_NAME("NOT Ew");
@@ -955,7 +982,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1);
emit_neg16(dyn, ninst, ed, x2, x12);
emit_neg16(dyn, ninst, ed, x2, x14);
EWBACK;
break;
case 4:
@@ -1000,23 +1027,19 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
} else {
MOVW(x1, 0);
}
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
SET_DFNONE(x1);
}
BFC(xFlags, F_CF, 1);
break;
case 0xF9:
INST_NAME("STC");
i32 = dyn->state_flags; //TODO: find a better way to do this
SETFLAGS(X_CF, SF_SUBSET);
if(i32!=SF_SET) {
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(x1);
}
MOVW(x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
break;
case 0xFF:
@@ -1026,14 +1049,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEW(x1);
emit_inc16(dyn, ninst, x1, x2, x12);
emit_inc16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SET);
GETEW(x1);
emit_dec16(dyn, ninst, x1, x2, x12);
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
default:
+167 -71
View File
@@ -107,8 +107,16 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
}
break;
case 0x13:
INST_NAME("MOVLPD Eq, Gx");
@@ -172,7 +180,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVfrV_D(x2, x3, v0+1);
VMOVtoV_D(v0+1,x2, x3);
}
break;
case 0x17:
@@ -334,6 +342,52 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VSUBQ_16(q0, q0, v1);
break;
case 0x08:
INST_NAME("PSIGNB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_8(v0, q0); // get NEG
VCLTQ_0_8(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_8(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x09:
INST_NAME("PSIGNW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_16(v0, q0); // get NEG
VCLTQ_0_16(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_16(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0A:
INST_NAME("PSIGND Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1);
v1 = fpu_get_scratch_quad(dyn);
v0 = fpu_get_scratch_quad(dyn);
VNEGNQ_32(v0, q0); // get NEG
VCLTQ_0_32(v1, q1); // calculate mask
VBICQ(q0, q0, v1); // apply not mask on dest
VANDQ(v0, v0, v1); // apply mask on src
VORRQ(q0, q0, v0); // merge
VCEQQ_0_32(v1, q1); // handle case where Ex is 0
VBICQ(q0, q0, v1);
break;
case 0x0B:
INST_NAME("PMULHRSW Gx,Ex");
nextop = F8;
@@ -341,6 +395,31 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q1);
VQRDMULHQ_S16(q0, q0, q1);
break;
case 0x1C:
INST_NAME("PABSB Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S8(q0, q1);
break;
case 0x1D:
INST_NAME("PABSW Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S16(q0, q1);
break;
case 0x1E:
INST_NAME("PABSD Gx,Ex");
nextop = F8;
GETEX(q1);
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S32(q0, q1);
break;
default:
DEFAULT;
}
@@ -386,107 +465,93 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x40:
INST_NAME("CMOVO Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cEQ, cNE, X_OF)
break;
case 0x41:
INST_NAME("CMOVNO Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_OF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_OF)
GO( TSTS_IMM8_ROR(xFlags, 0b10, 0x0b)
, cNE, cEQ, X_OF)
break;
case 0x42:
INST_NAME("CMOVC Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cEQ, cNE, X_CF)
break;
case 0x43:
INST_NAME("CMOVNC Gw, Ew");
GO( LDR_IMM9(2, 0, offsetof(x86emu_t, flags[F_CF]));
CMPS_IMM8(2, 1)
, cEQ, cNE, X_CF)
GO( TSTS_IMM8(xFlags, 1<<F_CF)
, cNE, cEQ, X_CF)
break;
case 0x44:
INST_NAME("CMOVZ Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cEQ, cNE, X_ZF)
break;
case 0x45:
INST_NAME("CMOVNZ Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_ZF)
GO( TSTS_IMM8(xFlags, 1<<F_ZF)
, cNE, cEQ, X_ZF)
break;
case 0x46:
INST_NAME("CMOVBE Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cEQ, cNE, X_CF|X_ZF)
break;
case 0x47:
INST_NAME("CMOVNBE Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORRS_REG_LSL_IMM5(x2, x2, x3, 0);
GO( TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF))
, cNE, cEQ, X_CF|X_ZF)
break;
case 0x48:
INST_NAME("CMOVS Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cEQ, cNE, X_SF)
break;
case 0x49:
INST_NAME("CMOVNS Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_SF)
GO( TSTS_IMM8(xFlags, 1<<F_SF)
, cNE, cEQ, X_SF)
break;
case 0x4A:
INST_NAME("CMOVP Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cNE, cEQ, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cEQ, cNE, X_PF)
break;
case 0x4B:
INST_NAME("CMOVNP Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_PF]));
CMPS_IMM8(x2, 1)
, cEQ, cNE, X_PF)
GO( TSTS_IMM8(xFlags, 1<<F_PF)
, cNE, cEQ, X_PF)
break;
case 0x4C:
INST_NAME("CMOVL Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cEQ, cNE, X_OF|X_SF)
break;
case 0x4D:
INST_NAME("CMOVGE Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
CMPS_REG_LSL_IMM5(x1, x2, 0)
, cNE, cEQ, X_OF|X_SF)
break;
case 0x4E:
INST_NAME("CMOVLE Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cEQ, cNE, X_OF|X_SF|X_ZF)
break;
case 0x4F:
INST_NAME("CMOVG Gw, Ew");
GO( LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_SF]));
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_OF]));
GO( UBFX(x2, xFlags, F_SF, 1);
UBFX(x1, xFlags, F_OF, 1);
XOR_REG_LSL_IMM5(x1, x1, x2, 0);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_ZF]));
UBFX(x2, xFlags, F_ZF, 1);
ORRS_REG_LSL_IMM5(x2, x1, x2, 0);
, cNE, cEQ, X_OF|X_SF|X_ZF)
break;
@@ -1115,8 +1180,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEW(x1);
AND_IMM8(x2, gd, 15);
MOV_REG_LSR_REG(x1, ed, x2);
AND_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
break;
case 0xA4:
case 0xA5:
@@ -1128,7 +1192,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
UXTB(x3, xECX, 0);
}
SETFLAGS(X_ALL, SF_SET);
GETEWW(x12, x1);
GETEWW(x14, x1);
GETGW(x2);
if(opcode==0xA4) {
u8 = F8;
@@ -1143,11 +1207,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
GETEW(x12);
GETEW(x14);
AND_IMM8(x2, gd, 15);
MOV_REG_LSR_REG(x1, ed, x2);
ANDS_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
B_NEXT(cNE);
MOVW(x1, 1);
ORR_REG_LSL_REG(ed, ed, x1, x2);
@@ -1163,7 +1227,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
UXTB(x3, xECX, 0);
}
SETFLAGS(X_ALL, SF_SET);
GETEWW(x12, x1);
GETEWW(x14, x1);
GETGW(x2);
if(opcode==0xAC) {
u8 = F8;
@@ -1196,11 +1260,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
GETEW(x12);
GETEW(x14);
AND_IMM8(x2, gd, 15);
MOV_REG_LSR_REG(x1, ed, x2);
ANDS_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
B_NEXT(cEQ);
MOVW(x1, 1);
XOR_REG_LSL_REG(ed, ed, x1, x2);
@@ -1241,11 +1305,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
GETEW(x12);
GETEW(x14);
AND_IMM8(x2, gd, 15);
MOV_REG_LSR_REG(x1, ed, x2);
AND_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
MOVW(x1, 1);
XOR_REG_LSL_REG(ed, ed, x1, x2);
EWBACK;
@@ -1263,9 +1326,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
XOR_REG_LSL_IMM5(x1, x1, x1, 0); //ZF not set
MARK;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBD:
INST_NAME("BSR Ew,Gw");
@@ -1281,9 +1343,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
XOR_REG_LSL_IMM5(x1, x1, x1, 0); //ZF not set
MARK;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBE:
INST_NAME("MOVSX Gw, Eb");
@@ -1377,13 +1438,26 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if(v0==v1 && u8==0) {
VMOVD(v0+1, v0);
} else {
q0 = fpu_get_scratch_quad(dyn);
if(v0==v1)
q0 = fpu_get_scratch_quad(dyn);
else
q0 = v0;
VMOVD(q0, v0+(u8&1));
VMOVD(q0+1, v1+((u8>>1)&1));
VMOVQ(v0, q0);
if(v0==v1) {
VMOVQ(v0, q0);
}
}
break;
case 0xD0:
INST_NAME("ADDSUBPD Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1);
VSUB_F64(v0+0, v0+0, v1+0);
VADD_F64(v0+1, v0+1, v1+1);
break;
case 0xD1:
INST_NAME("PSRLW Gx,Ex");
nextop = F8;
@@ -1593,7 +1667,17 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VRHADDQ_U16(v0, v0, q0);
break;
case 0xE4:
INST_NAME("PMULHUW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1);
q0 = fpu_get_scratch_quad(dyn);
VMULL_U32_U16(q0, v0, v1);
VSHRN_32(v0, q0, 16);
VMULL_U32_U16(q0, v0+1, v1+1);
VSHRN_32(v0+1, q0, 16);
break;
case 0xE5:
INST_NAME("PMULHW Gx,Ex");
nextop = F8;
@@ -1648,7 +1732,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VQSUBQ_S16(v0, v0, q0);
break;
case 0xEA:
INST_NAME("PMINSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0);
VMINQ_S16(v0, v0, q0);
break;
case 0xEB:
INST_NAME("POR Gx,Ex");
nextop = F8;
@@ -1670,7 +1760,13 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q0);
VQADDQ_S16(v0, v0, q0);
break;
case 0xEE:
INST_NAME("PMAXSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0);
VMAXQ_S16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
nextop = F8;
+17 -17
View File
@@ -28,7 +28,6 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
MAYUSE(i32);
@@ -46,7 +45,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
@@ -55,33 +54,36 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x12, ed);
STRH_REG(gd, x14, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
}
} else { // mem <= reg
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(gd, ed, x12, 0);
LDR_REG_LSL_IMM5(gd, x14, ed, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
POP(xESP, (1<<(xEAX+(nextop&7)))); // 67 ignored
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP(xESP, (1<<x2));
STR_REG_LSL_IMM5(x2, x1, x12, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x14, ed, 0);
}
break;
@@ -109,7 +111,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x12);
grab_fsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
@@ -117,8 +119,8 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x12, 0);
PUSH(xESP, 1<<x3);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
@@ -153,8 +155,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SUBS_IMM8(x1, x1, 1);
BFI(xECX, x1, 0, 16);
B_NEXT(cEQ); // CX is 0, no LOOP
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
GO(cNE, cEQ);
break;
case 0xE1:
@@ -165,8 +166,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SUBS_IMM8(x1, x1, 1);
BFI(xECX, x1, 0, 16);
B_NEXT(cEQ); // CX is 0, no LOOP
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
GO(cEQ, cNE);
break;
case 0xE2:
+7 -7
View File
@@ -23,13 +23,13 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static double d_1 = 1.0;
static double d_l2t = L2T;
static double d_l2e = L2E;
static double d_pi = PI;
static double d_lg2 = LG2;
static double d_ln2 = LN2;
static double d_0 = 0.0;
static const double d_1 = 1.0;
static const double d_l2t = L2T;
static const double d_l2e = L2E;
static const double d_pi = PI;
static const double d_lg2 = LG2;
static const double d_ln2 = LN2;
static const double d_0 = 0.0;
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
+4 -9
View File
@@ -54,8 +54,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cNE, v1, v2); // F_CF==1
break;
case 0xC8:
@@ -70,8 +69,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cNE, v1, v2); // F_ZF==1
break;
case 0xD0:
@@ -86,9 +84,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
VMOVcond_64(cNE, v1, v2); // F_CF==1 | F_ZF==1
break;
case 0xD8:
@@ -103,8 +99,7 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cNE, v1, v2); // F_PF==1
break;
case 0xE9:
+11 -16
View File
@@ -52,8 +52,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cEQ, v1, v2); // F_CF==0
break;
case 0xC8:
@@ -68,8 +67,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
break;
case 0xD0:
@@ -84,10 +82,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORRS_REG_LSL_IMM5(x1, x1, x2, 0);
VMOVcond_64(cEQ, v1, v2); // F_CF==0 | F_ZF==0
TSTS_IMM8(xFlags, (1<<F_CF)|(1<<F_ZF));
VMOVcond_64(cEQ, v1, v2); // F_CF==0 & F_ZF==0
break;
case 0xD8:
case 0xD9:
@@ -101,8 +97,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_PF]));
TSTS_REG_LSL_IMM5(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cEQ, v1, v2); // F_PF==0
break;
case 0xE1:
@@ -110,8 +105,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE2:
INST_NAME("FNCLEX");
MOVW(x1, 0);
LDRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
MOVW(x1, 0);
BFI(x2, x1, 0, 8); // IE .. PE, SF, ES
BFI(x2, x1, 15, 1); // B
STRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
@@ -188,8 +183,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
VMRS(x12); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x12, 0b001, 6); // enable exceptions
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_S32_F64(s0, v1);
@@ -198,13 +193,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, ed, 0b10, 1); // 0x80000000
WBACK;
VMSR(x12); // put back values
VMSR(x14); // put back values
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12); // x1 have the modified RPSCR reg
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
@@ -229,7 +224,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12); // x1 have the modified RPSCR reg
u8 = x87_setround(dyn, ninst, x1, x2, x14); // x1 have the modified RPSCR reg
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
+1 -1
View File
@@ -210,7 +210,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x12, &fixedaddress, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
MOVW(x2, offsetof(x86emu_t, sw));
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
+38 -29
View File
@@ -151,59 +151,68 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
VCVT_S32_F64(s0, v1);
MSR_nzcvq_0();
VMRS(x14); // get fpscr
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
VMSR(x14);
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x12);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
VMOVfrV(ed, s0);
MSR_nzcvq_0(); // reset Q flag (and all other flags too)
SSAT_REG_LSL_IMM5(ed, 16, ed, 0);
MRS_aspr(x3); // check Q flag
TSTS_IMM8_ROR(x3, 0b10, 3);
B_MARK(cEQ); // not saturated, continue
MOV32(ed, 0xffff8000);
MARK;
STRH_IMM8(ed, wback, fixedaddress);
TSTS_IMM8_ROR(x3, 0b00000001, 0);
SSAT_REG_LSL_IMM5_COND(cEQ, x3, 16, ed, 0);
CMPS_REG_LSL_IMM5_COND(cEQ, ed, x3, 0);
MOVW_COND(cNE, x3, 0x8000); // saturated
STRH_IMM8(x3, wback, fixedaddress);
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+168 -71
View File
@@ -30,17 +30,13 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_shl32);
SET_DF(s4, d_shl32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(s4);
}
if(c==0) {
IFX(F_OF) {
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
@@ -48,10 +44,8 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
return;
}
IFX(X_CF) {
if(c<31) {
UBFX(s3, s1, 32-c, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
}
MOV_REG_LSR_IMM5(s3, s1, 32-c);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_ZF|X_OF) {
MOVS_REG_LSL_IMM5(s1, s1, c);
@@ -62,22 +56,20 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {UBFX(s3, s1, 31, 1);}
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s3, s1, 31);}
XOR_IMM8_COND(cCS, s3, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFI(xFlags, s3, F_OF, 1);
} else {
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
@@ -87,8 +79,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
@@ -99,12 +90,9 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_shr32);
SET_DF(s4, d_shr32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
@@ -121,25 +109,22 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
MOVW_COND(cCC, s3, 0);
MOVW_COND(cCS, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
@@ -149,8 +134,7 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
@@ -161,12 +145,9 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_sar32);
SET_DF(s4, d_sar32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
@@ -183,18 +164,16 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cNE, s3, 0);
MOVW_COND(cEQ, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
MOVW_COND(cCC, s3, 0);
MOVW_COND(cCS, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
@@ -203,8 +182,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
@@ -214,12 +192,9 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_rol32);
SET_DF(s4, d_rol32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
@@ -232,14 +207,13 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
AND_IMM8(s3, s1, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, s1, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
ADD_REG_LSR_IMM5(s3, s1, s1, 31);
AND_IMM8(s3, s3, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFI(xFlags, s3, F_OF, 1);
}
}
}
@@ -250,12 +224,9 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_ror32);
SET_DF(s4, d_ror32);
} else IFX(X_ALL) {
MOVW(s4, d_none);
}
IFX(X_PEND|X_ALL) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df));
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
@@ -268,15 +239,141 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
UBFX(s3, s1, 31, 1);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFI(xFlags, s4, F_OF, 1);
}
}
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shr32
SET_DF(s4, d_shr32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_CF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
MOV_REG_LSR_IMM5(s1, s1, c);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_ZF) {
ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
} else {
ORR_REG_LSL_IMM5(s1, s1, s2, 32-c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags computation as with shl32
SET_DF(s4, d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c==0) {
IFX(F_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 32-c);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
MOVS_REG_LSL_IMM5(s1, s1, c);
} else {
MOV_REG_LSL_IMM5(s1, s1, c);
}
IFX(X_OF) {
if(c==1) {
UBFX(s3, s2, 0, 1);
XOR_IMM8_COND(cCS, s3, s3, 1);
BFI(xFlags, s3, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_ZF) {
ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
} else {
ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
AND_IMM8(s3, s1, 0xE0); // lsr 5 masking pre-applied
LDR_IMM9(s4, xEmu, offsetof(x86emu_t, x86emu_parity_tab));
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
+103 -154
View File
@@ -29,40 +29,30 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_cmp32);
SET_DF(s4, d_cmp32);
} else {
MOVW(s4, 0);
SET_DFNONE(s4);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUBS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
IFX(X_PEND) {
MOVW(s4, 0);
}
// first the easy flag, also found on ARM
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_OF) {
IFX(X_ZF|X_PEND) {
MOVW(s4, 0);
}
MOVW_COND(cVS, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
ORR_IMM8_COND(cVS, xFlags, xFlags, 0b10, 0x0b);
BIC_IMM8_COND(cVC, xFlags, xFlags, 0b10, 0x0b);
}
IFX(X_CF) {
IFX(X_ZF|X_OF|X_PEND) {
MOVW(s4, 0);
}
MOVW_COND(cCC, s4, 1); // Carry flags on ARM is reversed compared to x86 one
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
// reversed carry
ORR_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
// and now the tricky ones (and mostly unused), PF and AF
IFX(X_AF) {
@@ -73,8 +63,8 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
MOV_REG_LSR_IMM5(s4, s3, 3);
BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX(X_PF) {
@@ -88,47 +78,38 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s4, 0);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
MOVW(s4, d_cmp32);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
SET_DF(s4, d_cmp32);
} else {
SET_DFNONE(s4);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUBS_IMM8(s3, s1, 0); // res = s1 - 0
IFX(X_PEND) {
IFX(X_ZF|X_OF|X_CF|X_AF) {
MOVW(s4, 0);
}
}
// and now the tricky ones (and mostly unused), PF and AF
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80000000
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFC(xFlags, F_OF, 1);
}
IFX(X_ZF) {
// first the easy flags, also found on ARM
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
@@ -137,8 +118,7 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
@@ -148,11 +128,10 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, d_cmp16);
SET_DF(s3, d_cmp16);
} else {
MOVW(s3, 0);
SET_DFNONE(s3);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df)); // reset flags
SUB_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
@@ -160,13 +139,12 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_ZF) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s3, s4, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
@@ -176,18 +154,17 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x8000
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_CF, 1); // CF : bc & 0x8000
}
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
MOV_REG_LSR_IMM5(s4, s3, 3);
BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s3, 14);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
@@ -201,45 +178,38 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s3, 0);
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
MOVW(s3, 0);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
MOVW(s3, d_cmp16);
}
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df)); // reset flags
IFX(X_OF|X_CF|X_AF) {
MOVW(s4, 0);
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x8000
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
BFC(xFlags, F_OF, 1);
}
IFX(X_ZF) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s1, s4, 0);
MOVW(s4, 0);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s1, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
@@ -248,36 +218,31 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s4, d_cmp8);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_cmp8);
} else {
MOVW(s4, 0);
SET_DFNONE(s4);
}
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SUB_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 - s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
IFX(X_PEND) {
MOVW(s4, 0);
}
TSTS_IMM8(s3, 0xff);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
@@ -287,18 +252,17 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
BIC_REG_LSL_IMM5(s3, s2, s1, 0); // loosing res... s3 = s & ~d
ORR_REG_LSL_IMM5(s3, s4, s3, 0); // s3 = (res & (~d | s)) | (s & ~d)
IFX(X_CF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_CF, 1); // CF : bc & 0x80
}
IFX(X_AF) {
UBFX(s4, s3, 3, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
MOV_REG_LSR_IMM5(s4, s3, 3);
BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s3, 6);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
@@ -312,41 +276,36 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_cmp8);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
SET_DF(s3, d_cmp8);
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SET_DFNONE(s4);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF])); // CF : bc & 0x80
}
IFX(X_AF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_AF])); // AF: bc & 0x08
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF])); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
BFC(xFlags, F_OF, 1);
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s1, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
@@ -355,38 +314,35 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s1, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst32);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
SET_DF(s3, d_tst32);
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SET_DFNONE(s4);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFC(xFlags, F_OF, 1);
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFC(xFlags, F_CF, 1);
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 31, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
@@ -396,38 +352,35 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst16);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
SET_DF(s3, d_tst16);
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SET_DFNONE(s4);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFC(xFlags, F_OF, 1);
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFC(xFlags, F_CF, 1);
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 15, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
@@ -437,38 +390,35 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MOVW(s4, 0);
IFX(X_PEND) {
MOVW(s3, d_tst8);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, df));
SET_DF(s3, d_tst8);
} else {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, df)); // reset flags
SET_DFNONE(s4);
}
IFX(X_OF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_OF]));
BFC(xFlags, F_OF, 1);
}
IFX(X_CF) {
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFC(xFlags, F_CF, 1);
}
ANDS_REG_LSL_IMM5(s3, s1, s2, 0); // res = s1 & s2
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOVW_COND(cEQ, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_ZF]));
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
UBFX(s4, s3, 7, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_SF]));
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
@@ -478,7 +428,6 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
AND_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
AND_IMM8(s4, s4, 1);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, flags[F_PF]));
BFI(xFlags, s4, F_PF, 1);
}
}
+126 -118
View File
@@ -46,15 +46,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_add8(dyn, ninst, x1, x2, x12, x3, 0);
emit_add8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_add8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -65,12 +65,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x12);
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_add32(dyn, ninst, x1, gd, x3, x12);
emit_add32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -86,15 +86,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_or8(dyn, ninst, x1, x2, x12, x3, 0);
emit_or8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_or8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_or8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -105,12 +105,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x12);
emit_or32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_or32(dyn, ninst, x1, gd, x3, x12);
emit_or32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -126,15 +126,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_adc8(dyn, ninst, x1, x2, x12, x3, 0);
emit_adc8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_adc8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_adc8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -145,12 +145,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x12);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_adc32(dyn, ninst, x1, gd, x3, x12);
emit_adc32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -166,15 +166,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_sbb8(dyn, ninst, x1, x2, x12, x3, 0);
emit_sbb8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_sbb8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_sbb8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -185,12 +185,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x12);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_sbb32(dyn, ninst, x1, gd, x3, x12);
emit_sbb32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -206,15 +206,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_and8(dyn, ninst, x1, x2, x12, x3, 0);
emit_and8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_and8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_and8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -225,12 +225,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x12);
emit_and32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_and32(dyn, ninst, x1, gd, x3, x12);
emit_and32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -246,15 +246,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_sub8(dyn, ninst, x1, x2, x12, x3, 0);
emit_sub8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_sub8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_sub8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -265,12 +265,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x12);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_sub32(dyn, ninst, x1, gd, x3, x12);
emit_sub32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -286,15 +286,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
emit_xor8(dyn, ninst, x1, x2, x12, x3, 0);
emit_xor8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x1, wback);
emit_xor8(dyn, ninst, x1, x2, x12, x3, (wback==x3)?1:0);
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
emit_xor8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
@@ -305,12 +305,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x12);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_xor32(dyn, ninst, x1, gd, x3, x12);
emit_xor32(dyn, ninst, x1, gd, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -331,7 +331,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_add32c(dyn, ninst, ed, i32, x3, x12);
emit_add32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -339,16 +339,16 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
emit_add32c(dyn, ninst, x1, i32, x3, x12);
emit_add32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
B_NEXT(c__);
MARK; // unaligned! also, not enough
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8); // re-inject
emit_add32c(dyn, ninst, x1, i32, x3, x12);
LDREXB(x14, wback);
BFI(x1, x14, 0, 8); // re-inject
emit_add32c(dyn, ninst, x1, i32, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
@@ -361,13 +361,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_or32c(dyn, ninst, ed, i32, x3, x12);
emit_or32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_or32c(dyn, ninst, x1, i32, x3, x12);
emit_or32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -380,13 +380,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_adc32c(dyn, ninst, ed, i32, x3, x12);
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_adc32c(dyn, ninst, x1, i32, x3, x12);
emit_adc32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -399,13 +399,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sbb32c(dyn, ninst, ed, i32, x3, x12);
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_sbb32c(dyn, ninst, x1, i32, x3, x12);
emit_sbb32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -417,13 +417,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_and32c(dyn, ninst, ed, i32, x3, x12);
emit_and32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_and32c(dyn, ninst, x1, i32, x3, x12);
emit_and32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -435,7 +435,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x12);
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -443,16 +443,16 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
emit_sub32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
B_NEXT(c__);
MARK; // unaligned! also, not enough
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8); // re-inject
emit_sub32c(dyn, ninst, x1, i32, x3, x12);
LDREXB(x14, wback);
BFI(x1, x14, 0, 8); // re-inject
emit_sub32c(dyn, ninst, x1, i32, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
@@ -465,13 +465,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x12);
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
emit_xor32c(dyn, ninst, x1, i32, x3, x12);
emit_xor32c(dyn, ninst, x1, i32, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -485,9 +485,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(i32) {
MOV32(x2, i32);
emit_cmp32(dyn, ninst, ed, x2, x3, x12);
emit_cmp32(dyn, ninst, ed, x2, x3, x14);
} else {
emit_cmp32_0(dyn, ninst, ed, x3, x12);
emit_cmp32_0(dyn, ninst, ed, x3, x14);
}
break;
}
@@ -511,7 +511,17 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x87:
--addr;
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
--addr;
break;
case 0x0F:
nextop = F8;
switch(nextop) {
@@ -539,8 +549,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// AL == Eb
GETGB(x1);
if(wb1) {
STREXB(x12, x1, wback);
CMPS_IMM8(x12, 0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
if(!(gb1==xEAX && gb2==0)) {
UXTB(x1, xEAX, 0); // readback AL if needed
@@ -555,7 +565,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(xEAX, ed, 0, 8);
MARK3;
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x12);
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
break;
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
@@ -579,22 +589,22 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// EAX == Ed
if(wback) {
TSTS_IMM8(wback, 3);
STREX_COND(cEQ, x12, gd, wback);
STREXB_COND(cNE, x12, gd, wback);
CMPS_IMM8(x12, 0);
STREX_COND(cEQ, x14, gd, wback);
STREXB_COND(cNE, x14, gd, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
TSTS_IMM8(wback, 3); // anoying, all those test
STR_IMM9_COND(cNE, gd, wback, 0);
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
} else {
emit_cmp32(dyn, ninst, xEAX, ed, x1, x12);
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
MOV_REG(ed, gd);
}
// done
B_MARK3(c__); // not next, in case its called with a LOCK prefix
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x12);
emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);
MOV_REG(xEAX, ed);
MARK3
break;
@@ -616,15 +626,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = x1;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
@@ -652,8 +662,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG_LSR_IMM5(x1, ed, u8);
ed = x1;
}
AND_IMM8(x1, ed, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, ed, F_CF, 1);
break;
case 6:
INST_NAME("LOCK BTR Ed, Ib");
@@ -676,15 +685,15 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
ANDS_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to next instruction
//MOVW(x12, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x12, x2);
//MOVW(x14, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
@@ -711,14 +720,13 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x12, ed, x2);
AND_IMM8(x12, x12, 1);
STR_IMM9(x12, xEmu, offsetof(x86emu_t, flags[F_CF]));
MOVW(x12, 1);
XOR_REG_LSL_REG(ed, ed, x12, x2);
MOV_REG_LSR_REG(x14, ed, x2);
BFI(xFlags, x14, F_CF, 1);
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x12, ed, wback);
CMPS_IMM8(x12, 0);
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
break;
@@ -743,10 +751,10 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = x2;
}
BFI(gb1, ed, gb2*8, 8); // gb <- eb
emit_add8(dyn, ninst, ed, gd, x12, x3, 1);
emit_add8(dyn, ninst, ed, gd, x14, x3, 1);
if(wb1) {
STREXB(x12, ed, wback);
CMPS_IMM8(x12, 0);
STREXB(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
} else {
BFI(wback, ed, wb2*8, 8);
@@ -764,35 +772,35 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
}
emit_add32(dyn, ninst, ed, gd, x3, x12);
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
TSTS_IMM8(wback, 3);
B_MARK(cNE); // unaligned
MARKLOCK;
LDREX(x1, wback);
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
STREX(x3, x12, wback);
ADD_REG_LSL_IMM5(x14, x1, gd, 0);
STREX(x3, x14, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
IFX(X_ALL|X_PEND) {
MOV_REG(x2, x1);
emit_add32(dyn, ninst, x2, gd, x3, x12);
emit_add32(dyn, ninst, x2, gd, x3, x14);
}
MOV_REG(gd, x1);
B_NEXT(c__);
MARK;
LDR_IMM9(x1, wback, 0);
LDREXB(x12, wback);
BFI(x1, x12, 0, 8);
ADD_REG_LSL_IMM5(x12, x1, gd, 0);
STREXB(x3, x12, wback);
LDREXB(x14, wback);
BFI(x1, x14, 0, 8);
ADD_REG_LSL_IMM5(x14, x1, gd, 0);
STREXB(x3, x14, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x12, wback, 0);
STR_IMM9(x14, wback, 0);
IFX(X_ALL|X_PEND) {
MOV_REG(x2, x1);
emit_add32(dyn, ninst, x2, gd, x3, x12);
emit_add32(dyn, ninst, x2, gd, x3, x14);
}
MOV_REG(gd, x1);
}
@@ -815,9 +823,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(x2, xEBX);
MOV_REG(x3, xECX);
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x12, x2, wback);
STREX_COND(cNE, x12, x2, wback);
CMPS_IMM8(x12, 0);
STREXD_COND(cEQ, x14, x2, wback);
STREX_COND(cNE, x14, x2, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
TSTS_IMM8(wback, 7);
STR_IMM9_COND(cNE, x3, wback, 4);
@@ -828,7 +836,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
BFI(xFlags, x1, F_ZF, 1);
break;
default:
@@ -846,12 +854,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x12);
emit_inc32(dyn, ninst, ed, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_inc32(dyn, ninst, x1, x3, x12);
emit_inc32(dyn, ninst, x1, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
@@ -862,12 +870,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x12);
emit_dec32(dyn, ninst, ed, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
LDREX(x1, wback);
emit_dec32(dyn, ninst, x1, x3, x12);
emit_dec32(dyn, ninst, x1, x3, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
+2 -2
View File
@@ -58,7 +58,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
MAYUSE(d0);
switch(nextop) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
@@ -137,7 +137,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 0x2D:
INST_NAME("CVTSD2SI Gd, Ex");
u8 = x87_setround(dyn, ninst, x1, x2, x12);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
+58 -12
View File
@@ -63,9 +63,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
int v0, v1;
int s0, s1, s2;
int d0, d1;
int q0;
int q0, q1;
int parity;
MAYUSE(q1);
MAYUSE(s1);
MAYUSE(s2);
MAYUSE(j32);
@@ -132,6 +133,38 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 0x12:
INST_NAME("MOVSLDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VDUP_32(q0+0, q1+0, 0);
VDUP_32(q0+1, q1+1, 0);
break;
case 0x16:
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VDUP_32(q0+0, q1+0, 1);
VDUP_32(q0+1, q1+1, 1);
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
@@ -179,15 +212,22 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
}
VCVT_S32_F32(s0, s0);
VMOVfrV(gd, s0);
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
u8 = x87_setround(dyn, ninst, x1, x2, x12);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
@@ -201,8 +241,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VMOV_32(s0, d0*2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
}
VCVTR_S32_F32(s0, s0);
VMOVfrV(gd, s0);
@@ -460,7 +507,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VLD1Q_64(v1, ed);
}
u8 = F8;
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
// only high part need to be shuffled. VTBL only handle 8bits value, so the 16bits shuffles need to be changed in 8bits
u32 = 0;
for (int i=0; i<2; ++i) {
u32 |= (((u8>>(i*2))&3)*2+0)<<(i*16+0);
@@ -528,11 +575,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CLZ(gd, x1); // x2 gets leading 0 == TZCNT
MOVW_COND(cEQ, x1, 1);
MOVW_COND(cNE, x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_CF]));
BFI(xFlags, x1, F_CF, 1);
RSB_IMM8(x1, x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, flags[F_ZF]));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xC2:
@@ -588,7 +634,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVfrV_D(x2, x3, v0);
VMOVtoV_D(v0, x2, x3);
}
}
gd = (nextop&0x38)>>3;
+62 -22
View File
@@ -25,21 +25,6 @@
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
void arm_popf(x86emu_t* emu, uint32_t f)
{
emu->packed_eflags.x32 = (f & 0x3F7FD7) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
RESET_FLAGS(emu);
}
void arm_popf16(x86emu_t* emu, uint32_t f)
{
emu->packed_eflags.x32 &= 0xffff0000;
emu->packed_eflags.x32 |= (f & 0x7FD7) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
RESET_FLAGS(emu);
}
void arm_fstp(x86emu_t* emu, void* p)
{
if(ST0.ll!=STld(0).ref)
@@ -117,8 +102,10 @@ void arm_fbld(x86emu_t* emu, uint8_t* ed)
void arm_fild64(x86emu_t* emu, int64_t* ed)
{
ST0.d = *ed;
STll(0).ll = *ed;
int64_t tmp;
memcpy(&tmp, ed, sizeof(tmp));
ST0.d = tmp;
STll(0).ll = tmp;
STll(0).ref = ST0.ll;
}
@@ -134,10 +121,10 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
memcpy(ed, &STll(0).ll, sizeof(int64_t));
} else {
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
tmp = (int64_t)ST0.d;
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
@@ -264,11 +251,11 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
dyn->fpuused[i]=0;
}
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity)
{
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
uint32_t tested = (1<<parity)-1;
if((nextop&0xC0)==0xC0)
@@ -287,7 +274,7 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
return (tmp&tested)?0:1;
}
} else {
if(sib_reg==4)
if(sib_reg==4 && parity<3)
return 0; // simple [reg]
// don't try [reg1 + reg2<<N], unless reg1 is ESP
return ((sib&0x7)==4 && (sib>>6)>=parity)?1:0;
@@ -301,6 +288,59 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
} else {
return 0; //Form [reg1 + reg2<<N + XXXXXX]
}
}
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
if((nextop&0xC0)==0xC0)
return addr;
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
if((sib&0x7)==5) {
addr+=4;
}
} else if((nextop&7)==5) {
addr+=4;
}
} else {
if((nextop&7)==4) {
++addr;
}
if(nextop&0x80) {
addr+=4;
} else {
++addr;
}
}
return addr;
}
#undef F8
#undef F32
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(uint32_t*)(addr+a)
if(!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 = *(uint32_t*)a1;
}
if(addr<0x10000) // 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) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
#undef PK32
#undef PK
}
+5 -2
View File
@@ -3,8 +3,6 @@
typedef struct x86emu_s x86emu_t;
void arm_popf(x86emu_t* emu, uint32_t f);
void arm_popf16(x86emu_t* emu, uint32_t f);
void arm_fstp(x86emu_t* emu, void* p);
void arm_print_armreg(x86emu_t* emu, uintptr_t reg, uintptr_t n);
@@ -53,5 +51,10 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
+89 -89
View File
@@ -17,6 +17,7 @@
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "dynablock_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
@@ -152,31 +153,6 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
return addr;
}
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
if((sib&0x7)==5) {
addr+=4;
}
} else if((nextop&7)==5) {
addr+=4;
}
} else {
if((nextop&7)==4) {
++addr;
}
if(nextop&0x80) {
addr+=4;
} else {
++addr;
}
}
return addr;
}
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, uint32_t absmax, uint32_t mask)
{
@@ -270,8 +246,10 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to linker (#%d) nolinker=%d\n", dyn->tablei, dyn->nolinker);
#if 0
int j32;
MAYUSE(j32);
#endif
if(dyn->nolinker==2) {
jump_to_epilog(dyn, ip, reg, ninst);
} else {
@@ -292,18 +270,30 @@ void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
MOV32_(x1, (uintptr_t)table);
// TODO: This is not thread safe.
if(!ip) { // no IP, jump address in a reg, so need smart linker
#if 0
//version thread safe
MARK;
LDREXD(x2, x1); // load dest address in x2 and planned ip in x3
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
MOV_REG(x3, x14);
STREXD(x14, x2, x1); // nope, putting back linker & IP in place
// x14 now contain success / falure for write
CMPS_IMM8(x14, 1);
MOV_REG(x14, x3); // put back IP in place...
B_MARK(cEQ);
BX(x2); // go to linker
#else
// not thread safe, is that still ok?
LDRD_IMM8(x2, x1, 0);
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x14);
STRD_IMM8(x2, x1, 0);
BX(x2);
#endif
} else {
LDR_IMM9(x2, x1, 0);
BX(x2); // jump
@@ -311,6 +301,26 @@ void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
}
}
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MESSAGE(LOG_DUMP, "Jump to next nolinker=%d\n", dyn->nolinker);
if(dyn->nolinker==2) {
jump_to_epilog(dyn, ip, reg, ninst);
} else {
if(reg) {
if(reg!=xEIP) {
MOV_REG(xEIP, reg);
}
} else {
MOV32_(xEIP, ip);
}
MOV32_(x2, (uintptr_t)arm_next);
MOV_REG(x1, xEIP);
BX(x2);
}
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
// using linker here doesn't seem to bring any significant speed improvment. To much change in the jump table probably
@@ -319,16 +329,16 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
MAYUSE(i32);
if(dyn->nolinker) {
#endif
MESSAGE(LOG_DUMP, "Ret epilog\n");
POP(xESP, 1<<xEIP);
MESSAGE(LOG_DUMP, "Ret next\n");
POP1(xEIP);
cstack_pop(dyn, ninst, xEIP, x1, x2);
PASS3(void* epilog = arm_epilog);
MOV32_(x2, (uintptr_t)epilog);
MOV32_(x2, (uintptr_t)arm_next);
MOV_REG(x1, xEIP);
BX(x2);
#if 0
} else {
MESSAGE(LOG_DUMP, "Ret epilog with linker\n");
POP(xESP, 1<<xEIP);
POP1(xEIP);
uintptr_t* table = 0;
if(dyn->tablesz) {
table = &dyn->table[dyn->tablei];
@@ -342,11 +352,11 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
MOV_REG(x3, x14);
STREXD(x14, x2, x1); // nope, putting back linker & IP in place
// x14 now contain success / falure for write
CMPS_IMM8(x14, 1);
MOV_REG(x14, x3); // put back IP in place...
B_MARK(cEQ);
BX(x2); // go to linker
}
@@ -361,7 +371,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
if(dyn->nolinker) {
#endif
MESSAGE(LOG_DUMP, "Retn epilog\n");
POP(xESP, 1<<xEIP);
POP1(xEIP);
if(n>0xff) {
MOVW(x1, n);
ADD_REG_LSL_IMM5(xESP, xESP, x1, 0);
@@ -369,13 +379,13 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
ADD_IMM8(xESP, xESP, n);
}
cstack_pop(dyn, ninst, xEIP, x1, x2);
PASS3(void* epilog = arm_epilog);
MOV32_(x2, (uintptr_t)epilog);
MOV32_(x2, (uintptr_t)arm_next);
MOV_REG(x1, xEIP);
BX(x2);
#if 0
} else {
MESSAGE(LOG_DUMP, "Retn epilog with linker\n");
POP(xESP, 1<<xEIP);
POP1(xEIP);
ADD_IMM8(xESP, xESP, n);
uintptr_t* table = 0;
if(dyn->tablesz) {
@@ -390,11 +400,11 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
CMPS_REG_LSL_IMM5(xEIP, x3, 0);
BXcond(cEQ, x2);
MOV32_(x2, (uintptr_t)arm_linker);
MOV_REG(x3, x12);
STREXD(x12, x2, x1); // nope, putting back linker & IP in place
// x12 now contain success / falure for write
CMPS_IMM8(x12, 1);
MOV_REG(x12, x3); // put back IP in place...
MOV_REG(x3, x14);
STREXD(x14, x2, x1); // nope, putting back linker & IP in place
// x14 now contain success / falure for write
CMPS_IMM8(x14, 1);
MOV_REG(x14, x3); // put back IP in place...
B_MARK(cEQ);
BX(x2); // go to linker
}
@@ -405,18 +415,19 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
{
MESSAGE(LOG_DUMP, "IRet epilog\n");
// POP IP
POP(xESP, 1<<xEIP);
POP1(xEIP);
// POP CS
MOVW(x1, offsetof(x86emu_t, segs[_CS]));
POP(xESP, 1<<x2);
POP1(x2);
STRH_REG(x2, xEmu, x1);
MOVW(x1, 0);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_clean[_CS]));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, segs_serial[_CS]));
// POP EFLAGS
POP(xESP, (1<<x1));
CALL(arm_popf, -1, (1<<xEIP));
MOVW(x1, d_none);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, df));
POP1(xFlags);
MOV32(x1, 0x3F7FD7);
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
ORR_IMM8(xFlags, xFlags, 2, 0);
SET_DFNONE(x1);
// Ret....
cstack_pop(dyn, ninst, xEIP, x1, x2);
PASS3(void* epilog = arm_epilog);
@@ -424,12 +435,15 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
BX(x2);
}
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask)
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags)
{
if(ret!=-2) {
PUSH(xSP, (1<<xEmu) | mask);
}
fpu_pushcache(dyn, ninst, reg);
if(saveflags) {
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
MOV32(reg, (uintptr_t)fnc);
BLX(reg);
fpu_popcache(dyn, ninst, reg);
@@ -439,19 +453,25 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t
if(ret!=-2) {
POP(xSP, (1<<xEmu) | mask);
}
if(saveflags) {
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
}
SET_NODF();
}
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
{
MESSAGE(LOG_DUMP, "Get TLSData\n");
//int32_t i32;
//MAYUSE(i32);
//LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_clean[_GS]));
//CMPS_IMM8(x12, 1);
//LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_GS]));
//B_MARKSEG(cEQ);
int32_t j32;
MAYUSE(j32);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, context));
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, segs_serial[_GS])); // complete check here
LDR_IMM9(x1, x1, offsetof(box86context_t, sel_serial));
CMPS_REG_LSL_IMM5(x14, x1, 0);
LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_GS]));
B_MARKSEG(cEQ);
MOVW(x1, _GS);
call_c(dyn, ninst, GetSegmentBaseEmu, 12, reg, 0);
call_c(dyn, ninst, GetSegmentBaseEmu, x14, reg, 0, 1);
MARKSEG;
MESSAGE(LOG_DUMP, "----TLSData\n");
}
@@ -461,36 +481,16 @@ void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg)
int32_t j32;
MAYUSE(j32);
MESSAGE(LOG_DUMP, "Get FS: Offset\n");
LDR_IMM9(x12, xEmu, offsetof(x86emu_t, segs_clean[_FS]));
CMPS_IMM8(x12, 1);
LDR_IMM9_COND(cEQ, reg, xEmu, offsetof(x86emu_t, segs_offs[_FS]));
B_MARKSEG(cEQ);
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, segs_serial[_FS]));// fast check here
CMPS_IMM8(x14, 0);
LDR_IMM9_COND(cNE, reg, xEmu, offsetof(x86emu_t, segs_offs[_FS]));
B_MARKSEG(cNE);
MOVW(x1, _FS);
call_c(dyn, ninst, GetSegmentBaseEmu, 12, reg, 0);
call_c(dyn, ninst, GetSegmentBaseEmu, x14, reg, 0, 1);
MARKSEG;
MESSAGE(LOG_DUMP, "----FS: Offset\n");
}
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
if(!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 = *(uint32_t*)a1;
}
if(addr<0x10000) // 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) {
// found !
if(retn) *retn = (b->C3==0xC2)?b->N:0;
if(calladdress) *calladdress = addr+1;
return 1;
}
return 0;
}
// x87 stuffs
static void x87_reset(dynarec_arm_t* dyn, int ninst)
{
+64 -41
View File
@@ -132,6 +132,21 @@
wb1 = 1; \
ed = i; \
}
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
UXTB(i, wback, wb2); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
@@ -164,18 +179,22 @@
#define GBBACK BFI(gb1, gd, gb2*8, 8);
// Get Direction with size Z and based of F_DF flag, on register r ready for LDR/STR fetching
// F_DF is 1<<10, so 1 ROR 11*2 (so F_OF)
#define GETDIR(r, A) \
LDR_IMM9(r, xEmu, offsetof(x86emu_t, flags[F_DF])); \
CMPS_IMM8(r, 1); \
MOVW(r, A); \
RSB_COND_IMM8(cEQ, r, r, 0)
TSTS_IMM8_ROR(xFlags, 1, 0x0b); \
MOVW(r, A); \
RSB_COND_IMM8(cNE, r, r, 0)
// CALL will use x12 for the call address. Return value can be put in ret (unless ret is -1)
// CALL will use x14 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL(F, ret, M) call_c(dyn, ninst, F, x12, ret, M)
#define CALL(F, ret, M) call_c(dyn, ninst, F, x14, ret, M, 1)
// CALL_ will use x3 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2
#define CALL_(F, ret, M) call_c(dyn, ninst, F, x3, ret, M)
#define CALL_(F, ret, M) call_c(dyn, ninst, F, x3, ret, M, 1)
// CALL_S will use x3 for the call address. Return value can be put in ret (unless ret is -1)
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret, M) call_c(dyn, ninst, F, x3, ret, 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;}
@@ -235,40 +254,34 @@
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
VMRS_APSR(); /* 0b111 */ \
XOR_REG_LSL_IMM5(s2, s2, s2, 0); \
MOVW_COND(cVS, s1, 0b111); /* unordered */ \
MOVW_COND(cEQ, s1, 0b100); /* zero */ \
MOVW_COND(cGT, s1, 0b000); /* greater than */ \
MOVW_COND(cLO, s1, 0b001); /* less than */ \
IFX(X_CF|X_PEND) { \
UBFX(s2, s1, 0, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_CF]));\
MOVW_COND(cVS, s1, 0b1000101); /* unordered */ \
MOVW_COND(cEQ, s1, 0b1000000); /* zero */ \
MOVW_COND(cGT, s1, 0b0000000); /* greater than */ \
MOVW_COND(cLO, s1, 0b0000001); /* less than */ \
IFX(X_CF|X_PF|X_ZF|X_PEND) { \
BIC_IMM8(xFlags, xFlags, 0b1000101, 0); \
ORR_REG_LSL_IMM5(xFlags, xFlags, s1, 0); \
} \
IFX(X_PF|X_PEND) { \
UBFX(s2, s1, 1, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_PF]));\
} \
IFX(X_ZF|X_PEND) { \
UBFX(s2, s1, 2, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_ZF]));\
} \
MOVW(s2, d_none); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, df)); \
SET_DFNONE(s1); \
IFX(X_OF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_OF]));\
BFC(xFlags, F_OF, 1); \
} \
IFX(X_AF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_AF]));\
BFC(xFlags, F_AF, 1); \
} \
IFX(X_SF|X_PEND) { \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_SF]));\
BFC(xFlags, F_SF, 1); \
} \
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->dfnone = 0
#define SET_DFOK() dyn->dfnone = 1
#ifndef READFLAGS
#define READFLAGS(A) \
if(dyn->state_flags!=SF_SET) { \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
if(dyn->state_flags!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
@@ -278,6 +291,7 @@
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
SET_DFOK(); \
}
#endif
#ifndef SETFLAGS
@@ -295,11 +309,11 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, 0, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, 0, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {MOVW(r, A); STR_IMM9(r, 0, offsetof(x86emu_t, df));}
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x86.need_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
@@ -308,8 +322,17 @@
#define NEW_BARRIER_INST
#endif
#if STEP < 2
#define PASS2IF(A, B) if(A)
#elif STEP == 2
#define PASS2IF(A, B) if(A) dyn->insts[ninst].pass2choice = B; if(dyn->insts[ninst].pass2choice == B)
#else
#define PASS2IF(A, B) if(dyn->insts[ninst].pass2choice == B)
#endif
void arm_epilog();
void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
void* arm_next(x86emu_t* emu, uintptr_t addr);
#ifndef STEPNAME
#define STEPNAME3(N,M) N##M
@@ -339,17 +362,16 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#define dynarecF30F STEPNAME(dynarecF30F)
#define geted STEPNAME(geted_)
#define fakeed STEPNAME(fakeed_)
#define geted16 STEPNAME(geted16_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_linker STEPNAME(jump_to_linker_)
#define jump_to_next STEPNAME(jump_to_next_)
#define ret_to_epilog STEPNAME(ret_to_epilog_)
#define retn_to_epilog STEPNAME(retn_to_epilog_)
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define grab_fsdata STEPNAME(grab_fsdata_)
#define grab_tlsdata STEPNAME(grab_tlsdata_)
#define isNativeCall STEPNAME(isNativeCall_)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
@@ -415,6 +437,8 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define x87_do_push STEPNAME(x87_do_push)
#define x87_do_push_empty STEPNAME(x87_do_push_empty)
@@ -451,9 +475,6 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
@@ -461,13 +482,13 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
// generic x86 helper
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_linker(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
@@ -535,6 +556,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
// x87 helper
// cache of the local stack counter, to avoid upadte at every call
+11 -5
View File
@@ -34,6 +34,7 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
dyn->dfnone = 0;
fpu_reset(dyn, ninst);
// ok, go now
INIT;
@@ -52,7 +53,7 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
MOV32(x1, ip);
STM(xEmu, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
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(PrintTrace, -1, 0);
@@ -67,19 +68,24 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
if(dyn->insts && dyn->insts[ninst+1].x86.barrier) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
if(dyn->insts[ninst+1].x86.barrier!=2)
if(dyn->insts[ninst+1].x86.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
}
}
if(!ok && !need_epilog && dyn->insts && (addr < (dyn->start+dyn->isize))) {
ok = 1;
}
if(!ok && !need_epilog && !dyn->insts) { // check if need to continue
uintptr_t next = get_closest_next(dyn, addr);
if(next && ((next-addr)<15) && is_nops(dyn, addr, next-addr)) {
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
{
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
ok = 1;
} else if(next && (next-addr)<15) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4));
} else if(next && (next-addr)<30) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
if(ok<0) {ok = 0; need_epilog=1;}
+1 -1
View File
@@ -8,7 +8,7 @@
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
#define JUMP(A) dyn->insts[ninst].x86.jmp = A
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst+1<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
dyn->insts[ninst].x86.addr = ip; \
+3 -2
View File
@@ -2,8 +2,9 @@
#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
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4;\
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
+6
View File
@@ -10,10 +10,14 @@ typedef struct instruction_arm_s {
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
} instruction_arm_t;
typedef struct dynarec_arm_s {
@@ -39,6 +43,7 @@ typedef struct dynarec_arm_s {
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
int fpu_reg; // x87/sse/mmx reg counter
int nolinker; // disable use of (smart) linker in the block
int dfnone; // if defered flags is already set to df_none
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
@@ -50,5 +55,6 @@ typedef struct dynarec_arm_s {
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
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);
#endif //__DYNAREC_ARM_PRIVATE_H_
+6
View File
@@ -40,6 +40,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_HIPROC);
GO(SHT_LOUSER);
GO(SHT_HIUSER);
#ifdef SHT_GNU_versym
GO(SHT_GNU_versym);
GO(SHT_GNU_ATTRIBUTES);
GO(SHT_GNU_HASH);
@@ -51,6 +52,7 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_SUNW_syminfo);
GO(SHT_GNU_verdef);
GO(SHT_GNU_verneed);
#endif
#undef GO
default:
sprintf(buff, "0x%X unknown type", s->sh_type);
@@ -98,6 +100,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
GO(DT_RUNPATH, 0);
GO(DT_FLAGS, 0);
GO(DT_ENCODING, 0);
#ifdef DT_NUM
GO(DT_NUM, 0);
GO(DT_VALRNGLO, 0);
GO(DT_GNU_PRELINKED, 0);
@@ -133,6 +136,7 @@ const char* DumpDynamic(Elf32_Dyn *s) {
GO(DT_VERNEEDNUM, 0);
GO(DT_AUXILIARY, 0);
GO(DT_FILTER, 0);
#endif
#undef GO
default:
sprintf(buff, "0x%X unknown type", s->d_tag);
@@ -154,11 +158,13 @@ const char* DumpPHEntry(Elf32_Phdr *e)
GO(PT_SHLIB);
GO(PT_PHDR);
GO(PT_TLS);
#ifdef PT_NUM
GO(PT_NUM);
GO(PT_LOOS);
GO(PT_GNU_EH_FRAME);
GO(PT_GNU_STACK);
GO(PT_GNU_RELRO);
#endif
#undef GO
default: sprintf(buff, "type: %x, Off=%x vaddr=%p paddr=%p filesz=%u memsz=%u flags=%x align=%u", e->p_type, e->p_offset, (void*)e->p_vaddr, (void*)e->p_paddr, e->p_filesz, e->p_memsz, e->p_flags, e->p_align); break;
}
+85 -38
View File
@@ -28,6 +28,7 @@
#include "dynarec.h"
#include "box86stack.h"
#ifdef DYNAREC
#include "custommem.h"
#include "dynablock.h"
#endif
#include "../emu/x86emu_private.h"
@@ -64,10 +65,10 @@ void FreeElfHeader(elfheader_t** head)
return;
elfheader_t *h = *head;
#ifdef DYNAREC
if(h->text) {
/*if(h->text) {
dynarec_log(LOG_INFO, "Free Dynarec block for %s\n", h->path);
cleanDBFromAddressRange(h->text, h->textsz, 1);
}
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
}*/ // will be free at the end, no need to free it now
#endif
free(h->name);
free(h->path);
@@ -206,6 +207,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%x/0x%x) for elf \"%s\"\n", (void*)head->multiblock_offs[i], head->multiblock_size[i], head->align, head->name);
return 1;
}
updateProtection((uintptr_t)p, head->multiblock_size[i], PROT_READ | PROT_WRITE | PROT_EXEC);
head->multiblock[i] = p;
if(p<(void*)head->memory)
head->memory = (char*)p;
@@ -221,6 +223,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
printf_log(LOG_NONE, "Cannot create memory map (@%p 0x%x/0x%x) for elf \"%s\"\n", (void*)offs, head->memsz, head->align, head->name);
return 1;
}
updateProtection((uintptr_t)p, head->memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
head->memory = p;
memset(p, 0, head->memsz);
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
@@ -264,13 +267,14 @@ int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
printf_log(LOG_NONE, "Fail to read PT_LOAD part #%d (size=%d)\n", i, e->p_filesz);
return 1;
}
}
#ifdef DYNAREC
if(e->p_flags & PF_X) {
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
addDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
}
if(e->p_flags & PF_X) {
dynarec_log(LOG_DEBUG, "Add ELF eXecutable Memory %p:%p\n", dest, (void*)e->p_memsz);
addDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
}
#endif
}
// zero'd difference between filesz and memsz
/*if(e->p_filesz != e->p_memsz)
memset(dest+e->p_filesz, 0, e->p_memsz - e->p_filesz);*/ //block is already 0'd at creation
@@ -333,6 +337,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
uint32_t *p = (uint32_t*)(rel[i].r_offset + head->delta);
uintptr_t offs = 0;
uintptr_t end = 0;
uintptr_t tmp = 0;
elfheader_t* h_tls = head;
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
@@ -459,7 +464,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int cn
}
break;
case R_386_JMP_SLOT:
if(bind==STB_LOCAL) {
// apply immediatly for gobject closure marshal or for LOCAL binding. Also, apply immediatly if it doesn't jump in the got
tmp = (uintptr_t)(*p);
if (bind==STB_LOCAL
|| ((symname && strstr(symname, "g_cclosure_marshal_")==symname))
|| !tmp
|| !((tmp>=head->plt && tmp<head->plt_end) || (tmp>=head->gotplt && tmp<head->gotplt_end))
) {
if (!offs) {
if(bind==STB_WEAK) {
printf_log(LOG_INFO, "Warning: Weak Symbol %s not found, cannot apply R_386_JMP_SLOT @%p (%p)\n", symname, p, *(void**)p);
@@ -763,7 +774,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
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);
PrependPath(rpath, &box86->box86_ld_lib, 1);
PrependList(&box86->box86_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
free(rpath);
@@ -786,12 +797,27 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
return 0;
}
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
{
if(!h)
return 0;
for (int i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
if(!strcmp(needed, "libtcmalloc_minimal.so.4")) // tcmalloc needs to be the 1st lib loaded
return 1;
else
return 0;
}
return 0;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
return;
// reset Segs Cache
memset(emu->segs_clean, 0, sizeof(emu->segs_clean));
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
uintptr_t p = h->initentry + h->delta;
box86context_t* context = GetEmuContext(emu);
if(context->deferedInit) {
@@ -979,17 +1005,21 @@ void* GetTLSPointer(box86context_t* context, elfheader_t* h)
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
{
// this is one is fast, so start with that
dynablocklist_t* ret = getDBFromAddress(addr);
// if we are here, the there is not block in standard "space"
/*dynablocklist_t* ret = getDBFromAddress(addr);
if(ret) {
return ret;
}*/
if(box86_dynarec_forced) {
addDBFromAddressRange(addr, 1, 1);
return getDB(addr>>DYNAMAP_SHIFT);
}
//check if address is in an elf... if yes, grant a block (should I warn)
Dl_info info;
if(dladdr((void*)addr, &info)) {
dynarec_log(LOG_INFO, "Address %p is in a native Elf memory space (function \"%s\" in %s)\n", (void*)addr, info.dli_sname, info.dli_fname);
return NULL;
}
// nope
if(addr>0x100)
if((*(uint8_t*)addr)==0xCC || (((*(uint8_t*)addr)==0xC3 || (*(uint8_t*)addr)==0xC2) /*&& (*(uint8_t*)(addr-11))==0xCC*/) )
return context->dynablocks;
if(box86_dynarec_forced)
return context->dynablocks;
dynarec_log(LOG_INFO, "Address %p not found in Elf memory and is not a native call wrapper\n", (void*)addr);
return NULL;
}
@@ -1002,29 +1032,49 @@ typedef struct my_dl_phdr_info_s {
int dlpi_phnum;
} my_dl_phdr_info_t;
static int dl_iterate_phdr_callback(x86emu_t *emu, my_dl_phdr_info_t *info, size_t size, void* data)
static int dl_iterate_phdr_callback(x86emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
{
SetCallbackArgs(emu, 2, info, size);
int ret = RunCallback(emu);
int ret = RunFunctionWithEmu(emu, 0, (uintptr_t)F, 3, info, size, data);
return ret;
}
static int dl_iterate_phdr_native(struct dl_phdr_info* info, size_t size, void* data)
{
if(!info->dlpi_name)
return 0;
if(!info->dlpi_name[0]) // don't send informations about box86 itself
return 0;
#define SUPER() \
GO(0) \
GO(1) \
GO(2) \
GO(3) \
GO(4)
x86emu_t* emu = (x86emu_t*)data;
SetCallbackArgs(emu, 2, info, size);
int ret = RunCallback(emu);
return ret;
// 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); \
}
SUPER()
#undef GO
static void* find_dl_iterate_phdr_Fct(void* fct)
{
if(!fct) return fct;
if(GetNativeFnc((uintptr_t)fct)) return GetNativeFnc((uintptr_t)fct);
#define GO(A) if(my_dl_iterate_phdr_fct_##A == (uintptr_t)fct) return my_dl_iterate_phdr_##A;
SUPER()
#undef GO
#define GO(A) if(my_dl_iterate_phdr_fct_##A == 0) {my_dl_iterate_phdr_fct_##A = (uintptr_t)fct; return my_dl_iterate_phdr_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for elfloader dl_iterate_phdr callback\n");
return NULL;
}
#undef SUPER
EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
printf_log(LOG_INFO, "Warning: call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
x86emu_t* cbemu = AddSharedCallback(emu, (uintptr_t)F, 3, NULL, NULL, data, NULL);
box86context_t *context = GetEmuContext(emu);
const char* empty = "";
int ret = 0;
@@ -1034,15 +1084,12 @@ EXPORT int my_dl_iterate_phdr(x86emu_t *emu, void* F, void *data) {
info.dlpi_name = idx?context->elfs[idx]->name:empty; //1st elf is program, and this one doesn't get a name
info.dlpi_phdr = context->elfs[idx]->PHEntries;
info.dlpi_phnum = context->elfs[idx]->numPHEntries;
if((ret = dl_iterate_phdr_callback(cbemu, &info, sizeof(info), data))) {
FreeCallback(cbemu);
if((ret = dl_iterate_phdr_callback(emu, F, &info, sizeof(info), data))) {
return ret;
}
}
// and now, go on native version
ret = dl_iterate_phdr(dl_iterate_phdr_native, cbemu);
// all done
FreeCallback(cbemu);
ret = dl_iterate_phdr(find_dl_iterate_phdr_Fct(F), data);
return ret;
}
+4
View File
@@ -52,8 +52,12 @@ struct elfheader_s {
int pltent;
uint32_t pltrel;
uintptr_t gotplt;
uintptr_t gotplt_end;
uintptr_t pltgot;
uintptr_t got;
uintptr_t got_end;
uintptr_t plt;
uintptr_t plt_end;
uintptr_t text;
int textsz;
+9 -1
View File
@@ -254,12 +254,20 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
int ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got.plt");
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The GOT Table is at address %p\n", (void*)h->got);
h->got_end = h->got + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt");
if(ii) {
h->plt = h->SHEntries[ii].sh_addr;
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
+1
View File
@@ -146,5 +146,6 @@
// Alias
#define GET_EW GET_ED
#define GET_EW_OFFS GET_ED_OFFS
#define EW ED
#define GW GD
+14 -4
View File
@@ -682,7 +682,7 @@
NEXT;
_0f_0xA1: /* POP FS */
emu->segs[_FS] = Pop(emu); // no check, no use....
emu->segs_clean[_FS] = 0;
emu->segs_serial[_FS] = 0;
NEXT;
_0f_0xA2: /* CPUID */
tmp32u = R_EAX;
@@ -716,7 +716,7 @@
NEXT;
_0f_0xA9: /* POP GS */
emu->segs[_GS] = Pop(emu);
emu->segs_clean[_GS] = 0;
emu->segs_serial[_GS] = 0;
NEXT;
@@ -1126,7 +1126,12 @@
GM.uw[i] = (tmp32s < 0) ? 0 : tmp32s;
}
NEXT;
_0f_0xDA: /* PMINUB Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i)
GM.ub[i] = (GM.ub[i]<EM->ub[i])?GM.ub[i]:EM->ub[i];
NEXT;
_0f_0xDB: /* PAND Gm,Em */
nextop = F8;
GET_EM;
@@ -1148,7 +1153,12 @@
GM.uw[i] = (tmp32u>65535) ? 65535 : tmp32u;
}
NEXT;
_0f_0xDE: /* PMAXUB Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i)
GM.ub[i] = (GM.ub[i]>EM->ub[i])?GM.ub[i]:EM->ub[i];
NEXT;
_0f_0xDF: /* PANDN Gm,Em */
nextop = F8;
GET_EM;
+50 -8
View File
@@ -2,16 +2,29 @@
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;
@@ -30,7 +43,7 @@
NEXT;
_66_0x07: /* POP ES */
emu->segs[_ES] = Pop16(emu); // no check, no use....
emu->segs_clean[_ES] = 0;
emu->segs_serial[_ES] = 0;
NEXT;
_66_0x0F: /* 66 0f prefix */
@@ -39,6 +52,12 @@
Run660F(emu); // implemented in Run660f.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0x1F: /* POP DS */
emu->segs[_DS] = Pop16(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
NEXT;
_66_0x26: /* ES: */
@@ -215,7 +234,7 @@
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_clean[((nextop&0x38)>>3)] = 0;
emu->segs_serial[((nextop&0x38)>>3)] = 0;
NEXT;
_66_0x8F: /* POP Ew */
nextop = F8;
@@ -246,15 +265,12 @@
_66_0x9C: /* PUSHFW */
CHECK_FLAGS(emu);
PackFlags(emu);
Push16(emu, (uint16_t)emu->packed_eflags.x32);
Push16(emu, (uint16_t)emu->eflags.x32);
NEXT;
_66_0x9D: /* POPFW */
CHECK_FLAGS(emu);
PackFlags(emu);
emu->packed_eflags.x32 &=0xffff0000;
emu->packed_eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
UnpackFlags(emu);
emu->eflags.x32 &=0xffff0000;
emu->eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
NEXT;
_66_0xA1: /* MOV AX,Ow */
@@ -332,6 +348,22 @@
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;
@@ -355,6 +387,7 @@
Run66D9(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xDD:
@@ -363,8 +396,17 @@
Run66DD(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF0: /* LOCK prefix */
emu->old_ip = R_EIP;
R_EIP = ip;
RunLock66(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF2: /* REPNZ prefix */
_66_0xF3: /* REPZ prefix */
+2 -2
View File
@@ -111,7 +111,7 @@
break;
case 2: /* FIST Ed, ST0 */
GET_ED;
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
@@ -120,7 +120,7 @@
break;
case 3: /* FISTP Ed, ST0 */
GET_ED;
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff) || !isfinite(ST0.d))
ED->sdword[0] = 0x80000000;
else {
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
+23 -25
View File
@@ -98,28 +98,14 @@
break;
case 2: /* FIST Ew, ST0 */
GET_EW;
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else {
switch(emu->round) {
case ROUND_Nearest:
EW->sword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
EW->sword[0] = floor(ST0.d);
break;
case ROUND_Up:
EW->sword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
EW->sword[0] = ST0.d;
break;
}
}
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))
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff) || !isfinite(ST0.d))
EW->sword[0] = 0x8000;
else
EW->sword[0] = fpu_round(emu, ST0.d);
@@ -145,14 +131,26 @@
break;
case 7: /* FISTP i64 */
GET_ED;
if(STll(0).ref==ST(0).ll) {
*(int64_t*)ED = STll(0).ll;
} else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL))
*(int64_t*)ED = 0x8000000000000000LL;
if((uintptr_t)ED & 0x7) {
// un-aligned!
if(STll(0).ref==ST(0).ll)
memcpy(ED, &STll(0).ll, sizeof(int64_t));
else {
int64_t i64 = fpu_round(emu, ST0.d);
*(int64_t*)ED = i64;
int64_t i64;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
i64 = 0x8000000000000000LL;
else
i64 = fpu_round(emu, ST0.d);
memcpy(ED, &i64, sizeof(int64_t));
}
} else {
if(STll(0).ref==ST(0).ll)
*(int64_t*)ED = STll(0).ll;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = fpu_round(emu, ST0.d);
}
}
fpu_do_pop(emu);
+9
View File
@@ -230,6 +230,15 @@
GX.q[0]=(tmp8s)?0xffffffffffffffffLL:0LL;
break;
case 0xD0: /* ADDSUBPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] -= EX->f[0];
GX.f[1] += EX->f[1];
GX.f[2] -= EX->f[2];
GX.f[3] += EX->f[3];
break;
case 0xD6: /* MOVDQ2Q Gm, Ex */
nextop = F8;
GET_EX;
+13
View File
@@ -15,6 +15,19 @@
GET_EX;
EX->ud[0] = GX.ud[0];
break;
case 0x12: /* MOVSLDUP Gx, Ex */
nextop = F8;
GET_EX;
GX.ud[1] = GX.ud[0] = EX->ud[0];
GX.ud[3] = GX.ud[2] = EX->ud[2];
break;
case 0x16: /* MOVSHDUP Gx, Ex */
nextop = F8;
GET_EX;
GX.ud[1] = GX.ud[0] = EX->ud[1];
GX.ud[3] = GX.ud[2] = EX->ud[3];
break;
case 0x1E: /* NOP / ENDBR32 / ENDBR64 */
nextop = F8;
+22 -7
View File
@@ -15,6 +15,9 @@
#include "x86run.h"
#include "x86run_private.h"
#include "callback.h"
#ifdef DYNAREC
#include "custommem.h"
#endif
typedef struct cleanup_s {
void* f;
@@ -35,6 +38,13 @@ static uint32_t x86emu_parity_tab[8] =
};
static uint8_t EndEmuMarker[] = {0xcc, 'S', 'C', 0, 0, 0, 0};
#ifdef DYNAREC
void DynablockEmuMarker(box86context_t* context)
{
dynarec_log(LOG_DUMP, "Create bridge memory map for PushExit\n");
addDBFromAddressRange((uintptr_t)&EndEmuMarker[0], sizeof(EndEmuMarker), 0);
}
#endif
void PushExit(x86emu_t* emu)
{
Push(emu, (uint32_t)&EndEmuMarker);
@@ -53,8 +63,7 @@ static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t s
emu->sbiidx[i] = &emu->regs[i];
emu->sbiidx[4] = &emu->zero;
emu->x86emu_parity_tab = x86emu_parity_tab;
emu->packed_eflags.x32 = 0x202; // default flags?
UnpackFlags(emu);
emu->eflags.x32 = 0x202; // default flags?
// own stack?
emu->stack2free = (ownstack)?(void*)stack:NULL;
emu->init_stack = (void*)stack;
@@ -170,7 +179,7 @@ void FreeX86Emu(x86emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "Free a X86 Emu (%p)\n", *emu);
printf_log(LOG_DEBUG, "%04d|Free a X86 Emu (%p)\n", GetTID(), *emu);
internalFreeX86(*emu);
@@ -182,7 +191,7 @@ void FreeX86EmuFromStack(x86emu_t **emu)
{
if(!emu)
return;
printf_log(LOG_DEBUG, "Free a X86 Emu from stack (%p)\n", *emu);
printf_log(LOG_DEBUG, "%04d|Free a X86 Emu from stack (%p)\n", GetTID(), *emu);
internalFreeX86(*emu);
}
@@ -191,11 +200,10 @@ void CloneEmu(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->packed_eflags, &emu->packed_eflags, sizeof(emu->packed_eflags));
memcpy(&newemu->flags, &emu->flags, sizeof(emu->flags));
memcpy(&newemu->eflags, &emu->eflags, sizeof(emu->eflags));
newemu->old_ip = emu->old_ip;
memcpy(newemu->segs, emu->segs, sizeof(emu->segs));
memset(newemu->segs_clean, 0, sizeof(newemu->segs_clean));
memset(newemu->segs_serial, 0, sizeof(newemu->segs_serial));
memcpy(newemu->fpu, emu->fpu, sizeof(emu->fpu));
memcpy(newemu->fpu_ld, emu->fpu_ld, sizeof(emu->fpu_ld));
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
@@ -460,3 +468,10 @@ uint64_t ReadTSC(x86emu_t* emu)
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#endif
}
void ResetSegmentsCache(x86emu_t *emu)
{
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
+7 -6
View File
@@ -25,9 +25,9 @@ typedef struct forkpty_s {
typedef struct x86emu_s {
// cpu
reg32_t regs[8],ip;
int flags[F_LAST];
x86flags_t packed_eflags;
reg32_t regs[8];
x86flags_t eflags;
reg32_t ip;
uintptr_t old_ip;
// fpu
fpu_reg_t fpu[9];
@@ -56,7 +56,7 @@ typedef struct x86emu_s {
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
int segs_clean[6]; // are seg offset clean (1) or does they need to be re-computed (0)?
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
@@ -65,12 +65,13 @@ typedef struct x86emu_s {
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
// parent context
box86context_t *context;
#ifdef DYNAREC
// virtual return stack
int cstacki; // current index
uint64_t cstack[CSTACK+1]; // pair of x86 address / native address for call/ret, using uint64_t for alignement, +1 for allignment
#endif
// parent context
box86context_t *context;
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
+50 -16
View File
@@ -1,3 +1,5 @@
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -7,6 +9,7 @@
#include <sys/syscall.h>
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include "debug.h"
#include "box86stack.h"
@@ -67,6 +70,9 @@ void x86Int3(x86emu_t* emu)
if(Peek(emu, 0)=='S' && Peek(emu, 1)=='C') // Signature for "Out of x86 door"
{
R_EIP += 2;
#ifdef RK3399
volatile // to avoid addr to be put in an VFPU register
#endif
uint32_t addr = Fetch32(emu);
if(addr==0) {
//printf_log(LOG_INFO, "%p:Exit x86 emu (emu=%p)\n", *(void**)(R_ESP), emu);
@@ -89,7 +95,13 @@ void x86Int3(x86emu_t* emu)
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = GetNativeName((void*)addr);
const char *s = NULL;
{
Dl_info info;
if(dladdr((void*)addr, &info))
s = info.dli_sname;
}
if(!s) s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else
@@ -113,9 +125,16 @@ void x86Int3(x86emu_t* emu)
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "mkdir")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
@@ -137,16 +156,22 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "__xstat64")==s) {
} else if(strstr(s, "my___xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
} else if(strcmp(s, "my___xstat")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "my___lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "sem_timedwait")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p[%d sec %d ns])", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
perr = 1;
} else if(strstr(s, "waitpid")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, 0x%x)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "clock_gettime")==s || strstr(s, "__clock_gettime")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
post = 1;
@@ -155,10 +180,10 @@ void x86Int3(x86emu_t* emu)
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/%d], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "mmap64")) {
} else if(!strcmp(s, "my_mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 1;
} else if(!strcmp(s, "mmap")) {
} else if(!strcmp(s, "my_mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 1;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
@@ -171,36 +196,42 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "vsnprintf")==s) {
} else if(strstr(s, "my_vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "vsprintf")==s) {
} else if(strstr(s, "my_vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "snprintf")==s) {
} else if(strstr(s, "my_snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "sprintf")==s) {
} else if(strstr(s, "my_sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "printf")==s) {
} else if(strstr(s, "my_printf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "fprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "my_fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "vfprintf")==s) {
} else if(strstr(s, "my_vfprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "sscanf")==s) {
} else if(strstr(s, "vkGetInstanceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "vkGetDeviceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "my_sscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "vsscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "XCreateWindow")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, %u, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
@@ -220,7 +251,7 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "syscall")) {
} else if(!strcmp(s, "my_syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else {
@@ -260,7 +291,10 @@ void x86Int3(x86emu_t* emu)
}
return;
}
printf_log(LOG_INFO, "Warning, ignoring unsupported Int 3 call\n");
if(my_context->signals[SIGTRAP])
raise(SIGTRAP);
else
printf_log(LOG_INFO, "Warning, ignoring unsupported Int 3 call\n");
//emu->quit = 1;
}
+62 -48
View File
@@ -19,6 +19,7 @@
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
@@ -125,7 +126,7 @@ int Run(x86emu_t *emu, int step)
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_0f_0xC3, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
&&_0f_0xC8, &&_0f_0xC9, &&_0f_0xCA, &&_0f_0xCB, &&_0f_0xCC, &&_0f_0xCD, &&_0f_0xCE, &&_0f_0xCF, //0xC8-0xCF
&&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7
&&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF
&&_0f_0xD8, &&_0f_0xD9, &&_0f_0xDA, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_0f_0xDE, &&_0f_0xDF, //0xD8-0xDF
&&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_0f_0xE7, //0xE0-0xE7
&&_0f_0xE8, &&_0f_0xE9, &&_0f_0xEA, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_0f_0xEE, &&_0f_0xEF, //0xE8-0xEF
&&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_0f_0xF7, //0xF0-0xF7
@@ -133,13 +134,13 @@ int Run(x86emu_t *emu, int step)
};
static const void* opcodes66[256] = {
&&_default, &&_66_0x00_1, &&_default, &&_66_0x00_3, &&_default ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07
&&_default, &&_66_0x08_1, &&_default, &&_66_0x08_3, &&_default ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F
&&_default, &&_66_0x10_1, &&_default, &&_66_0x10_3, &&_default ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17
&&_default, &&_66_0x18_1, &&_default, &&_66_0x18_3, &&_default ,&&_66_0x18_5, &&_default, &&_default, //0x18-0x1F
&&_default, &&_66_0x20_1, &&_default, &&_66_0x20_3, &&_default ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27
&&_default, &&_66_0x28_1, &&_default, &&_66_0x28_3, &&_default ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F
&&_default, &&_66_0x30_1, &&_default, &&_66_0x30_3, &&_default ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37
&&_66_0x00_0, &&_66_0x00_1, &&_66_0x00_2, &&_66_0x00_3, &&_66_0x00_4 ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07
&&_66_0x08_0, &&_66_0x08_1, &&_66_0x08_2, &&_66_0x08_3, &&_66_0x08_4 ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F
&&_66_0x10_0, &&_66_0x10_1, &&_66_0x10_2, &&_66_0x10_3, &&_66_0x10_4 ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17
&&_66_0x18_0, &&_66_0x18_1, &&_66_0x18_2, &&_66_0x18_3, &&_66_0x18_4 ,&&_66_0x18_5, &&_default, &&_66_0x1F, //0x18-0x1F
&&_66_0x20_0, &&_66_0x20_1, &&_66_0x20_2, &&_66_0x20_3, &&_66_0x20_4 ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27
&&_66_0x28_0, &&_66_0x28_1, &&_66_0x28_2, &&_66_0x28_3, &&_66_0x28_4 ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F
&&_66_0x30_0, &&_66_0x30_1, &&_66_0x30_2, &&_66_0x30_3, &&_66_0x30_4 ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37
&&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_default, &&_default, //0x38-0x3F
&&_66_0x40, &&_66_0x41, &&_66_0x42, &&_66_0x43, &&_66_0x44, &&_66_0x45, &&_66_0x46, &&_66_0x47,
&&_66_0x48, &&_66_0x49, &&_66_0x4A, &&_66_0x4B, &&_66_0x4C, &&_66_0x4D, &&_66_0x4E, &&_66_0x4F,
@@ -158,18 +159,17 @@ int Run(x86emu_t *emu, int step)
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xB0-0xB7
&&_66_0xB8, &&_66_0xB9, &&_66_0xBA, &&_66_0xBB, &&_66_0xBC, &&_66_0xBD, &&_66_0xBE, &&_66_0xBF,
&&_default, &&_66_0xC1, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xC7,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF
&&_default, &&_default, &&_default, &&_66_0xCB, &&_66_0xCC ,&&_default, &&_default, &&_default, //0xC8-0xCF
&&_default, &&_66_0xD1, &&_default, &&_66_0xD3, &&_default, &&_default, &&_default, &&_default, //0xD0-0xD7
&&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF
&&_default, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
};
x86emurun:
ip = R_EIP;
// UnpackFlags(emu);
#ifdef HAVE_TRACE
_trace:
__builtin_prefetch((void*)ip, 0, 0);
@@ -262,7 +262,7 @@ _trace:
NEXT;
_0x07: /* POP ES */
emu->segs[_ES] = Pop(emu); // no check, no use....
emu->segs_clean[_ES] = 0;
emu->segs_serial[_ES] = 0;
NEXT;
_0x0E: /* PUSH CS */
@@ -277,7 +277,7 @@ _trace:
NEXT;
_0x17: /* POP SS */
emu->segs[_SS] = Pop(emu); // no check, no use....
emu->segs_clean[_SS] = 0;
emu->segs_serial[_SS] = 0;
NEXT;
_0x1E: /* PUSH DS */
@@ -285,7 +285,7 @@ _trace:
NEXT;
_0x1F: /* POP DS */
emu->segs[_DS] = Pop(emu); // no check, no use....
emu->segs_clean[_DS] = 0;
emu->segs_serial[_DS] = 0;
NEXT;
_0x26: /* ES: */
@@ -398,6 +398,7 @@ _trace:
RunFS(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x65: /* GS: */
emu->old_ip = R_EIP;
@@ -405,6 +406,7 @@ _trace:
RunGS(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x66: /* Prefix to change width of intructions, so here, down to 16bits */
@@ -415,6 +417,7 @@ _trace:
Run67(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x68: /* Push Id */
@@ -641,13 +644,11 @@ _trace:
// 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
do {
tmp32u = arm_lock_read_d(ED);
} while(arm_lock_write_d(ED, GD.dword[0]));
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
}
GD.dword[0] = tmp32u;
}
#else
GET_ED;
@@ -694,12 +695,21 @@ _trace:
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_clean[((nextop&0x38)>>3)] = 0;
emu->segs_serial[((nextop&0x38)>>3)] = 0;
if(((nextop&0x38)>>3)==_FS)
default_fs = EW->word[0];
NEXT;
_0x8F: /* POP Ed */
nextop = F8;
GET_ED;
ED->dword[0] = Pop(emu);
if((nextop&0xC0)==0xC0) {
emu->regs[(nextop&7)].dword[0] = Pop(emu);
} else {
tmp32u = Pop(emu); // this order allows handling POP [ESP] and variant
GET_ED;
R_ESP -= 4; // to prevent issue with SEGFAULT
ED->dword[0] = tmp32u;
R_ESP += 4;
}
NEXT;
_0x90: /* NOP */
NEXT;
@@ -726,12 +736,10 @@ _trace:
NEXT;
_0x9C: /* PUSHF */
CHECK_FLAGS(emu);
PackFlags(emu);
Push(emu, emu->packed_eflags.x32);
Push(emu, emu->eflags.x32);
NEXT;
_0x9D: /* POPF */
emu->packed_eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
NEXT;
_0x9E: /* SAHF */
@@ -745,8 +753,7 @@ _trace:
NEXT;
_0x9F: /* LAHF */
CHECK_FLAGS(emu);
PackFlags(emu);
R_AH = (uint8_t)emu->packed_eflags.x32;
R_AH = (uint8_t)emu->eflags.x32;
NEXT;
_0xA0: /* MOV AL,Ob */
@@ -893,14 +900,14 @@ _trace:
nextop = F8;
GET_ED;
emu->segs[_ES] = ED->word[0];
emu->segs_clean[_ES] = 0;
emu->segs_serial[_ES] = 0;
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
NEXT;
_0xC5: /* LDS Gd,Ed */
nextop = F8;
GET_ED;
emu->segs[_DS] = ED->word[0];
emu->segs_clean[_DS] = 0;
emu->segs_serial[_DS] = 0;
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
NEXT;
_0xC6: /* MOV Eb,Ib */
@@ -938,7 +945,7 @@ _trace:
_0xCB: /* FAR RET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu); // no check, no use....
emu->segs_clean[_CS] = 0;
emu->segs_serial[_CS] = 0;
// need to check status of CS register!
STEP
NEXT;
@@ -971,9 +978,8 @@ _trace:
_0xCF: /* IRET */
ip = Pop(emu);
emu->segs[_CS] = Pop(emu);
emu->segs_clean[_CS] = 0;
emu->packed_eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
UnpackFlags(emu);
emu->segs_serial[_CS] = 0;
emu->eflags.x32 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
NEXT;
_0xD0: /* GRP2 Eb,1 */
@@ -1053,6 +1059,7 @@ _trace:
--R_ECX; // don't update flags
if(R_ECX && !ACCESS_FLAG(F_ZF))
ip += tmp8s;
STEP
NEXT;
_0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
@@ -1060,19 +1067,20 @@ _trace:
--R_ECX; // don't update flags
if(R_ECX && ACCESS_FLAG(F_ZF))
ip += tmp8s;
STEP
NEXT;
_0xE2: /* LOOP */
tmp8s = F8S;
--R_ECX; // don't update flags
if(R_ECX)
ip += tmp8s;
STEP
NEXT;
_0xE3: /* JECXZ */
tmp8s = F8S;
if(!R_ECX) {
if(!R_ECX)
ip += tmp8s;
STEP
}
STEP
NEXT;
_0xE4: /* IN AL, Ib */
tmp32s = F8; // port address
@@ -1133,6 +1141,7 @@ _trace:
} else {
#include "runf20f.h"
}
STEP
NEXT;
} else if(nextop==0x66) {
nextop = F8;
@@ -1427,7 +1436,8 @@ _trace:
switch((nextop>>3)&7) {
case 0:
case 1: /* TEST Eb,Ib */
test8(emu, EB->byte[0], F8);
tmp8u = F8;
test8(emu, EB->byte[0], tmp8u);
break;
case 2: /* NOT Eb */
EB->byte[0] = not8(emu, EB->byte[0]);
@@ -1455,7 +1465,8 @@ _trace:
switch((nextop>>3)&7) {
case 0:
case 1: /* TEST Ed,Id */
test32(emu, ED->dword[0], F32);
tmp32u = F32;
test32(emu, ED->dword[0], tmp32u);
break;
case 2: /* NOT Ed */
ED->dword[0] = not32(emu, ED->dword[0]);
@@ -1500,6 +1511,7 @@ _trace:
NEXT;
_0xFE: /* GRP 5 Eb */
nextop = F8;
tmp32u2 = ip;
GET_EB;
switch((nextop>>3)&7) {
case 0: /* INC Eb */
@@ -1510,8 +1522,8 @@ _trace:
break;
default:
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1519,6 +1531,7 @@ _trace:
NEXT;
_0xFF: /* GRP 5 Ed */
nextop = F8;
tmp32u2 = ip;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
@@ -1528,15 +1541,16 @@ _trace:
ED->dword[0] = dec32(emu, ED->dword[0]);
break;
case 2: /* CALL NEAR Ed */
tmp32u = (uintptr_t)getAlternate((void*)ED->dword[0]);
Push(emu, ip);
ip = ED->dword[0]; // should get value in temp var. in case ED use ESP?
ip = tmp32u;
STEP
break;
case 3: /* CALL FAR Ed */
if(nextop>0xc0) {
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1549,14 +1563,14 @@ _trace:
}
break;
case 4: /* JMP NEAR Ed */
ip = ED->dword[0];
ip = (uintptr_t)getAlternate((void*)ED->dword[0]);
STEP
break;
case 5: /* JMP FAR Ed */
if(nextop>0xc0) {
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: 0x%02X 0x%02X %02X %02X\n", (void*)ip, opcode, nextop, PK(2), PK(3));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
@@ -1572,8 +1586,8 @@ _trace:
break;
default:
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X %02X %02X %02X %02X\n", opcode, nextop, PK(2), PK(3), PK(4), PK(5));
R_EIP = ip = tmp32u2;
printf_log(LOG_NONE, "Illegal Opcode %p: %02X %02X %02X %02X %02X %02X\n",(void*)ip, opcode, nextop, PK(2), PK(3), PK(4), PK(5));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
goto fini;
+214 -14
View File
@@ -288,16 +288,32 @@ void RunLock(x86emu_t *emu)
nextop = F8;
GET_ED;
#ifdef DYNAREC
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);
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]);
@@ -455,10 +471,19 @@ void RunLock(x86emu_t *emu)
nextop = F8;
GET_ED;
#ifdef DYNAREC
do {
tmp32u = arm_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD.dword[0]);
} while(arm_lock_write_d(ED, tmp32u2));
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);
@@ -473,6 +498,32 @@ void RunLock(x86emu_t *emu)
nextop = F8;
GET_ED;
#ifdef DYNAREC
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) {
@@ -547,6 +598,16 @@ void RunLock(x86emu_t *emu)
case 0x87: /* XCHG Ed,Gd */
ip--; // let the normal XCHG execute, it have integrated LOCK
break;
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
ip--;
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GET_ED;
@@ -588,6 +649,93 @@ void RunLock(x86emu_t *emu)
R_EIP = ip;
}
void RunLock66(x86emu_t *emu)
{
uintptr_t ip = R_EIP+2;
uint8_t opcode = F8;
uint8_t nextop;
reg32_t *oped;
uint16_t tmp16u, tmp16u2;
int16_t tmp16s;
int32_t tmp32s;
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:
ip-=4; // unfetch nextop, 0F, F0 & 66
UnimpOpcode(emu);
}
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;
default:
ip-=3; // unfetch nextop, F0 & 66
UnimpOpcode(emu);
// should trigger invalid unlock ?
}
R_EIP = ip;
}
void RunGS(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
@@ -823,6 +971,29 @@ void RunFS(x86emu_t *emu)
int32_t tmp32s;
uintptr_t tlsdata = GetFSBaseEmu(emu);
switch(opcode) {
case 0x01: /* ADD FS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = add32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x03: /* ADD Gd, FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = add32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x11: /* ADC FS:Ed, Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = adc32(emu, ED->dword[0], GD.dword[0]);
case 0x2B: /* SUB Gd, FS:Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
GD.dword[0] = sub32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x33: /* XOR Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -854,6 +1025,19 @@ void RunFS(x86emu_t *emu)
--ip; // so ignore prefix and continue
break;
case 0x66:
opcode = F8;
switch(opcode) {
case 0x8B: /* MOV Gw,FS:Ew */
nextop = F8;
GET_EW_OFFS(tlsdata);
GW.word[0] = EW->word[0];
break;
default:
ip-=2;
UnimpOpcode(emu);
}
break;
case 0x67:
opcode = F8;
switch(opcode) {
@@ -953,11 +1137,27 @@ void RunFS(x86emu_t *emu)
GET_ED_OFFS(tlsdata);
GD.dword[0] = ED->dword[0];
break;
case 0x8C: /* MOV FS:Ed, Seg */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8E: /* MOV Seg,FS: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 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);
+15 -4
View File
@@ -66,7 +66,7 @@ void Run660F(x86emu_t *emu)
&&_default, &&_default, &&_6f_0xBA, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
&&_6f_0xC8, &&_6f_0xC9, &&_6f_0xCA, &&_6f_0xCB, &&_6f_0xCC ,&&_6f_0xCD, &&_6f_0xCE, &&_6f_0xCF, //0xC8-0xCF
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
&&_6f_0xD0, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
&&_6f_0xD8, &&_6f_0xD9, &&_6f_0xDA, &&_6f_0xDB, &&_6f_0xDC, &&_6f_0xDD, &&_6f_0xDE, &&_6f_0xDF,
&&_6f_0xE0, &&_6f_0xE1, &&_6f_0xE2, &&_6f_0xE3, &&_6f_0xE4, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
@@ -188,12 +188,18 @@ void Run660F(x86emu_t *emu)
_6f_0x12: /* MOVLPD Gx, Eq */
nextop = F8;
GET_ED;
GX.q[0] = *(uint64_t*)ED;
if((uintptr_t)ED & 7)
memcpy(&GX.q[0], ED, 8);
else
GX.q[0] = *(uint64_t*)ED;
NEXT;
_6f_0x13: /* MOVLPD Eq, Gx */
nextop = F8;
GET_ED;
*(uint64_t*)ED = GX.q[0];
if((uintptr_t)ED & 7)
memcpy(ED, &GX.q[0], 8);
else
*(uint64_t*)ED = GX.q[0];
NEXT;
_6f_0x14: /* UNPCKLPD Gx, Ex */
nextop = F8;
@@ -1103,7 +1109,12 @@ void Run660F(x86emu_t *emu)
tmp8s = opcode&7;
emu->regs[tmp8s].word[0] = __builtin_bswap16(emu->regs[tmp8s].word[0]);
NEXT;
_6f_0xD0: /* ADDSUBPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] -= EX->d[0];
GX.d[1] += EX->d[1];
NEXT;
_6f_0xD1: /* PSRLW Gx, Ex */
nextop = F8;
GET_EX;
+13 -70
View File
@@ -56,23 +56,24 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
const char* GetNativeName(void* p)
{
static char unknown[10] = "???";
const char *ret = GetNameOffset(my_context->maplib, p);
if(ret)
return ret;
static char buff[500] = {0};
Dl_info info;
if(dladdr(p, &info)==0)
return unknown;
else {
if(dladdr(p, &info)==0) {
const char *ret = GetNameOffset(my_context->maplib, p);
if(ret)
return ret;
sprintf(buff, "%s(%p)", "???", p);
return buff;
} else {
if(info.dli_sname) {
strcpy(buff, info.dli_sname);
if(info.dli_fname) {
strcat(buff, " ("); strcat(buff, info.dli_fname); strcat(buff, ")");
}
} else
return unknown;
} else {
sprintf(buff, "%s(%s/%p)", "???", info.dli_fname, p);
return buff;
}
}
return buff;
}
@@ -684,69 +685,11 @@ void UpdateFlags(x86emu_t *emu)
RESET_FLAGS(emu);
}
void PackFlags(x86emu_t* emu)
{
#define GO(A) emu->packed_eflags.f.F__##A = emu->flags[F_##A];
#define GOC(A, C) emu->packed_eflags.f.F__##A = C;
GO(CF);
GOC(res1, 1);
GO(PF);
GOC(res2, 0);
GO(AF);
GOC(res3, 0);
GO(ZF);
GO(SF);
GO(TF);
GO(IF);
GO(DF);
GO(OF);
GO(IOPL);
GO(NT);
GOC(dummy, 0);
GO(RF);
GO(VM);
GO(AC);
GO(VIF);
GO(VIP);
GO(ID);
#undef GO
#undef GOC
}
void UnpackFlags(x86emu_t* emu)
{
#define GO(A) emu->flags[F_##A] = emu->packed_eflags.f.F__##A;
#define GOC(A, C) emu->flags[F_##A] = C;
GO(CF);
GOC(res1, 1);
GO(PF);
GOC(res2, 0);
GO(AF);
GOC(res3, 0);
GO(ZF);
GO(SF);
GO(TF);
GO(IF);
GO(DF);
GO(OF);
GO(IOPL);
GO(NT);
GOC(dummy, 0);
GO(RF);
GO(VM);
GO(AC);
GO(VIF);
GO(VIP);
GO(ID);
#undef GO
#undef GOC
}
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg)
{
if(!emu->segs_clean[seg] || seg==_GS) {
if(emu->segs_serial[seg] != emu->context->sel_serial) {
emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
emu->segs_clean[seg] = 1;
emu->segs_serial[seg] = emu->context->sel_serial;
}
return emu->segs_offs[seg];
}
+1 -3
View File
@@ -202,14 +202,12 @@ void Run6766(x86emu_t *emu);
void RunGS(x86emu_t *emu);
void RunFS(x86emu_t *emu);
void RunLock(x86emu_t *emu);
void RunLock66(x86emu_t *emu);
void x86Syscall(x86emu_t *emu);
void x86Int3(x86emu_t* emu);
x86emu_t* x86emu_fork(x86emu_t* e, int forktype);
void PackFlags(x86emu_t* emu);
void UnpackFlags(x86emu_t* emu);
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg);
#define GetGSBaseEmu(emu) GetSegmentBaseEmu(emu, _GS)
#define GetFSBaseEmu(emu) GetSegmentBaseEmu(emu, _FS)
+52 -5
View File
@@ -56,6 +56,9 @@ typedef struct x86_sigaction_s x86_sigaction_t;
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
int32_t my_open(x86emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
#ifndef __NR_memfd_create
int my_memfd_create(x86emu_t* emu, void* name, uint32_t flags);
#endif
#ifndef NOALIGN
int my_epoll_create(x86emu_t* emu, int size);
@@ -65,6 +68,10 @@ int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxeven
#endif
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
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);
int my_munmap(x86emu_t* emu, void* addr, unsigned long length);
int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
@@ -126,7 +133,7 @@ scwrap_t syscallwrap[] = {
{ 82, __NR_select, 5 },
#endif
{ 85, __NR_readlink, 3 },
{ 91, __NR_munmap, 2 },
//{ 91, __NR_munmap, 2 },
{ 94, __NR_fchmod, 2 },
{ 99, __NR_statfs, 2 },
#ifdef __NR_socketcall
@@ -163,7 +170,7 @@ scwrap_t syscallwrap[] = {
//{ 120, __NR_clone, 5 }, // need works
//{ 122, __NR_uname, 1 },
//{ 123, __NR_modify_ldt },
{ 125, __NR_mprotect, 3 },
//{ 125, __NR_mprotect, 3 },
{ 136, __NR_personality, 1 },
{ 140, __NR__llseek, 5 },
{ 141, __NR_getdents, 3 },
@@ -187,19 +194,30 @@ scwrap_t syscallwrap[] = {
{ 183, __NR_getcwd, 2 },
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
{ 191, __NR_ugetrlimit, 2 },
{ 192, __NR_mmap2, 6},
// { 192, __NR_mmap2, 6},
//{ 195, __NR_stat64, 2 }, // need proprer wrap because of structure size change
//{ 196, __NR_lstat64, 2 }, // need proprer wrap because of structure size change
//{ 197, __NR_fstat64, 2 }, // need proprer wrap because of structure size change
#ifndef POWERPCLE
{ 199, __NR_getuid32, 0 },
{ 200, __NR_getgid32, 0 },
{ 201, __NR_geteuid32, 0 },
{ 202, __NR_getegid32, 0 },
{ 208, __NR_setresuid32, 3 },
#else
// PowerPC uses the same syscalls for 32/64 bit processes.
{ 199, __NR_getuid, 0 },
{ 200, __NR_getgid, 0 },
{ 201, __NR_geteuid, 0 },
{ 202, __NR_getegid, 0 },
{ 208, __NR_setresuid, 3 },
#endif
{ 220, __NR_getdents64, 3 },
//{ 221, __NR_fcntl64, 3 },
{ 224, __NR_gettid, 0 },
{ 240, __NR_futex, 6 },
{ 241, __NR_sched_setaffinity, 3 },
{ 242, __NR_sched_getaffinity, 3 },
{ 252, __NR_exit_group, 1 },
#ifdef NOALIGN
{ 254, __NR_epoll_create, 1 },
@@ -212,12 +230,16 @@ scwrap_t syscallwrap[] = {
{ 271, __NR_utimes, 2 },
{ 311, __NR_set_robust_list, 2 },
{ 312, __NR_get_robust_list, 4 },
{ 318, __NR_getcpu, 3},
#ifdef NOALIGN
{ 329, __NR_epoll_create1, 1 },
#endif
#ifdef __NR_getrandom
{ 355, __NR_getrandom, 3 },
#endif
#ifdef __NR_memfd_create
{ 356, __NR_memfd_create, 2},
#endif
};
struct mmap_arg_struct {
@@ -323,7 +345,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 1: // sys_exit
emu->quit = 1;
emu->exit = 1;
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the program now
//R_EAX = syscall(__NR_exit, R_EBX); // the syscall should exit only current thread
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the thread now
break;
case 3: // sys_read
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
@@ -387,9 +410,12 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 90: // old_mmap
{
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
R_EAX = (uintptr_t)mmap((void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
R_EAX = (uintptr_t)my_mmap(emu, (void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
}
break;
case 91: // munmap
R_EAX = my_munmap(emu, (void*)R_EBX, (unsigned long)R_ECX);
break;
#ifndef __NR_socketcall
case 102: {
unsigned long *args = (unsigned long *)R_ECX;
@@ -501,6 +527,9 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 123: // SYS_modify_ldt
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
break;
case 125: // mprotect
R_EAX = my_mprotect(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX);
break;
case 168: // sys_poll
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
break;
@@ -517,6 +546,9 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
break;
case 192: // mmap2
R_EAX = (uint32_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
break;
case 195: // stat64
{
struct stat64 st;
@@ -577,6 +609,11 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 355: // getrandom
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
break;
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
@@ -630,10 +667,16 @@ 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));
case 91: // munmap
return (uint32_t)my_munmap(emu, p(4), u32(8));
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 125: // mprotect
return (uint32_t)my_mprotect(emu, p(4), u32(8), i32(12));
case 174: // sys_rt_sigaction
return (uint32_t)my_sigaction(emu, i32(4), (x86_sigaction_t*)p(8), (x86_sigaction_t*)p(12));
case 192: // mmap2
return (uint32_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
case 243: // set_thread_area
return my_set_thread_area((thread_area_t*)p(4));
#ifndef NOALIGN
@@ -661,6 +704,10 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
#ifndef __NR_getrandom
case 355: // getrandom
return (uint32_t)my_getrandom(emu, p(4), u32(8), u32(12));
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
+4
View File
@@ -89,6 +89,8 @@ uint32_t my_set_thread_area(thread_area_t* td)
pthread_setspecific(my_context->segtls[idx-7].key, (void*)my_context->segtls[idx-7].base);
ResetSegmentsCache(thread_get_emu());
return 0;
}
@@ -120,6 +122,8 @@ uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size)
my_context->segtls[idx].limit = td->limit;
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
*/
ResetSegmentsCache(thread_get_emu());
return 0;
}
+15 -15
View File
@@ -92,27 +92,27 @@ static inline void fpu_fcom(x86emu_t* emu, double b)
static inline void fpu_fcomi(x86emu_t* emu, double b)
{
RESET_FLAGS(emu);
emu->flags[F_AF] = 0;
emu->flags[F_OF] = 0;
emu->flags[F_SF] = 0;
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
emu->sw.f.F87_C1 = 0;
if(isnan(ST0.d) || isnan(b)) {
emu->flags[F_CF] = 1;
emu->flags[F_PF] = 1;
emu->flags[F_ZF] = 1;
SET_FLAG(F_CF);
SET_FLAG(F_PF);
SET_FLAG(F_ZF);
} else if (isgreater(ST0.d, b)) {
emu->flags[F_CF] = 0;
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 0;
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
} else if (isless(ST0.d, b)) {
emu->flags[F_CF] = 1;
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 0;
SET_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CLEAR_FLAG(F_ZF);
}
else {
emu->flags[F_CF] = 0;
emu->flags[F_PF] = 0;
emu->flags[F_ZF] = 1;
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
SET_FLAG(F_ZF);
}
}
+32 -16
View File
@@ -16,11 +16,21 @@
#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)
{
uint8_t nextop;
reg32_t *op1;
nextop = Fetch8(emu);
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch (nextop) {
case 0xC0:
case 0xC1:
@@ -66,31 +76,34 @@ void Run66D9(x86emu_t *emu)
case 0xFD:
case 0xFE:
case 0xFF:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FLDENV m */
// warning, incomplete
op1=GetEw(emu, nextop);
fpu_loadenv(emu, (char*)op1, 1);
GET_EW;
fpu_loadenv(emu, (char*)ED, 1);
break;
case 6: /* FNSTENV m */
// warning, incomplete
op1=GetEw(emu, nextop);
fpu_savenv(emu, (char*)op1, 1);
GET_EW;
fpu_savenv(emu, (char*)ED, 1);
break;
default:
ip = R_EIP-2;
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
void Run66DD(x86emu_t *emu)
{
uint8_t nextop;
reg32_t *op1;
nextop = Fetch8(emu);
uintptr_t ip = R_EIP;
uint8_t nextop = F8;
reg32_t *oped;
switch(nextop) {
case 0xC0:
@@ -137,17 +150,18 @@ void Run66DD(x86emu_t *emu)
case 0xFD:
case 0xFE:
case 0xFF:
ip = R_EIP-2;
UnimpOpcode(emu);
break;
default:
switch((nextop>>3)&7) {
case 4: /* FRSTOR m94byte */
op1=GetEw(emu, nextop);
fpu_loadenv(emu, (char*)op1, 1);
GET_EW;
fpu_loadenv(emu, (char*)ED, 1);
// get the STx
{
char* p =(char*)op1;
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
@@ -156,12 +170,12 @@ void Run66DD(x86emu_t *emu)
}
break;
case 6: /* FNSAVE m94byte */
op1=GetEw(emu, nextop);
GET_EW;
// ENV first...
fpu_savenv(emu, (char*)op1, 1);
fpu_savenv(emu, (char*)ED, 1);
// save the STx
{
char* p =(char*)op1;
char* p =(char*)ED;
p += 14;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
@@ -171,7 +185,9 @@ void Run66DD(x86emu_t *emu)
reset_fpu(emu);
break;
default:
ip = R_EIP-2; // unfetch
UnimpOpcode(emu);
}
}
R_EIP = ip;
}
+22 -29
View File
@@ -12,7 +12,6 @@ typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct callbacklist_s callbacklist_t;
typedef struct library_s library_t;
typedef struct kh_fts_s kh_fts_t;
typedef struct kh_threadstack_s kh_threadstack_t;
@@ -25,16 +24,16 @@ typedef struct atfork_fnc_s {
void* handle;
} atfork_fnc_t;
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct dynmap_s {
dynablocklist_t* dynablocks; // the dynabockist of the block
} dynmap_t;
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
#define DYNAMAP_SIZE (1<<20)
#define DYNAMAP_SHIFT 12
#endif
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
#define MAX_SIGNAL 64
@@ -62,6 +61,7 @@ typedef struct base_segment_s {
} base_segment_t;
typedef struct box86context_s {
uint32_t* memprot; // protection flags by 4K block
path_collection_t box86_path; // PATH env. variable
path_collection_t box86_ld_lib; // LD_LIBRARY_PATH env. variable
@@ -69,10 +69,9 @@ typedef struct box86context_s {
int x86trace;
int trace_tid;
#ifdef DYNAREC
int trace_dynarec;
pthread_mutex_t mutex_dyndump;
#endif
uint32_t sel_serial; // will be increment each time selectors changes
zydis_t *zydis; // dlopen the zydis dissasembler
void* box86lib; // dlopen on box86 itself
@@ -111,14 +110,18 @@ typedef struct box86context_s {
procaddess_t glxprocaddress;
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
callbacklist_t *callbacks; // all callbacks
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
vkprocaddess_t vkprocaddress;
pthread_mutex_t mutex_once;
pthread_mutex_t mutex_once2;
pthread_mutex_t mutex_trace;
#ifndef DYNAREC
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
#else
pthread_mutex_t mutex_dyndump;
int trace_dynarec;
#endif
pthread_mutex_t mutex_tls;
pthread_mutex_t mutex_thread;
@@ -167,14 +170,6 @@ typedef struct box86context_s {
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
#ifdef DYNAREC
pthread_mutex_t mutex_blocks;
pthread_mutex_t mutex_mmap;
dynablocklist_t *dynablocks;
mmaplist_t *mmaplist;
int mmapsize;
dynmap_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
#endif
#ifndef NOALIGN
kh_fts_t *ftsmap;
#endif
@@ -190,6 +185,7 @@ typedef struct box86context_s {
uintptr_t signals[MAX_SIGNAL];
uintptr_t restorer[MAX_SIGNAL];
int onstack[MAX_SIGNAL];
int is_sigaction[MAX_SIGNAL];
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
int no_sigsegv;
@@ -199,6 +195,8 @@ typedef struct box86context_s {
#endif
} box86context_t;
extern box86context_t *my_context; // global context
box86context_t *NewBox86Context(int argc);
void FreeBox86Context(box86context_t** context);
@@ -208,15 +206,10 @@ int AddElfHeader(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);
#define PROT_DYNAREC 0x10000
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
uint32_t getProtection(uintptr_t addr);
#ifdef DYNAREC
// the nolinker specified if static map or dynamic (can be deleted) has to be used
uintptr_t AllocDynarecMap(int size, int nolinker);
void FreeDynarecMap(uintptr_t addr, uint32_t size);
dynablocklist_t* getDBFromAddress(uintptr_t addr);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
void protectDB(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
#endif
+7
View File
@@ -4,6 +4,7 @@
typedef struct x86emu_s x86emu_t;
typedef struct bridge_s bridge_t;
typedef struct box86context_s box86context_t;
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
bridge_t *NewBridge();
@@ -12,7 +13,13 @@ void FreeBridge(bridge_t** bridge);
uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
uintptr_t AddCheckBridge(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);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
int hasAlternate(void* addr);
void* getAlternate(void* addr);
void addAlternate(void* addr, void* alt);
void cleanAlternate();
#endif //__BRIDGE_H_
-24
View File
@@ -3,36 +3,12 @@
#include <stdint.h>
typedef struct callbacklist_s callbacklist_t;
typedef struct x86emu_s x86emu_t;
callbacklist_t* NewCallbackList();
void FreeCallbackList(callbacklist_t** callbacks);
x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddVariableCallback(x86emu_t* emu, int stsize, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddSmallCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4);
x86emu_t* GetCallback1Arg(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1);
x86emu_t* FreeCallback(x86emu_t* emu);
uint32_t RunCallback(x86emu_t* emu);
void SetCallbackArg(x86emu_t* emu, int arg, void* val);
// set args starting from 0
void SetCallbackArgs(x86emu_t* emu, int nargs, ...);
// set args starting from N
void SetCallbackNArgs(x86emu_t* emu, int N, int nargs, ...);
void* GetCallbackArg(x86emu_t* emu, int arg);
void SetCallbackNArg(x86emu_t* emu, int narg);
void SetCallbackAddress(x86emu_t* emu, uintptr_t address);
uintptr_t GetCallbackAddress(x86emu_t* emu);
int IsCallback(box86context_t* context, x86emu_t* cb);
// use thread local emu to run the function (context is unused now)
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
// use thread local emu to run the function (context is unused now)
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
// use emu state to run function
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
// Find a cb using FNC address and argN as a key
x86emu_t* FindCallbackFnc1Arg(x86emu_t* emu, uintptr_t fnc, int argn, void* arg);
#endif //__CALLBACK_H__
+35
View File
@@ -0,0 +1,35 @@
#ifndef __CUSTOM_MEM__H_
#define __CUSTOM_MEM__H_
#include <unistd.h>
#include <stdint.h>
typedef struct box86context_s box86context_t;
void* customMalloc(size_t size);
void* customCalloc(size_t n, size_t size);
void* customRealloc(void* p, size_t size);
void customFree(void* p);
#define kcalloc customCalloc
#define kmalloc customMalloc
#define krealloc customRealloc
#define kfree customFree
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
// custom protection flag to mark Page that are Write protected for Dynarec purpose
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size, int nolinker);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
dynablocklist_t* getDB(uintptr_t idx);
#endif
void init_custommem_helper(box86context_t* ctx);
void fini_custommem_helper(box86context_t* ctx);
#endif //__CUSTOM_MEM__H_
+7 -4
View File
@@ -14,6 +14,7 @@ extern int box86_dynarec_trace;
extern int box86_dynarec_forced;
extern int box86_dynarec_largest;
extern int box86_dynarec_smc;
extern int box86_dynarec_safemmap;
#ifdef ARM
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
@@ -25,13 +26,15 @@ extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int allow_missing_libs;
extern int box86_steam;
extern int box86_nopulse; // diabling the use of pulseaudio
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
extern int box86_nogtk; // disabling the use of wrapped gtk
extern int box86_novulkan; // disabling the use of wrapped vulkan
extern uintptr_t trace_start, trace_end;
extern box86context_t *my_context; // global context
extern char* trace_func;
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
extern uint16_t default_fs;
extern uint32_t default_fs;
extern int jit_gdb; // launch gdb when a segfault is trapped
extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
#define LOG_NONE 0
#define LOG_INFO 1
#define LOG_DEBUG 2
@@ -41,7 +44,7 @@ extern FILE* ftrace;
#define printf_log(L, ...) do {if(L<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); /*fflush(ftrace);*/}} while(0)
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
+7 -12
View File
@@ -2,25 +2,24 @@
#define __DYNABLOCK_H_
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz, int nolinker, int direct);
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int nolinker, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db);
void MarkDynablock(dynablock_t* db);
void MarkDynablockList(dynablocklist_t** dynablocks);
void ProtectDynablock(dynablock_t* db);
void ProtectkDynablockList(dynablocklist_t** dynablocks);
void ProtectDynablockList(dynablocklist_t** dynablocks);
void ProtectDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
// for debugging purpose
dynablock_t* FindDynablockFromNativeAddress(void* addr);
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box86context.h
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
uintptr_t StartDynablockList(dynablocklist_t* db);
uintptr_t EndDynablockList(dynablocklist_t* db);
@@ -28,13 +27,9 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
// source is linked to dest (i.e. source->table[x] = dest->block), so add a "mark" in dest, add a "linked" info to source
void AddMark(dynablock_t* source, dynablock_t* dest, void** table);
// remove a Table mark (and also remove lined info from other dynablock, if any)
void RemoveMark(void** table);
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr);
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int with_marks, int* created);
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
#endif //__DYNABLOCK_H_
+1 -1
View File
@@ -4,6 +4,6 @@
typedef struct dynablock_s dynablock_t;
typedef struct x86emu_s x86emu_t;
void* FillBlock(dynablock_t* block);
void* FillBlock(dynablock_t* block, uintptr_t addr);
#endif //__DYNAREC_ARM_H_
+2
View File
@@ -53,5 +53,7 @@ dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
void ResetSpecialCaseMainElf(elfheader_t* h);
void CreateMemorymapFile(box86context_t* context, int fd);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
#endif //__ELF_LOADER_H_
+1 -1
View File
@@ -16,7 +16,7 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
// 1: if file is an x86 elf, 0: if not (or not found)
int FileIsX86ELF(const char* filename);
#ifdef RPI
#if defined(RPI) || defined(RK3399)
void sanitize_mojosetup_gtk_background();
#endif
+78 -6
View File
@@ -126,6 +126,65 @@ typedef struct my_GtkContainerClass_s
void (*_gtk_reserved4) (void);
} my_GtkContainerClass_t;
typedef struct my_GtkActionClass_s
{
my_GObjectClass_t parent_class;
void (* activate) (void* action);
int menu_item_type;
int toolbar_item_type;
void* (* create_menu_item) (void* action);
void* (* create_tool_item) (void* action);
void (* connect_proxy) (void* action, void* proxy);
void (* disconnect_proxy) (void* action, void* proxy);
void* (* create_menu) (void* action);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkActionClass_t;
typedef struct my_GtkMiscClass_s
{
my_GtkWidgetClass_t parent_class;
} my_GtkMiscClass_t;
typedef struct my_GtkLabelClass_s
{
my_GtkMiscClass_t parent_class;
void (* move_cursor) (void* label, int step, int count, int extend_selection);
void (* copy_clipboard) (void* label);
void (* populate_popup) (void* label, void* menu);
int (*activate_link) (void* label, void* uri);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkLabelClass_t;
typedef struct my_GtkTreeViewClass_s
{
my_GtkContainerClass_t parent_class;
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
void (* row_activated) (void* tree_view, void* path, void* column);
int (* test_expand_row) (void* tree_view, void* iter, void* path);
int (* test_collapse_row) (void* tree_view, void* iter, void* path);
void (* row_expanded) (void* tree_view, void* iter, void* path);
void (* row_collapsed) (void* tree_view, void* iter, void* path);
void (* columns_changed) (void* tree_view);
void (* cursor_changed) (void* tree_view);
int (* move_cursor) (void* tree_view, int step, int count);
int (* select_all) (void* tree_view);
int (* unselect_all) (void* tree_view);
int (* select_cursor_row) (void* tree_view, int start_editing);
int (* toggle_cursor_row) (void* tree_view);
int (* expand_collapse_cursor_row) (void* tree_view, int logical, int expand, int open_all);
int (* select_cursor_parent) (void* tree_view);
int (* start_interactive_search) (void* tree_view);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkTreeViewClass_t;
// GTypeValueTable
typedef struct my_GTypeValueTable_s {
void (*value_init) (void* value);
@@ -180,13 +239,25 @@ my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, int parent);
void InitGTKClass(bridge_t *bridge);
void FiniGTKClass();
void SetGObjectID(int id);
void SetGTKObjectID(int id);
void SetGTKWidgetID(int id);
void SetGTKContainerID(int id);
void SetGTypeName(void* f);
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget) \
GTKCLASS(GtkContainer) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel) \
GTKCLASS(GtkMisc) \
GTKCLASS(GtkTreeView) \
void* wrapCopyGTKClass(void* class, int type);
#define GTKCLASS(A) void Set##A##ID(int id);
GTKCLASSES()
#undef GTKCLASS
void SetGTypeName(void* f);
void AutoBridgeGtk(void*(*ref)(int), void(*unref)(void*));
void* wrapCopyGTKClass(void* cl, int type);
void* unwrapCopyGTKClass(void* klass, int type);
void my_checkGlobalGdkDisplay();
void my_setGlobalGThreadsInit();
@@ -205,6 +276,7 @@ typedef struct my_signal_s {
my_signal_t* new_mysignal(void* f, void* data, void* destroy);
void my_signal_delete(my_signal_t* sig);
int my_signal_is_valid(void* sig);
int my_signal_cb(void* a, void* b, void* c, void* d);
#endif //__GTKCLASS_H__
+20 -1
View File
@@ -1,5 +1,24 @@
#include <stdint.h>
#define CREATE_SYSV_VALIST(A) \
va_list sysv_varargs; \
sysv_varargs->gpr=8; \
sysv_varargs->fpr=8; \
sysv_varargs->overflow_arg_area=A;
#ifdef SYSV_VARARG
#define VARARGS sysv_varargs
#define PREPARE_VALIST CREATE_SYSV_VALIST(emu->scratch)
#define VARARGS_(A) sysv_varargs
#define PREPARE_VALIST_(A) CREATE_SYSV_VALIST(A)
#else
#define VARARGS emu->scratch
#define PREPARE_VALIST do {} while(0)
#define VARARGS_(A) A
#define PREPARE_VALIST_(A) do {} while(0)
#endif
void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack);
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack);
void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack);
@@ -306,4 +325,4 @@ void AlignFlock64(void* dest, void* source); // x86 -> Arm
// defined in wrapperlibc.c
int of_convert(int); // x86->arm
int of_unconvert(int); // arm->x86
int of_unconvert(int); // arm->x86
+27 -34
View File
@@ -132,33 +132,33 @@ typedef struct {
} fpu_ld_t;
typedef struct {
uint64_t ll;
uint64_t ref;
int64_t ll;
int64_t ref;
} fpu_ll_t;
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int F__CF:1;
unsigned int F__res1:1;
unsigned int F__PF:1;
unsigned int F__res2:1;
unsigned int F__AF:1;
unsigned int F__res3:1;
unsigned int F__ZF:1;
unsigned int F__SF:1;
unsigned int F__TF:1;
unsigned int F__IF:1;
unsigned int F__DF:1;
unsigned int F__OF:1;
unsigned int F__IOPL:2;
unsigned int F__NT:1;
unsigned int F__dummy:1;
unsigned int F__RF:1;
unsigned int F__VM:1;
unsigned int F__AC:1;
unsigned int F__VIF:1;
unsigned int F__VIP:1;
unsigned int F__ID:1;
unsigned int _F_CF:1;
unsigned int _F_res1:1;
unsigned int _F_PF:1;
unsigned int _F_res2:1;
unsigned int _F_AF:1;
unsigned int _F_res3:1;
unsigned int _F_ZF:1;
unsigned int _F_SF:1;
unsigned int _F_TF:1;
unsigned int _F_IF:1;
unsigned int _F_DF:1;
unsigned int _F_OF:1;
unsigned int _F_IOPL:2;
unsigned int _F_NT:1;
unsigned int _F_dummy:1;
unsigned int _F_RF:1;
unsigned int _F_VM:1;
unsigned int _F_AC:1;
unsigned int _F_VIF:1;
unsigned int _F_VIP:1;
unsigned int _F_ID:1;
} f;
uint32_t x32;
} x86flags_t;
@@ -262,16 +262,9 @@ typedef union {
#define R_FS emu->segs[_FS]
#define R_GS emu->segs[_GS]
#if 0
#define ACCESS_FLAG(F) emu->eflags.f.F
#define SET_FLAG(F) emu->eflags.f.F = 1
#define CLEAR_FLAG(F) emu->eflags.f.F = 0
#define CONDITIONAL_SET_FLAG(COND, F) emu->eflags.f.F = (COND)?1:0
#else
#define ACCESS_FLAG(F) emu->flags[F]
#define SET_FLAG(F) emu->flags[F] = 1
#define CLEAR_FLAG(F) emu->flags[F] = 0
#define CONDITIONAL_SET_FLAG(COND, F) emu->flags[F] = (COND)?1:0
#endif
#define ACCESS_FLAG(F) emu->eflags.f._##F
#define SET_FLAG(F) emu->eflags.f._##F = 1
#define CLEAR_FLAG(F) emu->eflags.f._##F = 0
#define CONDITIONAL_SET_FLAG(COND, F) emu->eflags.f._##F = (COND)?1:0
#endif //__REGS_H_
+4 -1
View File
@@ -15,6 +15,9 @@ void CleanStackSize(box86context_t* context);
emu_jmpbuf_t* GetJmpBuf();
void init_pthread_helper();
void fini_pthread_helper();
void fini_pthread_helper(box86context_t* context);
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet);
#endif //_THREADS_H_
+4
View File
@@ -6,4 +6,8 @@ void wine_prereserve(const char* reserve);
extern int wine_preloaded;
void* get_wine_prereserve();
#ifdef DYNAREC
void dynarec_wine_prereserve();
#endif
#endif //__WINE_TOOLS_H__
+4
View File
@@ -29,9 +29,13 @@ void SetFS(x86emu_t *emu, uint16_t v);
uint16_t GetFS(x86emu_t *emu);
uint32_t GetESP(x86emu_t *emu);
void ResetFlags(x86emu_t *emu);
void ResetSegmentsCache(x86emu_t *emu);
const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip);
void StopEmu(x86emu_t* emu, const char* reason);
#ifdef DYNAREC
void DynablockEmuMarker(box86context_t* context);
#endif
void PushExit(x86emu_t* emu);
void* GetExit();
void EmuCall(x86emu_t* emu, uintptr_t addr);
+15 -13
View File
@@ -39,10 +39,13 @@ void FreeLibrarian(lib_t **maplib)
if(!maplib || !*maplib)
return;
if((*maplib)->ownlibs)
if((*maplib)->ownlibs) {
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
for (int i=0; i<(*maplib)->libsz; ++i) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
Free1Library(&(*maplib)->libraries[i].lib);
}
}
free((*maplib)->libraries);
(*maplib)->libraries = NULL;
@@ -386,21 +389,18 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
uintptr_t start = 0;
uintptr_t end = 0;
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end))
if(start)
return maplib->context->elfs[0];
return maplib->context->elfs[0];
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
if(start)
return maplib->context->elfs[0];
return maplib->context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
if(start) {
int idx = GetElfIndex(maplib->libraries[i].lib);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
return NULL;
}
return maplib->context->elfs[idx];
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) {
int idx = GetElfIndex(maplib->libraries[i].lib);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
return NULL;
}
return maplib->context->elfs[idx];
}
}
// nope, not found
return NULL;
@@ -557,6 +557,8 @@ void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name)
const char* GetNameOffset(lib_t *maplib, void* offs)
{
if(!maplib || !maplib->mapoffsets)
return NULL;
khint_t k = kh_get(mapoffsets, maplib->mapoffsets, (uintptr_t)offs);
if (k!=kh_end(maplib->mapoffsets))
return kh_value(maplib->mapoffsets, k);
+2
View File
@@ -1,6 +1,8 @@
#ifndef __LIBRARIAN_PRIVATE_H_
#define __LIBRARIAN_PRIVATE_H_
#include <stdint.h>
#include "custommem.h"
#include "khash.h"
typedef struct box86context_s box86context_t;
+11 -5
View File
@@ -93,14 +93,14 @@ int EmuLib_Get(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz)
if(k!=kh_end(lib->priv.n.mapsymbols)) {
*offs = kh_value(lib->priv.n.mapsymbols, k).offs;
*sz = kh_value(lib->priv.n.mapsymbols, k).sz;
return *offs;
return 1;
}
// weak symbols...
k = kh_get(mapsymbols, lib->priv.n.weaksymbols, name);
if(k!=kh_end(lib->priv.n.weaksymbols)) {
*offs = kh_value(lib->priv.n.weaksymbols, k).offs;
*sz = kh_value(lib->priv.n.weaksymbols, k).sz;
return *offs;
return 1;
}
return 0;
}
@@ -111,7 +111,7 @@ int EmuLib_GetNoWeak(library_t* lib, const char* name, uintptr_t *offs, uint32_t
if(k!=kh_end(lib->priv.n.mapsymbols)) {
*offs = kh_value(lib->priv.n.mapsymbols, k).offs;
*sz = kh_value(lib->priv.n.mapsymbols, k).sz;
return *offs;
return 1;
}
return 0;
}
@@ -122,7 +122,7 @@ int EmuLib_GetLocal(library_t* lib, const char* name, uintptr_t *offs, uint32_t
if(k!=kh_end(lib->priv.n.localsymbols)) {
*offs = kh_value(lib->priv.n.localsymbols, k).offs;
*sz = kh_value(lib->priv.n.localsymbols, k).sz;
return *offs;
return 1;
}
return 0;
}
@@ -201,7 +201,6 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box86context_t*
ElfAttachLib(elf_header, lib);
lib->type = 1;
lib->context = context;
lib->fini = EmuLib_Fini;
lib->get = EmuLib_Get;
lib->getnoweak = EmuLib_GetNoWeak;
@@ -242,6 +241,7 @@ library_t *NewLibrary(const char* path, box86context_t* context)
lib->path = strdup(path);
lib->name = Path2Name(path);
lib->nbdot = NbDot(lib->name);
lib->context = context;
lib->type = -1;
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
if(box86_nopulse) {
@@ -250,6 +250,12 @@ library_t *NewLibrary(const char* path, box86context_t* context)
return NULL;
}
}
if(box86_novulkan) {
if(strstr(lib->name, "libvulkan.so")==lib->name) {
Free1Library(&lib);
return NULL;
}
}
int notwrapped = FindInCollection(lib->name, &context->box86_emulated_libs);
// And now, actually loading a library
// look for native(wrapped) libs first
+1
View File
@@ -2,6 +2,7 @@
#define __LIBRARY_PRIVATE_H_
#include <stdint.h>
#include "custommem.h"
#include "khash.h"
#include "wrappedlibs.h"
#include "box86context.h"
+15
View File
@@ -18,6 +18,7 @@ GO("libSDL2.so", sdl2)
GO("libsdl2-2.0.so.0", sdl2)
GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
GO("libSDL2_image-2.0.so.0", sdl2image)
GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
GO("libSDL-1.2.so.0", sdl1)
GO("libSDL-1.1.so.0", sdl1)
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
@@ -67,6 +68,7 @@ GO("openal.so", openal)
GO("libalut.so.0", alut)
GO("libjpeg.so.8", libjpeg)
GO("libjpeg.so.62", libjpeg62)
GO("libturbojpeg.so.0", turbojpeg)
GO("libcurl.so.4", curl)
GO("libcurl-gnutls.so.4", curl)
GO("libudev.so.0", udev0)
@@ -84,6 +86,8 @@ GO("libpulse.so.0", pulse)
GO("libsndfile.so.1", libsndfile)
GO("libgtk-x11-2.0.so.0", gtkx112)
GO("libgdk-x11-2.0.so.0", gdkx112)
GO("libgtk-3.so.0", gtk3)
GO("libgdk-3.so.0", gdk3)
GO("libgdk_pixbuf-2.0.so.0", gdkpixbuf2)
GO("libgio-2.0.so.0", gio2)
GO("libgmodule-2.0.so.0", gmodule2)
@@ -123,5 +127,16 @@ GO("libmpg123.so.0", mpg123)
GO("libgnutls.so.30", gnutls)
GO("libcups.so.2", libcups)
GO("d3dadapter9.so.1", d3dadapter9)
GO("libvulkan.so.1", vulkan)
GO("libvulkan.so", vulkan)
GO("libwayland-client.so.0", waylandclient)
GO("libxml2.so.2", xml2)
GO("libxslt.so.1", xslt)
GO("libldap_r-2.4.so.2", ldapr)
GO("liblber-2.4.so.2", lber)
GO("libnsl.so.1", nsl)
GO("liblcms2.so.2", lcms2)
GO("libkrb5.so.3", krb5)
GO("libgssapi_krb5.so.2", gssapikrb5)
GO("ld-linux.so.2", ldlinux)
+6 -3
View File
@@ -12,7 +12,6 @@
#include "emu/x86emu_private.h"
#include "myalign.h"
void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
{
if(!fmt)
@@ -65,7 +64,9 @@ void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
case '7':
case '8':
case '9':
case '.': ++p; break; // formating, ignored
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
@@ -356,7 +357,9 @@ void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
case '7':
case '8':
case '9':
case '.': ++p; break; // formating, ignored
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
Loaded 100 of 236 files, more files were not shown because too many files have changed in this diff. Show more