1420 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
ptitSeb 0edc037441 Bumped version to v0.1.4 2020-10-24 15:34:34 +02:00
ptitSeb d4a7f7e658 Simplified glib2 wrapped lib 2020-10-24 12:38:28 +02:00
ptitSeb fcf9668e8b Fixed wrapped g_variant_get function 2020-10-24 12:36:17 +02:00
ptitSeb 76e53e0869 Fixed execvp wrapped function to use PATH / BOX86_PATH to look for binary if needed 2020-10-24 10:47:59 +02:00
ptitSeb 74764253b4 Fixed pango_attribute_init wrapped function 2020-10-24 00:12:35 +02:00
ptitSeb c029c6c152 [DYNAREC] Avoid potential SIGBUS on 66 0F 13MOVLPD and 66 0F 16/17 MOVHPD opcodes 2020-10-24 00:11:44 +02:00
ptitSeb bb4b0d5f92 [DYNAREC] Avoid potential SIGBUS on F3 0F E6 CVTDQ2PD opcode 2020-10-24 00:10:04 +02:00
ptitSeb a355cf941b [DYNAREC] cosmetic changes on dynarec_arm_dd.c 2020-10-24 00:07:32 +02:00
ptitSeb e7c5ef1cca Added some wrapped function to lib pango and pangoft2 2020-10-23 20:03:07 +02:00
ptitSeb 09d0f7a3cb Fixed GVariant creation on wrapped glib2 2020-10-23 20:02:28 +02:00
ptitSeb 3e7dd07b4c Added a libpangoft2-1.0.so as wrapped too 2020-10-23 20:02:02 +02:00
ptitSeb c536eed349 [DYNAREC] Changed a bit how comon dynablock is selected 2020-10-23 20:00:29 +02:00
ptitSeb 93948021e6 Added DE D0..D7 FCOMP ([DYNAREC] too) 2020-10-23 19:59:40 +02:00
ptitSeb 77317f87c0 Simplify SDL2 Event Handler 2020-10-23 19:58:37 +02:00
ptitSeb b091ea9c6d Fixed wrapped lib appindicator 2020-10-23 14:36:56 +02:00
ptitSeb 208493da88 It seems mpg123 use 64bits off_t 2020-10-23 13:04:00 +02:00
ptitSeb 7015745c4f Silence a warning, and don't create a fake /sys/devices/system/cpu/cpuX/topology/core_id file if it exist 2020-10-22 23:50:59 +02:00
ptitSeb 41a5c72d46 [PANDORA] put all define at the same place (for #233) 2020-10-22 23:48:04 +02:00
ptitSeb 2b428641fb [PANDORA] forgot to close the ifdef (for #233) 2020-10-22 23:43:00 +02:00
ptitSeb 4ebb1e60db [PANDORA] Fix potential build issue (for #233) 2020-10-22 23:31:56 +02:00
ptitSeb 5e4c1feed1 [DYNAREC] Fixed the Free of Dynablock that weren't always sane (fixes RGPMaker 2000, among aother things) 2020-10-22 19:24:11 +02:00
ptitSeb d13e1da1a7 [DYNAREC] Added undocummented BOX86_DYNAREC_SMC to detect special case of SMC (slow things down, so use wizely) 2020-10-22 19:24:11 +02:00
ptitSeb 9f57cff43b [README] Fixed address of 86box github project (still for #232) 2020-10-22 17:40:56 +02:00
ptitSeb b9d9776d5c Added 86box precision on README, plus PILab Discord channel link (to mitigate #232) 2020-10-22 16:52:02 +02:00
ptitSeb b57ab8470d [DYNAREC] Some more small optims to some of the LOCK opcodes 2020-10-21 19:08:29 +02:00
ptitSeb fe402d2faa [DYNAREC] Use posix_memalign instead of mmap to for Dynarec block memory 2020-10-21 18:58:50 +02:00
ptitSeb 3d38210752 Improved (once more) signal handling 2020-10-21 17:52:42 +02:00
ptitSeb 6c4b047b58 Changed slightly the win prereserve mecanism 2020-10-20 11:00:22 +02:00
ptitSeb e861d3415a Changed, once again, the loading position of box86 2020-10-20 10:59:55 +02:00
ptitSeb cb251fe88b [DYNAREC] Fixed F0 0F B0 LOCK CMPXCHG Eb, Gb opcode (help KaM Remake) 2020-10-19 21:28:11 +02:00
ptitSeb b1e594f4d7 More work on signal handling 2020-10-19 11:04:45 +02:00
ptitSeb f9505f3c9f Improved a bit wrappedlibc 2020-10-19 11:03:02 +02:00
ptitSeb 52ee2bb769 A bit more logs when using BOX86_LOG=2 2020-10-19 11:01:45 +02:00
ptitSeb f0471fac14 Merge pull request #231 from icecream95/nine-2
Create a fake IDirect3D9 object instead of changing the vtable
2020-10-19 09:57:26 +02:00
Icecream95 7baac98959 Create a fake Direct3D9 object instead of changing the vtable
This means both x86 and ARM code can have the right function pointers
at the same time, allowing a hack in Gallium Nine to be removed.
2020-10-19 20:02:49 +13:00
ptitSeb 9119443c2a [DYNAREC] Go back to X_PEND (as it's more optimized) on end of block (now PvZ still works, thanks to previous commit) 2020-10-17 17:29:38 +02:00
ptitSeb c9c33929f0 [DYNAREC] Fixed (and optimized a bit) some Math emiter 2020-10-17 17:27:16 +02:00
ptitSeb 60717d38d4 Added wrapped libcups with a few functions 2020-10-17 15:21:27 +02:00
ptitSeb 858757f8d1 Merge pull request #230 from mogwa1/master
Fix presumable typo in wrappedlibncurses files
2020-10-17 09:38:22 +02:00
Bart De Vries f15a22a3cb Fix presumable typo in wrappedlibncurses files
A call to vmprintw is made, which is a non-existent function.
Presumably, vwprintw is meant to be called.
2020-10-17 09:34:24 +02:00
ptitSeb f6022de7d3 Don't try to alloc elf section that have so read/write/execute flags 2020-10-16 13:19:17 +02:00
ptitSeb 8214301231 Added handling of /sys/devices/system/cpu/cpuX/topology/core_id file 2020-10-16 13:17:59 +02:00
ptitSeb a4745098c5 Don't inject PLTResolver if it's not needed (should help #195) 2020-10-15 11:04:00 +02:00
ptitSeb 647b06a615 Fixed an issue with box86 shutdown 2020-10-15 10:51:49 +02:00
ptitSeb a7cbafee07 Added libssl.so.1.1 as a alt name for wrapped libssl 2020-10-14 21:18:32 +02:00
ptitSeb ee0eb2345c Added libcrytpo.so.1.1 as a alt name for wrapped libcrypto 2020-10-14 21:16:50 +02:00
ptitSeb d37c42761d Don't try to use XSAVE/XRSTR yet on signal handling 2020-10-14 20:06:05 +02:00
ptitSeb d4984fd0ee New attemps at improving Signal Handling 2020-10-14 17:43:08 +02:00
ptitSeb c770ea1859 Added an option to disable the loading of pulse audio libs 2020-10-14 09:29:59 +02:00
ptitSeb 4d1307e223 Improve signal handling, again (to help windows exception managers) 2020-10-12 22:16:23 +02:00
ptitSeb e9308c11ba [DYNAREC] Added 67 64 xx opcode (copy of 64 67 xx, need to factorise all this) 2020-10-12 21:50:48 +02:00
ptitSeb 5206ec0fcb Fixed 1 wrapped function signature in libXext 2020-10-12 21:50:12 +02:00
ptitSeb c65671a6f9 Added more libXext wrapped functions (for #226) 2020-10-12 10:40:33 +02:00
ptitSeb ec99203dc6 Better log for FF illegzal opcode 2020-10-12 10:22:05 +02:00
ptitSeb 1cdde047ff Added more ncurses wrapped function (for #215) 2020-10-12 08:35:30 +02:00
ptitSeb 2375d70782 [DYNAREC] Fixed a typo in 8D LEA Gd, Ed opcode 2020-10-11 22:10:44 +02:00
ptitSeb 5b0c395293 Added a even more wrapped libcrypto functions 2020-10-11 20:47:36 +02:00
ptitSeb ea0c1abb0b Added a few more wrapped libcrypto functions 2020-10-11 20:13:37 +02:00
ptitSeb cc841812ce Added 1 wrapped function to libcrypto 2020-10-11 19:07:48 +02:00
ptitSeb 5104bce7bb [DYNAREC] Added (fake) F2/F3 EB opcode 2020-10-11 18:28:45 +02:00
ptitSeb 357ce483a8 [DYNAREC] Added a workaround for some SMC trick using PUSH Id followed by RET (help RPGMaker RunTime) 2020-10-11 18:21:17 +02:00
ptitSeb 1a40b4b984 [DYNAREC] Added D9 F6/F7 FDECSTP/FINCSTP opcode 2020-10-11 15:30:02 +02:00
ptitSeb cdd0e542f1 Added (faked) XACQURE/XRELEASE prefix 2020-10-11 14:21:20 +02:00
ptitSeb a9d87a938d Added (fake?) 63 ARPL Ed, Gd opcode 2020-10-10 18:30:22 +02:00
ptitSeb 549ff980a3 [DYNAREC] Added FPREM1 opcode 2020-10-10 16:33:46 +02:00
ptitSeb 545af93972 [DYNAREC] Added FBSTSW opcode 2020-10-10 16:33:10 +02:00
ptitSeb 72b9ed9f54 Even more libjpeg.so.62 improvements 2020-10-10 15:01:27 +02:00
ptitSeb 536c7dd04b Big improvement in libjpeg.so.62 handling 2020-10-10 13:46:04 +02:00
ptitSeb 274d5d1e75 Also trap SIGILL now, like SIGSEGV and SIGBUS 2020-10-10 10:42:47 +02:00
ptitSeb 7b478e42c0 Improved libjpeg.so.8 and libjpeg.so.62 handling 2020-10-10 10:31:27 +02:00
ptitSeb d0ac1e61d4 Added libjpeg.so.62 as for wrapped libjpeg 2020-10-09 20:13:58 +02:00
ptitSeb 31d73927a3 [README] Added a Steam paragraph (for #223) 2020-10-09 17:38:45 +02:00
ptitSeb 7713bd042a Added wcsnlen wrapped function to libc 2020-10-08 12:00:16 +02:00
ptitSeb 664dab76e3 Fixed improved signal handler. It seems to work a bit now 2020-10-07 21:38:38 +02:00
ptitSeb 6e2c33866d Add DB E1 FDISI8087_NOP as NOP ([DYNAREC] too) 2020-10-07 20:03:43 +02:00
ptitSeb 7b6dd6765e Rermoved a forgotten debug trace 2020-10-07 19:57:50 +02:00
ptitSeb d55d2d0303 [DYNAREC] Added D5 Ib AAM and D6 Ib AAD opcodes 2020-10-07 19:37:40 +02:00
ptitSeb 4df7bec913 Some fixes to new signal handling functions 2020-10-07 19:15:44 +02:00
ptitSeb 4ddab1b691 Made fork to reset the main hread emu if needed 2020-10-07 19:14:54 +02:00
ptitSeb b0c0e96fca [DYNAREC] Added D6 SALC opcode 2020-10-07 19:12:34 +02:00
ptitSeb aeee2fc391 Try to better handle Signals when signal handler change any context value 2020-10-07 12:07:52 +02:00
ptitSeb 4f28cb5617 Added wrapped funciton logl to libm (help KeeperRL) 2020-10-07 11:42:46 +02:00
ptitSeb a442a841f2 Added wrapped function curl_free to libcurl (help KeeperRL) 2020-10-07 11:42:10 +02:00
ptitSeb 9201170ab8 [DYNAREC] Fixed and optimized F3 0F E6 CVTDQ2PD opcode 2020-10-06 23:12:32 +02:00
ptitSeb 4f06cfa0da [DYNAREC] Added F3 0F E6 CVTDQ2PD Gx, Ex opcode 2020-10-06 16:19:25 +02:00
ptitSeb fe03daa01f [DYNAREC] Cosmetic change in one of the emmiter 2020-10-06 16:18:57 +02:00
ptitSeb b64c4f6043 Better handling of path with space (for #220, but seriously, space in folder name are evil) 2020-10-06 13:04:07 +02:00
ptitSeb 5884c78b56 Use CMAKE_SOURCE_DIR instead of CMAKE_HOME_DIRECTORY as recommended in cmake documentation 2020-10-06 11:59:33 +02:00
ptitSeb b01b7373ac [DYNAREC] Added workaround for unaligned LOCK XADD Ed, Gd 2020-10-06 11:53:28 +02:00
ptitSeb 3cc9482a08 [DYNAREC] Added a workaround for unaligned LOCK SUB Ed, Id/Ib 2020-10-06 11:12:16 +02:00
ptitSeb 83c6b01fae Added a NOGIT option to build from sources that are not a git clone (should help #220) 2020-10-06 10:59:20 +02:00
ptitSeb 1f169bc67e [DYNAREC] Added a workaround for unaligned LOCK ADD Ed, Id/Ib and also fix potential issues when an opcode have internal jump 2020-10-06 08:05:40 +02:00
ptitSeb ea25675264 Merge pull request #221 from Botspot/patch-1
Optimize compilation & full install commands
2020-10-06 07:59:29 +02:00
Botspot c302cd680c Optimize compilation & full install commands 2020-10-05 18:28:43 -05:00
ptitSeb ebf46d0cfd Added a few more symbols and dependancies to gtk wrapped libs (should help #193) 2020-10-05 22:38:28 +02:00
ptitSeb 2c9b504688 Improve dlsym mecanism (should help #193) 2020-10-05 21:13:45 +02:00
ptitSeb 41d3de565c Added 2 symbols in wrapped libgtk-x11 2020-10-05 20:15:25 +02:00
ptitSeb 88430d845d Fixed an issue with a log of wrapped dlopen 2020-10-05 20:15:24 +02:00
ptitSeb c6e5e5d27e Added wrapped libxcb-present (partial) 2020-10-05 15:20:26 +02:00
ptitSeb cd673028b7 Added wrapped libxcb-dri2 and libxcb-dri3 (partial) 2020-10-05 14:29:56 +02:00
ptitSeb 2cafe12e4f Default to BOX86_LOG=NONE (use BOX86_LOG=1 to get previous behaviour) 2020-10-05 11:54:55 +02:00
ptitSeb febbaca66b Added BOX86_NOBANNER env. var. plus default to printing box86 version and build number at start 2020-10-05 11:53:46 +02:00
ptitSeb e410ca748a Merge pull request #219 from icecream95/nine
Wrap Gallium Nine
2020-10-05 10:02:15 +02:00
ptitSeb 524c04296e Fixed FXSR opcodes (should help #218) 2020-10-05 09:52:06 +02:00
Icecream95 ef360bf93e Add a final NULL to environment variables
Fixes Wine crashes with certain numbers of environment variables present.
2020-10-05 14:44:50 +13:00
Icecream95 bd4f7a4783 Update generated functions 2020-10-05 14:44:50 +13:00
Icecream95 3c2c242225 Add wrapping for d3d9 2020-10-05 14:44:50 +13:00
Icecream95 a8e657c86e Add some headers for d3d9 wrapping 2020-10-05 14:44:50 +13:00
Icecream95 70e103af49 Wrap some more libxcb functions 2020-10-05 14:44:50 +13:00
ptitSeb 006f7a79b4 Added C4 LES Gd, Ed opcode 2020-10-04 22:08:02 +02:00
ptitSeb c7a4dbe84b Fixed __res_state that is wrapped function and not a data in libc 2020-10-04 18:29:27 +02:00
ptitSeb 31c0c52d7f Added a few more wrapped function to libdbus 2020-10-04 17:28:07 +02:00
ptitSeb a4590d3771 Fix for commit 85dd704f86 2020-10-04 16:58:32 +02:00
ptitSeb 02b5e39c39 Improved signal handling 2020-10-04 16:23:11 +02:00
ptitSeb 85dd704f86 Don't protect executable memory until it's actually executed 2020-10-04 16:22:55 +02:00
ptitSeb b4d4efd40c Added 2 more wrapped functions to libdbus 2020-10-04 16:18:13 +02:00
ptitSeb 8745b0f31a Small changes in thread handling ([DYNAREC] Pre-compute first dynarec of thread function before creating a thread) 2020-10-04 10:59:36 +02:00
ptitSeb 3787b3bbfc Minor changein trace handling 2020-10-04 10:58:42 +02:00
ptitSeb 765e1b1231 [DYNAREC] Changed __builtin___clear_cache with __clear_cache 2020-10-04 10:58:09 +02:00
ptitSeb 2a2e2bf957 Improved a bit SIGSEGV/SIGBUS log message 2020-10-04 10:57:32 +02:00
ptitSeb c93913732b Added C5 LDS Gd, Ed opcode (not sure it's correct) 2020-10-04 10:54:11 +02:00
ptitSeb f5bbc99d7d Change how LD2D works, to avoid potential BusError 2020-10-03 21:42:54 +02:00
ptitSeb 27ce42b9b0 Added g_log_set_default_handler to wrapped glib2 lib 2020-10-03 09:10:43 +02:00
ptitSeb 008d51aeec Added in6addr_loopback data to wrapped libc 2020-10-03 09:10:06 +02:00
ptitSeb 8d0d264c0f Add some data to wrapped ncurses libs (should help #215) 2020-10-03 08:06:47 +02:00
ptitSeb 28717352b4 Improved detail when using BOX86_DLSYM_ERROR=1 2020-10-02 15:52:28 +02:00
ptitSeb f9e492dfdc Added FXSR in the CPU ID flags 2020-10-02 15:51:48 +02:00
ptitSeb a8e029f0e0 [DYNAREC] Added DF C0..C7 FFREEP opcode 2020-10-01 10:13:46 +02:00
ptitSeb f5be4503c5 Added DF C0..C7 FREEP opcode 2020-10-01 10:13:19 +02:00
ptitSeb cd1d3f5026 Added tputs wrapped function to libtsinfo.so.5 and libtsinfo.so.6 (for #211) 2020-10-01 09:38:46 +02:00
ptitSeb 4f55733bdd Added msgctl wrapped function to libc 2020-09-30 18:14:38 +02:00
ptitSeb 81819d04e8 Added msgsnd and msgrcv wrapped function to libc 2020-09-30 17:57:55 +02:00
ptitSeb 4d4adea6eb Added msgget wrapped function to libc 2020-09-30 17:36:08 +02:00
ptitSeb ca981fbc8e [DYNAREC] Added 66 0F 38 01/02/03/05 opcodes 2020-09-30 17:25:12 +02:00
ptitSeb b4c64abd1e Added 66 0F 38 03 PHADDSW opcode 2020-09-30 17:24:18 +02:00
ptitSeb a8787330d8 [DYNAREC] Added F2 0F F0 LDDQU opcode 2020-09-30 17:20:18 +02:00
ptitSeb 7725234b69 Added F2 0F F0 LDDQ opcode 2020-09-30 17:19:50 +02:00
ptitSeb 062d897fb1 Added 66 0F 38 05 PHSUBW opcode 2020-09-30 16:50:59 +02:00
ptitSeb e1ed95a638 Added a few more xcb wrapped functions 2020-09-30 16:35:08 +02:00
ptitSeb 7ffa5d076c Changed a bit FF /6 opcode to avoid potential issues with Ed with ESP 2020-09-30 16:32:51 +02:00
ptitSeb 1ae0ae630a Fixed some typo on some segments opcode ([DYNAREC] too) 2020-09-30 11:05:11 +02:00
ptitSeb d3e8daa9b5 Removed workaround that disabled SSSE3 for Steam, it's not needed anymore 2020-09-30 10:20:19 +02:00
ptitSeb 5f8be26b73 Added xcb_setup_roots_length wrapped function to libxcb (for #193) 2020-09-30 08:24:21 +02:00
ptitSeb 0eb575b472 Fixed some wrapped libXRandr functions 2020-09-28 15:03:47 +02:00
ptitSeb 1888d905a4 Try to handle SIGBUS like SIGSEGV 2020-09-28 15:03:18 +02:00
ptitSeb 3bc4dc8450 Fixed handling of file not found at start 2020-09-28 10:21:12 +02:00
ptitSeb 78719df8d4 Try to implement sigset wrapped function (for #211) 2020-09-27 15:03:17 +02:00
ptitSeb d3616b335f Improved wrapped ncurses / tsinfo symbols (for #209 and #211) 2020-09-27 14:38:40 +02:00
ptitSeb e72cd086b4 Better handling of /proc/PID/xxx in wrapped files open function (for #202) 2020-09-27 14:14:31 +02:00
ptitSeb c82e67c39a Added 66 0F 38 08/09/0A PSIGN(B/W/D) opcode 2020-09-27 14:02:38 +02:00
ptitSeb 9885cf6f10 [DYNAREC] Assorted fix and optim for some SSE2/SSSE3 opcodes 2020-09-27 13:42:26 +02:00
ptitSeb d923b5bc0f [DYNAREC] better log for unimplemented opcode 2020-09-27 09:39:25 +02:00
ptitSeb 611d2fcaff Assorted interpretor fixes for some SSE2 opcodes 2020-09-27 09:38:58 +02:00
ptitSeb 9b2b312719 Merge branch 'master' of https://github.com/ptitSeb/box86 2020-09-26 19:18:49 +02:00
ptitSeb f84161dafc Merge pull request #210 from rajdakin/printerFix
Fixed some instructions printer
2020-09-26 19:16:14 +02:00
rajdakin 8546a0d0bd [PRINTER] Fixed some instructions printer 2020-09-26 18:43:02 +02:00
ptitSeb 09f5873806 Fixed 66 0F E8 PSUBSB opcode 2020-09-26 13:49:14 +02:00
ptitSeb 18dc905a8c [DYNAREC] Various small optimisations, mainly SSE oriented 2020-09-26 11:48:19 +02:00
ptitSeb 30d64a0aa5 Small fix on 66 0F 67 PACKSSDW opcode 2020-09-26 10:24:46 +02:00
ptitSeb 8359c9e19f [DYNAREC] Added D9 /6 FNSTENV opcode 2020-09-26 10:23:48 +02:00
ptitSeb 571f0c0564 Small optim on D9 /6 FNSTENV opcode 2020-09-26 10:23:21 +02:00
ptitSeb 736a9ef442 Fixed 66 0F 67 PACKUSWB when EX and GX are the same 2020-09-25 13:49:43 +02:00
ptitSeb aee94b0e14 A bit more work on cpow(f) wrapped function 2020-09-25 12:08:54 +02:00
ptitSeb 4cfed0d394 [DYNAREC] Fixed 66 0F 38 04 PMADDUBSW opcode 2020-09-25 10:51:11 +02:00
ptitSeb c714d5d881 Fixed 0F 38 00 PSHUFB to use MM regs instead of XMM 2020-09-25 10:35:34 +02:00
ptitSeb 1c2d07ee56 [DYNAREC] Change implementation for 66 0F 6E MOVD Gx, Ex opcode 2020-09-25 08:25:06 +02:00
ptitSeb 96f7f3d88f Change implementation for 66 0F 3A 0F PALIGNR opcode 2020-09-25 08:24:17 +02:00
ptitSeb c743577369 Added 0F C3 MOVNTI opcode ([DYNAREC] too) 2020-09-25 08:21:28 +02:00
ptitSeb e5ea60fe88 Added more complex functions to wrapped libm 2020-09-24 21:39:05 +02:00
ptitSeb 330d93f335 Fixed wrapped libm function taht return float complex, plus added a few complex functions 2020-09-24 19:42:10 +02:00
ptitSeb f4936144d0 0F 38 01/02 PHADD(W/D) opcode 2020-09-24 19:41:33 +02:00
ptitSeb bbaa5dde92 Refactored gigantic Run function to create Run660F and try speedup build a bit 2020-09-24 17:45:37 +02:00
ptitSeb e6b46151ec Added (66) 0F 38 1C/1D/1E PABS(B/W/D) opcode 2020-09-24 17:23:12 +02:00
ptitSeb 655a8de652 Added 66 0F 7C HADDPD opcode 2020-09-24 16:53:44 +02:00
ptitSeb 771d69f38b [DYNAREC] Some (S)SSE2/3 opcodes fixes 2020-09-24 16:35:14 +02:00
ptitSeb 2a46dbf149 A bit more (S)SSE3 opcodes fixes 2020-09-24 16:34:49 +02:00
ptitSeb 95a0535462 Try to fix 0F 38 0B PMULHRSW opcode 2020-09-24 16:34:10 +02:00
ptitSeb 041758fead Fixed (66) 0F 38 04 PMULHRSW opcode 2020-09-24 11:59:20 +02:00
ptitSeb d6bb723c6a [DYNAREC] Added 0F E0 PAVGB Gm, Em opcode 2020-09-24 11:58:43 +02:00
ptitSeb 95f97e1c9f [DYNAREC] Added (66) 0F 38 0B PMULHRSW opcodes 2020-09-24 10:56:42 +02:00
ptitSeb b029292dd2 Added 0F 38 0B PMULHRSW Gm, Em opcode 2020-09-24 10:56:15 +02:00
ptitSeb 82ba663c24 [DYNAREC] Fixed 0F 38 00 opcode 2020-09-24 10:17:46 +02:00
ptitSeb fabd5b9d32 Added 0F 38 00 PSHUFB opcode ([DYNAREC] too) 2020-09-24 08:39:28 +02:00
ptitSeb 58736b707d [DYNAREC] Added workaround for unaligned LOCK CMPXCHG and LOCK CMPXCHG8B (fixes Unity Games and Steam) 2020-09-23 22:10:06 +02:00
ptitSeb 9219384650 [DYNAREC] Changed the method used on ARM to simulate LOCK prefix 2020-09-23 20:22:44 +02:00
ptitSeb 14a904cfa9 Added all 64 67 opcodes to 67 64 ... 2020-09-23 10:24:17 +02:00
ptitSeb e73f7a9c10 Added 67 64 FF /6 PUSH FS:Ew16 opcode 2020-09-23 07:50:24 +02:00
ptitSeb 09acd36c08 [DYNAREC] Make end of block need a X_ALL, but end because recursive loop need X_PEND (helps PvZ) 2020-09-22 18:11:19 +02:00
ptitSeb 69a6f44b8b Refined .gitignore for TwisterOS 2020-09-22 18:11:08 +02:00
ptitSeb 3ee8fd4ec6 [DYNAREC] Try to optimize runtime speed a bit 2020-09-22 12:21:55 +02:00
ptitSeb 4f6c0b45f8 [DYNAREC] Avoid deleting block that are not supposed to be volatile 2020-09-22 11:38:50 +02:00
ptitSeb 06a756a5eb [DYNAREC] Small optimization for 64 A1 and 64 A3 opcodes 2020-09-22 11:17:01 +02:00
ptitSeb b312df3b53 Bugfixe on Interpretor for some 64, 65, 66 and 67 prefixed opcodes 2020-09-22 11:16:18 +02:00
ptitSeb 8e4b2a90a4 [DYNAREC] Fixed 64 67 8F POP FS:Ew16 opcode 2020-09-21 23:03:23 +02:00
ptitSeb 85b3091b8a [DYNAREC] Added 64 67 A1 MOV EAX, FS:Ow opcode 2020-09-21 18:16:58 +02:00
ptitSeb 3838fc3d22 [DYNAREC] Added 64 67 8F POP FS:Ew16 opcode 2020-09-21 18:14:45 +02:00
ptitSeb 0f4722d580 Improved (f)open(64) wrapped function a bit more 2020-09-21 15:37:53 +02:00
ptitSeb 4241258158 Added a workaround for steam requieremnt checker 2020-09-21 15:37:23 +02:00
ptitSeb 13c446c918 Wrapped libappindicator (seems to fix Steam starting issues) 2020-09-21 06:17:08 -05:00
ptitSeb 9255026b84 [DYNAREC] Fix build 2020-09-21 11:56:32 +02:00
ptitSeb 119eb57a38 Added an option to Launch GDB when a Segfault occur (JIT Debugging) 2020-09-21 09:41:20 +02:00
ptitSeb 731f379bed Fixed a bug in FindDynablockDynablocklist(...) function, making message on segfault with dynarec more precise 2020-09-20 21:43:00 +02:00
ptitSeb bedcf304e1 Added 65 EB and 65 E9 opcode (also [DYNAREC]) 2020-09-20 16:50:33 +02:00
ptitSeb a4655484cb Added 64 EB and 64 E9 opcode (also [DYNAREC]) 2020-09-20 16:44:40 +02:00
ptitSeb babc5aba4f Added a few more wrapped functions to libc (for #204) 2020-09-20 09:45:55 +02:00
ptitSeb 763a6f8b02 Added syscall handling for syscall 11: execve (for #203) 2020-09-20 08:15:03 +02:00
ptitSeb b08960d4b9 Fixed some rounding issues with x87 interpretor (thx @pale) 2020-09-19 22:12:56 +02:00
ptitSeb 2c6e91622f Try to handle NULL argv and NULL envp in execv(e) wrapped function (still for #203) 2020-09-19 18:12:09 +02:00
ptitSeb 4679977612 Small optims on x87 interpretor 2020-09-19 18:03:18 +02:00
ptitSeb 0e387904b0 More work on execv(e) wrapped functions (still for #203) 2020-09-19 15:01:53 +02:00
ptitSeb f4238621a6 Handling of /proc/self/exe in execv(p) function (for #203) 2020-09-19 14:23:27 +02:00
ptitSeb 2fa19e8cae Handling of /proc/self/exe in (f)open(64) (for #202) 2020-09-19 14:13:41 +02:00
ptitSeb ab644d0638 Made same hacks for fopen64 as for fopen 2020-09-19 12:48:58 +02:00
ptitSeb 8d1db88e1a [DYNAREC] Free of dynablock log level is now DEBUG instead of INFO 2020-09-18 18:00:58 +02:00
ptitSeb 12215ac5dd Removed FLOAT build (was not compatible with Dynarec anyway) 2020-09-18 17:52:28 +02:00
ptitSeb 97d0b386ba Added more mpg123 wrapped functions 2020-09-16 08:33:47 +02:00
ptitSeb f8526be667 Reworked FPREM, FPREM1 and FXTRACT opcodes 2020-09-15 14:47:44 +02:00
ptitSeb 22624f6a29 Added g_pattern_spec_* wrapped functions to glib2.0 2020-09-15 10:39:31 +02:00
ptitSeb e70584e7fc Added some wrapped function to mpg123 2020-09-15 10:35:43 +02:00
ptitSeb ebd2346f3e Added some GLib2 wrapped functions 2020-09-15 10:08:38 +02:00
ptitSeb 03ce553620 Added 66 0F 38 0B PMULHRSW Gx, Ex opcode 2020-09-15 08:45:46 +02:00
ptitSeb 9418a37846 Added (F2) EB opcode 2020-09-14 08:01:23 +02:00
ptitSeb 4f186dec68 g_variant_new_va use va_list* and not just va_list... 2020-09-13 20:57:41 +02:00
ptitSeb 5867fd9912 Added D6 SACL opcode 2020-09-12 18:46:27 +02:00
ptitSeb cd327cfc5a Fixed a message when detecting Steam thta was obsolete 2020-09-11 15:06:21 +02:00
ptitSeb a3f95871b2 Fix loading of elf that have no header sections at all 2020-09-11 15:05:57 +02:00
ptitSeb 53021b770b Added 66 0F DA PMINUB Gx, Ex opcode ([DYNAREC] too) 2020-09-10 16:47:38 +02:00
ptitSeb 7f93731d0c [DYNAREC] Added 66 0F 50 MOVMSKPD Gd, Ex opcode 2020-09-10 16:30:44 +02:00
ptitSeb 570f82d7f8 Improved trace with pid when using fork 2020-09-10 11:27:59 +02:00
ptitSeb 2c8a069f47 Improved LOCK opcodes and locking on dynarec dumper 2020-09-09 20:19:19 +02:00
ptitSeb bbf23be1f3 Merge pull request #201 from rajdakin/NEONprinter_fix
Forgot to add those files
2020-09-08 23:15:56 +02:00
rajdakin accca4e700 [PRINTER] Also fixed VRSHL, VQSHL and VQRSHL 2020-09-08 23:11:40 +02:00
rajdakin ecc8ebef6a [PRINTER] Forgot to add those files 2020-09-08 19:04:35 +02:00
ptitSeb 6c8a807c8c Merge pull request #200 from rajdakin/NEONprinter_fix
Various printer fixes
2020-09-08 18:59:22 +02:00
rajdakin dfb2d5eaaa [PRINTER] Fixed the VMOV.<dt> R, D[imm] instruction printer 2020-09-08 18:52:12 +02:00
rajdakin 71c7ec6fed [PRINTER] Fixed a class of var. size opcodes printer 2020-09-08 18:30:35 +02:00
ptitSeb 55d216f024 [DYNAREC] Thoses fixes to 8bits and 16bits opcodes should have been pushed yesterday already 2020-09-08 08:35:30 +02:00
ptitSeb 5e22febd54 Fixed 0F BA /6 BTS opcode (thx @hmilyyang) 2020-09-08 08:34:21 +02:00
ptitSeb 436d871ea9 Reorganized a bit FreeBox86Context function 2020-09-08 08:33:20 +02:00
ptitSeb 02099912c5 [DYNAREC] Fixed (66) 0F D7 PMOVMSKB for good this time 2020-09-07 19:51:48 +02:00
ptitSeb 601aedb25a More improved to env. var. and other misc. attributes 2020-09-07 10:49:36 +02:00
ptitSeb c65aa3d507 Improvment to Env Var handling 2020-09-07 10:24:27 +02:00
ptitSeb 9b02837d5a Another small improvement to wrapped X11 2020-09-07 10:24:06 +02:00
ptitSeb dbbff7b833 Some fixes to some wrapped X11 function callbacks 2020-09-07 08:10:04 +02:00
ptitSeb e306db4d0c Added F2 25 opcode 2020-09-07 07:29:17 +02:00
ptitSeb 985266fc77 Small cosmetic change to one xcb wrapped function 2020-09-07 07:29:03 +02:00
ptitSeb a3f771cc7c Added a bunch of X11 / Xext / FontConfig wrapped functions 2020-09-06 17:05:09 +02:00
ptitSeb 71a1bea9c7 A few more xcb wrapped functions 2020-09-06 14:26:49 +02:00
ptitSeb 565543fbba Added a few more xcb wrapped functions 2020-09-06 12:20:19 +02:00
ptitSeb 9193194596 Less alarming error message on default log level when loading libraries 2020-09-06 11:03:54 +02:00
ptitSeb 83ea28ded7 Made BOX86_LOG=2 a bit less chatty 2020-09-06 10:55:35 +02:00
ptitSeb 1a69782f51 Added more libSSL/libcrypto wrapped functions 2020-09-05 21:10:48 +02:00
ptitSeb 394ea0f3d3 Added more xcb* wrapped functions 2020-09-05 16:09:27 +02:00
ptitSeb 0241bbdbc0 Added xcb_connect to wrapped libxcb 2020-09-05 14:51:14 +02:00
ptitSeb 5e00739776 Added more pulseaudio wrapped functions 2020-09-05 13:22:21 +02:00
ptitSeb 5d214ac965 Added some more libasound wrapped functions 2020-09-05 12:11:32 +02:00
ptitSeb d35ae51fbb Oops, fixed libxrandr and libxcb-randr private mixup 2020-09-05 11:19:29 +02:00
ptitSeb 717f319dc7 Fixed CPUID command 0 Max basic command supported 2020-09-05 11:18:56 +02:00
ptitSeb fbd2f52da2 Added a few xcb_*_id to xcb-* wrapped libs 2020-09-05 10:57:08 +02:00
ptitSeb 853d89ca9c Added (stub) mcount to wrapped libc 2020-09-05 10:56:44 +02:00
ptitSeb 9c9e3cef29 Added getentropy to wrapped libc 2020-09-05 10:46:46 +02:00
ptitSeb 2237afceff Some fixes to the new empty xcb-* wrapped libs 2020-09-05 10:34:10 +02:00
ptitSeb 180d036fd4 Added some empty xcb-* wrapped lib 2020-09-04 23:57:12 +02:00
ptitSeb 7248ee7ed2 Update README.md 2020-09-04 23:56:57 +02:00
ptitSeb d1e7944ad2 Fix shrd16/shld16 opcode (thx to @hmilyyang) 2020-09-03 13:28:04 +02:00
ptitSeb 2f53752e05 Added a workaround for Unreal, to avoid segfault when launching it whithout leading './' 2020-09-03 10:41:13 +02:00
ptitSeb 3c0de68a00 Fixes to PMOVMSKB opcode ([DYNREC] too, avoiding a segfault) 2020-09-02 14:09:32 +02:00
ptitSeb ef22236f35 [DYNAREC] Another attempt to fix 66 0F D7 PMOVMSKB opcode 2020-09-02 10:19:42 +02:00
ptitSeb 563fc27eae [DYNAREC] Try to fix 66 0F D7 PMOVMSKB opcode 2020-09-02 08:48:59 +02:00
ptitSeb d453e120c8 Added F2 0F 80..8F (BND) Jxx opcodes 2020-09-01 22:29:08 +02:00
ptitSeb 57bd72f147 [DYNAREC] Added 66 0F F1/F2/F3 PSLL(W/D/Q) opcodes 2020-09-01 18:42:23 +02:00
ptitSeb 298c62e00b [DYNAREC] 66 0F D7 PMOVMSKB Gd, Ex opcode 2020-09-01 18:41:31 +02:00
ptitSeb 3d4abfeba2 [DYNAREC] Fix(?) 0F D7 PMOVMSKB Gd, Em opcode 2020-09-01 18:40:43 +02:00
ptitSeb b412118a79 [DYNAREC] Added 66 0F D3 PSRLQ Gx, Ex opcode 2020-09-01 18:05:42 +02:00
ptitSeb c2b5c32a14 Added CB FAR RET opcode 2020-08-31 10:45:11 +02:00
ptitSeb 06cd0a518f Added 64 67 8F POP FS:Ew16 opcode 2020-08-29 21:21:58 +02:00
ptitSeb 947dcc3f3d Added 0F 1A NOP / BNDLDX (ignored) opcode 2020-08-28 17:04:26 +02:00
ptitSeb fa5eb23cae Added 0F 1B NOP / BNDSTX (ignored) opcode 2020-08-28 10:55:45 +02:00
ptitSeb c43895b602 Update CHANGELOG.md 2020-08-27 22:07:18 +02:00
ptitSeb 18cb2a2047 [DYNAREC] Added 64 67 89 MOV Gd, FS:Ew16 opcode 2020-08-26 18:07:18 +02:00
ptitSeb 91637c7b11 [DYNAREC] Added 66 9C PUSHF and 66 9D POPF opcodes 2020-08-26 17:50:24 +02:00
ptitSeb 7b70e987ba [DYNAREC] Added 64 67 FF /6 PUSH FS:Ew16 2020-08-26 16:56:26 +02:00
ptitSeb 74dfef3424 [DYNAREC] Added 64 67 8B MOV Gd, FS:Ew16 and 64 67 A3 MOV FS:Ow, EAX opcodes 2020-08-26 16:26:28 +02:00
ptitSeb 65255edec5 [DYNAREC] Added 66 F8 CLC and 66 F9 STC opcodes 2020-08-26 15:11:29 +02:00
ptitSeb 5b00412ba0 [DYNAREC] Added D7 XLAT opcode 2020-08-26 15:05:51 +02:00
ptitSeb ef43e3f8a0 [DYNAREC] Added 0F EA PMINPS Gm, Em opcode 2020-08-26 14:24:29 +02:00
ptitSeb 3fa06d865a [DYNAREC] Added 66 99 CWD opcode 2020-08-26 14:01:15 +02:00
ptitSeb 96f2f12dec [DYNAREC] Added 66 EE PMAXW Gm, Em opcode 2020-08-26 13:43:06 +02:00
ptitSeb 972079532c [DYNAREC] Added 0F 74 PCMPEQB opcode 2020-08-26 13:11:02 +02:00
ptitSeb 996d4efa32 [DYNAREC] Added PADDUSW opcode 2020-08-25 13:55:45 +02:00
ptitSeb 4704bfb7e6 Added 66 0F DD PADDUSW opcode 2020-08-24 17:58:33 +02:00
ptitSeb 5d3b237854 [DYNAREC] Don't delete volatile dynablock (just invalidate) when memory block loose it's eXecutable flag 2020-08-24 14:00:17 +02:00
ptitSeb dca290b3f0 [DYNAREC] Fixed potential bus error on 0F 13 MOVLPS and 0F 17 MOVHPS opcodes 2020-08-23 15:55:44 +02:00
ptitSeb a84473036d [DYNAREC] End of block now provoque an X_PEND flags instead of X_ALL, also, removed the hl_linux workaround (and made C3 RET also needing an X_PEND flags) 2020-08-23 15:17:48 +02:00
ptitSeb 1b3cb7abb5 Merge pull request #191 from rajdakin/ubfx_fix
[DYNAREC] Fixed the UBFX and others instructions
2020-08-23 14:05:44 +02:00
rajdakin 7dd99ae13e [DYNAREC] Fixed the UBFX and others instructions 2020-08-23 13:54:16 +02:00
ptitSeb 7af511b01a Added 66 0F E4 PMULHUW Gx, Ex opcode 2020-08-23 11:41:58 +02:00
ptitSeb bb3dc2d889 Added 66 0F BA /7 BTC Ew, Ib 2020-08-22 11:05:57 +02:00
ptitSeb 76268c41bc Added 66 0F BA /5 BTS Ew, Ib 2020-08-22 10:24:54 +02:00
ptitSeb b6963ba7c6 Added 66 0F C8..CF BSWAP Reg16 opcode 2020-08-22 04:21:20 +02:00
ptitSeb bd3ff8f828 [DYNAREC] Add a temporary workaround to have HalfLife 2 Engine running correctly 2020-08-20 13:47:30 +02:00
ptitSeb 385326f3a8 [DYNAREC] Fixed RETN with N on 2 bytes (should help #188) 2020-08-19 15:21:07 +02:00
ptitSeb d896fd9106 Merge pull request #186 from shahidali55/patch-1
Removed backslash which was breaking ccmake
2020-08-18 10:06:28 +02:00
shahidali55 9c18afee35 Removed backslash which was breaking ccmake 2020-08-18 13:23:58 +05:30
ptitSeb f0b87c8312 Try to fix the gtk_display workaround when using gtk-1.2 instead of gtk-2.0 2020-08-17 20:24:10 +02:00
ptitSeb 297b7d548a [DYNAREC] Added a few GS: and FS opcodes 2020-08-17 17:07:49 +02:00
ptitSeb 7c406e8f8a [DYNAREC] Fixed CF flag for SHL32c emiter (fixed Sega Rally with Dynarec) 2020-08-16 20:55:23 +02:00
ptitSeb f458d8dc39 [DYNAREC] Optimized a bit BT Ed, Ib opcode 2020-08-16 20:54:47 +02:00
ptitSeb 66ed78cf4d [TRACE][DYNAREC] Small cosmetic changes to block that generate trace 2020-08-16 20:53:56 +02:00
ptitSeb f6205182b9 [TRACE] Fix trace that was disabled at first signal handling 2020-08-16 20:53:11 +02:00
ptitSeb a661016824 Avoid a BUSERROR on FISTP Ed, ST0 (help Sega Rally with Interpretor) 2020-08-16 20:52:28 +02:00
ptitSeb 448afcea7a [DYNAREC] Don't optimize flags on C3 RET opcode, some app count on it (help PlantsVsZombies and GOG Setup under wine, maybe more, #183) 2020-08-16 12:17:58 +02:00
ptitSeb 23881ad861 [DYNAREC] Avoid potential BUSERROR on FIST(P)64 2020-08-16 12:16:40 +02:00
ptitSeb 9d41f49741 {DYNAREC] Fixed a crash that can occur on multithreaded apps (fix regression on NFS2SE) 2020-08-16 10:58:00 +02:00
ptitSeb b302ebfbb5 [DYNAREC] Added F2/F3 9C PUSHF 2020-08-16 09:35:40 +02:00
ptitSeb 88d428f03c Added F2/F3 9C PUSHF opcode 2020-08-16 09:25:58 +02:00
ptitSeb 7396b30615 Fixed some '67' opcodes 2020-08-15 19:27:14 +02:00
ptitSeb 6fe1cc9ed7 [DYNAREC] Fixed 66 0F 5B CVTPS2DQ opcode 2020-08-15 19:25:52 +02:00
ptitSeb 7622959657 Generate git_head.h (and so build build_info.c) only when something else needs to be built 2020-08-15 17:44:34 +02:00
ptitSeb 6f94fdf133 [DYNAREC] Changed PUSHAD to have ESP always up-to-date 2020-08-15 14:49:18 +02:00
ptitSeb b348ce3660 Fixed git_head.h no generated at every build (it's build 2 times now with Dynrarec) 2020-08-15 14:23:37 +02:00
ptitSeb f8638fef92 Added 0F 01 /4 SMSW (dummy) opcode 2020-08-15 14:22:56 +02:00
ptitSeb 9e895da7ed Added wrapped gnutls_check_version function 2020-08-15 13:00:37 +02:00
ptitSeb cb659fef0d Added 66 0F B7 MOVZX Gw, Ew ([DYNAREC] too) 2020-08-15 12:53:13 +02:00
ptitSeb 1a9042c8d1 [DYNAREC] Simplified and optimized Dynablocklist Hash 2 Direct handling 2020-08-15 12:33:10 +02:00
ptitSeb aac8cb9775 [DYNAREC] Optimized dynablock handling 2020-08-15 12:31:37 +02:00
ptitSeb 99962a68b6 [DYNAREC] Removed dynablocks from elfheader, only using global one now 2020-08-15 10:56:39 +02:00
ptitSeb 8ce6d7f369 [DYNAREC] The 'volatile' dynablocks are now 4096 bytes of size, like a page (instead of 65536) 2020-08-15 09:48:59 +02:00
ptitSeb 3bc5a586fa Started v0.1.3 dev. cycle 2020-08-15 09:47:49 +02:00
ptitSeb f7630dec30 Bumped to v0.1.2 2020-08-14 10:04:55 +02:00
ptitSeb 031f41a333 Added build info (time and date) and git hash tag, rebuilt at each build 2020-08-14 10:03:32 +02:00
ptitSeb d18eb1c9c5 Added version and help options to box86 2020-08-14 09:13:12 +02:00
ptitSeb a666619de7 Added 0F BA /7 BTC opcode 2020-08-13 19:31:21 +02:00
ptitSeb a6d55175ac Added 0E PUSH CS opcode 2020-08-13 19:17:31 +02:00
ptitSeb b33d952b47 [DYNAREC] Some minor changes to emit_cmp16 2020-08-13 18:13:44 +02:00
ptitSeb 65fc0f36e7 [DYNAREC] Added 0F E8 PSUBSB and 0F E9 PSUBSW opcodes 2020-08-13 16:31:09 +02:00
ptitSeb 4bb743bde0 [DYNAREC] Fixed emit_sub16c (fixed sound in DeusEx) 2020-08-13 16:20:33 +02:00
ptitSeb 1b8f92249d [DYNAREC] Minor changes, to avoid potential BUSERROR mainly 2020-08-13 16:18:46 +02:00
ptitSeb 42838834f6 [DYNAREC] More log info on Unimplemented opcode 2020-08-13 16:18:13 +02:00
ptitSeb 83508fa322 Added F1 INT1 dummy opcode 2020-08-12 18:05:28 +02:00
ptitSeb 044d667b9e Added GL_EXT_multisampled_render_to_texture wrapped functions to libGL 2020-08-12 16:58:11 +02:00
ptitSeb 97274871c8 Protect memory only if Dynarec is used 2020-08-12 16:29:31 +02:00
ptitSeb e5fabc828c [DYNAREC] Added utility function to get dynarecblock from arm native dynarec address (and used it in SegFault handler) 2020-08-12 14:01:52 +02:00
ptitSeb e5601cb09c [DYNAREC] Made 81 /7 CMP Ed, Id opcode resiliant to SMC (fixes DeusEx, maybe other too) 2020-08-12 13:58:05 +02:00
ptitSeb 6f87bd8570 Added 67 E8 xx opcode (should help #179 too) 2020-08-11 17:41:04 +02:00
ptitSeb b393923c6e Added 65 2B SUB Gd, GS:Ed and 65 03 ADD Gd, GS:Ed opcode ([DYNAREC] too) (should help #179) 2020-08-11 16:54:00 +02:00
ptitSeb 37ab148df6 Simplified a bit ResolveFile utility function 2020-08-11 13:58:37 +02:00
ptitSeb 2f977f200b Added libcurl-gnutls.so.4 as a synonym a libcurl.so.4 2020-08-11 11:18:15 +02:00
ptitSeb e674f1a528 Changed PltResolver, to be inject in PLT.GOT instead of GOT.PLT before GOT (fixes Don't Starve) 2020-08-11 11:17:28 +02:00
ptitSeb fc93d47b14 Removed some useless code in wrapped glib2 lib 2020-08-10 18:55:50 +02:00
ptitSeb 3028d096b9 Merge pull request #178 from rajdakin/makefix
x86 build fix
2020-08-10 16:52:19 +02:00
rajdakin e7313a4df4 [BOX86] Fixed multiple non-extern definitions (x86 build) 2020-08-10 16:49:24 +02:00
rajdakin 31af5ec181 [LIBTOOLS] Fixed x86 builds (__i386 is defined, not __x86__) 2020-08-10 16:48:13 +02:00
ptitSeb 98222c75c2 Merge pull request #177 from rajdakin/VMOVinsn_fix
[DYNAREC] Fixed the four VMOV VFPU instructions printer
2020-08-10 16:35:51 +02:00
rajdakin d0380eccf7 [DYNAREC] Fixed the four VMOV VFPU instructions printer 2020-08-10 16:28:03 +02:00
ptitSeb f570ee0ea2 Fixed nanoslepp that was broken with last commit 2020-08-09 15:38:43 +02:00
ptitSeb 6ac716b8ba Update README.md 2020-08-09 10:10:22 +02:00
ptitSeb e8a080f5c0 Added COLOR_PAIRS to ncurses* (help Dwarf Fortress in text mode) 2020-08-08 17:45:53 +02:00
ptitSeb 67237e54f9 Added some workaround for nanosleep with null parameter 2020-08-08 17:20:29 +02:00
ptitSeb 4acf0f080e refactored CPUID opcode, and added a few more SubCommand (80000001..80000005) 2020-08-08 11:23:09 +02:00
ptitSeb 8e576f3f7d Merge pull request #176 from spacepilotAV/patch-1
Fix spelling of surprisingly in README.md
2020-08-07 19:32:10 +02:00
ra1n 037859b007 Fix spelling of surprisingly in README.md
speeling is important guys ;)
2020-08-07 13:14:39 -04:00
ptitSeb e81e7c7ebd Allow the use of #ifndef in wrapper _private headers 2020-08-07 15:45:17 +02:00
ptitSeb a50079b920 Better wrapping of g_variant_new_va (should help #167) 2020-08-07 15:43:48 +02:00
ptitSeb 4a38d8199f Merge pull request #175 from truboxl/patch-1
Make test10 more robust
2020-08-06 12:38:27 +02:00
Jia Yuan Lo 4dd9337528 Make test10 more robust
Test10 currently only passes after "make install" (no regard to x86lib directory needed) or we build directly inside box86 folder.
This change make sure x86lib folder is properly located so that we can also "ctest" inside build folder after compile without "make install".

Signed-off-by: Jia Yuan Lo <[email protected]>
2020-08-06 18:22:01 +08:00
ptitSeb c6db07039f Merge pull request #174 from Icenowy/fld-double-sigbus
[DYNAREC] Avoid SIGBUS on FLD double
2020-08-06 09:57:43 +02:00
Icenowy Zheng 9294b59aae [DYNAREC] Avoid SIGBUS on FLD double
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-06 05:53:11 +08:00
ptitSeb 490f595d6d [DYNAREC] Avoid BUSERROR on 0F 7F MOVQ (should help #167) 2020-08-05 18:52:12 +02:00
ptitSeb 67af7a0baf [DYNAREC] Fixed freeze issue introduce with previous commit 2020-08-05 15:10:00 +02:00
ptitSeb 7da89748bb [DYNAREC] Small change on nolinker block handling (when son is outside the range of the parent) 2020-08-05 12:02:15 +02:00
ptitSeb 72a82ebece [DYNAREC] Reordered the cleaning of dynablocks / dynablocks list to avoid segfault 2020-08-05 11:17:21 +02:00
ptitSeb 12e44a3e62 Merge pull request #173 from Icenowy/blocks_hashmap_check
check whether blocks hashmap exists when removing block from it
2020-08-05 10:01:30 +02:00
Icenowy Zheng 5dd94df9dd check whether blocks hashmap exists when removing block from it
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:57:23 +08:00
ptitSeb 79051e04b4 Merge pull request #172 from Icenowy/dynablock_mark_foreach_fix
dynablock: do not access value when foreach on marks
2020-08-05 09:46:40 +02:00
ptitSeb 02a0a77bda Merge pull request #170 from Icenowy/sdl_tolowerupper
wrap SDL_to{lower,upper}
2020-08-05 09:39:33 +02:00
Icenowy Zheng b3c5115707 dynablock: do not access value when foreach on marks
Accessing the value of a kh_set (which has no values set) is an
undefined behavior, which may make monsters to appear.

Add a kh_foreach_key macro that do not touch values at all, and use it
when ennuerating marks in dynablock, to prevent SIGSEGV of accessing
non-existent values.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:26:55 +08:00
Icenowy Zheng e069681cfd wrap SDL_to{lower,upper}
These are very simple function that accepts an int and returns an int.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-05 15:00:30 +08:00
ptitSeb c93356fb1a Deactivated Segment optim for GS (should help #167) 2020-08-04 16:19:56 +02:00
ptitSeb c398c938e1 Added F2/F2 18..1D opcode (F2/F3 ignored) 2020-08-04 15:43:20 +02:00
ptitSeb f3c6dc31ac Added 66 36 prefix (and fixed 66 2E and 66 26 prefixes) 2020-08-04 15:28:44 +02:00
ptitSeb 06403425f9 Merge pull request #166 from Icenowy/ld_library_path_prepend
prepending LD_LIBRARY_PATH
2020-08-04 10:25:30 +02:00
ptitSeb a9fa9095d5 Merge pull request #165 from Icenowy/g_utf8_skip
wrap g_utf8_skip in glib, which is a pointer to an array of char
2020-08-04 09:40:17 +02:00
Icenowy Zheng 617eacfcd3 prepending LD_LIBRARY_PATH
LD_LIBRARY_PATH should be able to override system libraries, this is the
behavior of ld-linux.so.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-04 04:34:54 +08:00
Icenowy Zheng 7ba89639da wrap g_utf8_skip in glib, which is a pointer to an array of char
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-04 02:14:05 +08:00
ptitSeb 2914ed358e [DYNAREC] Don't allocate Direct Dynablock on mmap 2020-08-03 00:10:17 +02:00
ptitSeb 72041b6873 Make bridges allocate larger chunk 2020-08-03 00:09:41 +02:00
ptitSeb bf8da23a76 Added SS_ONSTACK fake handling to sigaltstack, so Unity game don't assert at start 2020-08-02 20:06:34 +02:00
ptitSeb f3f3d9cdfe Some small fixes to Segment offset cache mecanism 2020-08-02 19:57:43 +02:00
ptitSeb 05c7d8fec9 Use a Cache (per thread) of Segment Offset, to sppedup GS: and FS: access 2020-08-02 16:04:27 +02:00
ptitSeb 5201aeffa6 [DYNAREC] Small optim in GetDynablocksFromAddress, starting with fast getDBFromAddress before looking içnto elf memory 2020-08-02 16:03:55 +02:00
ptitSeb 2fba190d8b [DYNAREC] Improved son creation for large dynablock (or block near end of dynablocklist) by allow the use of a different dynablocklist parent 2020-08-02 14:17:54 +02:00
ptitSeb 9e669ad06b [DYNAREC] Added 66 F2/F3 A7 REP(N)Z CMPSW and 66 F2/F3 AF REP(N)Z SCASW 2020-08-02 14:16:36 +02:00
ptitSeb 7f66be599c [DYNAREC] Added D9 /4 FLDENV Ed opcode 2020-08-02 13:55:36 +02:00
ptitSeb 7d1f429ead [DYNAREC] Added 66 91..97 XCHG AX, reg opcode 2020-08-02 13:55:07 +02:00
ptitSeb 4e602abfcb Try to improve (and fix) obstack wrapping (should help #160) 2020-08-02 10:08:05 +02:00
ptitSeb aad016d418 Merge pull request #163 from Icenowy/obstack_free
Add an automatic wrapper for {,_}obstack_free
2020-08-01 22:12:25 +02:00
Icenowy Zheng 3544428e18 Add an automatic wrapper for {,_}obstack_free
Signed-off-by: Icenowy Zheng <[email protected]>
2020-08-02 04:07:29 +08:00
ptitSeb 459c3ef530 Various small x87 adjustments 2020-08-01 17:58:09 +02:00
ptitSeb a01f5b1f3f [DYNAREC] Added a warning when a son have no code 2020-08-01 17:57:52 +02:00
ptitSeb 9183391ab0 Forgot the EXPORT for my__obstack_begin (should help #160) 2020-08-01 17:56:51 +02:00
ptitSeb c22ca077ba [DYNAREC] Added CF IRET opcode 2020-08-01 15:11:17 +02:00
ptitSeb 63c224b073 Ajusted D9 F5 FPREM1 opcode 2020-08-01 14:07:48 +02:00
ptitSeb f36567593a Added _obstack_begin wrapped function to libc (for #160) 2020-07-31 18:11:10 +02:00
ptitSeb b2efee99fa Merge pull request #159 from Icenowy/main-fix
Fix compliation of non-dynarec build
2020-07-30 20:39:27 +02:00
Icenowy Zheng 6510dc9e45 Fix compliation of non-dynarec build
sysconf() is part of unistd.h, and src/main.c uses it. However, this
source code file only includes <unistd.h> when DYNAREC, makes
non-dynarec build fail for missing _SC_PAGESIZE macro.

Move the inclusion of <unistd.h> out of #ifdef DYNAREC.

Signed-off-by: Icenowy Zheng <[email protected]>
2020-07-31 01:55:06 +08:00
ptitSeb 213beed360 Merge branch 'master' of https://github.com/ptitSeb/box86 2020-07-29 17:24:13 +02:00
ptitSeb 801f374a66 Added a workaround to get wine run under interpretor only 2020-07-29 17:23:51 +02:00
ptitSeb 7f3eecec4c Merge pull request #157 from icecream95/cmsg
Add a wrapped function for __cmsg_nxthdr
2020-07-29 13:16:40 +02:00
Icecream95 bd92f64df9 Add a wrapped function for __cmsg_nxthdr 2020-07-29 22:55:02 +12:00
ptitSeb ab2617c20f [DYNAREC] This +1 was not needed, end is alread aligned and all 2020-07-29 08:00:39 +02:00
ptitSeb cd958240df [DYNAREC] More small change on memory protection scheme 2020-07-28 17:34:06 +02:00
ptitSeb 4254a2a2f7 Small change to vfprintf wrapped function 2020-07-28 16:57:38 +02:00
ptitSeb 9735f21f65 [DYNAREC] Some more small fixes on memory protection scheme 2020-07-28 13:25:59 +02:00
ptitSeb 62343cbb77 Made bridge structure slightly bigger so it align 2020-07-28 13:24:46 +02:00
ptitSeb 23eca257f4 Merge pull request #156 from Newbytee/patch-1
Language fixup in README
2020-07-27 15:41:02 +02:00
Newbyte 5a3c17e831 Language fixup in README
I did some language fixes in README. During this I took some liberties to improve consistently, like always writing Box86 with a capital B. I am not sure whether you have a preferred way to stylise it, but as it is prior to this PR the README mixes box86 and Box86 heavily, and I decided to go with the latter. If you prefer it to always be written box86 with a lowercase b I can change it to be so.
2020-07-27 15:11:05 +02:00
ptitSeb de1bb7e438 Improved internal path resolution (should help #154) 2020-07-27 10:03:56 +02:00
ptitSeb 6216d06d0e [DYNAREC] Fine-tuned, again, how cleanDBFromAddressRange worked 2020-07-27 09:03:13 +02:00
ptitSeb cb03a51d40 [DYNAREC] Fixed a crash in later dynarec log level 2020-07-27 09:01:41 +02:00
ptitSeb 09a65a622a [DYNAREC] Small change in protection of dynarec volatile block, with a better detection of start address to scan 2020-07-26 20:42:25 +02:00
ptitSeb 95f6ce1f3e Fixed a potentiel read isse with execv method 2020-07-25 16:48:38 +02:00
ptitSeb 7ede988cb1 Added 64 67 A3 xx xx MOV FS:[Ov], EAX 2020-07-24 15:32:52 +02:00
ptitSeb a06e05dc9e Added 64 67 89 MOV FS:ED16,GD opcode 2020-07-23 10:13:27 +02:00
ptitSeb 2a3c6dc55c Added 6E/6F OUTSB/OUTSD (faked) opcode 2020-07-23 10:12:13 +02:00
ptitSeb 814701324c Added F2/F3 66 A7 REP(N)Z CMPSW 2020-07-22 15:41:43 +02:00
ptitSeb 01fea9ce3f Checked all wrapped function used by ntdlls.so, fixing some of them 2020-07-21 08:06:39 +02:00
ptitSeb da5e795858 [DYNAREC] Disable the use of SWP arm opcode for XCHG x86 opcode, while the 8bit verison seems ok, the 32bits is not 2020-07-20 08:30:52 +02:00
ptitSeb b491241307 Added 64 67 FF /6 PUSH FS:[Ed16] opcode 2020-07-20 08:29:40 +02:00
ptitSeb 81f6e87416 Fixed glXCreatePbuffer wrapped function signature 2020-07-19 23:20:06 +02:00
ptitSeb 20a680561a Added wrapped libncurses.so.6 and libtsinfo.so.6 (based on .5 version) 2020-07-19 18:21:45 +02:00
ptitSeb a4f2a19505 Added EC INSB AL, DX 2020-07-18 12:47:32 +02:00
ptitSeb a263283c93 Added 16 PUSH SS and 17 POP SS opcodes 2020-07-17 20:36:41 +02:00
ptitSeb ac2cdc65a8 Added a few off opcodes 2020-07-17 16:08:37 +02:00
ptitSeb c1b7740ac4 Added 66 91..97 XCHG AX, Reg opcodes 2020-07-17 08:21:57 +02:00
ptitSeb a1c8868159 Added 66 60 and 66 61 PUSHA POPA opcodes 2020-07-16 21:38:05 +02:00
ptitSeb a157acd185 Added 64 67 A1 xx xx opcode 2020-07-16 20:19:32 +02:00
ptitSeb 12ec1309bb Added option to disable the hack to force X11 GLX Extension beeing detected (help wine stuff while gl4es is not uet compatible) 2020-07-16 09:22:37 +02:00
ptitSeb 042d55f734 Added 66 F3 A4 (alt) MOV SB ([DYNAREC] too) 2020-07-16 08:17:21 +02:00
ptitSeb 67f8c6df42 Added F2/F3 40..4F (alt)INC/DEC reg opcode 2020-07-15 20:38:15 +02:00
ptitSeb c9d6c72fe0 Added 0F F7 MASKMOVQ opcode 2020-07-15 15:41:08 +02:00
ptitSeb e5fcadae30 Fixed signature for XGetAtomNames wrapped function 2020-07-15 13:42:00 +02:00
ptitSeb cb0ee7990a Added a workaround to ignore failed test of GLX extension in X11 2020-07-15 13:33:14 +02:00
ptitSeb 0eea4c5913 Added 0F E7 MOVNTQ opcode ([DYNAREC] too) 2020-07-15 09:14:36 +02:00
ptitSeb 5a8466b0d7 Fix compilation for non-dynarec build 2020-07-15 08:36:46 +02:00
ptitSeb 372d811f66 Added 65 8A MOV Gb, GS:Eb 2020-07-14 23:48:13 +02:00
ptitSeb ff2027846b [DYNAREC] Fixed issue when dlclose then dlopen a library 2020-07-14 20:26:37 +02:00
ptitSeb 8318eb1a0d Added 0F BA /5 BTS Ed, Ib opcode 2020-07-14 19:20:31 +02:00
ptitSeb 57c0751793 Added 66 FF /6 PUSH Ed opcode 2020-07-14 19:19:58 +02:00
ptitSeb 86b00ef7fe Added 66 9D POPF opcode 2020-07-14 18:59:56 +02:00
ptitSeb 6e12a556ec Fixed a warning 2020-07-14 18:06:01 +02:00
ptitSeb fba165d121 Added 64 67 8B opcode 2020-07-14 18:05:40 +02:00
ptitSeb 68d77636b0 Changed again a bit the destruction sequence for box86context 2020-07-14 14:37:11 +02:00
ptitSeb 394d46f731 Added 66 0F BA BTR opcode 2020-07-14 14:36:44 +02:00
ptitSeb 702a9f6aa5 Added dummy 0F 00 VERR/VERW and 0F EA PMAXSW opcode 2020-07-14 13:48:41 +02:00
ptitSeb 7ae3813ac5 Set my_context to NULL when context is beeing destroyed 2020-07-14 12:13:55 +02:00
ptitSeb 34a933af0b Try to get more info on segfault (not sure it's a good idea) 2020-07-14 12:13:22 +02:00
ptitSeb 4ac5d6df7f Added 36 SS: (ignored) prefix ([DYNAREC] too) 2020-07-14 11:29:52 +02:00
ptitSeb 0260548d9c Fixed a few glX wrapped functions 2020-07-14 11:29:22 +02:00
ptitSeb 5b64623f50 [DYNAREC] Fix a potential crash when a volite dynablock is 0 len 2020-07-14 10:18:29 +02:00
ptitSeb 233e472503 Added 0F EA PMINSW Gm, Em opcode 2020-07-14 09:58:36 +02:00
ptitSeb 335512e96a Added fake 62 BOUND GD, Ed opcode ([DYNAREC] too) 2020-07-14 09:47:13 +02:00
ptitSeb d451a3fdd7 Added 64 3B CMP Gd,FS:Ed ([DYNAREC] too) 2020-07-14 09:13:50 +02:00
ptitSeb 499de4fd60 Oops, forgot to remove some debug code 2020-07-13 21:05:18 +02:00
ptitSeb caf9abc16f Added also F2/F3 E9 opcode ([DYNAREC] too) 2020-07-13 19:12:35 +02:00
ptitSeb 5dfce69c37 Added F2/F3 E8 opcode ([DYNAREC] too) 2020-07-13 19:04:03 +02:00
ptitSeb 8f12829e95 Added some more wrapper to opengl 2020-07-13 18:23:13 +02:00
ptitSeb 15a42f5407 Added some wine prereserve mecanism 2020-07-13 17:38:45 +02:00
ptitSeb c8cdd3f432 [DYNAREC] Added F2/F3 66 AF REP(N)Z SCASW opcode 2020-07-13 17:38:19 +02:00
ptitSeb ac7c72396d Added F2/F3 66 AF REP(N)Z SCASW opcode 2020-07-13 17:37:43 +02:00
ptitSeb ce3271f095 Fixed some case of bad error with mmap / mmap64, plus improve trace of it 2020-07-13 17:36:32 +02:00
ptitSeb 3ff4b04e52 [DYNAREC] More alignment fixes 2020-07-13 17:35:05 +02:00
ptitSeb ecd90a41d5 [DYNAREC] Try to avoid some SIGBUS on DC xx opcodes 2020-07-13 14:50:58 +02:00
ptitSeb 87695cf84b [DYNAREC] Try to avoid potention SIGBUS on some F2 0F xx opcodes 2020-07-13 14:32:12 +02:00
ptitSeb 3bb93e1fd9 Added F2 0F 7C HADDPS opcode ([DYNAREC] too) 2020-07-13 11:30:24 +02:00
ptitSeb 69279b2233 Added D9 F6 FDECSTP and D9 F7 FINCSTP opcodes 2020-07-13 10:54:46 +02:00
ptitSeb 7c811666fe Added 0F A0/A1/A8/A9 PUSH/POP FS/GS opcodes ([DYNAREC] too) 2020-07-13 10:43:49 +02:00
ptitSeb 9a18dd3718 Added 0F D7 PMOVMSKB opcode ([DYNAREC] too) 2020-07-12 15:03:06 +02:00
ptitSeb 3338d26aaa Add 2 more wrapped function to libpulse 2020-07-12 12:38:58 +02:00
ptitSeb 167ea1587e Chnaged a bit signals debug 2020-07-12 12:38:31 +02:00
ptitSeb 7ad6399940 Added workaround for _finite function not always present in libm, using regular function as fallback (should help #138) 2020-07-12 10:39:03 +02:00
ptitSeb 71db6b3275 Some changes to the interpretor to ensure R_EIP is always correct 2020-07-11 18:12:03 +02:00
ptitSeb 00626b9f3e Fixed an issue with FS: access (or any other custom selector) 2020-07-11 16:11:48 +02:00
ptitSeb d0fa79c9ca [DYNAREC] Fixed PUSH FS:Ed opcode 2020-07-11 15:54:10 +02:00
ptitSeb fc1f75c3f6 [DYNAREC] Added 2 segment related opcodes 2020-07-11 15:17:15 +02:00
ptitSeb 21b9676093 Added some wrapped function to libusb-1.0 2020-07-11 14:38:36 +02:00
ptitSeb ea2a7204df Forgot that fix for libpng12 2020-07-11 14:38:10 +02:00
ptitSeb bcdd09a2e6 Removed dup'd function in wrapped libpng16 2020-07-11 14:28:37 +02:00
ptitSeb 7c394ddeee Show args for emulated program on BOX86_LOG=1 at start 2020-07-11 13:57:23 +02:00
ptitSeb 50d7e2d1d7 Some fixes to wrapped libpng16 and libpng12 2020-07-11 13:55:10 +02:00
ptitSeb 395cecb082 More change on signal handler. Still not complete enough 2020-07-10 20:46:20 +02:00
ptitSeb c8888915d7 [DYNAREC] Very small optim on CALL Ed opcode 2020-07-09 22:13:00 +02:00
ptitSeb 38740ce1c9 [DYNAREC] Try to avoid a segfault, bad mix with PltResolver that can hapens (should help #145) 2020-07-08 22:46:43 +02:00
ptitSeb 73b893215e [DYNAREC] Added FSAVE and FRSTOR opcode 2020-07-08 22:45:58 +02:00
ptitSeb e93c3f0028 Added option to have different trace per pid (to avoid overwritting when multiple process are spawning) 2020-07-08 18:21:49 +02:00
ptitSeb be2e35381e Removed a dupe in wrapped lib xrender 2020-07-08 16:46:57 +02:00
ptitSeb c79f59c86f Added one more wrapped function to libxi 2020-07-08 16:30:10 +02:00
ptitSeb 6f02d5f2c4 Added more gnutls wrapped functions 2020-07-08 16:23:40 +02:00
ptitSeb 969bd84f1d Added more FreeType wrapped functions 2020-07-08 15:36:20 +02:00
ptitSeb 8865b7bfec Added wrapped libgnutls (with some wrapped functions) 2020-07-08 15:15:11 +02:00
ptitSeb f60ecc3626 Added more wrapped function to libpng16 2020-07-08 14:10:36 +02:00
ptitSeb 824b230bd0 Added some support for modify_ldt syscall, but pretty useless whle 16bits is not supported 2020-07-08 13:38:13 +02:00
ptitSeb 71a208334d [DYNAREC] Changed a bit what PUSH/POP DS/ES emit (more in line with PUSH/POP reg) 2020-07-08 13:37:08 +02:00
ptitSeb 1d75d23772 Added wrapped libmpg123 lib (partial) 2020-07-07 09:40:16 +02:00
ptitSeb 6dd848eac5 Added F2/F3 70..7F (BND) Jxx and 64 8F PUSH FS:Ed opcodes 2020-07-07 07:50:17 +02:00
ptitSeb 0c0684bfb7 Added support for set_thread_area and handling of FS: 2020-07-06 21:57:46 +02:00
ptitSeb b56337df19 [DYNAREC] Fix potential crash when deleting a dynoblock without map 2020-07-06 21:57:46 +02:00
ptitSeb 0f0512c67c Merge pull request #144 from Mashintime/master
Update CMakeLissts.txt to copy libstdc++.so.5
2020-07-06 21:35:46 +02:00
Mashintime b677261976 Update CMakeLissts.txt to copy libstdc++.so.5
Included in x86libs but not copied to /usr/lib when 'make installing'
2020-07-06 15:25:24 -04:00
ptitSeb 0d0a75319c Fixed an old typo on impacting thread_attr_setstacksize 2020-07-06 21:24:53 +02:00
ptitSeb 0d283757d5 Update README.md 2020-07-06 07:48:19 +02:00
ptitSeb c09f477251 Improvement to the trace of called wrapped functions 2020-07-05 18:48:13 +02:00
ptitSeb 1d2bf3cb48 Try to make the O_XXXX convert function more portable 2020-07-05 14:28:25 +02:00
ptitSeb 7057160b3e Improved handling of pthread get/set affinit (old and new version) 2020-07-04 18:53:26 +02:00
ptitSeb 4244f41c41 Added helper function to get function name based on address 2020-07-04 15:41:28 +02:00
ptitSeb 70f587e305 Fixed potential issue with cmake 2020-07-04 14:20:51 +02:00
ptitSeb 97c5119807 Update README.md 2020-07-03 21:04:08 +02:00
ptitSeb 77a74d64bf [DYNAREC] Try to avoid a crash caused by a bad mix of dynarec and unresolved plt 2020-07-02 09:53:55 +02:00
ptitSeb 0547cec24d More SDL2 wrapped function with dummy fallback (plus some refactor and a fix probably) 2020-06-30 19:51:20 +02:00
ptitSeb 6837f58a0e Added 1 unofficial wrapped function (with dummy fallback) to SDL2 2020-06-30 18:28:32 +02:00
ptitSeb 2518377f83 Some fix to SDL2 wrapped lib 2020-06-30 14:14:24 +02:00
ptitSeb d38e67f539 Improved libx11 callback handling 2020-06-30 13:55:09 +02:00
ptitSeb a3d16d3c71 [DYNAREC] Fixed a warning 2020-06-30 12:48:41 +02:00
ptitSeb 14e1363930 Changed how FXSAVE/FXRSTOR works (in [DYNAREC] too) 2020-06-30 12:45:54 +02:00
ptitSeb 86eba0aaeb [DYNAREC] Actually use 64 FS: prefix 2020-06-30 12:06:39 +02:00
ptitSeb 10d7e28de3 Added some wrapped functions to a few libs 2020-06-30 09:49:02 +02:00
ptitSeb 082d08755e Stop ignoring tgsysall for now 2020-06-30 09:41:38 +02:00
ptitSeb 195bbddd6f This should avoid the 'wall of segfault' that happens sometimes 2020-06-30 09:06:43 +02:00
ptitSeb d68cbfd837 Added CF IRET opcode (not sure if correct) 2020-06-30 00:42:21 +02:00
ptitSeb 851d487015 [DYNAREC] Fixed FXSAVE / FXRSTOR (partial) opcode 2020-06-30 00:16:18 +02:00
ptitSeb 0a3ae03043 Added libncurses.so.5 wrapped function (bases libncursesw) and added 1 wrapped function to lbtsinfo.so.5 2020-06-30 00:09:59 +02:00
ptitSeb d56fea52f3 Added preliminary dlinfo wrapped function 2020-06-29 23:25:08 +02:00
ptitSeb 1de0f14194 [DYNAREC] Fix hang when call address 0 2020-06-29 23:24:48 +02:00
ptitSeb d3addae744 Fixed a warning in x86tls.c 2020-06-29 21:30:22 +02:00
ptitSeb ee0e831efe [DYNAREC] Added some FS: opcode (copy of GS: ones) 2020-06-29 20:41:44 +02:00
ptitSeb 59559efbb5 Handling default value for FS when creating new x86emu_t structure 2020-06-29 19:52:56 +02:00
ptitSeb 05e2a9c824 Fixed pwrite64 wrapped function signature 2020-06-29 19:39:41 +02:00
ptitSeb 9038d94184 Added a few wrapped function to libm 2020-06-29 18:25:51 +02:00
ptitSeb 08a93fc5ae Added memccpy wrapped function to libc 2020-06-29 18:09:04 +02:00
ptitSeb 6b6075ca48 Fixed dladdr wrapped function 2020-06-29 17:43:54 +02:00
ptitSeb 51135b9222 Added support for DT_RUNPATH (handed the same way as DT_RPATH) 2020-06-29 16:49:39 +02:00
ptitSeb 922c1770a0 [DYNAREC] Fix PUSH/POP DS/ES that should handle 32bits value on the stack (even if segment is 16bits) 2020-06-29 14:24:11 +02:00
ptitSeb b9dc8d79e0 Added 1 wrapped function to libX11 2020-06-29 13:03:11 +02:00
ptitSeb 7b823e4185 Changed execv wrapped function to automaticaly call box86(t) for x86 binary (help valgrind with --trace-children=yes) 2020-06-29 12:27:53 +02:00
ptitSeb fbdb4aa619 Changed how actual box86 fullpath is found 2020-06-29 12:24:55 +02:00
ptitSeb 7716936f77 [DYNAREC] Better way to free dynablocks (when a son would be free because his parent is freed, but still accessed to check if it can be freed) 2020-06-29 12:02:25 +02:00
ptitSeb 9636fec9da Free elfs first thing in FreeBox86Context 2020-06-29 12:01:15 +02:00
ptitSeb e15676e946 Changed how argv strings are handled 2020-06-29 11:41:07 +02:00
ptitSeb 28fb4ed090 [DYNAREC] Fixed a small potential memory overwritting 2020-06-29 11:19:55 +02:00
ptitSeb 8b5474d0a8 Added a few libX11 wrapped functions 2020-06-29 10:02:17 +02:00
ptitSeb 35e5a48e63 Added some FreeType wrapped functions 2020-06-29 08:56:47 +02:00
ptitSeb 470446a104 Removed some debug leftover 2020-06-29 08:56:26 +02:00
ptitSeb c0cc48d129 Added preliminary support for FS: and set_thread_area 2020-06-29 08:44:13 +02:00
ptitSeb 1134294037 [DYNAREC] Fix (66) 8E MOV Seg,Ew opcodes 2020-06-29 07:45:25 +02:00
ptitSeb f0f49d4f8f [DYNAREC] Fixed 66 8C MOV Ew, Seg and 66 8E MOV Seg, Ew opcodes 2020-06-28 19:22:19 +02:00
ptitSeb 5f361cbd2d Added exception for win-preloader in main (to not preload but load directly) 2020-06-28 18:01:54 +02:00
ptitSeb 20d65d3685 Wrapped lib now have path set to actual name 2020-06-28 17:16:50 +02:00
ptitSeb 51f0780c66 [DYNAREC] Added 0F 63 PACKSSWB opcode 2020-06-28 16:22:02 +02:00
ptitSeb b3db9aece7 [DYNAREC] Fixed PUSH ES / POP ES 2020-06-28 15:58:29 +02:00
ptitSeb 4e22fd1a69 Enabled SYS_RECVMMSG and SYS_SENDMMSG on syscall 102 even if those 2 macro are not defined 2020-06-28 11:23:42 +02:00
ptitSeb d290ccee7f [DYNAREC] Added 0F 51 SQRTPS and 0F 52 RSQRTPS opcodes 2020-06-27 20:13:42 +02:00
ptitSeb 4d227ef882 [DYNAREC] Added MINPD and MAXPD 66 0F 5D and 66 0F 5F opcodes 2020-06-27 18:28:40 +02:00
ptitSeb 6f842cea8b Changed the way NEEDED lib and GLOBAL symbol are fetched (again, for good this time hopefully, at least is seems to fix #136) 2020-06-27 14:02:56 +02:00
ptitSeb 36da25e08e Added 1 wrapped function to x11 lib 2020-06-27 08:57:45 +02:00
ptitSeb f586bb2617 Added syscall 196 sys_lstat64 2020-06-26 23:10:31 +02:00
ptitSeb f3a81ac635 Added syscall 66 sys_setsid 2020-06-26 19:37:31 +02:00
ptitSeb 266fc0961b Added syscall 271: sys_utimes 2020-06-26 19:09:11 +02:00
ptitSeb 824ae55d77 Added DS: prefix (ignored), can be used as hint, along with CS: in conditionnal jump (also ignored) 2020-06-26 18:22:41 +02:00
ptitSeb 656bfdc569 Fixed a small warning in gio2 wrapped lib 2020-06-26 09:01:53 +02:00
ptitSeb 0f45dd5fee Added libc syscall 174 (rt_sigaction) 2020-06-25 08:53:28 +02:00
ptitSeb 82e7faf83d Added more slot for pthread_once_callback 2020-06-24 18:24:20 +02:00
ptitSeb 0c7310b18d Really fixed epoll_create1 2020-06-24 16:00:28 +02:00
ptitSeb 2cedd0d2c6 Do not convert argument for epoll_create1 2020-06-24 15:15:44 +02:00
ptitSeb b63d087d5c Improved trace on semop wrapped function 2020-06-24 15:15:16 +02:00
ptitSeb bccdb36bd3 Added 2 x11 related wrapped functions 2020-06-23 07:47:24 +02:00
ptitSeb 298ef551ce Merge pull request #132 from rajdakin/explicitELF64
Explicit error message when having 64-bits ELFs
2020-06-21 20:46:39 +02:00
rajdakin 9b23a0a7ab [ELF] Explicit error message when having 64-bits ELFs 2020-06-21 20:44:54 +02:00
ptitSeb 5e2546dd0c Try to stop at double-segfault 2020-06-21 17:44:57 +02:00
ptitSeb 4e9bef301d Reworks INIT/FINI process, and fixed epoll syscall (now Half-Life quit properly) 2020-06-21 15:45:31 +02:00
ptitSeb be5d718280 [DYNAREC] Fixed a warning 2020-06-21 10:45:21 +02:00
ptitSeb 3bc1d6d0a1 Added alternative name for libopenal.so as openal.so 2020-06-21 09:25:34 +02:00
ptitSeb 2d23169ea5 [DYNAREC] Fixed many F3 0F xxxxSS opcodes 2020-06-20 19:48:59 +02:00
ptitSeb b486c60d5e Merge pull request #130 from rajdakin/printer
Dynarec printer fix
2020-06-20 18:22:25 +02:00
rajdakin 3246d2bbb6 [SIGNAL] Fixed unknown architecture build 2020-06-20 18:13:09 +02:00
rajdakin 7d7765ce14 [DYNAREC] Fixed one more time the printer (VMOV.F32 S, imm) 2020-06-20 18:12:46 +02:00
ptitSeb c1f2750b05 [DYNAREC] Fixed some printer issue with VFPU registers 2020-06-20 17:39:12 +02:00
ptitSeb bb4d44499c [DYNAREC] Added 66 0F C2 CMPPD opcode 2020-06-20 15:32:37 +02:00
ptitSeb 195ac3e5b6 [DYNAREC] Added 0F 2D CVTPS2PI opcode 2020-06-20 15:22:14 +02:00
ptitSeb bc9679cad9 [DYNAREC] Added 66 0F E6 CVTTPD2DQ opcode 2020-06-20 14:55:08 +02:00
ptitSeb a603b58970 [DYNAREC] Fixed 66 0F 5E DIVPD opcode 2020-06-20 14:39:06 +02:00
ptitSeb a740dbf871 [DYNAREC] Added 66 0F 5E DIVPD and 66 0F 15 UNPCKHPD opcode 2020-06-20 14:32:26 +02:00
ptitSeb b10e462e03 [DYNAREC] Added (naive) 0F 50 MOVMSKPS opcode 2020-06-20 14:19:37 +02:00
ptitSeb 6f28eb16c6 [DYNAREC] Fixed another potential BUSERROR 2020-06-20 12:53:22 +02:00
ptitSeb 140a41141c Fixed a potential BUSERROR 2020-06-20 12:03:46 +02:00
ptitSeb 6f00b50c6e Added Faked libtcmalloc_minimal (empty wrapped, use regular malloc/new functions) 2020-06-20 11:45:16 +02:00
ptitSeb a9cb19933a Change order of Global and Weak symbol fetching. Should be good this time 2020-06-20 10:50:03 +02:00
ptitSeb cbd8ce408e Enabled Trace in LOCAL function works now 2020-06-20 09:51:44 +02:00
ptitSeb 9837888e50 Allow Trace on LOCAL symbol loaded at start (was ok on dlopenned libs) 2020-06-20 09:28:28 +02:00
ptitSeb 42176b6593 Added a few dbus and gtk wrapped functions 2020-06-19 21:05:10 +02:00
ptitSeb a320528e64 Added some workaround for g_threads_got_initialized 2020-06-19 20:13:26 +02:00
ptitSeb 69a9175c67 Small changes to atfork handling 2020-06-19 18:55:01 +02:00
ptitSeb 9fdc3196d9 Fixed loaing of dependant libs of a local lib 2020-06-19 17:12:36 +02:00
ptitSeb 0b271fc44f Added PltResolver, so JmpSlot symbols are resolved at runtime now 2020-06-19 16:26:21 +02:00
ptitSeb 0fa2f7b8f1 Added one wrapped function to FontConfig 2020-06-18 22:30:44 +02:00
ptitSeb 41c775fb44 Fixed a warning 2020-06-18 22:10:31 +02:00
ptitSeb 28b06f45fe Fixed R_386_TLS_TPOFF relocation (fixed libtcmalloc_minimal.so.4 loading) 2020-06-18 22:06:28 +02:00
ptitSeb 083b3d2a1c Improved vfprintf trace 2020-06-18 22:05:51 +02:00
ptitSeb 61866f6dae [DYNAREC] Made the printing of a segfault a permanent printf for now 2020-06-18 22:05:34 +02:00
ptitSeb 39d7274359 Changed BOX86 load address to a low address 2020-06-18 22:04:46 +02:00
ptitSeb a9b4d994eb [DYNAREC] Added F3 0F 1E and F3 0F 1F multibte NOP, also used a ENDBR opcode 2020-06-18 08:46:55 +02:00
ptitSeb 3701dcd0b4 Added F3 0F 1E and F3 0F 1F multibte NOP, also used a ENDBR opcode 2020-06-18 08:46:18 +02:00
ptitSeb efe2588fd9 Added__libc_dlXXX wrapped function 2020-06-18 08:45:10 +02:00
ptitSeb 3c17d886cc Added many libcrypto and libSSL wrapped functions (and now Minit runs) 2020-06-17 18:51:21 +02:00
ptitSeb 83fe3605f6 Merge pull request #129 from rajdakin/fixes
Fixed ARMS (ARM shifted) instruction category
2020-06-17 12:08:52 +02:00
rajdakin dec474953b [DYNAREC] Ran the printer generator 2020-06-17 11:50:08 +02:00
rajdakin f80964d8d7 [DYNAREC] Fixed ARMS (ARM shifted) instruction category 2020-06-17 11:41:09 +02:00
ptitSeb a43687ee30 Change how symbol are fetched in Elf Relocate mecanism (hacky and probably wrong, but seems to work pretty well) 2020-06-17 00:07:26 +02:00
ptitSeb e04233a897 Some debugging helper 2020-06-16 18:22:21 +02:00
ptitSeb 93cd9b00bd [DYNAREC] Made x86emu_t structure up-to-date when calling arm_linker 2020-06-16 18:21:59 +02:00
ptitSeb 3a592ca9c4 [DYNAREC] Added a special case on 'read' wrapped function when reading on a write protected block (because it's an executable one) 2020-06-16 18:18:48 +02:00
ptitSeb 555d0d51b0 CPUID detection actualy need this bit to be changeable, not fixed 2020-06-16 18:10:53 +02:00
ptitSeb a70f29a8c9 Merge pull request #128 from rajdakin/fixesARMs
Fixed the ARMs and ARM$ instructions type for the printer
2020-06-16 11:36:37 +02:00
ptitSeb dad53a84c8 Merge pull request #127 from rajdakin/fixes
Fixed the U/SXT* opcodes print (and probably others too)
2020-06-16 11:35:56 +02:00
rajdakin d03b21ee19 [DYNAREC] Fixed the ARMs and ARM$ instructions type for the printer 2020-06-16 11:34:50 +02:00
rajdakin 1a1bf5f76a [DYNAREC] Oops, fixed the fix that removes rbrackets of reglists 2020-06-16 11:28:27 +02:00
rajdakin 0ebc0f19b8 [DYNAREC] Fixed the U/SXT* opcodes print (and probably others too) 2020-06-16 11:23:25 +02:00
ptitSeb d4cfa94aaa Merge pull request #126 from M-HT/old_glibc
Allow compilation with older version of glibc
2020-06-16 07:58:20 +02:00
M-HT 383d4c8f9a Allow compilation with older version of glibc 2020-06-16 07:35:33 +02:00
ptitSeb 48b187edd1 [DYNAREC] Don't create a son at the 1st instruction 2020-06-15 18:15:48 +02:00
ptitSeb 316e18f8c5 The syscall 254 sys_epoll_create use a flags parameter that need transform... 2020-06-15 17:59:07 +02:00
ptitSeb 657595d363 Rollback: don't ignore unsupported Int 2020-06-15 17:59:07 +02:00
ptitSeb 9cd9ad16b2 Some fixes t DBUS wrapped lib 2020-06-15 16:50:33 +02:00
ptitSeb 7d49d0fc8a Complete handling of LOCAL/GLOBAL on glopen wrapped function 2020-06-15 16:25:38 +02:00
ptitSeb fa9bdbfd64 Added a few more syscall 2020-06-15 16:23:45 +02:00
ptitSeb 558dc58a52 Don't stop on unknown interrupt, just skip it 2020-06-15 16:23:15 +02:00
ptitSeb 383b1afe0b Try to handle LOCAL/GLOBAL on dlopen wrapped function 2020-06-14 22:32:11 +02:00
ptitSeb 3d757a2af6 Merge pull request #124 from M-HT/fix_64bit_inodes
Fix 64bit inodes in readdir and readdir_r functions
2020-06-14 13:49:31 +02:00
M-HT 2cb20b665d Fix 64bit inodes in readdir and readdir_r functions 2020-06-14 13:16:57 +02:00
ptitSeb eadb36bcdd Merge pull request #123 from M-HT/fix_64bit_inodes
Add option to fix 64bit inodes
2020-06-13 23:27:23 +02:00
M-HT a3bbaeb11b Add option to fix 64bit inodes 2020-06-13 23:03:30 +02:00
ptitSeb 816ee7e23b Fixed last commit 2020-06-10 21:54:45 +02:00
ptitSeb 2a10da129e [TRACE] Allow tracing function in the Init part of a dlopen lib 2020-06-10 18:58:10 +02:00
ptitSeb 9784c3bf2d Compensate for bad lib dependacie in libmss.so.6 (fixes #121 Neverwinter Night Diamond Edition) 2020-06-07 22:40:18 +02:00
ptitSeb f64a7e2c5b Added some png12 and libc wrapped functions 2020-06-07 18:17:54 +02:00
ptitSeb f01359a62e Added some pango wrapped functions 2020-06-07 17:26:57 +02:00
ptitSeb 729f392148 Added a large batch of cairo wrapped functions 2020-06-07 17:20:11 +02:00
ptitSeb e48802c898 Added a dbus wrapped function 2020-06-07 16:42:32 +02:00
ptitSeb 34ed9f03e1 Added cairo_pango wrapped functions 2020-06-07 15:54:25 +02:00
ptitSeb 4990b6db94 Added some FreeType wrapped functions 2020-06-07 15:54:25 +02:00
ptitSeb ecf50c8181 Added 2 wrapped functions to libfontconfig 2020-06-07 15:54:25 +02:00
ptitSeb 927159011c Some small fixes to cpuinfo file creation 2020-06-07 13:46:31 +02:00
ptitSeb 640db5e667 Added some cairo wrapped functions 2020-06-07 13:18:05 +02:00
ptitSeb 509f09dfbc Refined gdk_display hack 2020-06-07 13:07:40 +02:00
ptitSeb 4f42ae0d81 Added a few libm wrapped functions 2020-06-07 12:44:18 +02:00
ptitSeb 1b4391ac23 Added some DBus wrapped functions 2020-06-07 12:39:39 +02:00
ptitSeb 5cb6894657 Added a workaround, again, for gdk_display symbol 2020-06-07 12:14:39 +02:00
ptitSeb be66c8bffa Create a fake /proc/cpuinfo instead of opening the real one 2020-06-07 11:48:37 +02:00
ptitSeb 5f71bcfe9a Slight change in elfloader 2020-06-06 11:10:53 +02:00
ptitSeb 95d786e9a8 Added a special case for libSgGL to load libGL as needed (fixes Hotline Miami) 2020-06-06 11:08:52 +02:00
ptitSeb 8b5e977868 Improved wrapping of curl (and now UrbanTerror download maps) 2020-06-05 17:20:51 +02:00
ptitSeb 49a631b475 Forgot a debug printf in mmap 2020-06-05 16:26:53 +02:00
ptitSeb 8b98a68d1a Update README with latest improvments 2020-06-05 11:42:31 +02:00
ptitSeb c03e46814b [BOX86LIB] Some slight adjustments for box86 as a lib 2020-06-05 11:41:58 +02:00
ptitSeb 7efac81f8b Force RelWithDebInfo build type if none was specified 2020-06-05 08:28:34 +02:00
ptitSeb 58e98e9580 [DYNAREC] Change a message log level, so it's less alarming 2020-06-04 17:58:53 +02:00
ptitSeb 56c211fbeb Added a few libpng12 wrapped function (fixed old FTL 1.5.13) 2020-06-04 17:23:18 +02:00
ptitSeb 2aa2e53fef [DYNAREC] Use a mecanism with Memory Protection to handle JIT'd code (good improvment in speed for Unity games at least) 2020-06-04 16:56:00 +02:00
ptitSeb 3993c88fbb Simplified Lib/Elf loading process (hopefully fixing some bugs in the process) 2020-06-03 19:53:17 +02:00
ptitSeb f706e7eecc Added a few __libc_XXXX wrapped function 2020-06-03 18:54:36 +02:00
ptitSeb 549de25a49 Improved trace a bit (lib name added in front of function name) 2020-06-03 18:54:14 +02:00
ptitSeb 217b05fb80 Small change to Interpretor in non-trace build 2020-06-03 18:53:14 +02:00
ptitSeb e1b9d40ca6 Fixed TRACE build 2020-06-03 17:50:41 +02:00
ptitSeb 0eeba809f2 Added one GS:ADD and one GS:ADC opcode (fixes Arma3 DS, #120, but it crashes after loading everything) 2020-06-03 16:29:59 +02:00
ptitSeb 4a0df1042d Fixed 'Unimplemented Opcode' message that would crash without showing in certain cases on no trace build (mainly with Dynarec) 2020-06-03 16:18:00 +02:00
ptitSeb e7a4274511 [DYNAREC] Try to avoid to keep a reference of a block that will potentially get removed 2020-06-02 16:36:36 +02:00
ptitSeb b3def68a4f Added Logo and Icon from @grayduck 2020-06-01 21:50:16 +02:00
ptitSeb 3c67de08a3 [DYNAREC] Create a temp variable there, that seems more safe 2020-06-01 21:49:27 +02:00
ptitSeb cec67ef3e3 Fixed the TRACE that was broken since last refactor 2020-06-01 17:37:04 +02:00
ptitSeb 881501b278 Fixed issue with glDebugMessageCallbackARB (now 140 run with mesa) 2020-06-01 12:12:18 +02:00
ptitSeb d09a949755 Fixed PREFETCH opcode (especially for the Interpretor) 2020-06-01 11:42:27 +02:00
ptitSeb bf6fa0f335 Added sbrk and brk functions to wrapped libc 2020-05-31 09:28:40 +02:00
ptitSeb 9dcfa322a5 Added SDL_Sem function to wrapped SDL2 2020-05-30 18:15:46 +02:00
ptitSeb a1c21ce05f [DYNAREC] More improvements to FreeDynablock 2020-05-30 09:59:28 +02:00
ptitSeb 22be56179d [DYNAREC] Improved FreeDynablock function 2020-05-29 20:16:58 +02:00
ptitSeb 24da6fcb3b [DYNAREC] Add dest reference in table only when dest as a mark set 2020-05-28 21:48:15 +02:00
ptitSeb 8078b27172 [DYNAREC] Chnage DBGetBlock to forget current block if it gets removed 2020-05-27 21:21:22 +02:00
ptitSeb 89d1254106 [DYNAREC] Added 66 F3 variant for REP MOVSW and REP STOSW 2020-05-27 14:16:32 +02:00
ptitSeb 497f66f5dc Fix for previous fix, for some (not so?) rare cases 2020-05-26 19:37:30 +02:00
ptitSeb a321d54142 Fix a small issue when detecting owner of some memory 2020-05-26 18:49:45 +02:00
ptitSeb 8495b461b8 [DYNAREC] Added protect/unprotect of an address range (will be used later) 2020-05-24 18:35:21 +02:00
ptitSeb 35d6354898 [DYNAREC] Detect PageSize (will be used later) 2020-05-24 17:57:30 +02:00
ptitSeb a2b4af137c Update README.md 2020-05-23 21:03:09 +02:00
ptitSeb 756d1c12fd Update README.md 2020-05-23 21:01:46 +02:00
ptitSeb 63f2e52edb Merge branch 'master' of https://github.com/ptitSeb/box86 2020-05-21 13:54:37 +02:00
ptitSeb fd704eca00 Remove the creation of x86emu_t structure from the stack when using RunFunction, use the thread local onee now 2020-05-20 20:42:38 +02:00
ptitSeb 8c233f1861 Removed emu from context structure, and made a per thread one 2020-05-20 19:01:22 +02:00
ptitSeb 669bb00590 Added libudev.so.1 wrapped lib (straight copy of libudev.so.0 for now) 2020-05-18 10:54:01 +02:00
ptitSeb 815fd918cb Fixed non-dynarec build (#116) 2020-05-15 13:09:47 +02:00
ptitSeb 4249adbe4e Update COMPILE.md 2020-05-14 08:49:00 +02:00
ptitSeb 1aec17da4d Update COMPILE.md 2020-05-14 08:45:59 +02:00
ptitSeb 3680a3092e [DYNAREC] Made FillBlock candidate for threading 2020-05-13 16:47:52 +02:00
ptitSeb b11a269867 [DYNAREC] Fixed TRACE build 2020-05-13 14:52:26 +02:00
ptitSeb cccbf75878 Simplified some function, removing the x86emu_t* argument 2020-05-13 13:17:03 +02:00
ptitSeb 5ce309e64b [DYNAREC] 66 0F D6 MOVQ can be unaligned... (should help #115) 2020-05-12 22:08:11 +02:00
ptitSeb 4b48a43413 Removed a small warning in new pthread_cond handling 2020-05-12 16:08:35 +02:00
ptitSeb a05df24c8b Changed, again, how phtread_conditions are handled 2020-05-12 16:06:59 +02:00
ptitSeb 4f599b521a Improved a bit the handling of thread conditions 2020-05-12 11:13:02 +02:00
ptitSeb 44cf2fc4fb [DYNAREC] Removed some warning 2020-05-12 11:12:30 +02:00
ptitSeb 0ca9f70796 [DYNAREC] Add father/son notion in dynablock, to allow branging in the middle of a dynablock (and avoid generating a new one) 2020-05-11 19:54:54 +02:00
ptitSeb 83cb2dbc4d [DYNAREC] Added mecanism to allow liner with volite code blocks 2020-05-11 08:54:39 +02:00
ptitSeb b09937ad3d [DYAREC] Added a few more NOP variant 2020-05-10 16:21:08 +02:00
ptitSeb c88d5d462c Use another method to handle errors in wrapped libjpeg 2020-05-10 13:12:18 +02:00
ptitSeb 78c971cb87 Added a few more SDL2 wrapped functions 2020-05-09 10:39:59 +02:00
ptitSeb 1bafddcfe2 Rewrapped some non-64 libc functions, to avoid mixing with 64 bits on some plateforms (fixes Saves of IcewindDale on Pi4) 2020-05-08 22:20:53 +02:00
ptitSeb 047b2071f5 [BOX86LIB] Added some libs to the linking of libbox86.so 2020-05-07 20:15:25 +02:00
ptitSeb 8aca039ca6 Added some old and rarely used opcode (helps ZeldaClassic) 2020-05-07 11:50:49 +02:00
ptitSeb db8c6b0c9e Fixed build with cmake less than 3.13.5 (fix for #112) 2020-05-06 20:49:32 +02:00
ptitSeb dbc6aa83f3 Merge pull request #111 from rajdakin/cmake-fix
Fix configuration on older CMake
2020-05-06 20:03:06 +02:00
rajdakin 08472aa68b [CMake] Fix configuration on older CMake 2020-05-06 19:59:57 +02:00
ptitSeb 3010068660 Try a fix on Python finding with old cmake (should fix #110) 2020-05-06 19:28:22 +02:00
ptitSeb 5e2faff01d [DYNAREC] Small changes 2020-05-06 19:12:49 +02:00
ptitSeb 598338809f Take LD_PRELOAD into account if BOX86_LD_PRELOAD is not present 2020-05-06 19:12:11 +02:00
ptitSeb 4778760622 [DYNAREC] Improved handling of JIT'd code by marking potentialy changed block as dirty instead of purging the whole block 2020-05-06 16:41:59 +02:00
ptitSeb 3a23cc42f6 Small cosmetic changes 2020-05-06 14:16:56 +02:00
ptitSeb e23283e794 [BOX86LIB] Improved the Build as a lib version, and introduced build as dynamic lib 2020-05-06 14:09:56 +02:00
ptitSeb 4d730a31c4 Merge pull request #109 from icecream95/posix_spawn
Wrap some posix_spawn functions
2020-05-06 07:37:02 +02:00
ptitSeb 216b6407f3 Merge pull request #108 from rajdakin/reprinter
Printer automation
2020-05-05 20:38:11 +02:00
rajdakin e95988f402 [DYNAREC] Forgot to increase the version number 2020-05-05 19:32:40 +02:00
rajdakin 1ce3731d7d [DYNAREC] Refactored the printer generator (8) 2020-05-05 19:27:32 +02:00
rajdakin 7420d3c8de [DYNAREC] Refactored the printer generator (7) 2020-05-05 19:27:32 +02:00
rajdakin f1edcc06d3 [DYNAREC] Refactored the printer generator (6) 2020-05-05 19:27:32 +02:00
rajdakin ce5c3db346 [DYNAREC] Refactored the printer generator (5) 2020-05-05 19:27:32 +02:00
rajdakin cc0b7b3719 [DYNAREC] Refactored the printer generator (4) + major bug fix 2020-05-05 19:27:32 +02:00
rajdakin 7854fa2e18 [DYNAREC] Removed WIP spacing 2020-05-05 19:27:32 +02:00
rajdakin 1b7bc825d5 [DYNAREC] Refactored the printer generator (3) 2020-05-05 19:27:32 +02:00
rajdakin e65f58acb2 [DYNAREC] Refactored the printer generator (2) 2020-05-05 19:27:32 +02:00
rajdakin 18fe17dc2d [DYNAREC] Refactored the printer generator (1) 2020-05-05 19:27:32 +02:00
rajdakin 8098461e0f [DYNAREC] Changed a little how the printer generator works 2020-05-05 19:27:32 +02:00
rajdakin bf8e9f9242 [DYNAREC] Added an ARM instructions printer generator 2020-05-05 19:27:32 +02:00
rajdakin 4838067440 [WRAPPERS] Rewrote the wrappers generator a bit 2020-05-05 19:27:32 +02:00
rajdakin 53a080e32e [CMake] Cleanup the CMakeLists.txt file a bit 2020-05-05 19:27:32 +02:00
rajdakin 3ac41770b8 [CMake] Force the use of Python3 2020-05-05 19:27:32 +02:00
ptitSeb 6fe51fd7f4 [DYNAREC] Finaly found why Unreal crashes when CPUID detection was enabled: linfmod use some SMC, that's bad. So found some workaround 2020-05-05 17:16:46 +02:00
ptitSeb a6cbe15b5e [DYNAREC] Some small optim on 32bits float access 2020-05-05 17:15:33 +02:00
ptitSeb 3313eba45c [DYNAREC] When using BOX86_DYNAREC_DUMP, use some mutexes to avoid mixing block in dump 2020-05-05 17:14:04 +02:00
Icecream95 b01150f707 Wrap some posix_spawn functions 2020-05-05 14:13:52 +12:00
ptitSeb 4502948f89 Changed a bit the thread creation / cancellation, and associted mutex 2020-05-04 22:47:37 +02:00
ptitSeb 8cb2ffbd2e Added some crude (maybe incorrect?) workaround for function with 0 size in elf header (fixed some libfmod function, somehow) 2020-05-04 15:45:34 +02:00
ptitSeb be80cb03d6 Changed how Trace ona Function works, so it can works on defered (dlopen'd) library 2020-05-04 15:44:43 +02:00
ptitSeb 13d6e96cdc Set trace begin/end as global 2020-05-04 14:04:18 +02:00
ptitSeb 9f280b1f9c Set CPU Family to 6 (instead of 1) in CPUID 2020-05-03 18:53:43 +02:00
ptitSeb 786dfa6700 [DYNAREC] Small optimization on x87 Stack sync 2020-05-03 18:52:36 +02:00
ptitSeb e260aee2e6 [DYNAREC] Use NOP instead of B to ext instruction 2020-05-03 18:51:59 +02:00
ptitSeb 504c27c934 [DYNAREC], Nope, that Unreal bug is still not fixed, not enable CPUID detection yet 2020-05-03 18:51:25 +02:00
ptitSeb c4ba481561 In trace, function name with 0 sized are like infinite size 2020-05-03 18:48:43 +02:00
ptitSeb 841770aed1 [DYNAREC] Small dump improvment 2020-05-03 18:48:01 +02:00
ptitSeb 1a4643f3a2 [DYNAREC] Small improvment on x87 cache access 2020-05-03 12:56:17 +02:00
ptitSeb e89702d99d [DYNAREC] Fixed printer for rotated immadiate 2020-05-03 12:55:46 +02:00
ptitSeb 250e3820df [DYNAREC] Small fixe to the printer to get more printed opcodes in dumps 2020-05-03 11:14:36 +02:00
ptitSeb 8b2a509a32 [DYNAREC] A bit more color in dump 2020-05-02 19:48:31 +02:00
ptitSeb 6db92c56b9 [DYNAREC] Some trace improvments 2020-05-02 19:17:44 +02:00
ptitSeb e4914a2139 Rollback CPUID detection code until I found why Unreal crashes with it 2020-05-01 21:42:18 +02:00
ptitSeb 704c4b36ab Added support for CPUID detection in PUSHF/POPF 2020-05-01 09:32:47 +02:00
ptitSeb b9d61108bf Added a few wrapped function (should help X3) 2020-05-01 09:01:56 +02:00
ptitSeb e92d2f737b Small thread improvment 2020-04-30 21:10:10 +02:00
ptitSeb 6ec36072c4 A bit more wrapped libz functions 2020-04-30 15:06:00 +02:00
ptitSeb ab18d4d23a [DYNAREC] Fix build for non-trace enabled build (fix #105) 2020-04-30 14:01:28 +02:00
ptitSeb 1e6893a9d9 [DYNAREC] Added a few more opcodes (Int3 and FXSAVE/FXRSTOR) 2020-04-30 11:08:34 +02:00
ptitSeb 01bcc957e8 Added PSUBB opcode (should help 'The Journey Down Chapter One') 2020-04-29 14:44:39 +02:00
ptitSeb 3c989cfa04 Removed that yield in cond_broadcast, useless, and probably harming the performances 2020-04-28 18:55:18 +02:00
ptitSeb bde29ef155 Fixed some libz wrapped functions (fixed AM2R) 2020-04-28 18:41:23 +02:00
ptitSeb cee4cd26e0 [DYNAREC] Don't use x1, x2 or x3 scratch before use READFLAGS, also fixed the the bordercase fix call/ret optim (all this fixed zsnes and starfox) 2020-04-28 17:42:57 +02:00
ptitSeb f774b88211 [DYNAREC] Fixed PUSHAD/POPAD opcode, also small fix on border case for Call/Ret optimisation 2020-04-28 17:42:57 +02:00
ptitSeb 251f9b7338 Update README.md 2020-04-27 10:24:17 +02:00
ptitSeb dd5fc10a95 [DYNAREC] Optimised CALL/RET by using a local stack in x6emu_t struct (large improvment in some game, but doesn't help ShovelKnight) 2020-04-26 22:39:40 +02:00
ptitSeb 5e84efc542 Remove test on x87 stack status 2020-04-26 15:15:25 +02:00
ptitSeb b29fd4abbd [DYNAREC] Added missing change from previous commit 2020-04-26 15:15:03 +02:00
ptitSeb 1c6f2254f3 [DYNAREC] Store current block in table linker, to help find next block 2020-04-25 15:14:23 +02:00
ptitSeb 73685273f4 Added wrapped libdrm (almost empty) 2020-04-24 19:26:59 +02:00
ptitSeb 76d070777f Added a few wrapped functions to xcb, fontconfig and freetype 2020-04-24 17:23:21 +02:00
ptitSeb 42d18f7302 Added libstdc++.so.5 (along with the .6) in x86libs (usefull in some older games) 2020-04-24 16:15:25 +02:00
ptitSeb 963a7a527a On system where getrandom syscall is not supported, read /dev/urandom and not /dev/random 2020-04-24 12:02:05 +02:00
ptitSeb df61ed3048 [DYNAREC] Fixed potential issue when an opcode is not handled by the dynarec (fixed TeamSpeak3, for good) 2020-04-24 12:01:16 +02:00
ptitSeb 2a8e6061a2 Added BOX86_NOSIGILL 2020-04-24 11:11:22 +02:00
ptitSeb 96c4fe7057 Some changes in signal hanbdling (not sure it's a good idea) 2020-04-24 10:51:11 +02:00
ptitSeb 124df9ae83 Also add my_getrandom fallback to wrapped libc syscall 2020-04-24 08:30:49 +02:00
ptitSeb 62b2eecf6e Some system (like the Pandora) don't have the getrandom syscall 2020-04-24 08:26:29 +02:00
ptitSeb 9fb6b7bbd9 Use align on come fctnl function (fixes TeamSpeak3 server) 2020-04-23 22:27:15 +02:00
ptitSeb 0ac7929230 Added syscall 355 2020-04-23 21:39:38 +02:00
ptitSeb d16e8f1c51 Added some aio_*64 wrapped function to librt 2020-04-23 21:30:39 +02:00
ptitSeb 4b59f04930 Small fixes to some gobject signals 2020-04-23 16:06:12 +02:00
ptitSeb 7a375136cc Cosmetics in myalign.c 2020-04-23 16:05:49 +02:00
ptitSeb 62a328af45 Go back to using SharedCallback for qsort and qsort_r (should be faster and more reliable) 2020-04-23 08:37:42 +02:00
ptitSeb aafe35dca7 Changed how MMAP memory is alloced/freed 2020-04-22 14:40:27 +02:00
ptitSeb c73b728255 More cosmetic changes 2020-04-22 14:40:01 +02:00
ptitSeb 1186072e48 Added a sched_yield before cond_brodcast, just in case Dynarec is building a block with a cond_wait inside (to be tested) 2020-04-22 14:38:42 +02:00
ptitSeb 141de19804 Misc cosmetic changes 2020-04-22 14:37:41 +02:00
ptitSeb 97d71dfe09 [DYNAREC] Fixed some printer issues 2020-04-22 14:32:30 +02:00
ptitSeb f05b4fa7ff Some small changes to pthread_register_cancel, again, to hopefully have something working 100% 2020-04-21 19:34:37 +02:00
ptitSeb 2f36ec82f9 Made my_context global, plus some warning hunting... 2020-04-21 15:12:29 +02:00
ptitSeb c386a0a356 [DYNAREC] Warning hunt... 2020-04-21 15:11:57 +02:00
ptitSeb 4ba1f972b5 [DYNAREC] Fixed some emiter (missing parenthesis) 2020-04-21 13:50:08 +02:00
ptitSeb 525eb10854 [DYNAREC] Ooops, fixed ROR Ed, Ib opcode 2020-04-20 18:36:16 +02:00
ptitSeb 7176b08882 Fixed some potentiel memory overwrite (should help #102) 2020-04-20 16:57:32 +02:00
ptitSeb a6f4248502 [DYNAREC] Added complete emiter for ror32c 2020-04-20 12:18:14 +02:00
ptitSeb f0da6dd64f [DYNAREC] Added complete emiter for rol32c 2020-04-20 11:31:03 +02:00
ptitSeb af3c9042c3 Disabling that pthread_cancel test, box86 is still too unstable on that it seems 2020-04-19 21:38:40 +02:00
ptitSeb d8aa65bc17 Update README.md 2020-04-19 19:40:27 +02:00
ptitSeb da6ab3f752 Update README.md 2020-04-19 19:39:33 +02:00
ptitSeb 3cdf7fe742 Update README.md 2020-04-19 19:38:38 +02:00
ptitSeb cb54d7e343 Update README.md 2020-04-19 19:38:02 +02:00
ptitSeb 60611e54f3 [RPI] Call sanitize_mojosetup_gtk_background also on uninstall, to avoid extreme sluginess of the GUI 2020-04-19 19:33:17 +02:00
ptitSeb a4a78681ef More improvement to pthread_register_cancel handling 2020-04-19 17:56:15 +02:00
ptitSeb 4d85147077 Fixed a mamory averwriting issue 2020-04-19 17:55:27 +02:00
ptitSeb 857048f47c Small change in the init phase 2020-04-19 17:19:15 +02:00
ptitSeb 6084102d20 More improvement to thread_cancel_register mecanism 2020-04-19 16:52:31 +02:00
ptitSeb 2dc1fcc875 Improved handling of __pthread_register_cancel (and add a unit test about that) 2020-04-19 15:58:54 +02:00
ptitSeb 584479c10d Move around a bit thread helper initialization 2020-04-19 15:39:35 +02:00
ptitSeb 3430550dac Some attempt to improve __pthread_cancel_(un)register wrapped functions 2020-04-19 13:33:19 +02:00
ptitSeb 81f5bc79aa Various improvement to thread handling (should solve some memory issue when a lot of thread are created) 2020-04-19 13:33:19 +02:00
ptitSeb e20ccb7991 More changes to exec (now steam can start some game directly) 2020-04-19 13:33:19 +02:00
ptitSeb 5cf4af83b0 Update README.md 2020-04-18 15:42:47 +02:00
ptitSeb e5cb34d1f8 Update FUNDING.yml 2020-04-18 15:41:55 +02:00
ptitSeb 91c46f99a0 Update FUNDING.yml 2020-04-18 15:38:50 +02:00
ptitSeb dbdcaf8962 Create FUNDING.yml 2020-04-18 15:38:08 +02:00
ptitSeb 230d6246c6 Fixed a warning from previous commit 2020-04-18 15:32:20 +02:00
ptitSeb 066e5f966a Simplified some phtread wrapped functions 2020-04-18 15:24:16 +02:00
ptitSeb ff615cba03 Added preliminary FS: support 2020-04-18 15:06:08 +02:00
ptitSeb 631fa0f536 Move box86 on top of user memory (help Witcher 2, but not enough, as it use FS:) 2020-04-18 14:35:50 +02:00
ptitSeb ce2eb76703 Small changes in sem_open and set priority on threads 2020-04-18 10:56:15 +02:00
ptitSeb 9422039e09 Added IMG_LoadTexture and friend wrapped funcito to sdl2image 2020-04-17 22:24:47 +02:00
ptitSeb 0f13eb8611 More log for exev* wrapped functions 2020-04-17 21:49:59 +02:00
ptitSeb 196394f666 Added dummy syscall 243 (need work for a proper implementation 2020-04-17 21:49:21 +02:00
ptitSeb 9b2f7029df Improved elfloader to support elf with 'fragmented' memory map 2020-04-17 15:48:35 +02:00
ptitSeb a2e6b57c35 Simplified handling of exevl* 2020-04-17 14:02:24 +02:00
ptitSeb e5fdb4ba85 [DYNAREC] Added complete emiter for sar32c 2020-04-17 14:02:03 +02:00
ptitSeb 0c83522296 [DYNAREC] Fixed needed_flags function 2020-04-16 19:23:54 +02:00
ptitSeb f59e30442a Proprer support for timer_create with notify to SIGEV_THREAD 2020-04-16 17:40:00 +02:00
ptitSeb b67b750009 [DYNAREC] Added shr32c complete emiter 2020-04-16 15:41:02 +02:00
ptitSeb 61f2a43628 [DYNAREC] Reduce the recursivity of needed_flags function 2020-04-16 12:09:08 +02:00
ptitSeb 769545ccd7 Add proper support for RPATH with 2020-04-16 11:15:46 +02:00
ptitSeb c0b9272b82 Fixed ODroid and GameShell profile help that were mixed up 2020-04-16 09:30:40 +02:00
ptitSeb d5e5cbb393 Added ODROID profile 2020-04-16 07:52:09 +02:00
ptitSeb d8251ec441 Fix link on non-dynarec build 2020-04-16 07:40:47 +02:00
ptitSeb 0a04ef44d4 [DYNAREC] Fix issue when code use lots of FPU code with a few jump (i.e. x87 with loops), on dynarec pass 1 (helps Hotline Miami, and probably others) 2020-04-15 22:25:50 +02:00
ptitSeb 79ada49fdc Added some workaround to get steam somehow running 2020-04-15 21:36:08 +02:00
ptitSeb 1bf134c3ef Fixed interpretor for PALIGNR SSSE3 opcode 2020-04-15 16:54:56 +02:00
ptitSeb 38098290b7 [DYNAREC] Fixed psrlw and psraw opcode 2020-04-15 15:49:46 +02:00
ptitSeb b66c95d920 [DYNAREC] Added neg8 complete emiter 2020-04-15 15:42:35 +02:00
ptitSeb 25ae0f9311 [DYNAREC] Added neg16 complete emiter 2020-04-15 13:04:08 +02:00
ptitSeb f63799ecbb [DYNAREC] Small fixes to NEG and XADD opcodes 2020-04-15 12:03:25 +02:00
ptitSeb f2de080c68 [DYNAREC] Added shl32c complete emiter 2020-04-15 11:28:22 +02:00
ptitSeb 4ceaa7bd4b More workround on fcntl F_SETFL 2020-04-15 11:20:02 +02:00
ptitSeb 5753983f41 Fixed fctnl and fcntl64 wrapped function that weren't converting some parameter (should help OSS game, among other things) 2020-04-15 08:40:16 +02:00
ptitSeb 58768ca886 Merge pull request #97 from PokeEngineer/master
Include sysmacros.h in elfloader.c
2020-04-15 07:38:40 +02:00
Jacob Mullins d3d740c38f Included sysmacros.h
Some compilers (like the one on the GameShell) need this to be included or you get undefined references to "major," "minor," and "makedev."
2020-04-15 00:43:57 -04:00
ptitSeb 27f99bd3c0 Added some basic /proc/self/maps emulation (missing heap, stack and loaded lib) 2020-04-14 20:18:22 +02:00
ptitSeb 230fa96d2b Added basic support for RPATH 2020-04-14 14:27:08 +02:00
ptitSeb 1e7f5692ce Added syscall 266 2020-04-13 10:41:40 +02:00
ptitSeb af884e427d [DYNAREC] Added PSRAW/PSRAD/PRSRLW/PSRLD opcodes 2020-04-12 10:53:58 +02:00
ptitSeb 00b2002855 Added PAVGB and PAVGW SSE2 opcodes (also in DYNAREC) 2020-04-12 10:10:47 +02:00
ptitSeb e5d20ea8ae [DYNAREC] Fixed isue with CLC and STC opcodes 2020-04-12 09:37:01 +02:00
ptitSeb 3b4ca235d5 [DYNAREC] Added neg32 complete emiter with flags 2020-04-11 18:37:40 +02:00
ptitSeb 8633aca6fa Fixes isNativeCall (help FTL) 2020-04-11 18:17:14 +02:00
ptitSeb 85dde4b9d0 [DYNAREC] Assorted bugfixes (but still an issue in zsnes somewhere) 2020-04-11 15:30:58 +02:00
ptitSeb 43e981579f [DYNAREC] Added sbb8 and sbb16 complete emiter with flags 2020-04-10 10:44:31 +02:00
ptitSeb f12706599e [DYNAREC] Added sbb32 complete emiter with flags 2020-04-10 09:57:58 +02:00
ptitSeb 650668eaf7 [DYNAREC] Added adc16 complete emiter with flags 2020-04-10 08:41:43 +02:00
ptitSeb 6093589e41 [DYNAREC] Added adc8 complete emiter with flags 2020-04-09 23:38:37 +02:00
ptitSeb ce777c9393 [DYNAREC] Added complete emiter with flags for adc32 2020-04-09 22:55:50 +02:00
ptitSeb 983523c2f6 [DYNAREC] Inc/Dec doesn't change CC, plus many fixes on emiter with flags... 2020-04-09 20:02:47 +02:00
ptitSeb 8f5843e0fe [DYNAREC] Added or16/xor16/and16 and use the emiters 2020-04-09 18:24:09 +02:00
ptitSeb 98b0602ae5 [DYNAREC] Added complete emiter for sub16, and converted SUB and INC/DEC 16 opcodes 2020-04-09 17:06:10 +02:00
ptitSeb 0286e8362e [DYNAREC] Use emit_add8/32 and emit_sub8/32 for inc/dec opcodes 2020-04-09 16:20:38 +02:00
ptitSeb bcfc464f24 [DYNAREC] Fixed add8/sub8 and added complete emiter with flags for add16 2020-04-09 14:51:42 +02:00
ptitSeb 7a9e9df3c0 [DYNAREC] Added complete emiter with flags for or8, xor8 and and8 2020-04-09 11:49:28 +02:00
ptitSeb 829bf941f4 [DYNAREC] Added complete emiter for sub8 opcodes 2020-04-09 10:48:26 +02:00
ptitSeb 3e42161c35 [DYNAREC] Also use emit_addXX on XADD opcodes 2020-04-09 10:47:54 +02:00
ptitSeb 9cdaa5e028 [DYNAREC] Fixed some logic complete emiter (with constant) 2020-04-09 08:02:35 +02:00
ptitSeb 34ef7b9b79 [DYNAREC] Added more complete emiter, plus some reorganisation of sources 2020-04-08 21:59:56 +02:00
ptitSeb 201677899b [DYNAREC] Created emiter (with flags) for add32 and sub32 2020-04-08 18:56:00 +02:00
ptitSeb fd563c5b4b [DYNAREC] Fun with flags: improved Carry flag handling 2020-04-07 17:50:15 +02:00
ptitSeb d5b5031f5c [DYNAREC] Fun with flags: added the X_PEND flags to calculate flags + setting defered 2020-04-07 17:40:32 +02:00
ptitSeb 08f2fcd1b9 [DYNAREC] Fun with flags: done all test emiter too. 2020-04-06 16:38:45 +02:00
ptitSeb f7da6bc070 [DYNAREC] Fun with flags: Continue adding all cmp emiter, plus some bug fixes 2020-04-06 16:02:31 +02:00
ptitSeb 1414fed3b2 [DYNAREC] Added optionnal Coloring to Dump 2020-04-06 16:01:36 +02:00
ptitSeb 13ff5c80be [DYNAREC] Fun with flags: Optimized cmp16_0 emiter 2020-04-05 21:17:29 +02:00
ptitSeb 782dd645c3 [DYNAREC] Fun with flags: Optimized cmp16 emiter 2020-04-05 21:13:47 +02:00
ptitSeb 020bcd46c2 [DYNAREC] Fun with flags: Optimized cmp32_0 emiter 2020-04-05 21:08:02 +02:00
ptitSeb fefb01f930 [DYNAREC] Func with flags: optimzed cmp32 emiter 2020-04-05 21:02:38 +02:00
ptitSeb 6489a2ca3b [DYNAREC] Fun with flags: fixed a typo 2020-04-05 21:02:16 +02:00
ptitSeb cbe4ec30d1 [DYNAREC] Fun with flags: optimize FCOMI emiter 2020-04-05 20:35:22 +02:00
ptitSeb 38a9b04ce0 [DYNAREC] Change the way X86 Flags are handled 2020-04-05 20:10:18 +02:00
ptitSeb 7de59621c4 Changed how ROR and ROL handle flags (less exact but faster, seems ok on all tests) 2020-04-04 11:11:46 +02:00
ptitSeb e9560dd916 [DYNAREC] Improved is_nops function 2020-04-02 18:19:50 +02:00
ptitSeb 91fec006ae [DYNAREC] Improved dynarec by allowing each block to be bigger 2020-04-02 08:26:18 +02:00
ptitSeb 82af74c459 [PANDORA] Fix for the use of tremor in SDL(1/2)_mixer 2020-04-01 15:35:47 +02:00
ptitSeb 32dc46efac [DYNAREC] Improve DUMP info a bit 2020-04-01 13:05:41 +02:00
ptitSeb 020b94794b [DYNAREC] Removed duplicate include 2020-03-31 21:52:27 +02:00
ptitSeb bb59ef692e Improved a bit a warning message 2020-03-31 21:51:58 +02:00
ptitSeb 8280d4628d Fixed a few wrapped functions prototypes 2020-03-30 16:39:46 +02:00
ptitSeb 91c6a71353 [DYNAREC] Fixed CMPXCHG opcode (helps Telsagrad, and probably others) 2020-03-30 16:21:10 +02:00
ptitSeb fa9e8223b9 [DYNAREC] Fixed memory allocated with mmap64 that was tracked (fix Unity/Mono JIT not beeing Dynarec'd correctly) 2020-03-30 15:11:08 +02:00
ptitSeb 7057ce7a2c Fixes to some libc wrapper functions with callback (fixed Teslagrad) 2020-03-30 14:16:04 +02:00
ptitSeb b98febce24 Added one more synonim for SDL2 2020-03-29 15:52:40 +02:00
ptitSeb 11758cfa90 Improvments to libc wrapped function with callback 2020-03-29 09:38:26 +02:00
ptitSeb a37928110d Some improvments to vorbisfile wrapped lib 2020-03-29 09:38:02 +02:00
ptitSeb a3c7674676 [DYNAREC] Added PMADDUBSW opcode 2020-03-28 20:43:07 +01:00
ptitSeb ed68b17bac [DYNAREC] Added PACKSSWB opcode, and changed a MOVD one to avoid some BusError 2020-03-28 17:40:24 +01:00
ptitSeb aa86b8ecf4 [DYNAREC] Added PADDSB opcode 2020-03-28 17:04:44 +01:00
ptitSeb e0c5630ed7 [DYNAREC] Added PSUBSB opcode 2020-03-28 17:01:39 +01:00
ptitSeb c4b4107f57 [DYNAREC] Added PCMPEQB opcode 2020-03-28 16:58:08 +01:00
ptitSeb d198f6c64a [DYNAREC] Added PADDUSB opcode 2020-03-28 16:52:05 +01:00
ptitSeb fd3812c27e [DYNAREC] Added PSADBW and PMAXUB 2020-03-28 16:46:08 +01:00
ptitSeb ddbffd874b [DYNAREC] Added PSHUFB SSE3 opcode 2020-03-28 15:02:08 +01:00
ptitSeb bc1b5bed0b Refactored (and simplified) libc functions with callbacks 2020-03-28 14:04:37 +01:00
ptitSeb f7019e0ff8 Added 2 SSE3 opcodes 2020-03-28 14:01:58 +01:00
ptitSeb e47f88f4f3 Changed (optimized?) a bit the idiv operations 2020-03-28 14:01:35 +01:00
ptitSeb baf750b89a Added one dummy libc wrapped function 2020-03-28 10:39:30 +01:00
ptitSeb bea256ddc6 Added wrapped lib Xmu (with 2 functions) 2020-03-28 10:25:28 +01:00
ptitSeb e7f841b71e Made looking for emulated libs more resiliant 2020-03-27 22:19:54 +01:00
ptitSeb 1df10d7a48 [DYNAREC] Added UD2 opcode 2020-03-27 21:50:54 +01:00
ptitSeb 53c4a0d418 More SDL2 wrapped functions 2020-03-26 20:48:19 +01:00
ptitSeb 883f1990c6 Added some more GS: opcodes 2020-03-25 23:02:22 +01:00
ptitSeb c2efed56e0 Added 1 libX11 wrapped function 2020-03-25 19:28:21 +01:00
ptitSeb 37814194ae [PANDORA] Try some workaround for Xxf86vm Gamma issues 2020-03-25 14:29:54 +01:00
ptitSeb 03cc86c6d1 Added a few libc wrapped functions 2020-03-25 11:58:42 +01:00
ptitSeb 206f5d3aa8 Added barely used 82 opcode (same as 80) [DYNAREC] too 2020-03-25 11:41:36 +01:00
ptitSeb d5c71f3dcc Added FPREM1 opcode 2020-03-25 11:14:55 +01:00
ptitSeb 1ed35d06c7 Add some fail safe on program that use _IO_2_1_st* symbols 2020-03-25 08:56:31 +01:00
ptitSeb 4456ab2ab5 Add a libc symbol 2020-03-25 08:55:55 +01:00
ptitSeb 645297de61 Added one new syscall 2020-03-24 18:02:25 +01:00
ptitSeb 71dbfda219 Added 2 X11 wrapped functions 2020-03-24 17:06:28 +01:00
ptitSeb c8977e68d0 Added a wrapped x11 function 2020-03-23 13:57:58 +01:00
ptitSeb 9b1bfb17b0 Expose SSE3 and SSSE3 2020-03-23 13:46:25 +01:00
ptitSeb 95858b46b0 [DYNAREC] Changed MOVQ 0f 7f opcode to avoid potential Bus Error (helps steam) 2020-03-23 13:31:48 +01:00
ptitSeb d7ca13e7f7 Added wrapped libnm (also as a replacement for libnm-glib and libnm-util, to help steam, but need network-manager-gnome package) 2020-03-22 19:05:33 +01:00
ptitSeb a17dfe8ed6 Added a few gtk wrapped functions 2020-03-22 17:10:45 +01:00
ptitSeb 1d9eb8fa17 Added some more gio2 wrapped functions 2020-03-22 16:58:16 +01:00
ptitSeb 6d8e64a213 Added gudev wrapped functions 2020-03-22 14:55:45 +01:00
ptitSeb c5859a0d92 Added a large bunch of glib2 / gobject2 / gio2 wrapped functions 2020-03-22 14:38:23 +01:00
ptitSeb 058b199606 Added a large bunch of dbus and dbus-glib1 wrapped functions 2020-03-22 08:45:29 +01:00
ptitSeb 5b58985fdf One more glib2 wrapped function 2020-03-21 20:42:44 +01:00
ptitSeb b9e1192d69 Added more slot to gobject2 callbacks 2020-03-21 19:31:42 +01:00
ptitSeb 1d0a575773 Try to define all gobject cclosur_marshaler as DATA and not wrapped functions 2020-03-21 19:22:29 +01:00
ptitSeb 72e3e36f1b Added wrapped dbusmenu-glib library 2020-03-21 18:54:35 +01:00
ptitSeb bd2271de86 Fixed a wrapped gobject2 function (and steam is almost starting) 2020-03-21 17:52:42 +01:00
ptitSeb ffa2aa6f1c Added a few more libc wrapped functions 2020-03-21 16:44:49 +01:00
ptitSeb c0d35aa6e7 Some (speed) improvement to wrapped pulse library 2020-03-21 15:58:07 +01:00
ptitSeb 11c1396d83 Small change in epool_ctl wrapped function 2020-03-21 15:57:43 +01:00
ptitSeb 41e6ba1030 Init new stacks to 0 (in line with x86 behavour?) 2020-03-21 15:57:13 +01:00
ptitSeb e92e9043fa Fixed some multi-threaded libpulse wrapped functions 2020-03-21 15:29:56 +01:00
ptitSeb c53ab30b2e Improved autodetect of binary, and added special case for steam 2020-03-21 12:34:53 +01:00
ptitSeb c763ca269a Smalls changes on libudev wrapped function 2020-03-21 11:59:16 +01:00
ptitSeb bf4c05c41c Added a few more gobject2 wrapped functions 2020-03-21 10:06:22 +01:00
ptitSeb 9b9130ed57 Added a few more dbug-glib2 wrapped functions 2020-03-20 19:51:18 +01:00
ptitSeb 5fde277748 Added a wrapped function to gobject2 2020-03-19 21:39:07 +01:00
ptitSeb 7757666a0b Added some more glib2 wrapped functions 2020-03-18 21:00:29 +01:00
ptitSeb 4bc52873f7 Added some glib2 wrapped functions 2020-03-17 22:16:53 +01:00
ptitSeb a5a38203ae Added some gio dbus wrapped functions 2020-03-16 17:57:23 +01:00
ptitSeb 1209862996 Fixed fprintf trace (in case it's in fact __fprintf_chk that is called) 2020-03-16 17:56:57 +01:00
ptitSeb 4f0bb1010d Fixed return value for dladdr wrapped function 2020-03-15 15:29:03 +01:00
ptitSeb 050b974051 [DYNAREC] Fixed a MOVQ mmx opcode 2020-03-15 12:41:13 +01:00
ptitSeb 88fb7efec3 Use fopen64 and fseeko64 on main binary so >4Gb file can be open (now psychonauts installer can be run) 2020-03-15 09:53:39 +01:00
ptitSeb a91c562dcf Removed old monounity wrapped lib attempt (not working well enough) 2020-03-14 12:52:27 +01:00
ptitSeb f1a136c9b4 Added libXdamage wrapped lib (complete) 2020-03-13 20:21:43 +01:00
ptitSeb 57583b39e7 Added libXcomposite wrapped library (complete) 2020-03-13 19:31:13 +01:00
ptitSeb 3467ea2476 Added some more libcrypto wrapped functions 2020-03-12 20:23:23 +01:00
ptitSeb 0e6daf412d Fixed execl wrapped functions 2020-03-12 20:23:11 +01:00
ptitSeb 8468c5318d Improve trace, especialy in BUILDLIB scenario 2020-03-11 20:29:49 +01:00
ptitSeb 853f4865ce [BUILDLIB] Add some failsafe fallback for getauxval 2020-03-10 20:57:21 +01:00
ptitSeb 0742c694b0 Added a few gtk wrapped functions 2020-03-09 20:13:13 +01:00
ptitSeb 247622a6db [DYNAREC] Small change in how JIT'd code in handled in the linker 2020-03-08 16:36:26 +01:00
ptitSeb cbd4b4f73a Fixed an issue with TLS data (and now hotline_launcher works) 2020-03-08 15:59:05 +01:00
ptitSeb 3782d7f4df [TRACE] Fixed start of symbol that was not printed in the trace 2020-03-08 12:08:20 +01:00
ptitSeb bc13894b31 Added lots of libxcb wrapped functions 2020-03-08 11:24:57 +01:00
ptitSeb d6ff293d7f [BUILD] Added dependancie on wrapped functions between .c and _private.h 2020-03-07 17:11:11 +01:00
ptitSeb 9e2ba671b8 Added some FontConfig wrapped functions 2020-03-07 16:19:44 +01:00
ptitSeb fb56c5f422 Added a few more X11 wrapped functions 2020-03-07 13:03:54 +01:00
ptitSeb a45d6bd79b Added some wrapped function used by gtk-1.2 2020-03-06 15:53:47 +01:00
ptitSeb 28a26db054 Added dontstarve autodetect to force use of emulated SDL2 2020-03-06 10:17:35 +01:00
ptitSeb 95782e7311 Remove import glob from wrapper generator, not used anymore 2020-03-06 09:51:17 +01:00
ptitSeb 5f6221de7f [DYNAREC] Added TZCNT opcode 2020-03-06 09:50:26 +01:00
ptitSeb b42ac3eb11 Revert stat / lstat change 2020-03-05 18:32:32 +01:00
ptitSeb 2964727959 Reworked py generator to avoid useless recompiles 2020-03-05 17:05:15 +01:00
ptitSeb fca7808b55 [DYNAREC] Added a few more opcodes 2020-03-05 14:21:15 +01:00
ptitSeb 07c98d30ad [DYNAREC] Add preliminary support for JIT'd code 2020-03-05 11:41:43 +01:00
ptitSeb a7c95a783e [DYNAREC] Added a few opcodes 2020-03-05 11:40:49 +01:00
ptitSeb e84ebce421 [DYNAREC] Dump of Dynarec blocks is now a seprated option 2020-03-05 11:39:56 +01:00
ptitSeb 0df765bbbd Fixed some type in USAGE 2020-03-04 13:19:02 +01:00
ptitSeb 2af2fbfe6d [DYNAREC] Preliminary work to support JIT'd code in Dynarec 2020-03-03 16:09:24 +01:00
ptitSeb 96f5f92b09 Fixed some typo is libgthread2 wrapped lib 2020-03-03 10:25:01 +01:00
ptitSeb dedd7f4827 Use lstat instead of stat on filexist function (alow use of symlink of libs) 2020-03-02 16:57:52 +01:00
ptitSeb 28a066a7c9 Added a few more pulse wrapped functions (should help Paper, Please) 2020-03-02 14:40:43 +01:00
ptitSeb 6377884c4a Improved emulation of dl_iterate_phdr (fixed Paper, Please) 2020-03-02 13:56:23 +01:00
ptitSeb 41cc61e4c7 Fixed an issue with a wrapped function in gtk 2020-03-01 14:40:04 +01:00
ptitSeb 73e13baa84 And more SDL2 wrapped functions 2020-03-01 13:03:23 +01:00
rajdakin 403707bb5b A few more SDL2 wrapped functions 2020-03-01 11:02:06 +01:00
ptitSeb 873bdd793a Some more SDL2 wrapped functions 2020-02-29 09:49:41 +01:00
ptitSeb edbd6cdfa5 A few more SDL2 wrapped functions 2020-02-28 18:37:50 +01:00
ptitSeb e7a9679a20 More SDL2 wrapped functions 2020-02-27 21:28:20 +01:00
ptitSeb b9d09acf92 Added a few SDL2 wrapped functons 2020-02-26 22:04:30 +01:00
ptitSeb 7a02b1720e Fixed glXProcAddress and alGetProcAddress when querying a my_ wrapped functions (fixed Isaac Aftyerbirth, and probably others games) 2020-02-15 21:26:53 +01:00
ptitSeb 3c88e8aac0 Added a few wrapped functions to wrandr and dbus 2020-02-15 20:11:29 +01:00
ptitSeb df4e93973b [DYNAREC] revert the use of TryLock, it fallback to interpretor too often 2020-02-15 19:48:59 +01:00
ptitSeb c3dbe47f3c [DYNAREC] Fixed x87 TAG issues (causing massive FPU under/over flow messages) 2020-02-15 19:48:25 +01:00
ptitSeb af91d80c94 Added some handling of TAG for x87 emulation (DYNAREC too) 2020-02-15 18:22:46 +01:00
ptitSeb a133621934 Use Trylock instead of Lock RWMutex in Dynarec block creation, to allow fallback to Interpreter instead of waiting 2020-02-15 16:00:48 +01:00
ptitSeb 329bddc4f6 Avoid Dynarec in signal handler, to avoid potentiel deadlocks 2020-02-15 15:59:57 +01:00
ptitSeb 31785d6fbe Added wrapped mkstemps64 function 2020-02-15 12:53:45 +01:00
ptitSeb c7bf006b49 Added better support for pthread_cleanup_push and pop macros (help Unity games) 2020-02-14 10:47:15 +01:00
ptitSeb 3fc1458cc2 Added a few more SDL2 wrapped functions 2020-02-13 20:21:29 +01:00
ptitSeb 53be7dad84 Added better handing of thread stack querying 2020-02-12 17:29:46 +01:00
ptitSeb 7507a0f20f Added a few SDL2 wrapped functions 2020-02-11 20:20:12 +01:00
ptitSeb 32a6711898 Small improvment on trace, to avoid potention deadlock or segfault 2020-02-10 20:19:42 +01:00
ptitSeb 223c6513ba Simplified pulsesimple, as it use full pulse now 2020-02-09 10:47:41 +01:00
ptitSeb d395df1f37 [DYNAREC] Prepare SDIV and UDIV emmiter (but no use yet) 2020-02-08 15:58:28 +01:00
ptitSeb f5a7d96a77 [DYNAREC] Added support for SWP opcode when handling XCHG x86 opcode 2020-02-08 12:34:38 +01:00
ptitSeb 81ae020273 [DYNAREC] Added detection of hardware cpu extensions 2020-02-08 10:57:24 +01:00
ptitSeb 57024db6e6 Improved getauxval handling 2020-02-07 08:18:25 +01:00
ptitSeb e507b964a1 Added actual getauxval wrapped function, and support for native getauxval 2020-02-06 22:48:12 +01:00
ptitSeb d2bff48e88 New developpement cycle 2020-02-06 22:01:12 +01:00
361 changed files with 72359 additions and 17398 deletions

No files matched your search

+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: paypal.me/0ptitSeb
+4 -2
View File
@@ -1,4 +1,6 @@
build
build*
build/
build*/
.vscode
.gdb_history
src/git_head.h
backup/
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

+78
View File
@@ -1,3 +1,81 @@
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)
* Even more opcodes added.
* And some more Dynarec opcodes.
* Fixed some issue were PltResolver was injected but should not
* Fixed many Dynarec and non dynarec opcodes
* Improved Signal handling
* Added a few more wrapped lib (like curl)
* Gallium9 is wrapped (thx @icecream95)
* Fixed and simplied many wrapped functions (especialy the one were a callback is involved)
* Fixed Dynarec "freeing" a Dynablock somthime corrupting the heap (happens in case of JIT mainly)
* Optimized the way LOCK prefix work when using Dynarec on ARM
* Printer of ARM opcode (for dumping Dynarec blocks) improvement (thx @rajdakin)
v0.1.2
======
* The Dynarec now handle JIT code
* Added support for Unity games (not perfect yet)
* Added support for Wine (not perfect yet). You need an x86 build of Wine to use it
* Added support for Steam (not perfect yet). Note that steam have limited functionnalities on 32bits (only mini-mode is available)
* More wrapped libs
* Added support for "PltResolver", so order of library is less important and many symbol are resolved at runtime
* Added an option to build box86 as a lib (to wrapped dynamic library)
* Better Signal handling (not perfect yet)
* More opcodes added, more opcode fixes.
* More Dynarec opcodes.
* Added support for FS:, and creating custom selector (needed by Wine)
* There is now 1 x86emu_t structure per thread (simplifying/optimising many callback handling)
* Box86 now have a logo!
* Added options handling (only version and help for now). Now it's much usefull exept for version printing.
v0.1.0
=======
* Dynarec!!! Only for ARM (note that dynarec doesn't support JITed code for now)
+247 -62
View File
@@ -1,83 +1,131 @@
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(GAMESHELL "Set to ON if targeting a Gameshell device" ${GAMESHELL})
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(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR 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(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(USE_FLOAT "Set to ON to use only float, no double, in all x87 Emulation" ${USE_FLOAT})
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(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})
find_package(PythonInterp)
if(NOT PYTHONINTERP_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
if(${CMAKE_VERSION} VERSION_LESS "3.12.2")
find_package(PythonInterp 3)
if(NOT PYTHONINTERP_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
endif()
if(${PYTHON_VERSION_MAJOR} LESS 3)
message( FATAL_ERROR "You need a Python 3 interpretor, CMake will exit." )
endif()
else()
find_package(Python3)
if(NOT Python3_Interpreter_FOUND)
message( FATAL_ERROR "You need a Python interpretor, CMake will exit." )
endif()
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.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
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")
set(ARM_DYNAREC ON)
set(LD80BITS OFF)
set(NOALIGN OFF)
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")
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")
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)
add_definitions(-DNOGIT)
endif()
if(BOX86LIB)
set(BOX86 box86)
elseif(HAVE_TRACE)
set(BOX86 box86t)
else()
set(BOX86 box86)
endif()
set(BOX86_ELF_ADDRESS "0x62800000")
if(LD80BITS)
add_definitions(-DHAVE_LD80BITS)
@@ -91,10 +139,6 @@ if(HAVE_TRACE)
add_definitions(-DHAVE_TRACE)
endif()
if(USE_FLOAT)
add_definitions(-DUSE_FLOAT)
endif()
if(ARM_DYNAREC)
add_definitions(-DDYNAREC)
add_definitions(-DARM)
@@ -102,22 +146,33 @@ 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()
if(BOX86LIB)
add_definitions(-DBUILD_LIB)
if(BOX86DYNAMIC)
add_definitions(-DBUILD_DYNAMIC)
endif()
add_definitions(-fPIC)
if(NOT BOX86_ROOT)
message(FATAL_ERROR "BOX86_ROOT not set when build as lib")
endif()
else()
set(BOX86_ROOT ${CMAKE_HOME_DIRECTORY})
set(BOX86_ROOT ${CMAKE_SOURCE_DIR})
endif()
add_definitions(-g -std=gnu99 -funwind-tables -O3 -fvisibility=hidden)
add_definitions(-std=gnu11 -funwind-tables -fvisibility=hidden)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
@@ -133,15 +188,25 @@ include_directories(
"${BOX86_ROOT}/src/wrapped/generated"
)
# git_head.h is a generated file
set_source_files_properties(
"${BOX86_ROOT}/src/git_head.h"
PROPERTIES GENERATED TRUE
HEADER_FILE_ONLY TRUE)
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"
"${BOX86_ROOT}/src/tools/callback.c"
"${BOX86_ROOT}/src/tools/box86stack.c"
"${BOX86_ROOT}/src/tools/my_cpuid.c"
"${BOX86_ROOT}/src/tools/gtkclass.c"
"${BOX86_ROOT}/src/tools/wine_tools.c"
"${BOX86_ROOT}/src/elfs/elfloader.c"
"${BOX86_ROOT}/src/elfs/elfparser.c"
"${BOX86_ROOT}/src/elfs/elfload_dump.c"
@@ -150,19 +215,25 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run.c"
"${BOX86_ROOT}/src/emu/x86run66.c"
"${BOX86_ROOT}/src/emu/x86run660f.c"
"${BOX86_ROOT}/src/emu/x86run_private.c"
"${BOX86_ROOT}/src/emu/x86syscall.c"
"${BOX86_ROOT}/src/emu/x86primop.c"
"${BOX86_ROOT}/src/emu/x86trace.c"
"${BOX86_ROOT}/src/emu/x86int3.c"
"${BOX86_ROOT}/src/emu/x86tls.c"
"${BOX86_ROOT}/src/emu/x87emu_private.c"
"${BOX86_ROOT}/src/emu/x87run.c"
"${BOX86_ROOT}/src/libtools/auxval.c"
"${BOX86_ROOT}/src/libtools/myalign.c"
"${BOX86_ROOT}/src/libtools/myalign64.c"
"${BOX86_ROOT}/src/libtools/myfts.c"
"${BOX86_ROOT}/src/libtools/obstack.c"
"${BOX86_ROOT}/src/libtools/sdl1rwops.c"
"${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"
)
@@ -184,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"
@@ -205,16 +277,33 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibxdmcp.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxfixes.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshape.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbshm.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbrandr.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbimage.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbkeysyms.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbxtest.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri2.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbdri3.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcbpresent.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxtst.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxt.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxcomposite.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxdamage.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibxmu.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${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"
"${BOX86_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX86_ROOT}/src/wrapped/wrappediconv.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibdrm.c"
"${BOX86_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX86_ROOT}/src/wrapped/wrappedutil.c"
@@ -231,9 +320,14 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibusb1.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibformw.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${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"
@@ -242,6 +336,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangocairo.c"
@@ -250,19 +346,55 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedpango.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusglib1.c"
"${BOX86_ROOT}/src/wrapped/wrappedgudev1.c"
# "${BOX86_ROOT}/src/wrapped/wrappedmonounity.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibnm.c"
"${BOX86_ROOT}/src/wrapped/wrappedtcmallocminimal.c"
"${BOX86_ROOT}/src/wrapped/wrappedmpg123.c"
"${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"
)
set(WRAPPEDS_HEAD "")
set(WRAPPEDS_HEAD "${BOX86_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
foreach(A ${WRAPPEDS})
string(REPLACE ".c" "_private.h" B ${A})
set(WRAPPEDS_HEAD ${WRAPPEDS_HEAD} ${B})
set_source_files_properties(${A} PROPERTIES OBJECT_DEPENDS ${B})
endforeach()
set(WRAPPER "${BOX86_ROOT}/src/wrapped/generated/wrapper.c" "${BOX86_ROOT}/src/wrapped/generated/wrapper.h")
add_custom_command(OUTPUT ${WRAPPER} COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py" "${BOX86_ROOT}" "PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "USE_FLOAT" MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py" DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD})
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
"${BOX86_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
BYPRODUCTS ${WRAPPER}
)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/dynarec/last_run.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_printer.py" "${BOX86_ROOT}"
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_printer.py"
DEPENDS "${BOX86_ROOT}/src/dynarec/arm_instructions.txt"
BYPRODUCTS "${BOX86_ROOT}/src/dynarec/arm_printer.c"
)
add_custom_target(WRAPPERS DEPENDS "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt")
add_custom_target(PRINTER DEPENDS "${BOX86_ROOT}/src/dynarec/last_run.txt")
if(ARM_DYNAREC)
set(DYNAREC_SRC
@@ -276,13 +408,19 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
"${BOX86_ROOT}/src/dynarec/arm_linker.S"
"${BOX86_ROOT}/src/dynarec/arm_table.S"
"${BOX86_ROOT}/src/dynarec/arm_lock_helper.S"
)
set(DYNAREC_PASS
"${BOX86_ROOT}/src/dynarec/dynarec_arm_helper.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_tests.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_math.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_logic.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_emit_shift.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_pass.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_00.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_0f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_64.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_65.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_66.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_67.c"
@@ -312,6 +450,10 @@ if(ARM_DYNAREC)
set_target_properties(arm_pass2 PROPERTIES COMPILE_FLAGS "-DSTEP=2")
add_library(arm_pass3 OBJECT ${DYNAREC_PASS})
set_target_properties(arm_pass3 PROPERTIES COMPILE_FLAGS "-DSTEP=3")
add_dependencies(arm_pass0 WRAPPERS)
add_dependencies(arm_pass1 WRAPPERS)
add_dependencies(arm_pass2 WRAPPERS)
add_dependencies(arm_pass3 WRAPPERS)
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_arm>
@@ -320,30 +462,66 @@ if(ARM_DYNAREC)
$<TARGET_OBJECTS:arm_pass2>
$<TARGET_OBJECTS:arm_pass3>
)
endif()
# creates git_head.h
if(ARM_DYNAREC)
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS dynarec ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
else()
add_custom_command(
OUTPUT "${BOX86_ROOT}/src/git_head.h"
COMMAND bash -c "echo \\\#define GITREV \\\"$(git rev-parse --short HEAD)\\\">\"${BOX86_ROOT}/src/git_head.h\""
DEPENDS ${ELFLOADER_SRC} ${WRAPPEDS}
VERBATIM)
endif()
if(BOX86LIB)
#build a static lib...
add_library(box86 OBJECT ${ELFLOADER_SRC} ${WRAPPEDS})
#build a static or dynamic lib...
if(BOX86DYNAMIC)
add_library(box86 SHARED ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
else()
add_library(${BOX86} OBJECT ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec m dl rt pthread)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
else()
target_link_options(${BOX86} PUBLIC -rdynamic)
endif()
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
add_custom_target(buildinfo ${BOX86}
DEPENDS dynarec ${BOX86} )
else(BOX86LIB)
if(USE_FLOAT)
set(BOX86 box86f)
elseif(HAVE_TRACE)
set(BOX86 box86t)
else()
set(BOX86 box86)
endif()
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS})
add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head.h")
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
target_link_libraries(${BOX86} m dl rt pthread)
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
endif()
if(NOT NOLOADADDR)
target_link_libraries(${BOX86} -Wl,-Ttext-segment,0x03800000)
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
endif()
else()
target_link_options(${BOX86} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
@@ -352,8 +530,10 @@ 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/)
endif()
@@ -432,7 +612,12 @@ add_test(test13 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(test14 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
+38 -11
View File
@@ -2,31 +2,48 @@ Compiling
----
#### for Pandora
`mkdir build; cd build; cmake .. -DPANDORA=1; make`
`mkdir build; cd build; cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Pyra
`mkdir build; cd build; cmake .. -DPYRA=1; make`
`mkdir build; cd build; cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for Gameshell
`mkdir build; cd build; cmake .. -DGAMESHELL=1; make`
`mkdir build; cd build; cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### for RaspberryPI
_a build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
`mkdir build; cd build; cmake .. -DRPI4=1; make`
```
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -j4
sudo make install
sudo systemctl restart systemd-binfmt
```
_For Pi4. Change to RPI2 or RPI3 for other models._
#### for Other ARM Linux
#### for ODROID
`mkdir build; cd build; cmake .. ; make`
`mkdir build; cd build; cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### 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`
#### for x86 Linux
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1; make`
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
#### use ccmake
@@ -34,15 +51,25 @@ Alternatively, you can use the curses-bases ccmake (or any other gui frontend fo
#### Customize your build
*use ccache if you have it*
*use ccache if you have it*
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
*have some debug info*
*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.
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 ( ***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 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).
----
+58 -18
View File
@@ -1,21 +1,22 @@
# box86
![Official logo](Box86Logo.png "Official Logo")
Linux Userspace x86 Emulator with a twist
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=LU8Y2T62ZWFHU)
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux, like ARM (host system needs to be 32bit little-endian).
Box86 will let you run x86 Linux programs (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, and you'll need a multiarch or chroot environnement).
Because Box86 uses the native version for some "system" libraries, like libc, libm, or SDL and OpenGL, it's easy to integrate and use, and performances can be surprinsigly high in some cases.
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 probably needed.
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 integrate a DynaRec for ARM platform, providing a speed boost between 5 to 10 times compared to only the interpretor.
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.
Many games already work, like for example: WorldOfGoo, Airline Tycoon Deluxe or FTL. Many of the GameMaker linux games also run fine (there a long list, among them are UNDERTALE, A Risk of Rain, and Cook Server Delicious)
Many games already work, for example: WorldOfGoo, Airline Tycoon Deluxe, and FTL. Many of the GameMaker Linux games also run fine (there a long list, among them are UNDERTALE, A Risk of Rain, and Cook Server Delicious)
If you are serious about developing Box86, you should install ccache and activate it's support in the cmake project (use ccmake for example)
To have TRACE enabled (i.e. dumping to stdout all individual x86 instructions executed, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) accessible on your system.
If you are serious about developing Box86, you should install ccache and activate its support in the cmake project (use ccmake for example)
To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed, with dump of registers), you'll also need [Zydis library](https://github.com/zyantific/zydis) available on your system.
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/x86primop.c) for copyright details
@@ -23,46 +24,85 @@ Here are 6 videos, the first 2 of "Airline Tycoon Deluxe" and "Heretic 2" runnin
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
You can find many more Box86 video on [PI Lab Channel](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) [![PI Lab Channel](https://yt3.ggpht.com/a/AATXAJyMeWrgCjs78gr6To6yX4KtDPUCS7hsbX1rRA=s100-c-k-c0xffffffff-no-rj-mo)](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g).
Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="Box86Icon.png" width="96" height="96">
Logo and Icon made by @grayduck, thanks!
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(or have any problems) about box86, there is a Discord friendly server there: [PI Lab Discord](https://discord.gg/Fh8sjmu)
----
Compiling
----
How to compile can be found [here](COMPILE.md)
Compilation instructions can be found [here](COMPILE.md)
----
Usage
----
There are a few environment variables to control Box86 behaviour.
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: 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.
----
Version history
----
The change log is [here](CHANGELOG.md)
The change log is available [here](CHANGELOG.md)
----
A note about 64bits platform
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 32bits library. Box86 doesn't include any 32bits <-> 64bits translation. So basically, to run box86 on, for example, an ARM64 platform, you will need to build box86 for arm 32bits, and also need to have a chroot with 32bits library.
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 binary on 64bits platform. You will still need box86 (and see 32bits chroot) to run x86 binary (in fact, like it 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 not possible for now. Mono itself uses signals that are not well emulated enough. So the solution is to use a native version of the libmono used by Unity. It can be found here: https://github.com/Unity-Technologies/mono and it needs to be built from source. When built copy `libmonosgen-2.0.so` to `libmonounity.so` and put it somewhere it can be dlopen'd (so in `usr/lib` or friend or somewhere in your `LD_LIBRARY_PATH`).
Note that libmonounity is not completely wrapped yet, and the mechanism to call x86 library from libmonounity is not done yet, so the use of libmonounity is not enable for 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: mono games are not working for now anyway.
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.
----
Notes about Steam
----
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works. First problem is steam crashing after the Sign in window, if you encounter this issue, you may need to add libappindicator. 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)
----
Notes about Wine
----
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.
----
+78 -22
View File
@@ -1,25 +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
#### BOX86_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 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
@@ -27,16 +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 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
@@ -46,28 +53,44 @@ 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
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
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
#### BOX86_DYNAREC_LOG
Set level of DynaRec log
* 0 :
@@ -77,7 +100,7 @@ Set level of DynaRec log
* 2 :
* DEBUG : Debug Log for Dynarec (with detail on block created / executed)
* 3 :
* DUMP : All above plus dump of the x86 -> native opcode conversions
* VERBOSE : All above plus more
#### BOX86_DYNAREC
* 0 : Disable Dynarec
@@ -87,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)
@@ -102,11 +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.
Note that LittleInforno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs
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 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 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.
* 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`).
+1984
View File
File diff suppressed because it is too large. Load diff
+221 -149
View File
@@ -1,19 +1,17 @@
#!/usr/bin/env python
import os
import glob
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', "O", "S"]
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):
ret = [len(s)]
i = 0
for c in s:
i = i + 1
if i == 2:
continue
ret.append(values.index(c))
return ret
try:
ret = [len(s), values.index(s[0])]
for c in s[2:]:
ret.append(values.index(c))
return ret
except ValueError as e:
raise ValueError("Value is " + s) from e
def value(define):
return define[9:-1] if define.startswith("!") else define[8:-1]
@@ -36,16 +34,16 @@ def splitdef(dnf, defines):
def invert(define):
return define[1:] if define.startswith("!") else ("!" + define)
def main(root, defines, ver):
# Initialize variables: gbl for all values, vals for file-per-file values, redirects for redirections
def main(root, defines, files, ver):
global values
# Initialize variables: gbl for all values, redirects for redirections
gbl = {}
vals = {}
redirects = {}
# First read the files inside the headers
for filepath in glob.glob(os.path.join(root, "src/wrapped/", "wrapped*_private.h")):
for filepath in files:
filename = filepath.split("/")[-1]
locval = {}
dependants = []
with open(filepath, 'r') as file:
for line in file:
@@ -68,8 +66,8 @@ def main(root, defines, ver):
raise KeyError(preproc_cmd[5:].strip())
dependants.append("defined(" + preproc_cmd[5:].strip() + ")")
elif preproc_cmd.startswith("ifndef"):
if preproc_cmd[5:].strip() not in defines:
raise KeyError(preproc_cmd[5:].strip())
if preproc_cmd[6:].strip() not in defines:
raise KeyError(preproc_cmd[6:].strip())
dependants.append("!defined(" + preproc_cmd[6:].strip() + ")")
elif preproc_cmd.startswith("else"):
dependants[-1] = invert(dependants[-1])
@@ -91,29 +89,20 @@ def main(root, defines, ver):
if any(c not in values for c in ln[2:]) or (('v' in ln[2:]) and (len(ln) > 3)):
old = ln
# This needs more work
acceptables = ['v', 'o', '0', '1'] + values
acceptables = ['v', '0', '1'] + values
if any(c not in acceptables for c in ln[2:]):
raise NotImplementedError("{0} ({1}:{2})".format(ln[2:], filename, line[:-1]))
# Ok, this is acceptable: there is 0, 1, stdout and void
# Ok, this is acceptable: there is 0, 1 and/or void
ln = (ln
.replace("v", "") # void -> nothing
.replace("o", "p") # stdout -> pointer
.replace("0", "p") # 0 -> pointer
.replace("1", "i")) # 1 -> integer
redirects.setdefault(" && ".join(dependants), {})
redirects[" && ".join(dependants)][old] = ln
# Simply append the function name if it's not yet existing
locval.setdefault(" && ".join(dependants), [])
gbl.setdefault(" && ".join(dependants), [])
if ln not in locval[" && ".join(dependants)]:
locval[" && ".join(dependants)].append(ln)
if ln not in gbl[" && ".join(dependants)]:
gbl[" && ".join(dependants)].append(ln)
# Sort the file local values and add it to the dictionary
for k in locval:
locval[k].sort(key=splitchar)
vals[filename] = locval
gbl_vals = {}
for k in gbl:
@@ -180,24 +169,44 @@ def main(root, defines, ver):
redirects_idxs = []
for k, v in redirects_vals:
key = "(" + (") || (".join(redirects_vals[(k, v)])) + ")"
val = redirects.get(key, {})
val[k] = v
redirects[key] = val
if key in redirects:
redirects[key].append([k, v])
else:
redirects[key] = [[k, v]]
if (key not in redirects_idxs) and (key != "()"):
redirects_idxs.append(key)
redirects_idxs.sort(key=lambda v: splitdef(v, defines))
# Sort the table
# Sort the tables
for k in gbl:
gbl[k].sort(key=lambda v: splitchar(v))
values = values + ['0', '1']
for k in redirects:
redirects[k].sort(key=lambda v: splitchar(v[0]) + [0] + splitchar(v[1]))
values = values[:-2]
def length(s):
l = len(s)
if l < 10:
ret = "0" + str(l)
else:
ret = str(l)
return ret
# Check if there was any new functions
functions_list = ""
for k in ["()"] + gbl_idxs:
for v in gbl[k]:
functions_list = functions_list + "#" + k + " " + v + "\n"
for k in ["()"] + redirects_idxs:
for v in redirects[k]:
functions_list = functions_list + "#" + k + " " + v[0] + " -> " + v[1] + "\n"
# functions_list is a unique string, compare it with the last run
try:
last_run = ""
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'r') as file:
last_run = file.read()
if last_run == functions_list:
# Mark as OK for CMake
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
file.write(functions_list)
#return 0
except IOError:
# The file does not exist yet, first run
pass
# Now the files rebuilding part
# File headers and guards
@@ -221,6 +230,11 @@ typedef union ui64_s {
uint32_t d[2];
} ui64_t;
typedef struct _2uint_struct_s {
uint32_t a;
uint32_t b;
} _2uint_struct_t;
extern void* my__IO_2_1_stderr_;
extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
@@ -238,16 +252,36 @@ static void* io_convert(void* v)
return v;
}
#ifdef USE_FLOAT
#define ST0val ST0.f
#else
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
#endif
#ifndef NOALIGN
int of_convert(int flag) { return (flag&~0740000) | ((flag&0140000)<<2) | ((flag&0600000)>>2);}
#else
int of_convert(int flag) { return flag; }
#endif
int of_convert(int);
""",
"wrapper.h": """/*****************************************************************
* File automatically generated by rebuild_wrappers.py (v%s)
@@ -255,6 +289,7 @@ int of_convert(int flag) { return flag; }
#ifndef __WRAPPER_H_
#define __WRAPPER_H_
#include <stdint.h>
#include <string.h>
typedef struct x86emu_s x86emu_t;
@@ -274,7 +309,11 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
// O = libc O_ flags bitfield
// S = _IO_2_1_stdXXX_ pointer (or FILE*)
// Q = ...
// S8 = struct, 8 bytes
// 2 = struct of 2 uint
// P = Vulkan struture pointer
// G = a single GValue pointer
// N = ... automatically sending 1 arg
// M = ... automatically sending 2 args
"""
}
@@ -284,61 +323,122 @@ typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
"""
}
# Transform strings into arrays
for k in gbl:
gbl[k] = [[c for c in v] for v in gbl[k]]
# Rewrite the wrapper.h file:
with open(os.path.join(root, "src/wrapped/generated/", "wrapper.h"), 'w') as file:
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
file.write(files_headers["wrapper.h"] % ver)
for v in gbl["()"]:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("void " + v + "(x86emu_t *emu, uintptr_t fnc);\n")
for k in gbl_idxs:
if k != "()":
file.write("\n#if " + k + "\n")
for v in gbl[k]:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n#if " + k + "\n")
for v in gbl[k]:
file.write("void " + v + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("void " + v[0] + "(x86emu_t *emu, uintptr_t fnc);\n")
for k in redirects_idxs:
if k != "()":
file.write("\n#if " + k + "\n")
for v in redirects[k]:
file.write("void " + ''.join(v) + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n#if " + k + "\n")
for v in redirects[k]:
file.write("void " + v[0] + "(x86emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write(files_guards["wrapper.h"])
# Rewrite the wrapper.c file:
with open(os.path.join(root, "src/wrapped/generated/", "wrapper.c"), 'w') as file:
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_headers["wrapper.c"] % ver)
# 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
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*"]
# 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)))
file.write("typedef " + types[values.index(v[0])] + " (*" + ''.join(v) + "_t)"
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
for k in gbl_idxs:
if k != "()":
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
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*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
file.write("typedef " + types[values.index(v[0])] + " (*" + ''.join(v) + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
file.write("#endif\n")
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 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)))
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
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,89 +451,61 @@ 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
]
# E e v c w i I C W u U f d D K l L p V O S
deltas = [0, 0, 4, 4, 4, 4, 8, 4, 4, 4, 8, 4, 8, 12, 12, 4, 4, 4, 0, 4, 4]
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
]
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, ''.join(v), ''.join(v) + "_t", v[0], v[2:])
function_writer(file, v, v + "_t", v[0], v[2:])
for k in gbl_idxs:
if k != "()":
file.write("\n#if " + k + "\n")
for v in gbl[k]:
function_writer(file, ''.join(v), ''.join(v) + "_t", v[0], v[2:])
file.write("#endif\n")
file.write("\n#if " + k + "\n")
for v in gbl[k]:
function_writer(file, v, v + "_t", v[0], v[2:])
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
function_writer(file, v, redirects["()"][v] + "_t", v[0], v[2:])
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
for k in redirects_idxs:
if k != "()":
file.write("\n#if " + k + "\n")
for v in redirects[k]:
function_writer(file, v, redirects[k][v] + "_t", v[0], v[2:])
file.write("#endif\n")
file.write("\n#if " + k + "\n")
for v in redirects[k]:
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
file.write("#endif\n")
file.write(files_guards["wrapper.c"])
# Save the string for the next iteration, writing was successful
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
file.write(functions_list)
return 0
if __name__ == '__main__':
if main(sys.argv[1], sys.argv[2:], "1.1.1.06") != 0:
limit = []
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.2.0.09") != 0:
exit(2)
exit(0)
+9 -1
View File
@@ -13,7 +13,15 @@ if( NOT TEST_REFERENCE )
endif( NOT TEST_REFERENCE )
set(ENV{BOX86_LOG} 0)
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x86lib)
set(ENV{BOX86_NOBANNER} 1)
if( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
# we are inside box86 folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/x86lib)
else()
# we are inside build folder
set(ENV{LD_LIBRARY_PATH} ${CMAKE_SOURCE_DIR}/../x86lib)
endif( EXISTS ${CMAKE_SOURCE_DIR}/x86lib )
# run the test program, capture the stdout/stderr and the result var
execute_process(
COMMAND ${TEST_PROGRAM} ${TEST_ARGS} ${TEST_ARGS2}
+250 -123
View File
@@ -16,49 +16,112 @@
#include "callback.h"
#include "wrapper.h"
#include "myfts.h"
#ifdef DYNAREC
#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"
#endif
typedef struct mmaplist_s {
void* block;
uintptr_t offset; // offset in the block
} mmaplist_t;
#define MMAPSIZE (4*1024*1024) // allocate 4Mo sized blocks
uintptr_t AllocDynarecMap(box86context_t *context, int size)
#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)
{
// make size 0x10 bytes aligned
size = (size+0x0f)&~0x0f;
pthread_mutex_lock(&context->mutex_mmap);
// look for free space
for(int i=0; i<context->mmapsize; ++i) {
if(context->mmaplist[i].offset+size < MMAPSIZE) {
uintptr_t ret = context->mmaplist[i].offset + (uintptr_t)context->mmaplist[i].block;
context->mmaplist[i].offset+=size;
pthread_mutex_unlock(&context->mutex_mmap);
return ret;
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 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);
}
}
// no luck, add a new one !
int i = context->mmapsize++; // yeah, usefull post incrementation
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", context->mmapsize);
context->mmaplist = (mmaplist_t*)realloc(context->mmaplist, context->mmapsize*sizeof(mmaplist_t));
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);
--context->mmapsize;
pthread_mutex_unlock(&context->mutex_mmap);
return 0;
}
context->mmaplist[i].block = p;
context->mmaplist[i].offset=size;
pthread_mutex_unlock(&context->mutex_mmap);
return (uintptr_t)p;
}
#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)
{
static int inited = 0;
if(inited)
return;
my_context = context;
init_pthread_helper();
init_signal_helper(context);
#ifdef DYNAREC
if(box86_dynarec)
DynablockEmuMarker(context);
#endif
inited = 1;
}
EXPORTDYN
void finiAllHelpers(box86context_t* context)
{
static int finied = 0;
if(finied)
return;
fini_pthread_helper(context);
fini_signal_helper();
cleanAlternate();
fini_custommem_helper(context);
finied = 1;
}
void x86Syscall(x86emu_t *emu);
/// maxval not inclusive
@@ -66,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)
@@ -82,14 +145,31 @@ void free_tlsdatasize(void* p)
free(p);
}
EXPORTDYN
box86context_t *NewBox86Context(int argc)
{
#ifdef BUILD_DYNAMIC
if(my_context) {
++my_context->count;
return my_context;
}
#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;
context->maplib = NewLibrarian(context);
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();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x86Syscall, 0);
@@ -100,132 +180,147 @@ box86context_t *NewBox86Context(int argc)
#endif
context->dlprivate = NewDLPrivate();
context->callbacks = NewCallbackList();
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
pthread_mutex_init(&context->mutex_once, NULL);
pthread_mutex_init(&context->mutex_once2, NULL);
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);
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);
#endif
InitFTSMap(context);
for (int i=0; i<4; ++i) context->canary[i] = 1 + getrand(255);
context->canary[getrand(4)] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
initAllHelpers(context);
return context;
}
EXPORTDYN
void FreeBox86Context(box86context_t** context)
{
#ifdef BUILD_DYNAMIC
if(--(*context)->count)
return;
#endif
if(!context)
return;
if(--(*context)->forked >= 0)
return;
FreeFTSMap(*context);
box86context_t* ctx = *context; // local copy to do the cleanning
if((*context)->maplib)
FreeLibrarian(&(*context)->maplib);
#ifdef DYNAREC
dynarec_log(LOG_INFO, "Free global Dynarecblocks\n");
if((*context)->dynablocks)
FreeDynablockList(&(*context)->dynablocks);
for (int i=0; i<(*context)->mmapsize; ++i)
if((*context)->mmaplist[i].block)
munmap((*context)->mmaplist[i].block, MMAPSIZE);
free((*context)->mmaplist);
pthread_mutex_destroy(&(*context)->mutex_blocks);
pthread_mutex_destroy(&(*context)->mutex_mmap);
#endif
if((*context)->emu)
FreeX86Emu(&(*context)->emu);
FreeCollection(&(*context)->box86_path);
FreeCollection(&(*context)->box86_ld_lib);
FreeCollection(&(*context)->box86_emulated_libs);
if((*context)->zydis)
DeleteX86Trace(*context);
if((*context)->deferedInitList)
free((*context)->deferedInitList);
#ifndef BUILD_LIB
if((*context)->box86lib)
dlclose((*context)->box86lib);
#endif
FreeDLPrivate(&(*context)->dlprivate);
for(int i=0; i<(*context)->argc; ++i)
free((*context)->argv[i]);
free((*context)->argv);
for (int i=0; i<(*context)->envc; ++i)
free((*context)->envv[i]);
free((*context)->envv);
for(int i=0; i<(*context)->elfsize; ++i) {
FreeElfHeader(&(*context)->elfs[i]);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
}
free((*context)->elfs);
free(ctx->elfs);
free((*context)->stack);
FreeFTSMap(ctx);
free((*context)->fullpath);
free((*context)->box86path);
if(ctx->maplib)
FreeLibrarian(&ctx->maplib);
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib);
FreeBridge(&(*context)->system);
FreeCollection(&ctx->box86_path);
FreeCollection(&ctx->box86_ld_lib);
FreeCollection(&ctx->box86_emulated_libs);
// stop trace now
if(ctx->dec)
DeleteX86TraceDecoder(&ctx->dec);
if(ctx->zydis)
DeleteX86Trace(ctx);
if((*context)->glwrappers)
freeProcWrapper(&(*context)->glwrappers);
if((*context)->alwrappers)
freeProcWrapper(&(*context)->alwrappers);
if(ctx->deferedInitList)
free(ctx->deferedInitList);
FreeCallbackList(&(*context)->callbacks);
free(ctx->argv);
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
void* ptr;
if ((ptr = pthread_getspecific((*context)->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific((*context)->tlskey, NULL);
}
pthread_key_delete((*context)->tlskey);
if((*context)->tlsdata)
free((*context)->tlsdata);
pthread_mutex_destroy(&(*context)->mutex_once);
pthread_mutex_destroy(&(*context)->mutex_once2);
pthread_mutex_destroy(&(*context)->mutex_trace);
pthread_mutex_destroy(&(*context)->mutex_lock);
if((*context)->atfork_sz) {
free((*context)->atforks);
(*context)->atforks = NULL;
(*context)->atfork_sz = (*context)->atfork_cap = 0;
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((*context)->signals[i]!=0 && (*context)->signals[i]!=1) {
if(ctx->signals[i]!=0 && ctx->signals[i]!=1) {
signal(i, SIG_DFL);
}
*context = NULL; // bye bye my_context
free(*context);
*context = NULL;
CleanStackSize(ctx);
#ifndef BUILD_LIB
if(ctx->box86lib)
dlclose(ctx->box86lib);
#endif
FreeDLPrivate(&ctx->dlprivate);
free(ctx->stack);
free(ctx->fullpath);
free(ctx->box86path);
FreeBridge(&ctx->system);
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific(ctx->tlskey, NULL);
}
pthread_key_delete(ctx->tlskey);
if(ctx->tlsdata)
free(ctx->tlsdata);
for(int i=0; i<3; ++i) {
if(ctx->segtls[i].present) {
// key content not handled by box86, so not doing anything with it
pthread_key_delete(ctx->segtls[i].key);
}
}
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
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);
free(ctx->memprot);
ctx->memprot = NULL;
free_neededlib(&ctx->neededlibs);
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
finiAllHelpers(ctx);
free(ctx);
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
@@ -242,7 +337,39 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
}
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
context->tlssize += 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
}
}
void add_neededlib(needed_libs_t* needed, library_t* lib)
{
if(!needed)
return;
if(needed->size == needed->cap) {
needed->cap += 8;
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
}
needed->libs[needed->size++] = lib;
}
void free_neededlib(needed_libs_t* needed)
{
if(!needed)
return;
needed->cap = 0;
needed->size = 0;
if(needed->libs)
free(needed->libs);
needed->libs = NULL;
}
+1 -1
View File
@@ -2,7 +2,7 @@
#define __BOX86_VERSION_H_
#define BOX86_MAJOR 0
#define BOX86_MINOR 1
#define BOX86_MINOR 2
#define BOX86_REVISION 0
#endif //__BOX86_VERSION_H_
+27
View File
@@ -0,0 +1,27 @@
#include <stdio.h>
#include "debug.h"
#include "box86version.h"
#ifdef NOGIT
#define GITREV "nogit"
#else
#include "git_head.h"
#endif
void PrintBox86Version()
{
printf("Box86%s%s v%d.%d.%d %s built on %s %s\n",
#ifdef HAVE_TRACE
" with trace",
#else
"",
#endif
#ifdef DYNAREC
" with Dynarec",
#else
"",
#endif
BOX86_MAJOR, BOX86_MINOR, BOX86_REVISION,
GITREV,
__DATE__, __TIME__);
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef __BUILD_INFO_H__
#define __BUILD_INFO_H__
void PrintBox86Version();
#endif //__BUILD_INFO_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);
}
+411 -77
View File
@@ -21,28 +21,29 @@ 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
#define xSP 13
// barel roll operations (4 possibles)
#define brLSL(i, r) (0<<4 | 0<<5 | ((i&31)<<7) | r)
#define brLSR(i, r) (0<<4 | 1<<5 | ((i&31)<<7) | r)
#define brASR(i, r) (0<<4 | 2<<5 | ((i&31)<<7) | r)
#define brROR(i, r) (0<<4 | 3<<5 | ((i&31)<<7) | r)
#define brLSL(i, r) (0<<4 | 0<<5 | (((i)&31)<<7) | (r))
#define brLSR(i, r) (0<<4 | 1<<5 | (((i)&31)<<7) | (r))
#define brASR(i, r) (0<<4 | 2<<5 | (((i)&31)<<7) | (r))
#define brROR(i, r) (0<<4 | 3<<5 | (((i)&31)<<7) | (r))
#define brIMM(r) (abs(r))
// barel roll with a register
#define brRLSL(i, r) (1<<4 | 0<<5 | ((i&15)<<8) | r)
#define brRLSR(i, r) (1<<4 | 1<<5 | ((i&15)<<8) | r)
#define brRASR(i, r) (1<<4 | 2<<5 | ((i&15)<<8) | r)
#define brRROR(i, r) (1<<4 | 3<<5 | ((i&15)<<8) | r)
#define brRLSL(i, r) (1<<4 | 0<<5 | (((i)&15)<<8) | (r))
#define brRLSR(i, r) (1<<4 | 1<<5 | (((i)&15)<<8) | (r))
#define brRASR(i, r) (1<<4 | 2<<5 | (((i)&15)<<8) | (r))
#define brRROR(i, r) (1<<4 | 3<<5 | (((i)&15)<<8) | (r))
// conditions
@@ -79,12 +80,12 @@ Op is 20-27
// pseudo insruction: mov reg, #imm with imm a 32bits value
#define MOV32(dst, imm32) \
MOVW(dst, ((uint32_t)imm32)&0xffff); \
if (((uint32_t)imm32)>>16) { \
if (((uint32_t)(imm32))>>16) { \
MOVT(dst, (((uint32_t)imm32)>>16)); }
// pseudo insruction: mov reg, #imm with imm a 32bits value, fixed size
#define MOV32_(dst, imm32) \
MOVW(dst, ((uint32_t)imm32)&0xffff); \
MOVT(dst, (((uint32_t)imm32)>>16))
MOVW(dst, ((uint32_t)(imm32))&0xffff); \
MOVT(dst, (((uint32_t)(imm32))>>16))
// movw.cond dst, #imm16
#define MOVW_COND(cond, dst, imm16) EMIT(cond | 0x03000000 | ((dst) << 12) | (((imm16) & 0xf000) << 4) | brIMM((imm16) & 0x0fff) )
// mov dst #imm8 ror imm4*2
@@ -93,46 +94,66 @@ Op is 20-27
#define MOV_IMM_COND(cond, dst, imm8, rimm4) EMIT(cond | 0x03a00000 | ((dst) << 12) | (imm8) | ((rimm4) << 8) )
// mov dst, src lsl imm5
#define MOV_REG_LSL_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (0<<5) | (imm5<<7))
#define MOV_REG_LSL_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (0<<5) | ((imm5)<<7))
// mov dst, src lsr imm5
#define MOV_REG_LSR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (1<<5) | (imm5<<7))
#define MOV_REG_LSR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (1<<5) | ((imm5)<<7))
// mov dst, src asr imm5
#define MOV_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | (imm5<<7))
#define MOV_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
// mov dst, src ror imm5
#define MOV_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | (imm5<<7))
#define MOV_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
// mov.s dst, src lsl imm5
#define MOVS_REG_LSL_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (0<<5) | ((imm5)<<7))
// mov.s dst, src lsr imm5
#define MOVS_REG_LSR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (1<<5) | ((imm5)<<7))
// mov.s dst, src asr imm5
#define MOVS_REG_ASR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (2<<5) | ((imm5)<<7))
// mov.s dst, src ror imm5
#define MOVS_REG_ROR_IMM5(dst, src, imm5) EMIT(0xe1b00000 | ((dst) << 12) | (src) | (0<<4) | (3<<5) | ((imm5)<<7))
// mov dst, src lsl rs
#define MOV_REG_LSL_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (0<<5) | (rs<<8))
#define MOV_REG_LSL_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (0<<5) | ((rs)<<8))
// mov dst, src lsr rs
#define MOV_REG_LSR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (1<<5) | (rs<<8))
#define MOV_REG_LSR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (1<<5) | ((rs)<<8))
// mov dst, src asr rs
#define MOV_REG_ASR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (2<<5) | (rs<<8))
#define MOV_REG_ASR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (2<<5) | ((rs)<<8))
// mov dst, src ror rs
#define MOV_REG_ROR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (3<<5) | (rs<<8))
#define MOV_REG_ROR_REG(dst, src, rs) EMIT(0xe1a00000 | ((dst) << 12) | (src) | (1<<4) | (3<<5) | ((rs)<<8))
// sub dst, src, #(imm8)
#define SUB_IMM8(dst, src, imm8) \
EMIT(0xe2400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sub cond dst, src, #(imm8)
#define SUB_COND_IMM8(dst, src, imm8) \
#define SUB_COND_IMM8(cond, dst, src, imm8) \
EMIT((cond) | 0x02400000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sub.s dst, src, #(imm8)
#define SUBS_IMM8(dst, src, imm8) \
EMIT(0xe2500000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add dst, src1, src2, lsl #imm
#define SUB_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe0400000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
// add.s dst, src1, src2, lsl #imm
#define SUBS_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe0500000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
// sub dst, src1, src2, lsl #imm
#define SUB_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0400000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// sub.s dst, src1, src2, lsl #imm
#define SUBS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0500000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// sbc dst, src, #(imm8)
#define SBC_IMM8(dst, src, imm8) \
EMIT(0xe2c00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sbc.s dst, src, #(imm8)
#define SBCS_IMM8(dst, src, imm8) \
EMIT(0xe2d00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// sbc dst, src1, src2, lsl #imm
#define SBC_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0c00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// sbc.s dst, src1, src2, lsl #imm
#define SBCS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0d00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// rsb dst, src, #(imm8)
#define RSB_IMM8(dst, src, imm8) \
EMIT(0xe2600000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// rsb.s dst, src, #(imm8)
#define RSBS_IMM8(dst, src, imm8) \
EMIT(0xe2700000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// rsb cond dst, src, #(imm8)
#define RSB_COND_IMM8(cond, dst, src, imm8) \
EMIT((cond) | 0x02600000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -152,30 +173,56 @@ Op is 20-27
// and.s dst, src, #(imm8)
#define ANDS_IMM8(dst, src, imm8) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// and.s dst, src1, #imm ror rot*2
#define ANDS_IMM8_ROR(src, imm8, rot) \
EMIT(0xe2100000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// add dst, src, #(imm8)
#define ADD_IMM8(dst, src, imm8) \
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add dst, src, #imm8 ror rot*2
#define ADD_IMM8_ROR(dst, src, imm8, rot) \
EMIT(0xe2800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | brIMM((imm8)) )
// add.s dst, src, #(imm8)
#define ADDS_IMM8(dst, src, imm8) \
EMIT(0xe2900000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add.c dst, src, #(imm8)
#define ADD_IMM8_cond(cond, dst, src, imm8) \
EMIT((cond) | 0x02800000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.s dst, src1, src2, lsl #imm
#define ADDS_REG_LSL_IMM5(dst, src1, src2, imm8) \
#define ADDS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add dst, src1, src2, lsr #imm
#define ADD_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
#define ADC_IMM8(dst, src, imm8) \
EMIT(0xe2a00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add.s dst, src, #(imm8)
#define ADCS_IMM8(dst, src, imm8) \
EMIT(0xe2b00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add dst, src1, src2, lsl #imm
#define ADC_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0a00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.s dst, src1, src2, lsl #imm
#define ADCS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0b00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// 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) )
// tst.s dst, src1, src2, lsl #imm
#define TSTS_REG_LSL_IMM8(src1, src2, imm8) \
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#define TSTS_REG_LSL_IMM5(src1, src2, imm5) \
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// tst.s dst, src1, #imm
#define TSTS_IMM8(src, imm8) \
EMIT(0xe3100000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -183,26 +230,42 @@ Op is 20-27
#define TSTS_IMM8_ROR(src, imm8, rot) \
EMIT(0xe3100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// orr dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#define ORR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr.s dst, src1, src2, lsl #imm
#define ORRS_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#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 dst, src1, src2, lsl #rs
// orr.s dst, src1, #imm8
#define ORRS_IMM8(dst, src, imm8, rot) \
EMIT(0xe3900000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
// 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
#define XOR_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe0200000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#define XOR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0200000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// xor.s dst, src1, src2, lsl #imm
#define XORS_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe0300000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#define XORS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0300000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
#define XOR_REG_LSL_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT((cond) | 0x00200000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// xor dst, src, #(imm8)
#define XOR_IMM8(dst, src, imm8) \
EMIT(0xe2200000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
#define XORS_IMM8(dst, src, imm8) \
EMIT(0xe2300000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// xor.cond dst, src, #(imm8)
#define XOR_IMM8_COND(cond, dst, src, imm8) \
EMIT(cond | 0x02200000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
@@ -213,17 +276,23 @@ Op is 20-27
#define XOR_REG_LSR_IMM8(dst, src1, src2, imm8) \
EMIT(0xe0200000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm8, src2) )
// bic dst, src1, src2, lsl #imm
#define BIC_REG_LSL_IMM8(dst, src1, src2, imm8) \
EMIT(0xe1c00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm8, src2) )
#define BIC_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1c00000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// 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) )
// bic dst, src1, src2, lsl #imm
#define BIC_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1c00000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// mvn dst, src1, src2, lsl #imm
#define MVN_REG_LSL_IMM8(dst, rm, imm8) \
EMIT(0xe1e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm8, rm) )
#define MVN_REG_LSL_IMM5(dst, rm, imm5) \
EMIT(0xe1e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm5, rm) )
// mvn dst, src, IMM8
#define MVN_IMM8(dst, src, imm8, rot) \
EMIT(0xe3e00000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
@@ -234,8 +303,8 @@ Op is 20-27
#define MVN_REG_LSR_REG(dst, rm, rs) \
EMIT(0xe1e00000 | ((dst) << 12) | (0 << 16) | (1<<4) | (1<<5) | (rs<<8) | (rm) )
// mvn with condition dst, src1, src2, lsl #imm
#define MVN_COND_REG_LSL_IMM8(cond, dst, rm, imm8) \
EMIT(cond | 0x01e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm8, rm) )
#define MVN_COND_REG_LSL_IMM5(cond, dst, rm, imm5) \
EMIT(cond | 0x01e00000 | ((dst) << 12) | (0 << 16) | brLSL(imm5, rm) )
// Single data transfert construction
#define SDT_REG(Cond, P, U, B, W, L, Rn, Rd, ShiftRm) (Cond | (0b00<<26) | (1<<25) | (P<<24) | (U<<23) | (B<<22) | (U<<23) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | ShiftRm)
@@ -264,9 +333,15 @@ Op is 20-27
#define LDRBAI_REG_LSL_IMM5(reg, addr, rm, imm5) EMIT(0xe6d00000 | ((reg) << 12) | ((addr) << 16) | (1<<25) | brLSL(imm5, rm) )
// ldrd reg, reg+1, [addr, #+/-imm9], reg must be even, reg+1 is implicit
#define LDRD_IMM8(reg, addr, imm8) EMIT(c__ | 0b000<<25 | 1<<24 | (((imm8)<0)?0:1)<<23 | 1<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | ((abs(imm8))&0xf0)<<(8-4) | (0b1101<<4) | ((abs(imm8))&0x0f) )
// ldrd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
#define LDRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1101<<4 | (rm) )
// str reg, [addr, #+/-imm9]
#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
@@ -283,6 +358,8 @@ Op is 20-27
#define STRBAI_REG_LSL_IMM5(reg, addr, rm, imm5) EMIT(0xe6c00000 | ((reg) << 12) | ((addr) << 16) | (1<<25) | brLSL(imm5, rm) )
// strd reg, reg+1, [addr, #+/-imm8], reg must be even, reg+1 is implicit
#define STRD_IMM8(reg, addr, imm8) EMIT(c__ | 0b000<<25 | 1<<24 | (((imm8)<0)?0:1)<<23 | 1<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | ((abs(imm8))&0xf0)<<(8-4) | (0b1111<<4) | ((abs(imm8))&0x0f) )
// strd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
#define STRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1111<<4 | (rm) )
// bx reg
#define BX(reg) EMIT(0xe12fff10 | (reg) )
@@ -293,33 +370,39 @@ Op is 20-27
#define BLX(reg) EMIT(0xe12fff30 | (reg) )
// b cond offset
#define Bcond(C, O) EMIT(C | (0b101<<25) | (0<<24) | ((O)>>2)&0xffffff)
#define Bcond(C, O) EMIT(C | (0b101<<25) | (0<<24) | (((O)>>2)&0xffffff))
// bl cond offset
#define BLcond(C, O) EMIT(C | (0b101<<25) | (1<<24) | ((O)>>2)&0xffffff)
#define BLcond(C, O) EMIT(C | (0b101<<25) | (1<<24) | (((O)>>2)&0xffffff))
// push reg!, {list}
// all | const |pre-index| subs | no PSR |writeback| store | base |reg list
#define PUSH(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (1<<21) | (0<<20) | (reg<<16) | (list))
#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))
#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))
#define STMDB(reg, list) EMIT(c__ | (0b100<<25) | (1<<24) | (0<<23) | (0<<22) | (0<<21) | (0<<20) | ((reg)<<16) | (list))
// STMia reg, {list}
// all | const |postindex| add | no PSR | no wb | store | base |reg list
#define STM(reg, list) EMIT(c__ | (0b100<<25) | (0<<24) | (1<<23) | (0<<22) | (0<<21) | (0<<20) | (reg<<16) | (list))
#define STM(reg, list) EMIT(c__ | (0b100<<25) | (0<<24) | (1<<23) | (0<<22) | (0<<21) | (0<<20) | ((reg)<<16) | (list))
// LDMia reg, {list}
// all | const |postindex| add | no PSR | no wb | load | base |reg list
#define LDM(reg, list) EMIT(c__ | (0b100<<25) | (0<<24) | (1<<23) | (0<<22) | (0<<21) | (1<<20) | (reg<<16) | (list))
#define LDM(reg, list) EMIT(c__ | (0b100<<25) | (0<<24) | (1<<23) | (0<<22) | (0<<21) | (1<<20) | ((reg)<<16) | (list))
// Half Word and signed data transfert construction
#define HWS_REG(Cond, P, U, W, L, Rn, Rd, S, H, Rm) (Cond | (0b000<<25) | (P<<24) | (U<<23) | (0<<22) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | (1<<7) | (S<<6) | (H<<5) | (1<<4) | Rm)
#define HWS_OFF(Cond, P, U, W, L, Rn, Rd, S, H, Imm8) (Cond | (0b000<<25) | (P<<24) | (U<<23) | (1<<22) | (W<<21) | (L<<20) | (Rn<<16) | (Rd<<12) | ((Imm8&0xf0)<<(8-4)) | (1<<7) | (S<<6) | (H<<5) | (1<<4) | (Imm8&0x0f))
#define HWS_REG(Cond, P, U, W, L, Rn, Rd, S, H, Rm) (Cond | 0b000<<25 | (P)<<24 | (U)<<23 | 0<<22 | (W)<<21 | (L)<<20 | (Rn)<<16 | (Rd)<<12 | 1<<7 | (S)<<6 | (H)<<5 | 1<<4 | (Rm))
#define HWS_OFF(Cond, P, U, W, L, Rn, Rd, S, H, Imm8) (Cond | 0b000<<25 | (P)<<24 | (U)<<23 | 1<<22 | (W)<<21 | (L)<<20 | (Rn)<<16 | (Rd)<<12 | ((Imm8)&0xf0)<<(8-4) | 1<<7 | (S)<<6 | (H)<<5 | 1<<4 | ((Imm8)&0x0f))
#define LDRSB_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 1, 0, abs(imm8)))
#define LDRSH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 1, 1, abs(imm8)))
@@ -328,17 +411,26 @@ Op is 20-27
#define STRH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
#define STRSH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 1, 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 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 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))
#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))
#define UMULL(RdHi, RdLo, Rs, Rm) EMIT(MULLONG(c__, 0, 0, 0, RdHi, RdLo, Rs, Rm))
#define SMULL(RdHi, RdLo, Rs, Rm) EMIT(MULLONG(c__, 1, 0, 0, RdHi, RdLo, Rs, Rm))
// Mul and MulA
#define MULMULA(Cond, A, S, Rd, Rn, Rs, Rm) (Cond | (0b000000<<22) | (A<<21) | (S<<20) | (Rd<<16) | (Rn<<12) | (Rs<<8) | (0b1001<<4) | (Rm))
#define MULMULA(Cond, A, S, Rd, Rn, Rs, Rm) (Cond | 0b000000<<22 | (A)<<21 | (S)<<20 | (Rd)<<16 | (Rn)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
#define MUL(Rd, Rm, Rn) EMIT(MULMULA(c__, 0, 0, (Rd), 0, (Rm), (Rn)))
#define SMUL_16_gen(cond, Rd, Rm, M, N, Rn) (cond | 0b00010110<<20 | (Rd)<<16 | (Rm)<<8 | 1<<7 | (M)<<6 | (N)<<5 | (Rn))
@@ -362,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))
@@ -384,11 +484,33 @@ Op is 20-27
#define LDREXD_gen(cond, Rn, Rt) (cond | 0b000<<25 | 0b11011<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Rt/Rt+1 from Rn (tagging the memory)
#define LDREXD(Rn, Rt) EMIT(LDREXD_gen(c__, Rn, Rt))
#define LDREXD(Rt, Rn) EMIT(LDREXD_gen(c__, Rn, Rt))
#define LDREXD_COND(cond, Rt, Rn) EMIT(LDREXD_gen(cond, Rn, Rt))
#define STREXD_gen(cond, Rd, Rn, Rt) (cond | 0b000<<25 | 0b11010<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Rt/Rt+1 to Rn, with result in Rd if tag is ok (Rd!=Rn && Rd!=Rt && Rd!=Rt+1), Rd==1 if store failed
#define STREXD(Rd, Rn, Rt) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
#define STREXD(Rd, Rt, Rn) EMIT(STREXD_gen(c__, Rd, Rn, Rt))
#define STREXD_COND(cond, Rd, Rt, Rn) EMIT(STREXD_gen(cond, Rd, Rn, Rt))
#define LDREX_gen(cond, Rn, Rt) (cond | 0b0001100<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Rt from Rn (tagging the memory)
#define LDREX(Rt, Rn) EMIT(LDREX_gen(c__, Rn, Rt))
#define LDREX_COND(cond, Rt, Rn) EMIT(LDREX_gen(cond, Rn, Rt))
#define STREX_gen(cond, Rd, Rn, Rt) (cond | 0b0001100<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREX(Rd, Rt, Rn) EMIT(STREX_gen(c__, Rd, Rn, Rt))
#define STREX_COND(cond, Rd, Rt, Rn) EMIT(STREX_gen(cond, Rd, Rn, Rt))
#define LDREXB_gen(cond, Rn, Rt) (cond | 0b0001110<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Byte Rt from Rn (tagging the memory)
#define LDREXB(Rt, Rn) EMIT(LDREXB_gen(c__, Rn, Rt))
#define LDREXB_COND(cond, Rt, Rn) EMIT(LDREXB_gen(cond, Rn, Rt))
#define STREXB_gen(cond, Rd, Rn, Rt) (cond | 0b0001110<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive byte Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREXB(Rd, Rt, Rn) EMIT(STREXB_gen(c__, Rd, Rn, Rt))
#define STREXB_COND(cond, Rd, Rt, Rn) EMIT(STREXB_gen(cond, Rd, Rn, Rt))
// Count leading 0 bit of Rm, store result in Rd
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
@@ -401,6 +523,23 @@ Op is 20-27
// Preload Cache Rn-Rm
#define PLDn(Rn, Rm) EMIT(PLD_gen(0, 1, Rn, 0, 0, Rm))
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
#define SWP(Rt, Rt2, Rn) EMIT(SWP_gen(c__, 0, Rn, Rt, Rt2))
// SWAP Byte (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2, Byte is zero extended
#define SWPB(Rt, Rt2, Rn) EMIT(SWP_gen(c__, 1, Rn, Rt, Rt2))
#define SDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0001<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
// Signed Div Rd <- Rn/Rm
#define SDIV(Rd, Rm, Rn) EMIT(SDIV_gen(c__, Rd, Rm, Rn))
#define UDIV_gen(cond, Rd, Rm, Rn) (cond | 0b0111<<24 | 0b0011<<20 | (Rd)<<16 | 0b1111<<12 | (Rm)<<8 | 0b0001<<4 | (Rn))
// Unsigned Div Rd <- Rn/Rm
#define UDIV(Rd, Rm, Rn) EMIT(UDIV_gen(c__, Rd, Rm, Rn))
// Yield
#define YIELD(cond) EMIT(cond | 0b00110010<<20 | 0b1111<<12 | 1)
// VFPU
#define TRANSFERT64(C, op) ((0b1100<<24) | (0b010<<21) | (0b101<<9) | ((C)<<8) | ((op)<<4))
@@ -485,21 +624,21 @@ Op is 20-27
// Convert from int32 Sm to single Dd
#define VCVT_F32_S32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b111<<19) | (0b000<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (1<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
#define VCVT_16_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
#define VCVT_FP_gen(cond, D, op, U, Vd, sf, sx, i, imm4) (cond | 0b1110<<24 | 1<<23 | (D)<<22 | 0b11<<20 | 1<<19 | (op)<<18 | 1<<17 | (U)<<16 | (Vd)<<12 | 0b101<<9 | (sf)<<8 | (sx)<<7 | 1<<6 | (i)<<5 | (imm4))
// Inplace convert from F64 to S16. Rounding is not selectable
#define VCVT_S16_F64(Dd) EMIT(VCVT_16_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
#define VCVT_S16_F64(Dd) EMIT(VCVT_FP_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
// Mutiply F64 Dd = Dn*Dm
#define VMUL_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b10<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (((Dn>>4)&1)<<7) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VMUL_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b10<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Divide F64 Dd = Dn/Dm
#define VDIV_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (((Dn>>4)&1)<<7) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VDIV_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b00<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Add F64 Dd = Dn + Dm
#define VADD_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (((Dn>>4)&1)<<7) | (0<<6) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VADD_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | (0<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Sub F64 Dd = Dn + Dm
#define VSUB_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (((Dn>>4)&1)<<7) | (1<<6) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VSUB_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Mutiply F32 Sd = Sn*Sm
#define VMUL_F32(Sd, Sn, Sm) EMIT(c__ | (0b1110<<24) | (0<<23) | (((Sd)&1)<<22) | (0b10<<20) | ((((Sn)>>1)&15)<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (((Sn)&1)<<7) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
@@ -514,7 +653,7 @@ Op is 20-27
#define VSUB_F32(Sd, Sn, Sm) EMIT(c__ | (0b1110<<24) | (0<<23) | (((Sd)&1)<<22) | (0b11<<20) | ((((Sn)>>1)&15)<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (((Sn)&1)<<7) | (1<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Cmp between 2 double Dd and Dm
#define VCMP_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0100<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VCMP_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0100<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Cmp between 1 double Dd and 0.0
#define VCMP_F64_0(Dd) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0101<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0<<7) | (1<<6) | (0<<5) | (0) )
// Cmp between 2 single Sd and Sm
@@ -523,10 +662,10 @@ Op is 20-27
#define VCMP_F32_0(Sd) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0101<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0<<7) | (1<<6) | (0<<5) | (0) )
// Neg F64 Dd = - Dm
#define VNEG_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VNEG_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Sqrt F64 Dd = - Dm
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | (((Dm>>4)&1)<<5) | ((Dm)&15) )
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Sqrt F32 Dd = - Dm
#define VSQRT_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b11<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
@@ -590,12 +729,26 @@ Op is 20-27
#define VEORQ(Dd, Dn, Dm) EMIT(VEOR_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_gen(U, D, imm3, Vd, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (imm3)<<19 | (Vd)<<12 | 0b1010<<8 | (M)<<5 | 1<<4 | (Vm))
#define VMOVL_S8(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_U8(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b001, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_S32(Dd, Dm) EMIT(VMOVL_gen(0, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOVL_U32(Dd, Dm) EMIT(VMOVL_gen(1, ((Dd)>>4)&1, 0b100, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VMOV_gen(D,Vd, M, Vm, Q) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | 0b10<<20 | (Vm)<<16 | (Vd)<<12 | 0b0001<<8 | (M)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VMOVD(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0))
#define VMOVQ(Dd, Dm) EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1))
#define VMOVD(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 0));}
#define VMOVQ(Dd, Dm) if((Dd)!=(Dm)) {EMIT(VMOV_gen(((Dd)>>4)&1, (Dd)&15, ((Dm)>>4)&1, (Dm)&15, 1));}
#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))
@@ -644,6 +797,9 @@ Op is 20-27
#define VBICD(Dd, Dn, Dm) EMIT(VBIC_gen(((Dd)>>4)&1, (Dd)&15, ((Dn)>>4)&1, (Dn)&15, ((Dm)>>4)&1, (Dm)&15, 0))
#define VBICQ(Dd, Dn, Dm) EMIT(VBIC_gen(((Dd)>>4)&1, (Dd)&15, ((Dn)>>4)&1, (Dn)&15, ((Dm)>>4)&1, (Dm)&15, 1))
#define VBIC_igen(i, D, imm3, Vd, cmode, Q, imm4) (0b1111<<28 | 0b001<<25 | (i)<<24 | 1<<23 | (D)<<22 | (imm3)<<16 | (Vd)<<12 | (cmode)<<8 | (Q)<<6 | 0b11<<4 | (imm4))
#define VBICQ_16_imm(Dd, imm) EMIT(VBIC_16_imm(((imm)>>7)&1, (Dd>>4)&1, ((imm)>>4)&7, (Dd)&15, 0b1001, 1, (imm)&15))
#define VCEQ_I_gen(size, D, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1000<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VCEQ_8(Dd, Dn, Dm) EMIT(VCEQ_I_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_8(Dd, Dn, Dm) EMIT(VCEQ_I_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -657,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))
@@ -682,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))
@@ -728,6 +901,11 @@ Op is 20-27
#define VSHLQ_S32(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHLQ_S64(Dd, Dm, Dn) EMIT(VSHLR_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_gen(D, imm6, Vd, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | (imm6)<<16 | (Vd)<<12 | 1<<11 | (M)<<5 | 1<<4 | (Vm))
#define VSHRN_16(Dd, Dm, imm3) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b001<<3 | (8-(imm3)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_32(Dd, Dm, imm4) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b01<<4 | (16-(imm4)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VSHRN_64(Dd, Dm, imm5) EMIT(VSHRN_gen(((Dd)>>4)&1, 0b1<<5 | (32-(imm5)), (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define VTRN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b10<<16 | (Vd)<<12 | 0b0000<<8 | 1<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VTRN_32(Dd, Dm) EMIT(VTRN_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -766,6 +944,8 @@ Op is 20-27
#define VCVTn_S32_F32(Dd, Dm) EMIT(VCVT_NEON_gen(((Dd)>>4)&1, 2, (Dd)&15, 0b10, 0, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_NEON_gen(U, D, size, Vn, Vd, op, N, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 1<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b11<<10 | (op)<<9 | (N)<<7 | (M)<<5 | (Vm))
#define VMULL_S16_S8(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_U16_U8(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_S32_S16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_U32_U16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_S64_S32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
@@ -778,8 +958,8 @@ Op is 20-27
#define VMUL_16(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXT_gen(D, Vn, Vd, imm4, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (Vn)<<16 | (Vd)<<12 | (imm4)<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, imm4, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, imm4, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VEXT_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VEXTQ_8(Dd, Dn, Dm, imm4) EMIT(VEXT_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, (imm4)&0xf, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMVN_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b1011<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#define VMVNQ(Dd, Dm) EMIT(VMVN_gen(((Dd)>>4)&1, 0, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -809,6 +989,10 @@ Op is 20-27
#define VTBL1_8(Dd, Dn, Dm) EMIT(VTBL_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, 0b00, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
// Vector Table lookup, take elements from Dn/Dn+1, and using lookup table Dm, put elements in Dd
#define VTBL2_8(Dd, Dn, Dm) EMIT(VTBL_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, 0b01, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
// Vector Table lookup eXtension, take elements from Dn, and using lookup table Dm, put elements in Dd, outer element untouched
#define VTBLX1_8(Dd, Dn, Dm) EMIT(VTBL_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, 0b00, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
// Vector Table lookup eXtension, take elements from Dn/Dn+1, and using lookup table Dm, put elements in Dd, outer element untouched
#define VTBLX2_8(Dd, Dn, Dm) EMIT(VTBL_gen(((Dd)>>4)&1, (Dn)&15, (Dd)&15, 0b01, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRECPE_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b11<<16 | (Vd)<<12 | 0b010<<9 | (F)<<8 | (Q)<<6 | (M)<<5 | (Vm))
// Vector Reciprocal Estimate of Dm to Dd
@@ -818,11 +1002,20 @@ Op is 20-27
// Vector Reciprocal Step of Dn and Dm to Dd
#define VRECPSQ_F32(Dd, Dn, Dm) EMIT(VRECPS_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSWAP_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<20 | (size)<<18 | 0b10<<16 | (Vd)<<12 | 0b0000<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VRSQRTE_gen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b11<<16 | (Vd)<<12 | 0b010<<9 | (F)<<8 | 1<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Vector Reciprocal Square Root Estimate of Dm to Dd
#define VRSQRTEQ_F32(Dd, Dm) EMIT(VRSQRTE_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRSQRTS_gen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | 1<<21 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1111<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
// Vector Reciprocal Square Root Step of Dn and Dm to Dd
#define VRSQRTSQ_F32(Dd, Dn, Dm) EMIT(VRSQRTS_gen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VSWP_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b10<<16 | (Vd)<<12 | 0b0000<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Swap Double vectors content
#define VSWAP(Dd, Dm) EMIT(VSWAP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15)))
#define VSWP(Dd, Dm) EMIT(VSWP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
// Swap Quad vectors content
#define VSWAPQ(Dd, Dm) EMIT(VSWAP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15)))
#define VSWPQ(Dd, Dm) EMIT(VSWP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VQADD_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0000<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
// Add with saturation unsigned 8bits
@@ -903,4 +1096,145 @@ Op is 20-27
#define VNEGN_F32(Dd, Dm) EMIT(VNEGN_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VNEGNQ_F32(Dd, Dm) EMIT(VNEGN_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMINMAXF_gen(D, op, sz, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | (D)<<22 | (op)<<21 | (sz)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1111<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VMINQ_F32(Dd, Dn, Dm) EMIT(VMINMAXF_gen(((Dd)>>4)&1, 1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VMAXQ_F32(Dd, Dn, Dm) EMIT(VMINMAXF_gen(((Dd)>>4)&1, 0, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABD_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 1<<25 | (U)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0111<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Compute absolute difference of U8
#define VABD_U8(Dd, Dn, Dm) EMIT(VABD_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VABDQ_U8(Dd, Dn, Dm) EMIT(VABD_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VPADAL_gen(D, size, Vd, op, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<8 | (op)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Add pair of U8 from Dm, Add result in U16 in Dd (some position as U8U8)
#define VPADAL_U8(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U16 from Dm, Add result in U32 in Dd
#define VPADAL_U16(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U32 from Dm, Add result in U64 in Dd
#define VPADAL_U32(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S8 from Dm, Add result in S16 in Dd (some position as S8S8)
#define VPADAL_S8(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S16 from Dm, Add result in S32 in Dd
#define VPADAL_S16(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S32 from Dm, Add result in S64 in Dd
#define VPADAL_S32(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U8 from Dm, Add result in U16 in Dd (some position as U8U8)
#define VPADALQ_U8(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U16 from Dm, Add result in U32 in Dd
#define VPADALQ_U16(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U32 from Dm, Add result in U64 in Dd
#define VPADALQ_U32(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S8 from Dm, Add result in S16 in Dd (some position as S8S8)
#define VPADALQ_S8(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S16 from Dm, Add result in S32 in Dd
#define VPADALQ_S16(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S32 from Dm, Add result in S64 in Dd
#define VPADALQ_S32(Dd, Dm) EMIT(VPADAL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VPADDL_gen(D, size, Vd, op, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0010<<8 | (op)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Add pair of U8, store result in U16
#define VPADDL_U8(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U16, store result in U32
#define VPADDL_U16(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U32, store result in U64
#define VPADDL_U32(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S8, store result in S16
#define VPADDL_S8(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S16, store result in S32
#define VPADDL_S16(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S32, store result in S64
#define VPADDL_S32(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U8, store result in U16
#define VPADDLQ_U8(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U16, store result in U32
#define VPADDLQ_U16(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of U32, store result in U64
#define VPADDLQ_U32(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S8, store result in S16
#define VPADDLQ_S8(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S16, store result in S32
#define VPADDLQ_S16(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
// Add pair of S32, store result in S64
#define VPADDLQ_S32(Dd, Dm) EMIT(VPADDL_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VPADD_gen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VPADD_8(Dd, Dn, Dm) EMIT(VPADD_gen(((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VPADD_16(Dd, Dn, Dm) EMIT(VPADD_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VPADD_32(Dd, Dn, Dm) EMIT(VPADD_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
// NO VPADDQ....
#define VPADD_Fgen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1101<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
// Add pair of F32, store result in F32
#define VPADD_F32(Dd, Dn, Dm) EMIT(VPADD_Fgen(((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VMINMAX_gen(U, D, size, Vn, Vd, N, Q, M, op, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b110<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (op)<<4 | (Vm))
#define VMIN_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_U16(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_U32(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_U64(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_S8(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_S16(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_S32(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMIN_S64(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_U16(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_U32(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_U64(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_S8(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_S16(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_S32(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMINQ_S64(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 1, (Dm)&15))
#define VMAX_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_U16(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_U32(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_U64(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_S8(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_S16(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_S32(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAX_S64(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_U8(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_U16(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_U32(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_U64(Dd, Dn, Dm) EMIT(VMINMAX_gen(1, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_S8(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_S16(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_S32(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VMAXQ_S64(Dd, Dn, Dm) EMIT(VMINMAX_gen(0, ((Dd)>>4)&1, 0b11, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, 0, (Dm)&15))
#define VRHADD_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 1<<25 | (U)<<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0001<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= (Dn + Dm + 1)>>1
#define VRHADD_U8(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADD_U16(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADD_U32(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADD_S8(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADD_S16(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADD_S32(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_U8(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_U16(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_U32(Dd, Dn, Dm) EMIT(VRHADD_gen(1, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_S8(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b00, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_S16(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VRHADDQ_S32(Dd, Dn, Dm) EMIT(VRHADD_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULH_gen(D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0011 <<24 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= (2*Dn*Dm + 1<<(size-1))>>size
#define VQRDMULH_S16(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b01, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VQRDMULH_S32(Dd, Dn, Dm) EMIT(VQRDMULH_gen(((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#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__
+10 -1
View File
@@ -10,7 +10,16 @@
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}
//end, return...
//bx lr
.global arm_epilog_fast
arm_epilog_fast:
//restore all used register
//vpop {d8-d15}
pop {r4-r11, pc}
+594
View File
@@ -0,0 +1,594 @@
; TYPE fields separated by spaces Assembler syntax
; When there are mutiple assembler syntax (like for LDR (immediate)), separate them based on the bytes
; E.G. for LDR (immediate), there are 3 lines with the 3 different asm syntaxes
# Field options:
# --------------
# Syntax: ... field/coption1(coption2)* ... (inside fields)
# Where each c correspond to the option character
# and optionN to the Nth option value
# ---
# c = '0'..'9'/'A'..'F': option=[01]
# Force the cth bit (hex) of the field (starting from LSB) to be <option>
# c = '=': option=[01x]{field_len}
# Force the field to have the given bits (where x = anything, starts from MSB)
# Post-fields option:
# -------------------
# Syntax: [fields] @ typeoption1 args1 typeoption2 args2 @ [Assembler syntax]
# ---
# typeoption contains '=' (l=r): args1=((.*) )?([^, ]*),([^, ]*),([^, ]*)@
# Changes a value between two other depending on whether l == r
# \2 is init (suffixed by ';', optional), \3 is set to \4 if true or \5 if false
# (cf VMOV/VORR aka V\op\, VEOR/VBIF/VBIT/VBSL aka V\op\)
# The 'true regex' is typeoption=([^= ]*)(=([^= ]*))+
# args1=((.*) )?([^, ]*),(([^, ]*),)+([^, ]*)@
# with the number of typeoption:\2 being equal to the number of args1:\4
# <a>=<b>[=<c>...] <initialization> <variable-changed>,<changed-into-if-a=b>[,<changed-into-if-a=c>...],<changed-into-else>@
# OR
# typeoption is discarded and must be set to '=', args1=((.*) )?(@@ (( ?.*[^@])*)@ )+([^, ]*),(([^, ]*),)+([^, ]*)
# \2 is init (suffixed by ';', optional), \6 is set to \7 if true or \8 if false
# The difference with the simple switch is that \4 is the test (inside the `if`)
# If there are multiple @@s, there are multiple `if`s (separated by `else`s)
# The 'true regex' is [DISCARDED]typeoption==
# args1=((.*) )?(@@ (( ?.*[^@])*)@ )+([^, ]*),([^, ]*),([^, ]*)
# <.>=<.>[=<c>...] <initialization> @@ <test>@[ @@ <test2>@...] <variable-changed>,<changed-into-if-a=b>,<changed-into-else>
# OR
# args1=((.*) )?!@(( [^%]*[^%@])*)%(( ?[^%]*[^%@])*)@(( .*[^@])*)@(( .*[^@])*)@
# Replaced by '\1; if (<equality>) { \3\7\5; } else { \3\9\5; }'
# Meaning, <.=.> <initialization> !@ <common-left-part>%<common-right-part>@ <substitute-true>@ <substitute-false>@ <...>
# (cf VMOV/VORR, aka V\op\ with the lastop variable)
# You can also add more '=' with corresponding substitutes.
# You can also add more '%' with corresponding substitutes.
# ----
# Inside the assembler syntax, you can add \var\ to mark a variable to be replaced
# (Meaning, %s and `var` as argument to printf)
# Full syntax: \\(%[0-9+]*.)?(.*)\\
# If \1 != "", add \1 to the string in printf, and in any case append \2 as argument to printf
! HACKS: (list of notable differences between the doc and this file)
! ------
! In theory, (0) and (1) bits are as important as 0 and 1:
! > An instruction is UNPREDICTABLE if:
! > • It is declared as UNPREDICTABLE in an instruction description or in this chapter.
! > • The pseudocode for that encoding does not indicate that a different special case applies, and a bit marked (0)
! or (1) in the encoding diagram of an instruction is not 0 or 1 respectively.
! - ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
! In practice, they are ignored here.
! SWP, SWPB, VMOV (VFPU): Rt2 (field and assembly) -> Rn (field and assembly)
! BKPT: must be AL, so cond (field) -> cond/=1110 (constrained field)
! PKHBT and PKHTB: {, LSL/ASR #<imm>} (assembly) -> {, <shift>} (assembly)
! PKHBT and PKHTB: immediate shift but shift & 1 -> ARMs (type)
! All NEON operations (advanced SIMD): limited, so multiply the lines
! VMOV (register): Vm ... Vm VMOV (field, assembly) -> Vn ... Vm @ m=n ...@ @ V\op\ (field, switchable var, assembly)
! VMOV is VORR constrained -> (removed VORR)
! VEOR, VBSL, VBIT, VBIF differ only depending on 2 bits: 0/1 0/1 ... VEOR -> @<2> ... @ ... @ V\op\ (field, switchable var, assembly)
! Three registers of different lengths (when having L and W variants): op (field) -> Q (field)
; ========== BEGINNING OF REGISTERED INSTRUCTIONS =========
# This instruction changes the instruction set to Thumb! Disabled (but valid)
#ARM_ 1 1 1 1 1 0 1 @<1> imm24 @ set imm24 = (imm24 << 2) + (param << 1)@ @ BLX <label>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 0 Vn Vd 0 0 0 1 N Q M 1 Vm VAND<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 1 Vn Vd 0 0 0 1 N Q M 1 Vm VBIC<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 0 Vn Vd 0 0 0 1 N Q M 1 Vm @ m=n const char* op op,"MOV","ORR"@ m=n char lastop[6] !@ %@ lastop[0] = '\0'@ sprintf(lastop, ", %s", vecname[(q << 5) + 0x20 + n])@ @ V\op\<c> <Qd>, <Qm>\lastop\
NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 op 0 D size Vn Vd 1 0 0 0 N Q M 0 Vm @ op=0 const char* opname opname,"ADD","SUB"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VTST<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VCEQ<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 0 Vm @ set size = 8 << size@ @ VML\(u ? "S" : "A")\<c>.I\%dsize\ <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 1 Vm VMUL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQRDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q/=0 M 1 Vm VPADD<c>.<dt> <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 0 N Q M 1 Vm @ u=0 const char* y y,"A","S"@ @ VFM\y\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm @ u=0 const char* op op,"ADD","SUB"@ @ V\op\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q/=0 M 0 Vm VPADD.F32 <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 1 0 D 1 sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm VABD.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VML\(op ? "S" : "A")\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VMUL.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm VCEQ.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm @ op=1 const char* strict strict,"T","E"@ @ VCG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 1 Vm @ op=1 const char* strict strict,"T","E"@ @ VACG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRECPS.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRSQRTS.F32 <Qd>, <Qn>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 <1> 0 <23>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=11xx 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=1 1 imm4 VBIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
;INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <3> <4> <4>/=1111 0 <1> <1>/=1 1 <4>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
# Special case for VMOVL (harder to do it on the documented place)
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 1 L Q M 1 Vm VRSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 1 0 1 0 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #<imm>
; VCVT: if imm6 IN "0xxxxx" then UNDEFINED;
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 <9> 1 1 1 <1> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.S32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.S32.F32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.U32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.U32.F32 <Qd>, <Qm>, #<fbits>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <18> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 1 1 Vn Vd IMM4 N Q M 0 Vm VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
# size + param < 3
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=11 0 0 <4> 0 0 0 <2> <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 0 Q M 0 Vm VCNT<c>.8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 1 Q M 0 Vm VMVN<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 0 U Q M 0 Vm VPADAL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 0 Q M 0 Vm VQABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 1 Q M 0 Vm VQNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 0 Q M 0 Vm VCGT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 1 Q M 0 Vm VCGE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 0 Q M 0 Vm VCEQ<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 1 Q M 0 Vm VCLE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 0 0 Q M 0 Vm VCLT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 0 Q M 0 Vm VABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 1 Q M 0 Vm VNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 1 0 Vd 0 0 0 0 0 Q M 0 Vm VSWP<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 0 1 Q M 0 Vm VTRN<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 0 Q M 0 Vm VRECPE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 1 Q M 0 Vm VRSQRTE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 0 Q M 0 Vm VCVT<c>.F32.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 1 Q M 0 Vm VCVT<c>.S32.F32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 0 Q M 0 Vm VCVT<c>.F32.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 1 Q M 0 Vm VCVT<c>.U32.F32 <Qd>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <8> 0 <6> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 Vn Vd 1 0 @<2> N op M 0 Vm @ param=0b00 char list[10] !@ sprintf(list, %)@ "{%s}", vecname[0x20 + n]@ "{%s-%s}", vecname[0x20 + n], vecname[0x20 + n + param]@ @ VTB\(op ? "X" : "L")\<c>.8 <Dd>, \list\, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 imm4 Vd 1 1 0 0 0 Q M 0 Vm VDUP<c>.\%dsize\ <Qd>, <Dm[x]>
; size != 11
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 1 1 <13> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 0 Q N 0 M 0 Vm VADD\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 1 Q N 0 M 0 Vm VSUB\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm @ set size = 16 << size@ @ VADDHN<c>.I\%dsize\ <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm VRADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 0 1 N 0 M 0 Vm VABAL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VRSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 1 1 N 0 M 0 Vm VABDL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 op 0 N 0 M 0 Vm VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 op 1 N 0 M 0 Vm VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 1 0 0 N 0 M 0 Vm VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 1 0 1 N 0 M 0 Vm VQDMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U/=0 1 D size/=00 Vn Vd 1 1 1 0 N 0 M 0 Vm @ set uint8_t size = 0@ @ VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
; Put after, otherwise some instructions are shadowed
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 0 op 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 op 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 op 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 0 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMUL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 0 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 0 0 <20>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 0 <1> 1 0 <22>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
;INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <20>
;INVALIDATE 1 1 1 1 0 1 0 0 <2> 1 0 <20>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
; ===== No more 1 1 1 1 ..., so invalidate all of them ====
INVALIDATE 1 1 1 1 <28>
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 0 1 S Rn Rd imm5 type 0 Rm EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 1 S Rd Ra Rm 1 0 0 1 Rn MLA{S}<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 0 1 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 1 0 S Rn Rd imm5 type 0 Rm SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 0 0 RdHi RdLo Rm 1 0 0 1 Rn UMAAL<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 0 1 1 S Rn Rd imm5 type 0 Rm RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 1 0 Rd Ra Rm 1 0 0 1 Rn MLS<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 1 1 0 Rn Rt imm4H 1 0 1 1 imm4L STRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 0 1 1 imm4L LDRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSBT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 1 0 0 S Rn Rd imm5 type 0 Rm ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 0 S RdHi RdLo Rm 1 0 0 1 Rn UMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 0 1 S Rn Rd imm5 type 0 Rm ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 1 S RdHi RdLo Rm 1 0 0 1 Rn UMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 0 S Rn Rd imm5 type 0 Rm SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 0 S RdHi RdLo Rm 1 0 0 1 Rn SMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 1 S Rn Rd imm5 type 0 Rm RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 1 S RdHi RdLo Rm 1 0 0 1 Rn SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 0 0 Rn SMLABB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 1 0 Rn SMLATB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 0 0 Rn SMLABT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 1 0 Rn SMLATT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWP<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
ARM_ cond/=1110 0 0 0 1 0 0 1 0 imm12 0 1 1 1 imm4 BKPT #<imm16>
ARMS cond 0 0 0 1 0 0 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TEQ<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 0 1 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWPB<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 0 1 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMP<c> <Rn>, <Rm>{, <shift>}
ARMS cond 0 0 0 1 0 1 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMN<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 1 0 0 S Rn Rd imm5 type 0 Rm ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 0 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREX<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREX<c> <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 0 0 0 Rm MOV{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 0 0 Rm LSL{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 0 1 Rn LSL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 1 0 Rm LSR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 1 1 Rn LSR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 0 0 Rm ASR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 0 1 Rn ASR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 1 1 0 Rm RRX{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 1 0 Rm ROR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 1 1 Rn ROR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXD<c> <Rd>, <Rt>, <Rt2>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXD<c> <Rt>, <Rt2>, [<Rn>]
ARMS cond 0 0 0 1 1 1 0 S Rn Rd imm5 type 0 Rm BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXB<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXB<c> <Rt>, [<Rn>]
ARMS cond 0 0 0 1 1 1 1 S (0) (0) (0) (0) Rd imm5 type 0 Rm MVN{S}<c> <Rd>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 1 1 Rn (0) (0) (0) (0) imm12 CMN<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 0 S Rn Rd imm12 ORR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 1 S (0) (0) (0) (0) Rd imm12 MOV{S}<c> <Rd>, #<const>
ARM_ cond 0 0 1 1 1 1 0 S Rn Rd imm12 BIC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 1 1 S (0) (0) (0) (0) Rd imm12 MVN{S}<c> <Rd>, #<const>
ARM_ cond 0 1 0 0 1 0 0 1 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 POP<c> {<Rt>}
ARM_ cond 0 1 0 0 U 0 0 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 0 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 0 Rn Rt imm12 STRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 1 Rn Rt imm12 LDRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 0 Rn Rt imm12 STRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 1 Rn Rt imm12 LDRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 1 0 0 1 0 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 PUSH<c> {<Rt>}
ARM_ cond 0 1 0 1 U 0 W 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 0 W 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm SSAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm SSUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm SSUB8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm USAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm USUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm USUB8<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 0 0 1 Rm PKHBT<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 1 0 1 Rm PKHTB<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 1 1 0 1 0 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 0 1 sat_imm Rd imm5 sh 0 1 Rn SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 0 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn SSAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 0 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 0 0 1 1 Rm REV<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REV16<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 1 1 sat_imm Rd imm5 sh 0 1 Rn USAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 1 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn USAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 1 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REVSH<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 1 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 U 0 0 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 0 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 0 Rn Rt imm5 type 0 Rm STRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 1 Rn Rt imm5 type 0 Rm LDRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARM_ cond 0 1 1 1 1 0 0 0 Rd 1 1 1 1 Rm 0 0 0 1 Rn USAD8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn register_list LDMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn/=1101 register_list STMEA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn register_list STM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 0 1 Rn/=1101 register_list LDMEA<c> <Rn>, <registers>
ARM_ cond 1 0 0 0 1 0 1 1 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"POP","LDMEA"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 0 1 0 W 1 Rn register_list LDM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 0 0 Rn/=1101 register_list STMFD<c> <Rn>, <registers>
ARM_ cond 1 0 0 1 0 0 1 0 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"PUSH","STMFD"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 1 0 0 W 0 Rn register_list STMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn/=1101 register_list LDMFD<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn register_list LDMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn/=1101 register_list STMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn register_list STMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn/=1101 register_list LDMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn register_list LDMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 1 0 imm24 B<c> <label>
ARM_ cond 1 0 1 1 imm24 BL<c> <label>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Sm>, <Sm1>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Sm>, <Sm1>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Dm>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Dm>
;INVALIDATE <4> 1 1 0 0 0 1 0 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
INVALIDATE <4> 1 1 1 0 0 0 <1> 0 <8> 1 0 1 1 <1> 1 0 1 (0) (0) (0) (0)
;INVALIDATE <4> 1 1 1 0 1 <2> 0 <8> 1 0 1 1 <1> 0 <1> 1 (0) (0) (0) (0)
VFPU cond 1 1 1 0 0 0 0 0 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Sn>, <Rt>
VFPU cond 1 1 1 0 1 1 1 0 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMSR<c> FPSCR, <Rt>
VFPU cond 1 1 1 0 0 @<2> 0 Vd Rt 1 0 1 1 D @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (param1_2 << 2) + param2_2@ = uint8_t shift @@ (opc & 0b1000) == 0b1000@ @@ (opc & 0b1001) == 0b0001@ @@ (opc & 0b1011) == 0b0000@ shift,0,1,2,0xFF@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.\%d8 &l&l shift\ <Dd[x]>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 1 M 0 Vm VNMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 0 M 0 Vm VADD<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 1 M 0 Vm VSUB<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VDIV<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VFNM\(op ? "A" : "S")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 0 Vn Vd 1 0 1 sz N op M 0 Vm VFM\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
!/VFPU cond 1 1 1 0 1 x 1 1 opc2 <4> 1 0 1 <1> - - <1> 0 opc4 Table A7-17
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 0 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set float mantissa = 16 + param2_4@ set float imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F32 <Sd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 1 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set double mantissa = 16 + param2_4@ set double imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F64 <Dd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 0 1 M 0 Vm VMOV<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 1 1 M 0 Vm VABS<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 0 1 M 0 Vm VNEG<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 1 1 M 0 Vm VSQRT<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 0 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F32.F16 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 1 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F16.F32 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 1 Vd 1 0 1 sz op 1 (0) 0 (0) (0) (0) (0) VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, #0.0
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
;INVALIDATE <4> 1 1 1 0 1 <1> 1 1 <8> 1 0 1 <4> 0 <4>
;INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 0 <4>
; ============= END OF REGISTERED INSTRUCTIONS ============
INVALIDATE <32>
+19 -4
View File
@@ -7,18 +7,33 @@
.align 4
.extern UpdateLinkTable
.extern LinkNext
.global arm_linker
arm_linker:
// emu is r0
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
+89
View File
@@ -0,0 +1,89 @@
//arm lock helper
//there is 2 part: read and write
// write return 0 on success, 1 on fail (value has been changed)
.text
.align 4
.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
ldrexb r0, [r0]
bx lr
arm_lock_write_b:
// address is r0, value is r1, return is r0
mov r2, r0
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
ldrex r0, [r0]
bx lr
arm_lock_write_d:
// address is r0, value is r1, return is r0
// r0 needs to be aligned
mov r2, r0
strex r0, r1, [r2]
bx lr
arm_lock_read_dd:
// address is r2, return is r0, r1
ldrexd r2, r3, [r2]
str r2, [r0]
str r3, [r1]
bx lr
arm_lock_write_dd:
// address is r2, value is r0, r1, return is r0
// r0 needs to be aligned
strexd r3, r0, r1, [r2]
mov r0, r3
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
+31
View File
@@ -0,0 +1,31 @@
#ifndef __ARM_LOCK_HELPER__H__
#define __ARM_LOCK_HELPER__H__
#include <stdint.h>
// LDREXB of ADDR
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
extern int arm_lock_write_d(void* addr, uint32_t val);
// LDREXD of ADDR
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__
Executable → Regular
+5048 -886
View File
File diff suppressed because it is too large. Load diff
+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
+392 -108
View File
@@ -3,7 +3,6 @@
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
@@ -17,163 +16,448 @@
#include "x86trace.h"
#include "dynablock.h"
#include "dynablock_private.h"
#include "dynarec_private.h"
#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*)
dynablocklist_t* NewDynablockList(uintptr_t base, uintptr_t text, int textsz)
uint32_t X31_hash_code(void* addr, int len)
{
if(!len) return 0;
uint8_t* p = (uint8_t*)addr;
int32_t h = *p;
for (--len, ++p; len; --len, ++p) h = (h << 5) - h + (int32_t)*p;
return (uint32_t)h;
}
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 = kh_init(dynablocks);
ret->base = base;
ret->text = text;
ret->textsz = textsz;
pthread_rwlock_init(&ret->rwlock_blocks, NULL);
ret->nolinker = nolinker;
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);}
}
return ret;
}
void FreeDynablock(dynablock_t* db)
{
if(db) {
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;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x86_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
}
free(db->sons);
free(db->table);
free(db->instsize);
free(db);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_INFO, "Free %d Blocks from Dynablocklist (with %d buckets)%s\n", kh_size((*dynablocks)->blocks), kh_n_buckets((*dynablocks)->blocks), ((*dynablocks)->direct)?" With Direct mapping enabled":"");
dynablock_t* db;
kh_foreach_value((*dynablocks)->blocks, db,
free(db->table);
free(db);
);
kh_destroy(dynablocks, (*dynablocks)->blocks);
if((*dynablocks)->direct)
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)
FreeDynablock((*dynablocks)->direct[i]);
}
free((*dynablocks)->direct);
(*dynablocks)->direct = 0;
pthread_rwlock_destroy(&(*dynablocks)->rwlock_blocks);
}
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
}
void ConvertHash2Direct(dynablocklist_t* dynablocks)
void MarkDynablock(dynablock_t* db)
{
if(dynablocks->textsz==0 || dynablocks->text==0)
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;
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->nolinker)
db->need_test = 1; // test only blocks that can be marked (and so deleted)
}
}
void ProtectDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
return; // protect only father, child(ren) will be automatically
protectDB((uintptr_t)db->x86_addr, db->x86_size);
}
}
void MarkDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
if(!(*dynablocks)->nolinker)
return;
dynarec_log(LOG_DEBUG, "Marked Blocks from Dynablocklist nolinker=%d %p:0x%x\n", (*dynablocks)->nolinker, (void*)(*dynablocks)->text, (*dynablocks)->textsz);
dynablock_t* db;
uintptr_t key;
uintptr_t start = dynablocks->text-dynablocks->base;
uintptr_t end = dynablocks->text + dynablocks->textsz-dynablocks->base;
kh_foreach(dynablocks->blocks, key, db,
if(key>=start && key<end)
direct[key-start] = db;
else {
k = kh_put(dynablocks, blocks, key, &ret);
if(ret) { // don't try to insert if already done...
kh_value(blocks, k) = db;
}
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
db = (*dynablocks)->direct[i];
if(db)
MarkDynablock(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 = blocks;
dynablocks->direct = direct;
}
}
void ProtectDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
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)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
db = (*dynablocks)->direct[i];
if(db)
ProtectDynablock(db);
}
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz-1;
return 0;
}
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
{
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 || !dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
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((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)
{
if(!dynablocks)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
protectDB(start, end-start); //no +1; as end/enddb is exclusive and not inclusive
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct) {
dynablock_t* db;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
);
kh_destroy(dynablocks, blocks);
}
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(!dynablocks->nolinker)
return;
if(dynablocks->direct) {
MarkDirectDynablock(dynablocks, addr, size);
// 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, kh_dynablocks_t* dynablocks)
{
if(!dynablocks)
return NULL;
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;
}
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
{
const int idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if (!*created)
return block;
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);
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;
}
#define MAGIC_SIZE 256
/*
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
dynablock_t* DBGetBlock(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(dynablocks->direct && addr>=dynablocks->text && addr<=dynablocks->text+dynablocks->textsz) {
block = dynablocks->direct[addr-dynablocks->text];
if(block)
return block;
}
if(!(addr>=dynablocks->text && addr<=dynablocks->text+dynablocks->textsz))
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
}
// nope, lets do the long way
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;
// nope, put rwlock in read mode and check hash
pthread_rwlock_rdlock(&dynablocks->rwlock_blocks);
// but first, check again just in case it has been created while waiting for mutex
if(dynablocks->direct && addr>=dynablocks->text && addr<=dynablocks->text+dynablocks->textsz)
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
return block;
}
// check if the block exist
int ret;
khint_t k = kh_get(dynablocks, dynablocks->blocks, addr-dynablocks->base);
if(k!=kh_end(dynablocks->blocks)) {
/*atomic_store(&dynalock, 0);*/
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
return block;
}
// unlock now
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
// Blocks doesn't exist. If creation is not allow, just return NULL
if(!create)
return block;
// Lock as write now!
pthread_rwlock_wrlock(&dynablocks->rwlock_blocks);
// create and add new block
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block creation @%p\n", 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 {
k = kh_put(dynablocks, dynablocks->blocks, addr-dynablocks->base, &ret);
if(!ret) {
// Ooops, block is already there? retreive it and bail out
block = kh_value(dynablocks->blocks, k);
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
return block;
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
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 && kh_size(dynablocks->blocks)==MAGIC_SIZE)
ConvertHash2Direct(dynablocks);
}
block->parent = dynablocks;
// create an empty block first, so if other thread want to execute the same block, they can, but using interpretor path
pthread_rwlock_unlock(&dynablocks->rwlock_blocks);
// check direct first, without lock
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
int created = create;
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
FillBlock(emu, block, addr);
dynarec_log(LOG_DEBUG, " --- DynaRec Block created @%p (%p, 0x%x bytes)\n", addr, block->block, block->size);
block->x86_addr = (void*)addr;
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;
}
}
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, 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) 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, addr, create, *current);
} else {
father->need_test = 0;
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;
}
+26 -13
View File
@@ -1,26 +1,39 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct instsize_s {
unsigned int x86:4;
unsigned int nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t *parent;
void* block;
int size;
uintptr_t* table;
int tablesz;
int done;
dynablocklist_t* parent;
void* block;
int size;
void* x86_addr;
uintptr_t x86_size;
uint32_t hash;
uintptr_t* table;
int tablesz;
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
instsize_t* instsize;
} dynablock_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
typedef struct dynablocklist_s {
kh_dynablocks_t *blocks;
pthread_rwlock_t rwlock_blocks;
uintptr_t base;
uintptr_t text;
int textsz;
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_
+135 -45
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <setjmp.h>
#include "debug.h"
#include "box86context.h"
@@ -14,69 +15,117 @@
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "threads.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynablock_private.h"
#endif
#ifdef ARM
void arm_prolog(x86emu_t* emu, void* addr);
void arm_epilog();
void arm_linker();
int arm_tableupdate(void* jump, uintptr_t addr, void** table);
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
void arm_epilog() EXPORTDYN;
void arm_epilog_fast() EXPORTDYN;
void arm_linker() EXPORTDYN;
int arm_tableupdate(void* jump, uintptr_t addr, void** table) EXPORTDYN;
#endif
void tableupdate(void* jumpto, uintptr_t ref, void** table)
{
#ifdef ARM
if(arm_tableupdate(jumpto, ref, table))
#endif
{
table[0] = jumpto;
table[1] = (void*)ref;
}
}
void resettable(void** table)
{
void* p = table[1];
#ifdef ARM
tableupdate(arm_linker, (uintptr_t)p, table);
#endif
//table[2] = own_dynablock // unchanged
table[3] = NULL; // removed "linked" information
}
#ifdef DYNAREC
void* UpdateLinkTable(x86emu_t* emu, void** table, uintptr_t addr)
{
dynablock_t* block = DBGetBlock(emu, addr, 1, NULL); // keep a copy of parent block?
int r;
if(block==0) {
// no block, don't try again, ever
#ifdef ARM
r = arm_tableupdate(arm_epilog, addr, table);
if(r) dynarec_log(LOG_DEBUG, "Linker: failed to set table data @%p, for emu=%p\n", table, emu);
#else
table[0] = arm_epilog;
table[1] = addr;
#endif
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(!block) {
// no block, let link table as is...
//tableupdate(arm_epilog, addr, table);
return arm_epilog_fast;
}
if(!block->done) {
// not finished yet... leave linker
//tableupdate(arm_linker, addr, table);
return arm_epilog_fast;
}
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) {
//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
tableupdate(jblock, addr, table);
}
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
#ifdef ARM
r = arm_tableupdate(arm_linker, addr, table);
if(r) dynarec_log(LOG_DEBUG, "Linker: failed to set table data @%p, for emu=%p\n", table, emu);
#else
table[0] = arm_linker;
table[1] = addr;
#endif
//tableupdate(arm_linker, addr, table);
return arm_epilog;
}
if(!block->block) {
// null block, but done, go to epilog
#ifdef ARM
r = arm_tableupdate(arm_epilog, addr, table);
if(r) dynarec_log(LOG_DEBUG, "Linker: failed to set table data @%p, for emu=%p\n", table, emu);
#else
table[0] = arm_epilog;
table[1] = addr;
#endif
if(!(jblock=block->block)) {
// null block, but done: go to epilog, no linker here
return arm_epilog;
}
#ifdef ARM
r = arm_tableupdate(block->block, addr, table);
if(r) dynarec_log(LOG_DEBUG, "Linker: failed to set table data @%p, for emu=%p\n", table, emu);
#else
table[0] = block->block;
table[1] = addr;
#endif
return block->block;
//dynablock_t *father = block->father?block->father:block;
return jblock;
}
#endif
void DynaCall(x86emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
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
if(!box86_dynarec)
#endif
@@ -93,15 +142,17 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
R_EIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, block);
block = DBGetBlock(emu, R_EIP, 1, &current);
current = (block && !block->parent->nolinker)?block:NULL;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "Calling Interpretor @%p, emu=%p\n", R_EIP, emu);
dynarec_log(LOG_DEBUG, "Calling Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "Calling DynaRec Block @%p (%p) emu=%p\n", R_EIP, block->block, emu);
dynarec_log(LOG_DEBUG, "Calling DynaRec Block @%p (%p) of %d x86 instructions (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize ,block->parent->nolinker, block->father, emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
@@ -113,6 +164,16 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(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;
}
}
}
}
emu->quit = 0; // reset Quit flags...
@@ -129,10 +190,26 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
}
}
#endif
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
}
int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 1;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
@@ -140,15 +217,17 @@ int DynaRun(x86emu_t* emu)
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, block);
block = DBGetBlock(emu, R_EIP, 1, &current);
current = (block && !block->parent->nolinker)?block:NULL;
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "Running Interpretor @%p, emu=%p\n", R_EIP, emu);
dynarec_log(LOG_DEBUG, "Running Interpretor @%p, emu=%p\n", (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "Running DynaRec Block @%p (%p) emu=%p\n", R_EIP, block->block, emu);
dynarec_log(LOG_DEBUG, "Running DynaRec Block @%p (%p) of %d x86 insts (nolinker=%d, father=%p) emu=%p\n", (void*)R_EIP, block->block, block->isize, block->parent->nolinker, block->father, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
@@ -159,9 +238,20 @@ int DynaRun(x86emu_t* emu)
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
}
}
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
return 0;
#endif
}
+358 -25
View File
@@ -2,9 +2,11 @@
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "debug.h"
#include "box86context.h"
#include "custommem.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "tools/bridge_private.h"
@@ -18,27 +20,289 @@
#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) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uint32_t a = *(uint32_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%p: Exit x86emu\n", (void*)ip);
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%p: Native call to %p\n", (void*)ip, (void*)a);
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%p: %s\n", inst->addr, DecodeX86Trace(dec, inst->addr));
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[1m":"", ip, DecodeX86Trace(dec, inst->addr));
} else {
dynarec_log(LOG_NONE, "%p: ", inst->addr);
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[1m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
}
dynarec_log(LOG_NONE, " %s\n", name);
dynarec_log(LOG_NONE, " %s", name);
}
// print Call function name if possible
if(ip[0]==0xE8 || ip[0]==0xE9) { // Call / Jmp
uintptr_t nextaddr = (uintptr_t)ip + 5 + *((int32_t*)(ip+1));
printFunctionAddr(nextaddr, "=> ");
} else if(ip[0]==0xFF) {
if(ip[1]==0x25) {
uintptr_t nextaddr = (uintptr_t)ip + 6 + *((int32_t*)(ip+2));
printFunctionAddr(nextaddr, "=> ");
}
}
// end of line and colors
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
}
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
dyn->next[dyn->next_sz++] = addr;
}
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
// get closest, but no addresses befores
uintptr_t best = 0;
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
}
return best;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
if(!n)
return 1;
if(PK(0)==0x90)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
if(n>2 && PK(0)==0x8d && PK(1)==0x76 && PK(2)==0x00) // lea esi, [esi]
return is_nops(dyn, addr+3, n-3);
if(n>3 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x40 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>3 && PK(0)==0x8d && PK(1)==0x74 && PK(2)==0x26 && PK(3)==0x00)
return is_nops(dyn, addr+4, n-4);
if(n>4 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x44 && PK(3)==0x00 && PK(4)==0x00)
return is_nops(dyn, addr+5, n-5);
if(n>5 && PK(0)==0x8d && PK(1)==0xb6 && PK(2)==0x00 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00)
return is_nops(dyn, addr+6, n-6);
if(n>6 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x80 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00)
return is_nops(dyn, addr+7, n-7);
if(n>6 && PK(0)==0x8d && PK(1)==0xb4 && PK(2)==0x26 && PK(3)==0x00 && PK(4)==0x00 && PK(5)==0x00 && PK(6)==0x00) // lea esi, [esi+0]
return is_nops(dyn, addr+7, n-7);
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;
}
// 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)
{
if(recurse == 10)
return X_PEND;
if(ninst == dyn->size)
return X_PEND; // no more instructions, or too many jmp loop, stop
uint32_t needed = dyn->insts[ninst].x86.use_flags;
if(needed) {
setf &= ~needed;
if(!setf) // all flags already used, no need to continue
return needed;
}
if(!needed && !dyn->insts[ninst].x86.set_flags && !dyn->insts[ninst].x86.jmp_insts) {
int start = ninst;
int end = ninst;
while(end<dyn->size && !dyn->insts[end].x86.use_flags && !dyn->insts[end].x86.set_flags && !dyn->insts[end].x86.jmp_insts)
++end;
needed = needed_flags(dyn, end, setf, recurse);
for(int i=start; i<end; ++i)
dyn->insts[i].x86.need_flags = needed;
return needed;
}
if(dyn->insts[ninst].x86.set_flags && (dyn->insts[ninst].x86.state_flags!=SF_MAYSET)) {
if((setf & ~dyn->insts[ninst].x86.set_flags) == 0)
return needed; // all done, gives all the flags needed
setf |= dyn->insts[ninst].x86.set_flags; // add new flags to continue
}
int jinst = dyn->insts[ninst].x86.jmp_insts;
if(dyn->insts[ninst].x86.jmp) {
dyn->insts[ninst].x86.need_flags = (jinst==-1)?X_PEND:needed_flags(dyn, jinst, setf, recurse+1);
if(dyn->insts[ninst].x86.use_flags) // conditionnal jump
dyn->insts[ninst].x86.need_flags |= needed_flags(dyn, ninst+1, setf, recurse);
} else
dyn->insts[ninst].x86.need_flags = needed_flags(dyn, ninst+1, setf, recurse);
if(dyn->insts[ninst].x86.state_flags==SF_MAYSET)
needed |= dyn->insts[ninst].x86.need_flags;
else
needed |= (dyn->insts[ninst].x86.need_flags & ~dyn->insts[ninst].x86.set_flags);
if(needed == (X_PEND|X_ALL))
needed = X_ALL;
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);
@@ -46,15 +310,17 @@ 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(x86emu_t* emu, dynablock_t* block, uintptr_t addr) {
void* FillBlock(dynablock_t* block, uintptr_t addr) {
// init the helper
dynarec_arm_t helper = {0};
helper.emu = emu;
helper.nolinker = box86_dynarec_linker?(block->parent->nolinker):1;
helper.start = addr;
arm_pass0(&helper, addr);
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
return;
free(helper.next);
return (void*)block;
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
@@ -80,44 +346,111 @@ void FillBlock(x86emu_t* emu, dynablock_t* block, uintptr_t addr) {
helper.insts[i].x86.jmp_insts = k;
}
}
// remove useless flags calulation
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.flags==X86_FLAGS_CHANGE) {
int done = 0;
for(int i2=i+1; i2<helper.size+1 && done==0; ++i2) {
if(helper.insts[i2].x86.barrier || helper.insts[i2].x86.jmp)
done = 1;
else if(helper.insts[i2].x86.flags==X86_FLAGS_USE)
done = 1;
else if(helper.insts[i2].x86.flags==X86_FLAGS_CHANGE) {
done = 1;
helper.insts[i].x86.flags=X86_FLAGS_NONE;
}
}
if(helper.insts[i].x86.set_flags && !helper.insts[i].x86.need_flags) {
helper.insts[i].x86.need_flags = needed_flags(&helper, i+1, helper.insts[i].x86.set_flags, 0);
if((helper.insts[i].x86.need_flags&X_PEND) && (helper.insts[i].x86.state_flags==SF_MAYSET))
helper.insts[i].x86.need_flags = X_ALL;
}
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(emu->context, sz);
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);
return;
free(helper.next);
return NULL;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
helper.tablesz = helper.tablei;
if(helper.tablesz)
helper.table = (uintptr_t*)calloc(helper.tablesz, sizeof(uintptr_t));
if(helper.sons_size) {
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
}
// pass 3, emit (log emit arm opcode)
dynarec_log(LOG_DEBUG, "Emitting %d bytes for %d x86 bytes\n", helper.arm_size, helper.isize);
if(box86_dynarec_dump) {
dynarec_log(LOG_NONE, "%sEmitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
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);
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...
__builtin___clear_cache(p, p+helper.arm_size); // need to clear the cache before execution...
__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;
block->tablesz = helper.tablesz;
for (int i=0; i<helper.tablesz/4; ++i)
block->table[i*4+2] = (uintptr_t)block;
block->size = sz;
block->isize = helper.size;
block->block = p;
block->nolinker = helper.nolinker;
block->need_test = 0;
//block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
block->hash = (helper.nolinker)?X31_hash_code(block->x86_addr, block->x86_size):0;
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
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], &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];
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
free(sons);
}
free(helper.sons_x86);
free(helper.sons_arm);
block->done = 1;
return (void*)block;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+325
View File
@@ -0,0 +1,325 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
int fixedaddress;
MAYUSE(j32);
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
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, x14);
nextop = F8;
GETGD;
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, x14);
nextop = F8;
GETGD;
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, x14);
nextop = F8;
GETGD;
GETEDO(x14);
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x67:
// reduced EA size...
opcode = F8;
switch(opcode) {
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
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, x14, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x1, x14, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Ow");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
LDR_IMM9(xEAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV FS:Ow, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
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, x14, 0);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
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, x14, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ed");
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 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);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
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);
i32 = F32S;
if(i32>-4096 && i32<4096) {
STR_IMM9(xEAX, x1, i32);
} else {
MOV32(x2, i32);
STR_REG_LSL_IMM5(xEAX, x2, x1, 0);
}
break;
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
case 0xE9:
case 0xEB:
INST_NAME("(ignored) FS:");
--addr;
break;
case 0xFF:
nextop = F8;
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, x14, 0);
PUSH1(x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+175 -18
View File
@@ -25,53 +25,186 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t opcode = F8;
uint8_t nextop;
int32_t i32;
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t u8;
int fixedaddress;
MAYUSE(j32);
MAYUSE(wback);
MAYUSE(wb2);
switch(opcode) {
case 0x33:
grab_tlsdata(dyn, addr, ninst, x12);
INST_NAME("GS:XOR Gd, Ed");
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x12);
XOR_REG_LSL_IMM8(gd, gd, ed, 0);
UFLAG_RES(gd);
UFLAG_DF(1, d_xor32);
UFLAGS(0);
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, x14);
nextop = F8;
GETGD;
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, x14);
nextop = F8;
GETGD;
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, x14);
nextop = F8;
GETGD;
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:
grab_tlsdata(dyn, addr, ninst, x12);
INST_NAME("MOV GS:Ed, Gd");
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:
grab_tlsdata(dyn, addr, ninst, x12);
INST_NAME("MOV Gd, GS:Ed");
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, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
break;
case 0xA1:
grab_tlsdata(dyn, addr, ninst, x1);
INST_NAME("MOV EAX, GS:Id");
grab_tlsdata(dyn, addr, ninst, x1);
i32 = F32S;
if(i32>-4096 && i32<4096) {
LDR_IMM9(xEAX, x1, i32);
@@ -83,8 +216,8 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xA3:
grab_tlsdata(dyn, addr, ninst, x1);
INST_NAME("MOV GS:Od, EAX");
grab_tlsdata(dyn, addr, ninst, x1);
u32 = F32;
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, x1, x2, 0);
@@ -92,8 +225,8 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC7:
grab_tlsdata(dyn, addr, ninst, x12);
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
i32 = F32S;
@@ -103,12 +236,36 @@ 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;
case 0xE9:
case 0xEB:
INST_NAME("(ignored) GS:");
--addr;
break;
case 0xFF:
nextop = F8;
grab_tlsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH GS: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, x14, 0);
PUSH1(x3);
}
break;
default:
DEFAULT;
}
break;
default:
*ok = 0;
DEFAULT;
}
return addr;
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+108 -18
View File
@@ -21,22 +21,117 @@
#include "dynarec_arm_helper.h"
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
uint8_t nextop, opcode;
int8_t i8;
int32_t i32, j32;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int fixedaddress;
switch(opcode) {
MAYUSE(i32);
MAYUSE(j32);
nextop = F8;
switch(nextop) {
case 0x64:
// reduced EA size...
opcode = F8;
switch(opcode) {
case 0x89:
INST_NAME("MOV FS:Ew16, Gw");
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
}
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
STRH_REG(gd, x14, ed);
}
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
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, x14, ed, 0);
}
break;
case 0x8F:
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
POP1(x2);
STR_REG_LSL_IMM5(x2, x14, ed, 0);
}
break;
case 0xA1:
INST_NAME("MOV EAX, FS:Ow");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
LDR_IMM9(xEAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV FS:Ow, EAX");
grab_fsdata(dyn, addr, ninst, x1);
u32 = F16;
if(u32) {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x1, x1, x2, 0);
}
STR_IMM9(xEAX, x1, 0);
break;
case 0xFF:
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted16(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
@@ -54,31 +149,28 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
USEFLAG(1);
READFLAGS(X_ZF);
i8 = F8S;
UXTH(x1, xECX, 0);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
GO(cNE, cEQ);
break;
case 0xE1:
INST_NAME("LOOPZ (16bits)");
USEFLAG(1);
READFLAGS(X_ZF);
i8 = F8S;
UXTH(x1, xECX, 0);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
GO(cEQ, cNE);
break;
case 0xE2:
INST_NAME("LOOP (16bits)");
USEFLAG(1);
i8 = F8S;
UXTH(x1, xECX, 0);
SUBS_IMM8(x1, x1, 1);
@@ -87,16 +179,14 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE3:
INST_NAME("JCXZ");
USEFLAG(1);
i8 = F8S;
UXTH(x1, xECX, 0);
TSTS_REG_LSL_IMM8(x1, x1, 0);
TSTS_REG_LSL_IMM5(x1, x1, 0);
GO(cNE, cEQ);
break;
#undef GO
default:
*ok = 0;
DEFAULT;
}
return addr;
+76 -27
View File
@@ -26,17 +26,19 @@
uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int v1, v2, v3;
int s0, s1, s2;
int d0, d1;
uint8_t ed;
uint8_t wback;
int v1, v2;
int s0;
int d1;
int fixedaddress;
int parity;
MAYUSE(d1);
MAYUSE(s0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(ed);
switch(nextop) {
case 0xC0:
@@ -152,30 +154,48 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VADD_F64(v1, v1, d1);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VMUL_F64(v1, v1, d1);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
FCOM(x1, x2);
@@ -183,10 +203,16 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VCMP_F64(v1, d1);
FCOM(x1, x2);
@@ -195,45 +221,68 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, v1, d1);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VSUB_F64(v1, d1, v1);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, v1, d1);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
GETED;
s0 = fpu_get_scratch_single(dyn);
d1 = fpu_get_scratch_double(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_F32(d1, s0);
VDIV_F64(v1, d1, v1);
break;
default:
*ok = 0;
DEFAULT;
}
}
+86 -36
View File
@@ -23,28 +23,29 @@
#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)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t ed;
uint8_t wback, wb1;
int fixedaddress;
int v1, v2, v3;
int s0, s1, s2;
int v1, v2;
int s0;
int i1, i2, i3;
int parity;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
@@ -204,6 +205,28 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1, 0);
break;
case 0xF5:
INST_NAME("FPREM1");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem1, -1, 0);
break;
case 0xF6:
INST_NAME("FDECSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
SUB_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
break;
case 0xF7:
INST_NAME("FINCSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
ADD_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
break;
case 0xF8:
INST_NAME("FPREM");
x87_forget(dyn, ninst, x1, x2, 0);
@@ -259,10 +282,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE6:
case 0xE7:
case 0xEF:
case 0xF5:
case 0xF6:
case 0xF7:
*ok = 0;
DEFAULT;
break;
@@ -271,37 +290,59 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
s0 = fpu_get_scratch_single(dyn);
// to avoid bus error
//VLDR_32(s0, ed, 0);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
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_F64_F32(v1, s0);
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
// to avoid bus error...
//VSTR_32(s0, ed, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
s0 = fpu_get_scratch_single(dyn);
VCVT_F32_F64(s0, v1);
// to avoid bus error...
//VSTR_32(s0, ed, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FLDENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
MOVW(x2, 0);
CALL(fpu_loadenv, -1, 0);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1);
@@ -309,6 +350,16 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
UBFX(x1, x1, 10, 2); // extract round
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
break;
case 6:
INST_NAME("FNSTENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {
MOV_REG(x1, ed);
}
MOVW(x2, 0);
CALL(fpu_savenv, -1, 0);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0);
@@ -318,7 +369,6 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
EWBACK;
break;
default:
*ok = 0;
DEFAULT;
}
}
+21 -23
View File
@@ -26,17 +26,21 @@
uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int32_t j32;
uint8_t ed;
uint8_t wback;
int v1, v2;
int d0;
int s0;
int fixedaddress;
MAYUSE(s0);
MAYUSE(d0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(ed);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -47,11 +51,10 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FCMOVB ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cNE, v1, v2); // F_CF==1
break;
case 0xC8:
@@ -63,11 +66,10 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCE:
case 0xCF:
INST_NAME("FCMOVE ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cNE, v1, v2); // F_ZF==1
break;
case 0xD0:
@@ -79,12 +81,10 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FCMOVBE ST0, STx");
USEFLAG(1);
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_IMM8(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:
@@ -96,17 +96,16 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDE:
case 0xDF:
INST_NAME("FCMOVU ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cNE, v1, v2); // F_PF==1
break;
case 0xE9:
INST_NAME("FUCOMPP ST0, STx");
INST_NAME("FUCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
@@ -123,7 +122,6 @@ uintptr_t dynarecDA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF8:
case 0xF9:
case 0xFD:
*ok = 0;
DEFAULT;
break;
+39 -40
View File
@@ -22,22 +22,22 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static double maxint32 = (double)0x7fffffff;
uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int v1, v2, v3;
int s0, s1, s2;
int d0;
int32_t j32;
uint8_t ed;
uint8_t wback;
int v1, v2;
int s0;
int fixedaddress;
int parity;
MAYUSE(s0);
MAYUSE(v1);
MAYUSE(v2);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
@@ -49,11 +49,10 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
case 0xC7:
INST_NAME("FCMOVNB ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_CF);
VMOVcond_64(cEQ, v1, v2); // F_CF==0
break;
case 0xC8:
@@ -65,11 +64,10 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCE:
case 0xCF:
INST_NAME("FCMOVNE ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_ZF);
VMOVcond_64(cEQ, v1, v2); // F_ZF==0
break;
case 0xD0:
@@ -81,13 +79,11 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD6:
case 0xD7:
INST_NAME("FCMOVNBE ST0, STx");
USEFLAG(1);
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_IMM8(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:
@@ -98,17 +94,19 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDE:
case 0xDF:
INST_NAME("FCMOVNU ST0, STx");
USEFLAG(1);
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_IMM8(x1, x1, 0);
TSTS_IMM8(xFlags, 1<<F_PF);
VMOVcond_64(cEQ, v1, v2); // F_PF==0
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
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));
@@ -127,12 +125,11 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
UFLAGS(0);
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
UFLAGS(1);
break;
case 0xF0:
case 0xF1:
@@ -143,21 +140,18 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FCOMI ST0, STx");
UFLAGS(0);
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
UFLAGS(1);
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
*ok = 0;
DEFAULT;
break;
@@ -166,9 +160,15 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst);
GETED;
s0 = fpu_get_scratch_single(dyn);
VMOVtoV(s0, ed);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
VMOVtoV(s0, ed);
}
VCVT_F64_S32(v1, s0);
break;
case 1:
@@ -183,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);
@@ -193,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;
@@ -224,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;
@@ -267,7 +267,6 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_pop(dyn, ninst);
break;
default:
*ok = 0;
DEFAULT;
}
}
+89 -26
View File
@@ -26,17 +26,16 @@
uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int v1, v2, v3;
int s0, s1;
int d0, d1;
uint8_t wback;
int v1, v2;
int d1;
int fixedaddress;
int parity;
MAYUSE(d1);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
@@ -150,34 +149,66 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
INST_NAME("FADD ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VADD_F64(v1, v1, d1);
break;
case 1:
INST_NAME("FMUL ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VMUL_F64(v1, v1, d1);
break;
case 2:
INST_NAME("FCOM ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2);
break;
case 3:
INST_NAME("FCOMP ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VCMP_F64(v1, d1);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
@@ -185,33 +216,65 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
INST_NAME("FSUB ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VSUB_F64(v1, v1, d1);
break;
case 5:
INST_NAME("FSUBR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VSUB_F64(v1, d1, v1);
break;
case 6:
INST_NAME("FDIV ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VDIV_F64(v1, v1, d1);
break;
case 7:
INST_NAME("FDIVR ST0, double[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
d1 = fpu_get_scratch_double(dyn);
VLDR_64(d1, wback, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
}
VDIV_F64(v1, d1, v1);
break;
}
+61 -17
View File
@@ -27,15 +27,13 @@
uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int fixedaddress;
int v1, v2, v3;
int parity;
uint8_t ed;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
@@ -133,7 +131,6 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFD:
case 0xFE:
case 0xFF:
*ok = 0;
DEFAULT;
break;
@@ -147,9 +144,16 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
#else
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255, 0);
LDRD_IMM8(x2, ed, fixedaddress);
VMOVtoV_D(v1, x2, x3);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
}
#endif
break;
case 1:
@@ -163,18 +167,58 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress); // check alignment?
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress); // check alignment?
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FRSTOR m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_frstor, -1, 0);
break;
case 6:
INST_NAME("FSAVE m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
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);
LDRH_IMM8(x3, x2, 0);
BFI(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_IMM8(x3, ed, 0); // store whole sw flags
break;
default:
*ok = 0;
DEFAULT;
}
}
+21 -21
View File
@@ -25,16 +25,10 @@
uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int v1, v2, v3;
int s0, s1, s2;
int fixedaddress;
int v1, v2;
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
@@ -65,7 +59,23 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMUL_F64(v2, v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xD9: /* FCOMPP */
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOM(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xD9:
INST_NAME("FCOMPP ST0, ST1");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, 1);
@@ -131,14 +141,6 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_pop(dyn, ninst);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xDA:
case 0xDB:
@@ -146,7 +148,6 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDD:
case 0xDE:
case 0xDF:
*ok = 0;
DEFAULT;
break;
@@ -154,7 +155,6 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
default:
switch((nextop>>3)&7) {
default:
*ok = 0;
DEFAULT;
}
}
+63 -52
View File
@@ -28,18 +28,32 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
uint8_t nextop = F8;
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
int v1, v2, v3;
int s0, s1;
int d0;
int32_t j32;
uint8_t wback;
uint8_t ed;
int v1, v2;
int s0;
int fixedaddress;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREEP STx");
// not handling Tag...
x87_do_pop(dyn, ninst);
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
@@ -57,13 +71,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xEE:
case 0xEF:
INST_NAME("FUCOMIP ST0, STx");
UFLAGS(0);
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
UFLAGS(1);
break;
case 0xF0:
case 0xF1:
@@ -74,23 +87,14 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xF6:
case 0xF7:
INST_NAME("FCOMIP ST0, STx");
UFLAGS(0);
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
VCMP_F64(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
UFLAGS(1);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
@@ -130,7 +134,6 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xFD:
case 0xFE:
case 0xFF:
*ok = 0;
DEFAULT;
break;
@@ -148,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;
@@ -235,7 +247,6 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_pop(dyn, ninst);
break;
default:
*ok = 0;
DEFAULT;
}
}
+874
View File
@@ -0,0 +1,874 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// emit OR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
ORR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit OR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
ORRS_IMM8(s1, s1, c, 0);
} else {
ORR_IMM8(s1, s1, c, 0);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
ORR_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit XOR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
XOR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit XOR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
XORS_IMM8(s1, s1, c);
} else {
XOR_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
XOR_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit AND32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
AND_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit AND32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
ANDS_IMM8(s1, s1, c);
} else {
AND_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
AND_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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);
}
}
// emit OR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
ORR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit OR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
ORRS_IMM8(s1, s1, c, 0);
} else {
ORR_IMM8(s1, s1, c, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
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);
}
}
// emit XOR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
XOR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit XOR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
XORS_IMM8(s1, s1, c);
} else {
XOR_IMM8(s1, s1, c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
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);
}
}
// emit AND8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
AND_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_ALL) {
ANDS_IMM8(s1, s1, c);
} else {
AND_IMM8(s1, s1, c);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 7);
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);
}
}
// emit OR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
ORR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit OR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, 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));
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
ORRS_IMM8(s1, s1, c, 0);
} else {
ORR_IMM8(s1, s1, c, 0);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
ORR_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
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);
}
}
// emit XOR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
XOR_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit XOR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, 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));
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
XORS_IMM8(s1, s1, c);
} else {
XOR_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
XOR_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
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);
}
}
// emit AND16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s2, 0);
} else {
AND_REG_LSL_IMM5(s1, s1, s2, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_PF) {
if(save_s4) {PUSH(xSP, 1<<s4);}
// 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);
if(save_s4) {POP(xSP, 1<<s4);}
}
}
// emit AND16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, 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));
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c>=0 && c<256) {
IFX(X_ALL) {
ANDS_IMM8(s1, s1, c);
} else {
AND_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
AND_REG_LSL_IMM5(s1, s1, s3, 0);
}
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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, 15);
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);
}
}
+2026
View File
File diff suppressed because it is too large. Load diff
+379
View File
@@ -0,0 +1,379 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, 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));
SET_DF(s4, d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c==0) {
IFX(F_OF) {
BIC_IMM8(xFlags, xFlags, 0b10, 0x0b);
}
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_ZF|X_OF) {
MOVS_REG_LSL_IMM5(s1, s1, c);
} else {
MOV_REG_LSL_IMM5(s1, s1, 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) {
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s3, s1, 31);}
XOR_IMM8_COND(cCS, s3, s3, 1);
BFI(xFlags, s3, F_OF, 1);
} else {
BFC(xFlags, 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);
}
}
// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, 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));
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_ZF|X_CF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
MOV_REG_LSR_IMM5(s1, s1, 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_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
// 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);
}
}
// emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, 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));
SET_DF(s4, d_sar32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
IFX(X_ZF|X_CF) {
MOVS_REG_ASR_IMM5(s1, s1, c);
} else {
MOV_REG_ASR_IMM5(s1, s1, 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_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
BIC_IMM8_COND(cCC, xFlags, xFlags, 1<<F_CF, 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);
}
}
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_rol32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
MOV_REG_ROR_IMM5(s1, s1, 32-c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_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);
BFI(xFlags, s3, F_OF, 1);
}
}
}
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_ror32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
MOV_REG_ROR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_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);
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);
}
}
+433
View File
@@ -0,0 +1,433 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "../tools/bridge_private.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
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));
SET_DF(s4, d_cmp32);
} else {
SET_DFNONE(s4);
}
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) {
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_OF) {
ORR_IMM8_COND(cVS, xFlags, xFlags, 0b10, 0x0b);
BIC_IMM8_COND(cVC, xFlags, xFlags, 0b10, 0x0b);
}
IFX(X_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) {
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) {
// bc = (res & (~d | s)) | (~d & s)
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
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) {
MOV_REG_LSR_IMM5(s4, s3, 3);
BFI(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
}
IFX(X_PF) {
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_CF|X_AF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
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
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s4, 0);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
SET_DF(s4, d_cmp32);
} else {
SET_DFNONE(s4);
}
SUBS_IMM8(s3, s1, 0); // res = s1 - 0
// and now the tricky ones (and mostly unused), PF and AF
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
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(s4, s3, 31);
BFI(xFlags, s4, 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);
}
}
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
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));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
}
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) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s3, s4, 0);
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(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
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) {
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_CF, 1); // CF : bc & 0x8000
}
IFX(X_AF) {
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);
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 14) ^ ((bc>>14)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
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
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
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));
SET_DF(s3, d_cmp16);
} else {
SET_DFNONE(s3);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_ZF) {
MOVW(s4, 0xffff);
TSTS_REG_LSL_IMM5(s1, s4, 0);
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(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
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);
}
}
// 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) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_cmp8);
} else {
SET_DFNONE(s4);
}
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) {
TSTS_IMM8(s3, 0xff);
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(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
// bc = (res & (~d | s)) | (~d & s)
IFX(X_CF|X_AF|X_OF) {
MVN_REG_LSL_IMM5(s4, s1, 0); // s4 = ~d
ORR_REG_LSL_IMM5(s4, s4, s2, 0); // s4 = ~d | s
AND_REG_LSL_IMM5(s4, s4, s3, 0); // s4 = res & (~d | s)
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) {
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_CF, 1); // CF : bc & 0x80
}
IFX(X_AF) {
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);
BFI(xFlags, s4, F_OF, 1); // OF: ((bc >> 6) ^ ((bc>>6)>>1)) & 1
}
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
IFX(X_CF|X_AF|X_OF) {
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
}
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
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
SUB_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
MOVW(s4, 0);
STR_IMM9(s4, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
SET_DF(s3, d_cmp8);
} else {
SET_DFNONE(s4);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF) {
BIC_IMM8(xFlags, xFlags, (1<<F_CF)|(1<<F_AF), 0);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
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(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
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);
}
}
// 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)
{
IFX(X_PEND) {
SET_DF(s3, d_tst32);
} else {
SET_DFNONE(s4);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_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) {
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(s4, s3, 31);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
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_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit 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)
{
IFX(X_PEND) {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_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) {
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(s4, s3, 15);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
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_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
// emit 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)
{
IFX(X_PEND) {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
}
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_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) {
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(s4, s3, 7);
BFI(xFlags, s4, F_SF, 1);
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 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_REG_LSL_IMM5(s3, s1, s2, 0);
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
}
}
+824 -40
View File
@@ -24,21 +24,477 @@
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = PK(0); // don't increment addr
uint8_t u8;
uint32_t u32;
int32_t i32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t nextop, opcode = F8;
uint8_t wback, wb1, wb2, gb1, gb2;
uint8_t ed, gd, u8;
int fixedaddress;
int locked = 0;
switch(nextop) {
// generic case
int32_t i32, j32;
MAYUSE(i32);
MAYUSE(j32);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
switch(opcode) {
case 0x00:
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x08:
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x09:
INST_NAME("LOCK OR Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x10:
INST_NAME("LOCK ADC Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x11:
INST_NAME("LOCK ADC Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x18:
INST_NAME("LOCK SBB Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x19:
INST_NAME("LOCK SBB Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x20:
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x21:
INST_NAME("LOCK AND Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x28:
INST_NAME("LOCK SUB Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x38:
INST_NAME("LOCK XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x1, wback, wb2);
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, x14, x3, (wback==x3)?1:0);
STREXB(x14, x1, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE); // write failed, try again
}
break;
case 0x39:
INST_NAME("LOCK XOR Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ed, Id");
} else {
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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;
TSTS_IMM8(wback, 0x3);
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
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(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);
STR_IMM9(x1, wback, 0); // put the whole value
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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;
TSTS_IMM8(wback, 0x3);
B_MARK(cNE);
MARKLOCK;
LDREX(x1, wback);
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(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);
STR_IMM9(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(i32) {
MOV32(x2, i32);
emit_cmp32(dyn, ninst, ed, x2, x3, x14);
} else {
emit_cmp32_0(dyn, ninst, ed, x3, x14);
}
break;
}
break;
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
#define GO(A) \
case A+0x00: \
case A+0x01: \
case A+0x02: \
case A+0x03: \
case A+0x04: \
@@ -51,62 +507,390 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GO(0x28);
GO(0x30);
#undef GO
case 0x81:
case 0x83:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x86: // for this two, the lock is already done by the opcode, so just ignoring it
case 0x87:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
--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 = PK(1);
nextop = F8;
switch(nextop) {
case 0xB0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x2, wback, wb2);
ed = x2;
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x2, wback);
ed = x2;
wb1 = 1;
}
UXTB(x1, xEAX, 0);
CMPS_REG_LSL_IMM5(x1, ed, 0);
B_MARK(cNE);
// AL == Eb
GETGB(x1);
if(wb1) {
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
}
} else {
BFI(wback, x1, wb2*8, 8);
}
// done
B_MARK3(c__);
MARK;
// AL != Eb
BFI(xEAX, ed, 0, 8);
MARK3;
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
break;
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0);
MARKLOCK;
TSTS_IMM8(wback, 3); // can be unaligned it seems
LDREX_COND(cEQ, x1, wback);
LDR_IMM9_COND(cNE, x1, wback, 0);
LDREXB_COND(cNE, x3, wback); // dummy read, to arm the write...
ed = x1;
}
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
if(wback) {
TSTS_IMM8(wback, 3);
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, x14);
} else {
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, x14);
MOV_REG(xEAX, ed);
MARK3
break;
case 0xB3:
INST_NAME("LOCK BTR Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
wback = x3;
MARKLOCK;
LDREX(x1, wback);
ed = x1;
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
gd = x2;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
u8 = F8;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0);
u8 = F8;
fixedaddress+=(u8>>5)*4;
LDR_IMM9(x1, ed, fixedaddress);
ed = x1;
}
u8&=0x1f;
if(u8) {
MOV_REG_LSR_IMM5(x1, ed, u8);
ed = x1;
}
BFI(xFlags, ed, F_CF, 1);
break;
case 6:
INST_NAME("LOCK BTR 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, 0, 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;
MARKLOCK;
LDREX(x1, x3);
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(cEQ); // bit already clear, jump to next instruction
//MOVW(x14, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
default:
DEFAULT;
}
break;
case 0xBB:
INST_NAME("LOCK BTC Ed, Gd");
SETFLAGS(X_CF, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
UBFX(x1, gd, 5, 3); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
MARKLOCK;
LDREX(x1, x3);
ed = x1;
wback = x3;
}
AND_IMM8(x2, gd, 0x1f);
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(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
break;
case 0xC0:
INST_NAME("LOCK XADD Gb, Eb");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGB(x1);
if((nextop&0xC0)==0xC0) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
UXTB(x2, wback, wb2);
wb1 = 0;
ed = x2;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0);
MARKLOCK;
LDREXB(x2, wback);
wb1 = 1;
ed = x2;
}
BFI(gb1, ed, gb2*8, 8); // gb <- eb
emit_add8(dyn, ninst, ed, gd, x14, x3, 1);
if(wb1) {
STREXB(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
} else {
BFI(wback, ed, wb2*8, 8);
}
break;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
XOR_REG_LSL_IMM5(ed, gd, ed, 0);
XOR_REG_LSL_IMM5(gd, gd, ed, 0);
}
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(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, x14);
}
MOV_REG(gd, x1);
B_NEXT(c__);
MARK;
LDR_IMM9(x1, wback, 0);
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(x14, wback, 0);
IFX(X_ALL|X_PEND) {
MOV_REG(x2, x1);
emit_add32(dyn, ninst, x2, gd, x3, x14);
}
MOV_REG(gd, x1);
}
break;
case 0xC7:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog);
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0);
MARKLOCK;
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDREX_COND(cNE, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
CMPS_REG_LSL_IMM5(xEAX, x2, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x3, 0);
B_MARK(cNE); // EDX != Ed[1]
MOV_REG(x2, xEBX);
MOV_REG(x3, xECX);
TSTS_IMM8(wback, 7);
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);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x2);
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
break;
default:
addr = dynarec0F(dyn, addr+1, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
addr-=2;
}
break;
case 0xFF:
nextop = PK(1);
nextop = F8;
switch((nextop>>3)&7)
{
case 0:
case 1:
MESSAGE(LOG_DUMP, "LOCK\n");
locked = 1;
LOCK;
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog);
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
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, x14);
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
addr-=2;
}
break;
default:
addr = dynarec00(dyn, addr, ip, ninst, ok, need_epilog); // no lock, regular instruction...
// dafault to NO LOCK
--addr;
}
if(locked) {UNLOCK;}
return addr;
}
+74 -25
View File
@@ -22,43 +22,53 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
// Get Ex as a double, not a quad
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
#define GETEX(a) \
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
VLDR_64(a, ed, fixedaddress); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
VLDR_64(a, ed, fixedaddress); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);\
LDR_IMM9(x2, ed, fixedaddress+0); \
LDR_IMM9(x3, ed, fixedaddress+4); \
VMOVtoV_D(a, x2, x3); \
} \
}
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t u8;
int32_t i32, i32_;
int16_t i16;
uint32_t u32;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
uint8_t wback;
int v0, v1;
int q0, q1;
int d0, d1;
int s0, s1;
int s0;
int fixedaddress;
int parity;
MAYUSE(s0);
MAYUSE(d1);
MAYUSE(d0);
switch(nextop) {
case 0x10:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
@@ -85,18 +95,18 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
VMOVD(v0+1, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
VMOVD(v0+1, v0);
}
VMOVD(v0+1, v0);
break;
case 0x2A:
@@ -127,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);
@@ -256,6 +266,26 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
break;
case 0x7C:
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
VPADD_F32(v0, v0, v0+1);
if(v0==v1) {
VMOVD(v0+1, v0);
} else {
VPADD_F32(v0+1, v1, v1+1);
}
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex");
nextop = F8;
@@ -267,20 +297,39 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
MOVW(x2, 0);
u8 = F8;
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM8(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM8(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM8(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM8(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM8(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM8(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM8(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM8(cVC, x2, x2, 0); break; // not NaN
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM5(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0, x2, x2);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
LDR_IMM9(x2, ed, fixedaddress+8);
LDR_IMM9(x3, ed, fixedaddress+12);
VMOVtoV_D(v0+1, x2, x3);
}
break;
default:
*ok = 0;
DEFAULT;
}
return addr;
+301 -152
View File
@@ -34,27 +34,43 @@
} \
a *= 2; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3); \
a = fpu_get_scratch_single(dyn); \
VLDR_32(a, ed, fixedaddress); \
b = fpu_get_scratch_double(dyn); \
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0); \
VLDR_32(a, ed, fixedaddress); \
} else { \
GETED; \
VMOVtoV(a, ed); \
} \
}
#define GETGX(a) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd)
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, i32_;
int32_t j32;
uint32_t u32;
int16_t i16;
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1, wb2;
uint8_t eb1, eb2;
uint8_t wback;
int fixedaddress;
int v0, v1;
int s0, s1;
int s0, s1, s2;
int d0, d1;
int q0, q1;
int parity;
MAYUSE(q1);
MAYUSE(s1);
MAYUSE(s2);
MAYUSE(j32);
switch(opcode) {
case 0x10:
@@ -117,6 +133,49 @@ 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");
nextop = F8;
FAKEED;
break;
case 0x1F:
INST_NAME("REP NOP");
nextop = F8;
FAKEED;
break;
case 0x2A:
INST_NAME("CVTSI2SS Gx, Ed");
@@ -153,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);
@@ -175,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);
@@ -186,104 +259,118 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VSQRT_F32(d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VSQRT_F32(s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x52:
INST_NAME("RSQRTSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
s1 = fpu_get_scratch_single(dyn);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
s2 = fpu_get_scratch_single(dyn);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
VMOV_i_32(s1, 0b01110000);
VDIV_F32(s0, s1, s0);
VSQRT_F32(d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
VMOV_i_32(s2, 0b01110000);
VSQRT_F32(s0, s1);
VDIV_F32(s0, s2, s0);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x53:
INST_NAME("RCPSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
s1 = fpu_get_scratch_single(dyn);
VMOV_i_32(s1, 0b01110000);
VDIV_F32(d1*2, s1, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
s2 = fpu_get_scratch_single(dyn);
VMOV_i_32(s2, 0b01110000);
VDIV_F32(s0, s2, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x58:
INST_NAME("ADDSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VADD_F32(d1*2, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VADD_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x59:
INST_NAME("MULSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VMUL_F32(d1*2, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VMUL_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5A:
INST_NAME("CVTSS2SD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETGX(v0);
GETEX(s0, d0);
VCVT_F64_F32(v0, s0);
break;
@@ -304,75 +391,87 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VSUB_F32(d1*2, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VSUB_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5D:
INST_NAME("MINSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
// MINSS: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
VCMP_F32(d1*2, s0);
VCMP_F32(s0, s1);
VMRS_APSR();
VMOVcond_32(cPL, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
VMOVcond_32(cPL, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5E:
INST_NAME("DIVSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VDIV_F32(d1*2, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VDIV_F32(s0, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
case 0x5F:
INST_NAME("MAXSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
// MAXSS: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
VCMP_F32(s0, d1*2);
VCMP_F32(s1, s0);
VMRS_APSR();
VMOVcond_32(cPL, d1*2, s0);
if(v0!=d1) {
VMOV_64(v0, d1);
VMOVcond_32(cPL, s0, s1);
if(v0!=d0) {
VMOV_64(v0, d0);
}
break;
@@ -408,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);
@@ -450,8 +549,8 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
v0 = sse_get_reg(dyn, ninst, x1, gd);
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
v0 = sse_get_reg(dyn, ninst, x1, gd);
@@ -465,37 +564,87 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SET);
nextop = F8;
GETED;
GETGD;
TSTS_REG_LSL_IMM5(ed, ed, 0);
RBIT(x1, ed); // reverse
CLZ(gd, x1); // x2 gets leading 0 == TZCNT
MOVW_COND(cEQ, x1, 1);
MOVW_COND(cNE, x1, 0);
BFI(xFlags, x1, F_CF, 1);
RSB_IMM8(x1, x1, 1);
BFI(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(s0, d0);
if(v0<16)
d1 = v0;
else {
d1 = fpu_get_scratch_double(dyn);
VMOV_64(d1, v0);
}
VCMP_F32(d1*2, s0);
GETGX(v0);
GETEX(s1, v1);
if(v0==v1)
d0 = s1/2;
else
if(v0<16)
d0 = v0;
else {
d0 = fpu_get_scratch_double(dyn);
VMOV_64(d0, v0);
}
s0 = d0*2;
VCMP_F32(s0, s1);
VMRS_APSR();
MOVW(x2, 0);
u8 = F8;
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM8(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM8(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM8(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM8(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM8(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM8(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM8(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM8(cVC, x2, x2, 0); break; // not NaN
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: MVN_COND_REG_LSL_IMM5(cPL, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoDx_32(v0, 0, x2);
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7);
if(v1<16)
v0 = v1;
else {
v0 = fpu_get_scratch_double(dyn);
VMOV_64(v0, v1); // vfpu opcode here
}
} else {
v0 = fpu_get_scratch_double(dyn);
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); // vfpu opcode here
} 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);
}
}
gd = (nextop&0x38)>>3;
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
//v0 is a low reg now
VCVT_F64_S32(q0+1, v0*2+1);
VCVT_F64_S32(q0+0, v0*2+0);
break;
default:
*ok = 0;
DEFAULT;
}
return addr;
+159 -103
View File
@@ -5,6 +5,9 @@
#include <errno.h>
#include <string.h>
#include <math.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box86context.h"
@@ -22,13 +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_fstp(x86emu_t* emu, void* p)
{
if(ST0.ll!=STld(0).ref)
@@ -106,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;
}
@@ -118,13 +116,16 @@ void arm_fbstp(x86emu_t* emu, uint8_t* ed)
void arm_fistp64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).ref==ST(0).ll) {
*ed = STll(0).ll;
memcpy(ed, &STll(0).ll, sizeof(int64_t));
} else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*ed = 0x8000000000000000LL;
int64_t tmp;
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL) || !isfinite(ST0.d))
tmp = 0x8000000000000000LL;
else
*ed = (int64_t)ST0.d;
tmp = fpu_round(emu, ST0.d);
memcpy(ed, &tmp, sizeof(tmp));
}
}
@@ -135,97 +136,47 @@ void arm_fld(x86emu_t* emu, uint8_t* ed)
STld(0).ref = ST0.ll;
}
void arm_cpuid(x86emu_t* emu, uint32_t tmp32u)
void arm_ud(x86emu_t* emu)
{
switch(tmp32u) {
case 0x0:
// emulate a P4
R_EAX = 0x80000004;
// return GenuineIntel
R_EBX = 0x756E6547;
R_EDX = 0x49656E69;
R_ECX = 0x6C65746E;
break;
case 0x1:
R_EAX = 0x00000101; // familly and all
R_EBX = 0; // Brand indexe, CLFlush, Max APIC ID, Local APIC ID
R_EDX = 1 // fpu
| 1<<8 // cmpxchg8
| 1<<11 // sep (sysenter & sysexit)
| 1<<15 // cmov
| 1<<19 // clflush (seems to be with SSE2)
| 1<<23 // mmx
//| 1<<24 // fxsr (fxsave, fxrestore)
| 1<<25 // SSE
| 1<<26 // SSE2
;
R_ECX = 1<<12 // fma
| 1<<13 // cx16 (cmpxchg16)
; // also 1<<0 is SSE3 and 1<<9 is SSSE3
break;
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...
R_EAX = 0x665B5001;
R_EBX = 0x00000000;
R_ECX = 0x00000000;
R_EDX = 0x007A7000;
break;
case 0x4: // Cache info
switch (R_ECX) {
case 0: // L1 data cache
R_EAX = (1 | (1<<5) | (1<<8)); //type
R_EBX = (63 | (7<<22)); // size
R_ECX = 63;
R_EDX = 1;
break;
case 1: // L1 inst cache
R_EAX = (2 | (1<<5) | (1<<8)); //type
R_EBX = (63 | (7<<22)); // size
R_ECX = 63;
R_EDX = 1;
break;
case 2: // L2 cache
R_EAX = (3 | (2<<5) | (1<<8)); //type
R_EBX = (63 | (15<<22)); // size
R_ECX = 4095;
R_EDX = 1;
break;
default:
R_EAX = 0x00000000;
R_EBX = 0x00000000;
R_ECX = 0x00000000;
R_EDX = 0x00000000;
break;
}
break;
case 0x5: //mwait info
R_EAX = 0;
R_EBX = 0;
R_ECX = 1 | 2;
R_EDX = 0;
break;
case 0x6: // thermal
case 0x9: // direct cache access
case 0xA: // Architecture performance monitor
R_EAX = 0;
R_EBX = 0;
R_ECX = 0;
R_EDX = 0;
break;
case 0x7: // extended bits...
/*if(R_ECX==0) R_EAX = 0;
else*/ R_EAX = R_ECX = R_EBX = R_EDX = 0;
break;
case 0x80000000: // max extended
break; // no extended, so return same value as beeing the max value!
default:
printf_log(LOG_INFO, "Warning, CPUID command %X unsupported (ECX=%08x)\n", tmp32u, R_ECX);
R_EAX = 0;
}
kill(getpid(), SIGILL);
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
p+=10;
}
}
void arm_frstor(x86emu_t* emu, uint8_t* ed)
{
fpu_loadenv(emu, (char*)ed, 0);
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
p+=10;
}
}
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
{
@@ -241,14 +192,25 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn)
// Get a FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn)
{
if(dyn->fpu_scratch>4) {
if(dyn->fpu_extra_qscratch) {
dynarec_log(LOG_NONE, "Warning, Extra QScratch slot taken and need another one!\n");
} else
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn);
return dyn->fpu_extra_qscratch;
}
int i = (dyn->fpu_scratch+3)&(~3);
dyn->fpu_scratch = i+4;
return i/2; // Return a Dx, not a Qx
}
// Reset scratch regs counter
int fpu_reset_scratch(dynarec_arm_t* dyn)
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->fpu_scratch = 0;
if(dyn->fpu_extra_qscratch) {
fpu_free_reg_quad(dyn, dyn->fpu_extra_qscratch);
dyn->fpu_extra_qscratch = 0;
}
}
#define FPUFIRST 8
// Get a FPU double reg
@@ -282,9 +244,103 @@ void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
dyn->fpuused[i] = dyn->fpuused[i+1] = 0;
}
// Reset fpu regs counter
int fpu_reset_reg(dynarec_arm_t* dyn)
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->fpu_reg = 0;
for (int i=0; i<24; ++i)
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)
{
uint32_t tested = (1<<parity)-1;
if((nextop&0xC0)==0xC0)
return 0; // direct register, no parity...
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = (sib>>3)&7;
if((sib&0x7)==5) {
uint32_t tmp = F32;
if (sib_reg!=4) {
// if XXXXXX+reg<<N then check parity of XXXXX and N should be enough
return ((tmp&tested)==0 && (sib>>6)>=parity)?1:0;
} else {
// just a constant...
return (tmp&tested)?0:1;
}
} else {
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;
}
} else if((nextop&7)==5) {
uint32_t tmp = F32;
return (tmp&tested)?0:1;
} else {
return 0;
}
} 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
}
+14 -4
View File
@@ -3,7 +3,6 @@
typedef struct x86emu_s x86emu_t;
void arm_popf(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);
@@ -25,8 +24,11 @@ void arm_fild64(x86emu_t* emu, int64_t* ed);
void arm_fbstp(x86emu_t* emu, uint8_t* ed);
void arm_fistp64(x86emu_t* emu, int64_t* ed);
void arm_fld(x86emu_t* emu, uint8_t* ed);
void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
void arm_cpuid(x86emu_t* emu, uint32_t tmp32u);
void arm_ud(x86emu_t* emu);
// Get an FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn);
@@ -35,7 +37,7 @@ int fpu_get_scratch_double(dynarec_arm_t* dyn);
// Get an FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn);
// Reset scratch regs counter
int fpu_reset_scratch(dynarec_arm_t* dyn);
void fpu_reset_scratch(dynarec_arm_t* dyn);
// Get an FPU double reg
int fpu_get_reg_double(dynarec_arm_t* dyn);
// Free a FPU double reg
@@ -45,6 +47,14 @@ int fpu_get_reg_quad(dynarec_arm_t* dyn);
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg);
// Reset fpu regs counter
int fpu_reset_reg(dynarec_arm_t* dyn);
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__
File diff suppressed because it is too large. Load diff
+280 -71
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,16 +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)
#define CALL(F, ret, M) call_c(dyn, ninst, F, x12, ret, M)
// 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, x14, ret, M, 1)
// CALL_ will use x3 for the call address. Return value can be put in ret (unless ret is -1)
#define CALL_(F, ret, M) call_c(dyn, ninst, F, x3, ret, M)
// R0 will not be pushed/popd if ret is -2
#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;}
@@ -182,94 +203,136 @@
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
// Branch to MARK if cond (use i32)
// Branch to MARK if cond (use j32)
#define B_MARK(cond) \
i32 = GETMARK-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK2 if cond (use i32)
j32 = GETMARK-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARK2 if cond (use j32)
#define B_MARK2(cond) \
i32 = GETMARK2-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to MARK3 if cond (use i32)
j32 = GETMARK2-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARK3 if cond (use j32)
#define B_MARK3(cond) \
i32 = GETMARK3-(dyn->arm_size+8); \
Bcond(cond, i32)
// Branch to next instruction if cond (use i32)
j32 = GETMARK3-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to next instruction if cond (use j32)
#define B_NEXT(cond) \
i32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
Bcond(cond, i32)
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
Bcond(cond, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
j32 = GETMARKSEG-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARKLOCK if cond (use j32)
#define B_MARKLOCK(cond) \
j32 = GETMARKLOCK-(dyn->arm_size+8); \
Bcond(cond, j32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A)))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2) \
VMRS_APSR(); /* 0b0100011100000000 */ \
LDRH_IMM8(s2, xEmu, offsetof(x86emu_t, sw)); /*offset is 8bits right?*/ \
MOVW(s1, 0b0100011100000000); \
BIC_REG_LSL_IMM8(s2, s2, s1, 0); \
BIC_REG_LSL_IMM5(s2, s2, s1, 0); \
MOVW_COND(cVS, s1, 0b0100010100000000); /* unordered */ \
MOVW_COND(cEQ, s1, 0b0100000000000000); /* zero */ \
MOVW_COND(cGT, s1, 0b0000000000000000); /* greater than */ \
MOVW_COND(cLO, s1, 0b0000000100000000); /* less than */ \
ORR_REG_LSL_IMM8(s2, s2, s1, 0); \
ORR_REG_LSL_IMM5(s2, s2, s1, 0); \
STRH_IMM8(s2, xEmu, offsetof(x86emu_t, sw))
// Generate FCOMI with s1 and s2 scratch regs (the VCMP is already done)
#define FCOMI(s1, s2) \
VMRS_APSR(); /* 0b111 */ \
XOR_REG_LSL_IMM8(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 */ \
UBFX(s2, s1, 0, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_CF])); \
UBFX(s2, s1, 1, 1); \
STR_IMM9(s2, xEmu, offsetof(x86emu_t, flags[F_PF])); \
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));
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); \
} \
SET_DFNONE(s1); \
IFX(X_OF|X_PEND) { \
BFC(xFlags, F_OF, 1); \
} \
IFX(X_AF|X_PEND) { \
BFC(xFlags, F_AF, 1); \
} \
IFX(X_SF|X_PEND) { \
BFC(xFlags, F_SF, 1); \
} \
#ifndef UFLAGS
#define UFLAGS(A) dyn->cleanflags=A
#endif
#ifndef USEFLAG
// USEFLAG will check status of defered flags the call update flags if needed. x3 will be used
#define USEFLAG(A) \
if(!dyn->cleanflags) { \
if(A) { \
#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(((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_IMM8(x3, x3, 0); \
i32 = (GETMARKF)-(dyn->arm_size+8); \
Bcond(cEQ, i32); \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->cleanflags=1; \
} \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
j32 = (GETMARKF)-(dyn->arm_size+8); \
Bcond(cEQ, j32); \
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
SET_DFOK(); \
}
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)|X_PEND)))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A))); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
#endif
#ifndef JUMP
#define JUMP(A)
#endif
#define BARRIER(A) if (dyn->insts && !dyn->insts[ninst].x86.barrier) dyn->insts[ninst].x86.barrier = A
#define UFLAG_OP1(A) if(dyn->insts && dyn->insts[ninst].x86.flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts && dyn->insts[ninst].x86.flags) {STR_IMM9(A, 0, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts && dyn->insts[ninst].x86.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.flags) {STR_IMM9(A, 0, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts && dyn->insts[ninst].x86.flags) {MOVW(r, A); STR_IMM9(r, 0, offsetof(x86emu_t, df));}
#define UFLAG_IF if(dyn->insts && dyn->insts[ninst].x86.flags)
#ifndef BARRIER
#define BARRIER(A)
#endif
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#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 BARRIER(2)
#define DEFAULT *ok = -1; BARRIER(2)
#endif
#ifndef NEW_BARRIER_INST
#define NEW_BARRIER_INST
#endif
// Emit the LOCK mutex (x1, x2 and x3 are lost)
#define LOCK emit_lock(dyn, addr, ninst)
// Emit the UNLOCK mutex (x1, x2 and x3 are lost)
#define UNLOCK emit_unlock(dyn, addr, ninst)
#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
@@ -281,6 +344,7 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#define dynarec00 STEPNAME(dynarec00)
#define dynarec0F STEPNAME(dynarec0F)
#define dynarecFS STEPNAME(dynarecFS)
#define dynarecGS STEPNAME(dynarecGS)
#define dynarec66 STEPNAME(dynarec66)
#define dynarec67 STEPNAME(dynarec67)
@@ -298,25 +362,83 @@ 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_lock STEPNAME(emit_lock)
#define emit_unlock STEPNAME(emit_unlock)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
#define emit_cmp8_0 STEPNAME(emit_cmp8_0)
#define emit_cmp16_0 STEPNAME(emit_cmp16_0)
#define emit_cmp32_0 STEPNAME(emit_cmp32_0)
#define emit_test8 STEPNAME(emit_test8)
#define emit_test8 STEPNAME(emit_test8)
#define emit_test16 STEPNAME(emit_test16)
#define emit_test32 STEPNAME(emit_test32)
#define emit_add32 STEPNAME(emit_add32)
#define emit_add32c STEPNAME(emit_add32c)
#define emit_add8 STEPNAME(emit_add8)
#define emit_add8c STEPNAME(emit_add8c)
#define emit_sub32 STEPNAME(emit_sub32)
#define emit_sub32c STEPNAME(emit_sub32c)
#define emit_sub8 STEPNAME(emit_sub8)
#define emit_sub8c STEPNAME(emit_sub8c)
#define emit_or32 STEPNAME(emit_or32)
#define emit_or32c STEPNAME(emit_or32c)
#define emit_xor32 STEPNAME(emit_xor32)
#define emit_xor32c STEPNAME(emit_xor32c)
#define emit_and32 STEPNAME(emit_and32)
#define emit_and32c STEPNAME(emit_and32c)
#define emit_or8 STEPNAME(emit_or8)
#define emit_or8c STEPNAME(emit_or8c)
#define emit_xor8 STEPNAME(emit_xor8)
#define emit_xor8c STEPNAME(emit_xor8c)
#define emit_and8 STEPNAME(emit_and8)
#define emit_and8c STEPNAME(emit_and8c)
#define emit_add16 STEPNAME(emit_add16)
#define emit_add16c STEPNAME(emit_add16c)
#define emit_sub16 STEPNAME(emit_sub16)
#define emit_sub16c STEPNAME(emit_sub16c)
#define emit_or16 STEPNAME(emit_or16)
#define emit_or16c STEPNAME(emit_or16c)
#define emit_xor16 STEPNAME(emit_xor16)
#define emit_xor16c STEPNAME(emit_xor16c)
#define emit_and16 STEPNAME(emit_and16)
#define emit_and16c STEPNAME(emit_and16c)
#define emit_inc32 STEPNAME(emit_inc32)
#define emit_inc16 STEPNAME(emit_inc16)
#define emit_inc8 STEPNAME(emit_inc8)
#define emit_dec32 STEPNAME(emit_dec32)
#define emit_dec16 STEPNAME(emit_dec16)
#define emit_dec8 STEPNAME(emit_dec8)
#define emit_adc32 STEPNAME(emit_adc32)
#define emit_adc32c STEPNAME(emit_adc32c)
#define emit_adc8 STEPNAME(emit_adc8)
#define emit_adc8c STEPNAME(emit_adc8c)
#define emit_adc16 STEPNAME(emit_adc16)
#define emit_adc16c STEPNAME(emit_adc16c)
#define emit_sbb32 STEPNAME(emit_sbb32)
#define emit_sbb32c STEPNAME(emit_sbb32c)
#define emit_sbb8 STEPNAME(emit_sbb8)
#define emit_sbb8c STEPNAME(emit_sbb8c)
#define emit_sbb16 STEPNAME(emit_sbb16)
#define emit_sbb16c STEPNAME(emit_sbb16c)
#define emit_neg32 STEPNAME(emit_neg32)
#define emit_neg16 STEPNAME(emit_neg16)
#define emit_neg8 STEPNAME(emit_neg8)
#define emit_shl32c STEPNAME(emit_shl32c)
#define emit_shr32c STEPNAME(emit_shr32c)
#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)
@@ -341,6 +463,9 @@ void* arm_linker(x86emu_t* emu, void** table, uintptr_t addr);
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
#define cstack_push STEPNAME(cstack_push)
#define cstack_pop STEPNAME(cstack_pop)
// get the single reg that from the double "reg" (so Dx[idx])
#define fpu_get_single_reg STEPNAME(fpu_get_single_reg)
@@ -350,17 +475,20 @@ 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);
// 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 call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
void 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);
@@ -372,6 +500,64 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_test32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_add32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sub32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_inc32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_adc32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int save_s4);
void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_neg32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_neg16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_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
@@ -425,9 +611,9 @@ int fpu_get_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx);
// put back (if needed) the single reg in place
void fpu_putback_single_reg(dynarec_arm_t* dyn, int ninst, int reg, int idx, int s);
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
@@ -444,4 +630,27 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
// PUSH a x86/native couple of address in cstack, using s1, s2, s2+1
void cstack_push(dynarec_arm_t* dyn, int ninst, uintptr_t x86ip, uintptr_t armip, int s1, int s2);
// POP a x86/native couple of address from cstack, and generate the jump is x86 address is s0, use s1, s2 and s2+1 as scratch
void cstack_pop(dynarec_arm_t* dyn, int ninst, int s0, int s1, int s2);
#if STEP < 2
#define PASS2(A)
#else
#define PASS2(A) A
#endif
#if STEP < 3
#define PASS3(A)
#else
#define PASS3(A) A
#endif
#if STEP < 3
#define MAYUSE(A) (void)A
#else
#define MAYUSE(A)
#endif
#endif //__DYNAREC_ARM_HELPER_H__
+35 -23
View File
@@ -24,45 +24,38 @@
#error No STEP defined
#endif
#include "dynarec_arm_helper.h"
void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
uint8_t nextop, opcode;
int ok = 1;
int ninst = 0;
uintptr_t ip = addr;
uintptr_t natcall;
int retn;
uint8_t gd, ed;
int8_t i8;
int32_t i32, tmp;
uint8_t u8;
uint8_t gb1, gb2, eb1, eb2;
uint32_t u32;
int need_epilog = 1;
uint8_t wback, wb1, wb2;
int fixedaddress;
dyn->tablei = 0;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->cleanflags = 0;
dyn->state_flags = 0;
dyn->dfnone = 0;
fpu_reset(dyn, ninst);
// ok, go now
INIT;
while(ok) {
if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);}
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x86.barrier==1)) {
NEW_BARRIER_INST;
}
NEW_INST;
fpu_reset_scratch(dyn);
#ifdef HAVE_TRACE
if(dyn->emu->dec && box86_dynarec_trace) {
if((dyn->emu->trace_end == 0)
|| ((ip >= dyn->emu->trace_start) && (ip <= dyn->emu->trace_end))) {
if(my_context->dec && box86_dynarec_trace) {
if((trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) {
MESSAGE(LOG_DUMP, "TRACE ----\n");
fpu_reflectcache(dyn, ninst, x1, x2, x3);
MOV32(1, ip);
STM(0, (1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11));
STR_IMM9(1, 0, offsetof(x86emu_t, ip));
MOV32(2, 1);
MOV32(x1, ip);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP));
STR_IMM9(x1, xEmu, offsetof(x86emu_t, ip));
MOVW(x2, 1);
CALL(PrintTrace, -1, 0);
MESSAGE(LOG_DUMP, "----------\n");
}
@@ -75,9 +68,27 @@ 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)
dyn->cleanflags = 0;
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))
||(((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)<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;}
++ninst;
}
if(need_epilog) {
@@ -85,4 +96,5 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
}
+17 -8
View File
@@ -2,15 +2,24 @@
#define INIT uintptr_t sav_addr=addr
#define FINI dyn->isize = addr-sav_addr
#define MESSAGE(A, ...)
#define SETFLAGS(A, B)
#define READFLAGS(A)
#define EMIT(A)
#define UFLAGS(A) {}
#define USEFLAGS(A) {}
#define JUMP(A) add_next(dyn, (uintptr_t)A)
#define NEW_INST ++dyn->size
#define INST_EPILOG
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
dynarec_log(LOG_INFO, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X\n", \
ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6))
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
PKip(10),PKip(11),PKip(12), \
PKip(13),PKip(14)); \
printFunctionAddr(ip, " => "); \
dynarec_log(LOG_NONE, "\n"); \
}
+7 -5
View File
@@ -1,15 +1,17 @@
#define INIT
#define FINI \
dyn->insts[ninst].x86.addr = addr; \
dyn->insts[ninst].x86.flags = X86_FLAGS_USE; \
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
#define MESSAGE(A, ...)
#define EMIT(A)
#define UFLAGS(A) dyn->insts[ninst+(A?1:0)].x86.flags = X86_FLAGS_CHANGE
#define USEFLAG(A) dyn->insts[ninst].x86.flags = X86_FLAGS_USE
#define JUMP(A) dyn->insts[ninst].x86.jmp = A
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
#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<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
dyn->insts[ninst].x86.addr = ip; \
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;
#define INST_EPILOG
#define INST_NAME(name)
#define INST_NAME(name)
+1
View File
@@ -6,3 +6,4 @@
#define NEW_INST if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
+27 -5
View File
@@ -1,12 +1,34 @@
#define INIT
#define FINI
#define EMIT(A) \
if(box86_dynarec_log>=LOG_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
if(box86_dynarec_dump) {dynarec_log(LOG_NONE, "\t%08x\t%s\n", (A), arm_print(A));} \
*(uint32_t*)(dyn->block) = A; \
dyn->block += 4; dyn->arm_size += 4;\
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) dynarec_log(A, __VA_ARGS__);
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
#define INST_EPILOG
#define INST_NAME(name) if(box86_dynarec_log>=LOG_DUMP) printf_x86_instruction(dyn->emu->dec, &dyn->insts[ninst].x86, name)
#define INST_NAME(name) \
if(box86_dynarec_dump) {\
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, state=%d/%d, set=%X, use=%X, need=%X%s\n", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
dyn->insts[ninst].x86.state_flags, \
dyn->state_flags, \
dyn->insts[ninst].x86.set_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_flags, \
(box86_dynarec_dump>1)?"\e[m":""); \
}
#define NEW_BARRIER_INST \
if(ninst) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here\n");\
++dyn->sons_size; \
}
+21 -2
View File
@@ -10,8 +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 {
@@ -21,12 +27,12 @@ typedef struct dynarec_arm_s {
uintptr_t start; // start of the block
uint32_t isize; // size in byte of x86 instructions included
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
x86emu_t* emu;
uintptr_t* table; // jump table
int tablesz; // size of the jump table
int tablei; // index
int cleanflags; // flags are clean (CMP or TST have been just executed)
int state_flags;// actual state for on-demand flags
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int x87reg[8]; // reg used for x87cache entry
int mmxcache[8];// cache status for the 8 MMX registers
@@ -34,8 +40,21 @@ typedef struct dynarec_arm_s {
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
int x87stack; // cache stack counter
int fpu_scratch;// scratch counter
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;
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
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_
+23 -5
View File
@@ -1,19 +1,37 @@
#ifndef __DYNAREC_PRIVATE_H_
#define __DYNAREC_PRIVATE_H_
#define X86_FLAGS_NONE 0
#define X86_FLAGS_CHANGE 1
#define X86_FLAGS_USE 2
// all flags for the use_flags field
#define X_CF (1<<0)
#define X_PF (1<<1)
#define X_AF (1<<2)
#define X_ZF (1<<3)
#define X_SF (1<<4)
#define X_OF (1<<5)
#define X_ALL ((1<<6)-1)
#define X_PEND (0x1000)
// all state flags
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_MAYSET 3
#define SF_SUBSET 4
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
int flags; // flags for this instruction (see X86_FLAGS_XXXX)
int barrier; // next instruction is a jump point, so no optim allowed
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint32_t use_flags; // 0 or combination of X_?F
uint32_t set_flags; // 0 or combination of X_?F
uint32_t need_flags; // calculated
int state_flags; // One of SF_XXX state
} instruction_x86_t;
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
void tableupdate(void* jumpto, uintptr_t ref, void** table);
void resettable(void** table);
#endif //__DYNAREC_PRIVATE_H_
#endif //__DYNAREC_PRIVATE_H_
+475
View File
@@ -0,0 +1,475 @@
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 op 0 N Q M 0 Vm VH\(op ? "SUB" : "ADD")\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 0 N Q M 1 Vm VQADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 0 1 N Q M 0 Vm VRHADD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 0 Vn Vd 0 0 0 1 N Q M 1 Vm VAND<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 1 Vn Vd 0 0 0 1 N Q M 1 Vm VBIC<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 0 Vn Vd 0 0 0 1 N Q M 1 Vm @ m=n const char* op op,"MOV","ORR"@ m=n char lastop[6] !@ %@ lastop[0] = '\0'@ sprintf(lastop, ", %s", vecname[(q << 5) + 0x20 + n])@ @ V\op\<c> <Qd>, <Qm>\lastop\
NEON 1 1 1 1 0 0 1 0 0 D 1 1 Vn Vd 0 0 0 1 N Q M 1 Vm VORN<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D @<2> Vn Vd 0 0 0 1 N Q M 1 Vm @ param=0b00=0b01=0b10 const char* op op,"EOR","BSL","BIT","BIF"@ @ V\op\<c> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 0 N Q M 1 Vm VQSUB<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 0 1 1 N Q M op Vm @ op=0 const char* strict strict,"T","E"@ @ VCG\strict\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 0 Vm VSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 0 N Q M 1 Vm VQSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 0 Vm VRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 0 1 N Q M 1 Vm VQRSHL<c>.<dt> <Qd>, <Qm>, <Qn>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 0 Vm VABD<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 0 1 1 1 N Q M 1 Vm VABA<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 op 0 D size Vn Vd 1 0 0 0 N Q M 0 Vm @ op=0 const char* opname opname,"ADD","SUB"@ @ V\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VTST<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 0 0 N Q M 1 Vm VCEQ<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 0 Vm @ set size = 8 << size@ @ VML\(u ? "S" : "A")\<c>.I\%dsize\ <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 0 1 N Q M 1 Vm VMUL<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 0 D size Vn Vd 1 0 1 0 N Q M op Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D size Vn Vd 1 0 1 1 N Q M 0 Vm VQRDMULH<c>.<dt> <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D size Vn Vd 1 0 1 1 N Q/=0 M 1 Vm VPADD<c>.<dt> <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 0 N Q M 1 Vm @ u=0 const char* y y,"A","S"@ @ VFM\y\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D U sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm @ u=0 const char* op op,"ADD","SUB"@ @ V\op\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q/=0 M 0 Vm VPADD.F32 <Dd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 1 0 D 1 sz/=0 Vn Vd 1 1 0 1 N Q M 0 Vm VABD.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VML\(op ? "S" : "A")\<c>.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D 0 sz/=0 Vn Vd 1 1 0 1 N Q M 1 Vm VMUL.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm VCEQ.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 0 Vm @ op=1 const char* strict strict,"T","E"@ @ VCG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 0 N Q M 1 Vm @ op=1 const char* strict strict,"T","E"@ @ VACG\strict\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ V\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 0 D op sz/=0 Vn Vd 1 1 1 1 N Q M 0 Vm @ op=0 const char* opname opname,"MAX","MIN"@ @ VP\opname\.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 0 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRECPS.F32 <Qd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 0 0 D 1 sz/=0 Vn Vd 1 1 1 1 N Q M 1 Vm VRSQRTS.F32 <Qd>, <Qn>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 <1> 0 <23>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=0 1 imm4 VORR<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=11xx 0 Q op/=0 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=0xx1 0 Q op/=1 1 imm4 VBIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x0 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=10x1 0 Q op/=1 1 imm4 BIC<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=110x 0 Q op/=1 1 imm4 VMVN<c>.<dt> <Qd>, #<imm>
NEON 1 1 1 1 0 0 1 i 1 D 0 0 0 imm3 Vd cmode/=1110 0 Q op/=1 1 imm4 VMOV<c>.<dt> <Qd>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 0 0 <11> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.S32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 0 1 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U8 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 0 1 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 0 0 0 0 0 Vd 1 0 1 0 0 0 M 1 Vm VMOVL<c>.U32 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 0 L Q M 1 Vm VSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 0 1 L Q M 1 Vm VSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 0 L Q M 1 Vm VRSHR<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 0 0 1 1 L Q M 1 Vm VRSRA<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D imm6 Vd 0 1 0 0 L Q M 1 Vm VSRI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSHL<c>.I<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D Imm6 Vd 0 1 0 1 L Q M 1 Vm VSLI<c>.<size> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 0 1 1 op L Q M 1 Vm VQSHL\((u & op) ? "U" : "")\<c>.<dt> <Qd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 0 M 1 Vm @ set ++size@ @ VSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 0 1 D imm6 Vd 1 0 0 0 0 1 M 1 Vm VRSHRN<c>.I<size> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 0 M 1 Vm VQSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 U 1 D imm6 Vd 1 0 0 op 0 1 M 1 Vm VQRSHR\((u & op) ? "U" : "")\N<c>.<dt> <Dd>, <Qm>, #<imm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 U 1 D Imm6 Vd 1 0 1 0 0 0 M 1 Vm VSHLL<c>.<dt> <Qd>, <Dm>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 0 <9> 1 1 1 <1> 0 <2> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.S32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 0 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.S32.F32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 0 0 Q M 1 Vm VCVT<c>.F32.U32 <Qd>, <Qm>, #<fbits>
NEON 1 1 1 1 0 0 1 1 1 D IMM6 Vd 1 1 1 1 0 Q M 1 Vm VCVT<c>.U32.F32 <Qd>, <Qm>, #<fbits>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <18> 1 <4>
NEON 1 1 1 1 0 0 1 0 1 D 1 1 Vn Vd IMM4 N Q M 0 Vm VEXT<c>.8 <Qd>, <Qn>, <Qm>, #<imm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=11 0 0 <4> 0 0 0 <2> <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 0 Q M 0 Vm VCNT<c>.8 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 0 0 Vd 0 1 0 1 1 Q M 0 Vm VMVN<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 0 U Q M 0 Vm VPADAL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 0 Q M 0 Vm VQABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 1 1 1 Q M 0 Vm VQNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 0 Q M 0 Vm VCGT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 0 1 Q M 0 Vm VCGE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 0 Q M 0 Vm VCEQ<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 0 1 1 Q M 0 Vm VCLE<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 0 0 Q M 0 Vm VCLT<c>.<dt> <Qd>, <Qm>, #0
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 0 Q M 0 Vm VABS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 1 Vd 0 F 1 1 1 Q M 0 Vm VNEG<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=00 1 0 Vd 0 0 0 0 0 Q M 0 Vm VSWP<c> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 0 1 Q M 0 Vm VTRN<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 0 Q M 0 Vm VUZP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 0 1 1 Q M 0 Vm VZIP<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 0 M 0 Vm VMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 0 1 M 0 Vm VQMOVUN<c>.S\%d16 &l&l size\ <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 0 1 U M 0 Vm @ set ++size@ @ VQMOVN<c>.<dt> <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 0 Vd 0 0 1 1 0 0 M 0 Vm VSHLL<c>.I\%d8 &l&l size\ <Qd>, <Dm>, #\%d8 &l&l size\
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 0 0 0 M 0 Vm VCVT<c>.F16.F32 <Dd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=01 1 0 Vd 0 1 1 1 0 0 M 0 Vm VCVT<c>.F32.F16 <Qd>, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 0 Q M 0 Vm VRECPE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 1 1 Vd 0 1 0 F 1 Q M 0 Vm VRSQRTE<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 0 Q M 0 Vm VCVT<c>.F32.S32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 0 1 Q M 0 Vm VCVT<c>.S32.F32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 0 Q M 0 Vm VCVT<c>.F32.U32 <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size/=10 1 1 Vd 0 1 1 1 1 Q M 0 Vm VCVT<c>.U32.F32 <Qd>, <Qm>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <8> 0 <6> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 Vn Vd 1 0 @<2> N op M 0 Vm @ param=0b00 char list[10] !@ sprintf(list, %)@ "{%s}", vecname[0x20 + n]@ "{%s-%s}", vecname[0x20 + n], vecname[0x20 + n + param]@ @ VTB\(op ? "X" : "L")\<c>.8 <Dd>, \list\, <Dm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 imm4 Vd 1 1 0 0 0 Q M 0 Vm VDUP<c>.\%dsize\ <Qd>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <1> 1 1 <13> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 0 Q N 0 M 0 Vm VADD\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 0 1 Q N 0 M 0 Vm VSUB\(q ? "W" : "L")\<c>.<dt> <qd>, <Qn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm @ set size = 16 << size@ @ VADDHN<c>.I\%dsize\ <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 0 0 N 0 M 0 Vm VRADDHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 0 1 N 0 M 0 Vm VABAL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D size Vn Vd 0 1 1 0 N 0 M 0 Vm VRSUBHN<c>.<dt> <Dd>, <Qn>, <Qm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 1 1 1 N 0 M 0 Vm VABDL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 op 0 N 0 M 0 Vm VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 op 1 N 0 M 0 Vm VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 1 0 0 N 0 M 0 Vm VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 1 0 1 N 0 M 0 Vm VQDMULL<c>.<dt> <Qd>, <Dn>, <Dm>
NEON 1 1 1 1 0 0 1 U/=0 1 D size/=00 Vn Vd 1 1 1 0 N 0 M 0 Vm @ set uint8_t size = 0@ @ VMULL<c>.<dt> <Qd>, <Dn>, <Dm>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 0 op 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 0 op 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 0 op 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDML\(op ? "S" : "A")\L<c>.<dt> <Qd>, <Dn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 0 0 F N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMUL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 U 1 D size Vn Vd 1 0 1 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 0 1 D size Vn Vd 1 0 1 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULL<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 0 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
NEON 1 1 1 1 0 0 1 Q 1 D size Vn Vd 1 1 0 1 N 1 M 0 Vm @ size=0b01=0b10 unsigned int decodedImm !@ decodedImm = m >> %; m %@ 3@ &= 0x7@ 4@ &= 0xF@ 5@ = 0x21@ @ VQRDMULH<c>.<dt> <Qd>, <Qn>, <Dm[x]>
INVALIDATE 1 1 1 1 0 0 1 <1> 1 <16> 0 <1> 0 <4>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 0 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 0 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VST1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VST3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 0 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VST4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\, \vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\, \vecname[0x26 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 0 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x23 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 0 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 0 1 size @<2> Rm @ param=0b00 char align[4] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 63 + param)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\, \vecname[0x24 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\-\vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 0 1 1 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 0 1 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x22 + d]\}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 1 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> 1 1 0 1 @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 0 D 1 0 Rn Vd 1 0 1 0 size @<2> Rm @ param=0b00 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 32 << param)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\, \vecname[0x21 + d]\}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 1 <1> 1 0 <8> 1 1 <10>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ set uint8_t temp = param & (1 << size)@ temp=0 uint8_t spacing spacing,0,1@ set uint8_t x = param >> (size + 1)@ @ VLD3<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\]}, [<Rn>], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0b0=0b1=0b10 char align[6] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", (size ? 64 : 32))@ sprintf(align, ":128")@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD4<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\], \vecname[0x22 + d + 2*spacing]\[\%dx\], \vecname[0x23 + d + 3*spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
INVALIDATE 1 1 1 1 0 1 0 0 <3> 0 <20>
INVALIDATE 1 1 1 1 <28>
ARMS cond 0 0 0 0 0 0 0 S Rn Rd imm5 type 0 Rm AND{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 0 S Rd (0) (0) (0) (0) Rm 1 0 0 1 Rn MUL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 0 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 0 1 S Rn Rd imm5 type 0 Rm EOR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 0 1 S Rd Ra Rm 1 0 0 1 Rn MLA{S}<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 0 1 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRHT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSBT<c> <Rt>, [<Rn>], +/-<Rm>
ARM_ cond 0 0 0 0 U 0 1 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSHT<c> <Rt>, [<Rn>], +/-<Rm>
ARMS cond 0 0 0 0 0 1 0 S Rn Rd imm5 type 0 Rm SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 0 0 RdHi RdLo Rm 1 0 0 1 Rn UMAAL<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 0 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 0 1 1 S Rn Rd imm5 type 0 Rm RSB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 0 1 1 0 Rd Ra Rm 1 0 0 1 Rn MLS<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 0 U 1 1 0 Rn Rt imm4H 1 0 1 1 imm4L STRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 0 1 1 imm4L LDRHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSBT<c> <Rt>, [<Rn>], #+/-<imm8>
ARM_ cond 0 0 0 0 U 1 1 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSHT<c> <Rt>, [<Rn>], #+/-<imm8>
ARMS cond 0 0 0 0 1 0 0 S Rn Rd imm5 type 0 Rm ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 0 S RdHi RdLo Rm 1 0 0 1 Rn UMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 0 1 S Rn Rd imm5 type 0 Rm ADC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 0 1 S RdHi RdLo Rm 1 0 0 1 Rn UMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 0 S Rn Rd imm5 type 0 Rm SBC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 0 S RdHi RdLo Rm 1 0 0 1 Rn SMULL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARMS cond 0 0 0 0 1 1 1 S Rn Rd imm5 type 0 Rm RSC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 0 1 1 1 S RdHi RdLo Rm 1 0 0 1 Rn SMLAL{S}<c> <RdLo>, <RdHi>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 0 0 Rn SMLABB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 0 1 0 Rn SMLATB<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 0 0 Rn SMLABT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rd Ra Rm 1 1 1 0 Rn SMLATT<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 0 0 1 0 0 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWP<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm STRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 0 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm STRD<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}
ARMS cond 0 0 0 1 0 0 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TST<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 0 1 1 Rm LDRH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 0 1 Rm LDRSB<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 U 0 W 1 Rn Rt (0) (0) (0) (0) 1 1 1 1 Rm LDRSH<c> <Rt>, [<Rn>, +/-<Rm>]{!}
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 0 1 Rm BX<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 0 Rm BXJ<c> <Rm>
ARM_ cond 0 0 0 1 0 0 1 0 (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) 0 0 1 1 Rm BLX<c> <Rm>
ARM_ cond/=1110 0 0 0 1 0 0 1 0 imm12 0 1 1 1 imm4 BKPT #<imm16>
ARMS cond 0 0 0 1 0 0 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm TEQ<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 0 1 0 0 Rn Rt (0) (0) (0) (0) 1 0 0 1 Rm SWPB<c> <Rt>, <Rm>, [<Rn>]
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 0 1 1 imm4L STRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 0 1 imm4L LDRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 0 Rn Rt imm4H 1 1 1 1 imm4L STRD<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 0 1 0 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMP<c> <Rn>, <Rm>{, <shift>}
ARMS cond 0 0 0 1 0 1 1 1 Rn (0) (0) (0) (0) imm5 type 0 Rm CMN<c> <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 0 1 1 imm4L LDRH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 0 1 imm4L LDRSB<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARM_ cond 0 0 0 1 U 1 W 1 Rn Rt imm4H 1 1 1 1 imm4L LDRSH<c> <Rt>, [<Rn>, #+/-<imm8>]{!}
ARMS cond 0 0 0 1 1 0 0 S Rn Rd imm5 type 0 Rm ORR{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 0 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREX<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREX<c> <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 0 0 0 Rm MOV{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 0 0 Rm LSL{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 0 1 Rn LSL{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 0 1 0 Rm LSR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 0 1 1 Rn LSR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 0 0 Rm ASR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 0 1 Rn ASR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd 0 0 0 0 0 1 1 0 Rm RRX{S}<c> <Rd>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd imm5 1 1 0 Rm ROR{S}<c> <Rd>, <Rm>, #<imm>
ARM_ cond 0 0 0 1 1 0 1 S (0) (0) (0) (0) Rd Rm 0 1 1 1 Rn ROR{S}<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 0 0 1 1 0 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXD<c> <Rd>, <Rt>, <Rt2>, [<Rn>]
ARM_ cond 0 0 0 1 1 0 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXD<c> <Rt>, <Rt2>, [<Rn>]
ARMS cond 0 0 0 1 1 1 0 S Rn Rd imm5 type 0 Rm BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 0 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXB<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 0 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXB<c> <Rt>, [<Rn>]
ARMS cond 0 0 0 1 1 1 1 S (0) (0) (0) (0) Rd imm5 type 0 Rm MVN{S}<c> <Rd>, <Rm>{, <shift>}
ARM_ cond 0 0 0 1 1 1 1 0 Rn Rd (1) (1) (1) (1) 1 0 0 1 Rt STREXH<c> <Rd>, <Rt>, [<Rn>]
ARM_ cond 0 0 0 1 1 1 1 1 Rn Rt (1) (1) (1) (1) 1 0 0 1 (1) (1) (1) (1) LDREXH<c> <Rt>, [<Rn>]
ARM_ cond 0 0 1 0 0 0 0 S Rn Rd imm12 AND{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 0 1 S Rn Rd imm12 EOR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 0 S Rn Rd imm12 SUB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 0 1 1 S Rn Rd imm12 RSB{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 0 S Rn Rd imm12 ADD{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 0 1 S Rn Rd imm12 ADC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 0 S Rn Rd imm12 SBC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 0 1 1 1 S Rn Rd imm12 RSC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 0 0 imm4 Rd imm12 MOVW<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 0 0 1 Rn (0) (0) (0) (0) imm12 TST<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 0 1 0 0 0 0 0 (1) (1) (1) (1) (0) (0) (0) (0) 0 0 0 0 0 0 0 0 NOP<c>
ARM_ cond 0 0 1 1 0 0 1 1 Rn (0) (0) (0) (0) imm12 TEQ<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 0 0 imm4 Rd imm12 MOVT<c> <Rd>, #<imm16>
ARM_ cond 0 0 1 1 0 1 0 1 Rn (0) (0) (0) (0) imm12 CMP<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 0 1 1 1 Rn (0) (0) (0) (0) imm12 CMN<c> <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 0 S Rn Rd imm12 ORR{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 0 1 S (0) (0) (0) (0) Rd imm12 MOV{S}<c> <Rd>, #<const>
ARM_ cond 0 0 1 1 1 1 0 S Rn Rd imm12 BIC{S}<c> <Rd>, <Rn>, #<const>
ARM_ cond 0 0 1 1 1 1 1 S (0) (0) (0) (0) Rd imm12 MVN{S}<c> <Rd>, #<const>
ARM_ cond 0 1 0 0 1 0 0 1 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 POP<c> {<Rt>}
ARM_ cond 0 1 0 0 U 0 0 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 0 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 0 Rn Rt imm12 STRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 0 1 1 Rn Rt imm12 LDRT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 0 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 0 Rn Rt imm12 STRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 0 U 1 1 1 Rn Rt imm12 LDRBT<c> <Rt>, [<Rn>], #+/-<imm12>
ARM_ cond 0 1 0 1 0 0 1 0 1 1 0 1 Rt 0 0 0 0 0 0 0 0 0 1 0 0 PUSH<c> {<Rt>}
ARM_ cond 0 1 0 1 U 0 W 0 Rn Rt imm12 STR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 0 W 1 Rn Rt imm12 LDR<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 0 Rn Rt imm12 STRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 0 1 U 1 W 1 Rn Rt imm12 LDRB<c> <Rt>, [<Rn>, #+/-<imm12>]{!}
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm SSAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm SSUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 0 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm SSUB8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 0 1 Rm USAX<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 0 1 1 1 Rm USUB16<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 0 0 1 0 1 Rn Rd (1) (1) (1) (1) 1 1 1 1 Rm USUB8<c> <Rd>, <Rn>, <Rm>
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 0 0 1 Rm PKHBT<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARMs cond 0 1 1 0 1 0 0 0 Rn Rd imm5 1 0 1 Rm PKHTB<c> <Rd>, <Rn>, <Rm>{, <shift>}
ARM_ cond 0 1 1 0 1 0 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 0 1 sat_imm Rd imm5 sh 0 1 Rn SSAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 0 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn SSAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 0 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 0 0 1 1 Rm REV<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REV16<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 0 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm SXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 0 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm SXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB16<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 0 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB16<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 1 1 1 sat_imm Rd imm5 sh 0 1 Rn USAT<c> <Rd>, #<imm>, <Rn>{, <shift>}
ARM_ cond 0 1 1 0 1 1 1 0 sat_imm Rd (1) (1) (1) (1) 0 0 1 1 Rn USAT16<c> <Rd>, #<imm>, <Rn>
ARM_ cond 0 1 1 0 1 1 1 0 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTB<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 0 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAB<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 1 1 1 1 Rd rotate (0) (0) 0 1 1 1 Rm UXTH<c> <Rd>, <Rm>{, <rotation>}
ARM_ cond 0 1 1 0 1 1 1 1 (1) (1) (1) (1) Rd (1) (1) (1) (1) 1 0 1 1 Rm REVSH<c> <Rd>, <Rm>
ARM_ cond 0 1 1 0 1 1 1 1 Rn Rd rotate (0) (0) 0 1 1 1 Rm UXTAH<c> <Rd>, <Rn>, <Rm>{, <rotation>}
ARMs cond 0 1 1 0 U 0 0 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 0 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 0 Rn Rt imm5 type 0 Rm STRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 0 1 1 Rn Rt imm5 type 0 Rm LDRT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 0 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 0 Rn Rt imm5 type 0 Rm STRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 0 U 1 1 1 Rn Rt imm5 type 0 Rm LDRBT<c> <Rt>, [<Rn>], +/-<Rm>{, <shift>}
ARMs cond 0 1 1 1 U 0 W 0 Rn Rt imm5 type 0 Rm STR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 0 W 1 Rn Rt imm5 type 0 Rm LDR<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 0 Rn Rt imm5 type 0 Rm STRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARMs cond 0 1 1 1 U 1 W 1 Rn Rt imm5 type 0 Rm LDRB<c> <Rt>, [<Rn>, +/-<Rm>{, <shift>}]{!}
ARM_ cond 0 1 1 1 1 0 0 0 Rd 1 1 1 1 Rm 0 0 0 1 Rn USAD8<c> <Rd>, <Rn>, <Rm>
ARM_ cond 0 1 1 1 1 0 0 0 Rd Ra Rm 0 0 0 1 Rn USADA8<c> <Rd>, <Rn>, <Rm>, <Ra>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 1 1 1 1 BFC<c> <Rd>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 0 msb Rd lsb 0 0 1 Rn BFI<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 0 1 1 1 1 1 1 widthm1 Rd lsb 1 0 1 Rn UBFX<c> <Rd>, <Rn>, #<lsb>, #<width>
ARM_ cond 1 0 0 0 0 0 W 0 Rn/=1101 register_list STMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 0 Rn register_list STMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn/=1101 register_list LDMED<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 0 0 W 1 Rn register_list LDMDA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn/=1101 register_list STMEA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 W 0 Rn register_list STM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 0 1 0 0 1 Rn/=1101 register_list LDMEA<c> <Rn>, <registers>
ARM_ cond 1 0 0 0 1 0 1 1 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"POP","LDMEA"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 0 1 0 W 1 Rn register_list LDM<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 0 0 Rn/=1101 register_list STMFD<c> <Rn>, <registers>
ARM_ cond 1 0 0 1 0 0 1 0 1 1 0 1 register_list @ = const char* op @@ (reglist != 0) && ((reglist & (reglist - 1)) == 0)@ op,"PUSH","STMFD"@ @ \op\<c> <registers>
ARM_ cond 1 0 0 1 0 0 W 0 Rn register_list STMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn/=1101 register_list LDMFD<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 0 0 W 1 Rn register_list LDMDB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn/=1101 register_list STMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 0 Rn register_list STMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn/=1101 register_list LDMFA<c> <Rn>{!}, <registers>
ARM_ cond 1 0 0 1 1 0 W 1 Rn register_list LDMIB<c> <Rn>{!}, <registers>
ARM_ cond 1 0 1 0 imm24 B<c> <label>
ARM_ cond 1 0 1 1 imm24 BL<c> <label>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Sm>, <Sm1>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 0 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Sm>, <Sm1>
VFPU cond 1 1 0 0 0 1 0 0 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Dm>, <Rt>, <Rn>
VFPU cond 1 1 0 0 0 1 0 1 Rn Rt 1 0 1 1 0 0 M 1 Vm VMOV<c> <Rt>, <Rn>, <Dm>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 0 0 <11> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
INVALIDATE <4> 1 1 0 1 1 <1> 1 <9> 1 0 1 <9>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTMX<c> <LIst>
VFPU cond 1 1 0 1 0 D 1 0 1 1 0 1 Vd 1 0 1 sz imm8 VPUSH<c> <list>
VFPU cond 1 1 0 1 U D 0 0 Rn Vd 1 0 1 sz imm8 VSTR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FSTM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 0 Rn Vd 1 0 1 sz imm8 VSTM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDMX<c> <LIst>
VFPU cond 1 1 0 0 1 D 1 1 1 1 0 1 Vd 1 0 1 sz imm8 VPOP<c> <list>
VFPU cond 1 1 0 1 0 D 0 1 1 1 1 1 Vd 1 0 1 sz 0 0 0 0 0 0 0 0 VLDR<c> <Dd>, [PC, #-0]
VFPU cond 1 1 0 1 U D 0 1 1 1 1 1 Vd 1 0 1 sz imm8 VLDR<c> <Dd>, <label>
VFPU cond 1 1 0 1 U D 0 1 Rn Vd 1 0 1 sz imm8 VLDR<c> <Dd>, [<Rn>{, #+/-<imm>}]
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 1 imm8/01 @ set --imm8@ @ FLDM\(param == 0b01 ? "IA" : "DB")\X<c> <Rn>{!}, <LIst>
VFPU cond 1 1 0 @<2> D W 1 Rn Vd 1 0 1 sz imm8 VLDM\(param == 0b01 ? "IA" : "DB")\<c> <Rn>{!}, <list>
INVALIDATE <4> 1 1 0 <25>
INVALIDATE <4> 1 1 1 0 0 0 <1> 0 <8> 1 0 1 1 <1> 1 0 1 (0) (0) (0) (0)
VFPU cond 1 1 1 0 0 0 0 0 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Sn>, <Rt>
VFPU cond 1 1 1 0 1 1 1 0 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMSR<c> FPSCR, <Rt>
VFPU cond 1 1 1 0 0 @<2> 0 Vd Rt 1 0 1 1 D @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (param1_2 << 2) + param2_2@ = uint8_t shift @@ (opc & 0b1000) == 0b1000@ @@ (opc & 0b1001) == 0b0001@ @@ (opc & 0b1011) == 0b0000@ shift,0,1,2,0xFF@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.\%d8 &l&l shift\ <Dd[x]>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.32 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 0 Q 0 Vd Rt 1 0 1 1 D 0 1 1 (0) (0) (0) (0) VDUP<c>.16 <Qd>, <Rt>
VFPU cond 1 1 1 0 1 1 Q 0 Vd Rt 1 0 1 1 D 0 0 1 (0) (0) (0) (0) VDUP<c>.8 <Qd>, <Rt>
VFPU cond 1 1 1 0 0 0 0 1 Vn Rt 1 0 1 0 N (0) (0) 1 (0) (0) (0) (0) VMOV<c> <Rt>, <Sn>
VFPU cond 1 1 1 0 1 1 1 1 0 0 0 1 Rt 1 0 1 0 (0) (0) (0) 1 (0) (0) (0) (0) VMRS<c> <Rt>, FPSCR
VFPU cond 1 1 1 0 U @<2> 1 Vn Rt 1 0 1 1 N @<2> 1 (0) (0) (0) (0) @ set uint8_t opc = (u << 4) + (param1_2 << 2) + param2_2@ = uint8_t shift, size @@ (opc & 0b01000) == 0b01000@ @@ (opc & 0b01001) == 0b00001@ @@ (opc & 0b11011) == 0b00000@ shift,0,1,2,0xFF;size,0,1,2,4@ set uint8_t decodedImm = (opc & 0x7) >> shift@ @ VMOV<c>.<dt> <Rt>, <Dn[x]>
INVALIDATE <4> 1 1 1 0 <12> 1 0 1 <4> 1 <4>
VFPU cond 1 1 1 0 0 D 0 0 Vn Vd 1 0 1 sz N op M 0 Vm VML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VNML\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 0 Vn Vd 1 0 1 sz N 1 M 0 Vm VNMUL<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 0 M 0 Vm VADD<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 0 D 1 1 Vn Vd 1 0 1 sz N 1 M 0 Vm VSUB<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 0 Vn Vd 1 0 1 sz N 0 M 0 Vm VDIV<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 0 1 Vn Vd 1 0 1 sz N op M 0 Vm VFNM\(op ? "A" : "S")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 0 Vn Vd 1 0 1 sz N op M 0 Vm VFM\(op ? "S" : "A")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dn>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 0 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set float mantissa = 16 + param2_4@ set float imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F32 <Sd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 @<4> Vd 1 0 1 1 (0) 0 (0) 0 @<4> @ set int8_t sign = (param1_4 >> 3) ? -1 : 1@ set uint8_t exp = ((param1_4 & 0b111) ^ 0b100)@ set double mantissa = 16 + param2_4@ set double imm = sign * (1 << exp) * mantissa / 128.@ @ VMOV<c>.F64 <Dd>, #\%fimm\
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 0 1 M 0 Vm VMOV<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 0 Vd 1 0 1 sz 1 1 M 0 Vm VABS<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 0 1 M 0 Vm VNEG<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 0 1 Vd 1 0 1 sz 1 1 M 0 Vm VSQRT<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 0 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F32.F16 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 0 1 1 Vd 1 0 1 (0) @<1> 1 M 0 Vm VCVT\(param ? "T" : "B")\<c>.F16.F32 <Sd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 0 1 Vd 1 0 1 sz op 1 (0) 0 (0) (0) (0) (0) VCMP\(op ? "E" : "")\<c>.F\(size ? "64" : "32")\ <Dd>, #0.0
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 0 1 1 M 0 Vm VCVT<c>.F64.F32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 0 1 1 1 Vd 1 0 1 1 1 1 M 0 Vm VCVT<c>.F32.F64 <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 0 0 Vd 1 0 1 sz op 1 M 0 Vm VCVT<c>.F\(size ? "64" : "32")\.\(op ? "S" : "U")\32 <Dd>, <Sm>
VFPU cond 1 1 1 0 1 D 1 1 1 0 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.F\(size ? "64" : "32")\.\Td\ <Dd>, <Dd>, #<imm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 0 U Vd 1 0 1 sz op 1 M 0 Vm VCVT\(op ? "" : "R")\<c>.\(u ? "U" : "S")\32.F\(size ? "64" : "32")\ <Sd>, <Dm>
VFPU cond 1 1 1 0 1 D 1 1 1 1 1 U Vd 1 0 1 sz op 1 i 0 imm4 @ set uint8_t td = (u << 2) + op + 1@ td=0b001=0b010=0b101 const char* Td Td,"S16","U16","S32","U32"@ set imm5 = (16 << op) - (imm5 >> 4) - ((imm5 & 0xF) << 1)@ @ VCVT<c>.\Td\.F\(size ? "64" : "32")\ <Dd>, <Dd>, #<imm>
INVALIDATE <32>
+22
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;
}
@@ -284,6 +290,22 @@ void DumpDynamicNeeded(elfheader_t *h)
}
}
void DumpDynamicRPath(elfheader_t *h)
{
if(box86_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
}
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
}
}
void DumpRelTable(elfheader_t *h, int cnt, Elf32_Rel *rel, const char* name)
{
if(box86_log>=LOG_DUMP) {
+477 -234
View File
File diff suppressed because it is too large. Load diff
+16 -3
View File
@@ -5,10 +5,14 @@
typedef struct dynablocklist_s dynablocklist_t;
#endif
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
#include <pthread.h>
struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
Elf32_Phdr *PHEntries;
int numSHEntries;
@@ -48,7 +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;
@@ -67,9 +76,13 @@ struct elfheader_s {
int fini_done;
char* memory; // char* and not void* to allow math on memory pointer
#ifdef DYNAREC
dynablocklist_t *blocks;
#endif
void** multiblock;
uintptr_t* multiblock_offs;
uint32_t* multiblock_size;
int multiblock_n;
library_t *lib;
needed_libs_t *neededlibs;
};
#define R_386_NONE 0
+27 -11
View File
@@ -1,3 +1,4 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -23,7 +24,7 @@ int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type)
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
}
*SH = calloc(1, s->sh_size);
fseek(f, s->sh_offset ,SEEK_SET);
fseeko64(f, s->sh_offset ,SEEK_SET);
if(fread(*SH, s->sh_size, 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
return -1;
@@ -60,8 +61,9 @@ void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const ch
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
{
Elf32_Ehdr header;
int level = (exec)?LOG_INFO:LOG_DEBUG;
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read ELF Header\n");
printf_log(level, "Cannot read ELF Header\n");
return NULL;
}
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
@@ -69,11 +71,15 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return NULL;
}
if(header.e_ident[EI_CLASS]!=ELFCLASS32) {
printf_log(LOG_INFO, "Not an 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
if(header.e_ident[EI_CLASS]==ELFCLASS64) {
printf_log(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
} else {
printf_log(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
}
return NULL;
}
if(header.e_ident[EI_DATA]!=ELFDATA2LSB) {
printf_log(LOG_INFO, "Not an LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
printf_log(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
return NULL;
}
if(header.e_ident[EI_VERSION]!=EV_CURRENT) {
@@ -91,7 +97,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
}
if(header.e_machine != EM_386) {
printf_log(LOG_INFO, "Not an i386 ELF (%d)\n", header.e_machine);
printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine);
return NULL;
}
@@ -114,12 +120,12 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
h->SHIdx = header.e_shstrndx;
if(header.e_shentsize!=0) {
if(header.e_shentsize && header.e_shnum) {
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
// read 1st section header and grab actual number from here
fseek(f, header.e_shoff, SEEK_SET);
fseeko64(f, header.e_shoff, SEEK_SET);
Elf32_Shdr section;
if(fread(&section, sizeof(Elf32_Shdr), 1, f)!=1) {
free(h);
@@ -131,7 +137,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
// now read all section headers
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)calloc(h->numSHEntries, sizeof(Elf32_Shdr));
fseek(f, header.e_shoff ,SEEK_SET);
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Section Header\n");
@@ -147,14 +153,14 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
h->PHEntries = (Elf32_Phdr*)calloc(h->numPHEntries, sizeof(Elf32_Phdr));
fseek(f, header.e_phoff ,SEEK_SET);
fseeko64(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Program Header\n");
return NULL;
}
if(header.e_shentsize!=0) {
if(header.e_shentsize && header.e_shnum) {
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
h->SHIdx = h->SHEntries[0].sh_link;
@@ -194,6 +200,8 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->relasz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELAENT)
h->relaent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
h->pltgot = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTREL)
h->pltrel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
@@ -246,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");
+63
View File
@@ -47,10 +47,60 @@
base+=(nextop&0x80)?(F32S):(F8S); \
A = (T*)(base+O); \
}
#define getecommon16(A, T) \
{ \
uint32_t m = nextop&0xC7; \
uint32_t base = 0; \
switch(m&7) { \
case 0: base = R_BX+R_SI; break; \
case 1: base = R_BX+R_DI; break; \
case 2: base = R_BP+R_SI; break; \
case 3: base = R_BP+R_DI; break; \
case 4: base = R_SI; break; \
case 5: base = R_DI; break; \
case 6: base = R_BP; break; \
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
A = (T*)base; \
}
#define getecommon16o(A, T, O) \
{ \
uint32_t m = nextop&0xC7; \
uint32_t base = 0; \
switch(m&7) { \
case 0: base = R_BX+R_SI; break; \
case 1: base = R_BX+R_DI; break; \
case 2: base = R_BP+R_SI; break; \
case 3: base = R_BP+R_DI; break; \
case 4: base = R_SI; break; \
case 5: base = R_DI; break; \
case 6: base = R_BP; break; \
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
A = (T*)(base+O); \
}
#define geteb(A) \
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommon(A, reg32_t)
#define getebo(A, O) \
if((nextop&0xC0)==0xC0) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommono(A, reg32_t, O)
#define geted(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
@@ -67,12 +117,24 @@
if((nextop&0xC0)==0xC0) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
#define getew16(A) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16(A, reg32_t)
#define getew16o(A, O) \
if((nextop&0xC0)==0xC0) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16o(A, reg32_t, O)
// Macros for ModR/M gets
#define GET_EB geteb(oped)
#define GET_ED geted(oped)
#define GET_ED_OFFS(o) getedo(oped, o)
#define GET_EB_OFFS(o) getebo(oped, o)
#define GET_EM getem(opem)
#define GET_EX getex(opex)
#define GET_EW16 getew16(oped)
#define GET_EW16_OFFS(o) getew16o(oped, o)
#define EB oped
#define ED oped
#define EM opem
@@ -84,5 +146,6 @@
// Alias
#define GET_EW GET_ED
#define GET_EW_OFFS GET_ED_OFFS
#define EW ED
#define GW GD
+223 -99
View File
@@ -1,5 +1,33 @@
opcode = F8;
goto *opcodes0f[opcode];
_0f_0x00: /* VERx Ed */
nextop = F8;
switch((nextop>>3)&7) {
case 4: //VERR
case 5: //VERW
GET_EW;
if(!EW->word[0])
CLEAR_FLAG(F_ZF);
else
SET_FLAG(F_ZF); // should test if selector is ok
break;
default:
goto _default;
}
NEXT;
_0f_0x01:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* SMSW Ew */
GET_ED;
// dummy for now... Do I need to track CR0 state?
ED->word[0] = (1<<0) | (1<<4); // only PE and ET set...
break;
default:
goto _default;
}
NEXT;
_0f_0x0B: /* UD2 */
kill(getpid(), SIGILL); // this is undefined instruction
NEXT;
@@ -54,7 +82,27 @@
_0f_0x18: /* PREFETCHh Ed */
nextop = F8;
GET_ED;
__builtin_prefetch((void*)ED->dword[0], 0, 0); // inoring wich level of cache (roughly (nextop>>3)&7)
if((nextop&0xC0)==0xC0) {
} else
switch((nextop>>3)&7) {
case 0: //PREFETCHnta
case 1: //PREFETCH1
case 2: //PREFETCH2
case 3: //PREFETCH3
__builtin_prefetch((void*)ED, 0, 0); // ignoring wich level of cache
break;
default: //NOP
break;
}
NEXT;
_0f_0x1A: /* NOP (multi-byte) / ignored BNDLDX */
nextop = F8;
GET_ED;
NEXT;
_0f_0x1B: /* NOP (multi-byte) / ignored BNDSTX */
nextop = F8;
GET_ED;
NEXT;
_0f_0x1F: /* NOP (multi-byte) */
@@ -139,6 +187,64 @@
R_EAX = tmp64u&0xFFFFFFFF;
NEXT;
_0f_0x38: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: /* PSHUFB */
nextop = F8;
GET_EM;
eam1 = GM;
for (int i=0; i<8; ++i) {
if(EM->ub[i]&128)
GM.ub[i] = 0;
else
GM.ub[i] = eax1.ub[EM->ub[i]&7];
}
break;
case 0x04: /* PMADDUBSW Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
tmp32s = (int32_t)(GM.ub[i*2+0])*EM->sb[i*2+0] + (int32_t)(GM.ub[i*2+1])*EM->sb[i*2+1];
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x0B: /* PMULHRSW Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
tmp32s = ((((int32_t)(GM.sw[i])*(int32_t)(EM->sw[i]))>>14) + 1)>>1;
GM.uw[i] = tmp32s&0xffff;
}
break;
case 0x1C: /* PABSB Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<8; ++i) {
GM.sb[i] = abs(EM->sb[i]);
}
break;
case 0x1D: /* PABSW Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i) {
GM.sw[i] = abs(EM->sw[i]);
}
break;
case 0x1E: /* PABSD Gm, Em */
nextop = F8;
GET_EM;
for (int i=0; i<2; ++i) {
GM.sd[i] = abs(EM->sd[i]);
}
break;
default:
goto _default;
}
NEXT;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
_0f_##BASE##_0: \
PREFIX \
@@ -571,95 +677,16 @@
EM->q = GM.q;
NEXT;
_0f_0xA0: /* PUSH FS */
Push(emu, emu->segs[_FS]); // even if a segment is a 16bits, a 32bits push/pop is done
NEXT;
_0f_0xA1: /* POP FS */
emu->segs[_FS] = Pop(emu); // no check, no use....
emu->segs_serial[_FS] = 0;
NEXT;
_0f_0xA2: /* CPUID */
tmp32u = R_EAX;
switch(tmp32u) {
case 0x0:
// emulate a P4
R_EAX = 0x80000004;
// return GenuineIntel
R_EBX = 0x756E6547;
R_EDX = 0x49656E69;
R_ECX = 0x6C65746E;
break;
case 0x1:
R_EAX = 0x00000101; // familly and all
R_EBX = 0; // Brand indexe, CLFlush, Max APIC ID, Local APIC ID
R_EDX = 1 // fpu
| 1<<8 // cmpxchg8
| 1<<11 // sep (sysenter & sysexit)
| 1<<15 // cmov
| 1<<19 // clflush (seems to be with SSE2)
| 1<<23 // mmx
//| 1<<24 // fxsr (fxsave, fxrestore)
| 1<<25 // SSE
| 1<<26 // SSE2
;
R_ECX = 1<<12 // fma
| 1<<13 // cx16 (cmpxchg16)
; // also 1<<0 is SSE3 and 1<<9 is SSSE3
break;
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...
R_EAX = 0x665B5001;
R_EBX = 0x00000000;
R_ECX = 0x00000000;
R_EDX = 0x007A7000;
break;
case 0x4: // Cache info
switch (R_ECX) {
case 0: // L1 data cache
R_EAX = (1 | (1<<5) | (1<<8)); //type
R_EBX = (63 | (7<<22)); // size
R_ECX = 63;
R_EDX = 1;
break;
case 1: // L1 inst cache
R_EAX = (2 | (1<<5) | (1<<8)); //type
R_EBX = (63 | (7<<22)); // size
R_ECX = 63;
R_EDX = 1;
break;
case 2: // L2 cache
R_EAX = (3 | (2<<5) | (1<<8)); //type
R_EBX = (63 | (15<<22)); // size
R_ECX = 4095;
R_EDX = 1;
break;
default:
R_EAX = 0x00000000;
R_EBX = 0x00000000;
R_ECX = 0x00000000;
R_EDX = 0x00000000;
break;
}
break;
case 0x5: //mwait info
R_EAX = 0;
R_EBX = 0;
R_ECX = 1 | 2;
R_EDX = 0;
break;
case 0x6: // thermal
case 0x9: // direct cache access
case 0xA: // Architecture performance monitor
R_EAX = 0;
R_EBX = 0;
R_ECX = 0;
R_EDX = 0;
break;
case 0x7: // extended bits...
/*if(R_ECX==0) R_EAX = 0;
else*/ R_EAX = R_ECX = R_EBX = R_EDX = 0;
break;
case 0x80000000: // max extended
break; // no extended, so return same value as beeing the max value!
default:
printf_log(LOG_INFO, "Warning, CPUID command %X unsupported (ECX=%08x)\n", tmp32u, R_ECX);
R_EAX = 0;
}
my_cpuid(emu, tmp32u);
NEXT;
_0f_0xA3: /* BT Ed,Gd */
CHECK_FLAGS(emu);
@@ -684,6 +711,15 @@
ED->dword[0] = shld32(emu, ED->dword[0], GD.dword[0], tmp8u);
NEXT;
_0f_0xA8: /* PUSH GS */
Push(emu, emu->segs[_GS]); // even if a segment is a 16bits, a 32bits push/pop is done
NEXT;
_0f_0xA9: /* POP GS */
emu->segs[_GS] = Pop(emu);
emu->segs_serial[_GS] = 0;
NEXT;
_0f_0xAB: /* BTS Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
@@ -725,16 +761,23 @@
case 0: /* FXSAVE m512byte */
// should save flags & all
// copy MMX regs...
memcpy(ED->dword+32/4, &emu->mmx[0], sizeof(emu->mmx));
for(int i=0; i<8; ++i)
memcpy(((void*)(ED))+32+i*16, &emu->mmx[0], sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(ED->dword+160/4, &emu->xmm[0], sizeof(emu->xmm));
memcpy(((void*)(ED))+160, &emu->xmm[0], sizeof(emu->xmm));
// put also FPU regs in a reserved area...
for(int i=0; i<8; ++i)
memcpy(((void*)(ED))+416+i*8, &emu->fpu[0], sizeof(emu->fpu[0]));
break;
case 1: /* FXRSTOR m512byte */
// should restore flags & all
// copy MMX regs...
memcpy(&emu->mmx[0], ED->dword+32/4, sizeof(emu->mmx));
// copy back MMX regs...
for(int i=0; i<8; ++i)
memcpy(&emu->mmx[i], ((void*)(ED))+32+i*16, sizeof(emu->mmx[0]));
// copy SSE regs
memcpy(&emu->xmm[0], ED->dword+160/4, sizeof(emu->xmm));
memcpy(&emu->xmm[0], ((void*)(ED))+160/4, sizeof(emu->xmm));
for(int i=0; i<8; ++i)
memcpy(&emu->fpu[0], ((void*)(ED))+416+i*8, sizeof(emu->fpu[0]));
break;
case 2: /* LDMXCSR Md */
emu->mxcsr = ED->dword[0];
@@ -818,6 +861,22 @@
else
CLEAR_FLAG(F_CF);
break;
case 5: /* BTS Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->dword[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
break;
case 6: /* BTR Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
@@ -833,6 +892,21 @@
} else
CLEAR_FLAG(F_CF);
break;
case 7: /* BTC Ed, Ib */
CHECK_FLAGS(emu);
GET_ED;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
ED=(reg32_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
break;
default:
goto _default;
@@ -926,7 +1000,11 @@
GX.ud[i]=(tmp8s)?0xffffffff:0;
}
NEXT;
_0f_0xC3: /* MOVNTI Ed,Gd */
nextop = F8;
GET_ED;
ED->dword[0] = GD.dword[0];
NEXT;
_0f_0xC4: /* PINSRW Gm,Ew,Ib */
nextop = F8;
GET_ED;
@@ -1021,6 +1099,17 @@
}
NEXT;
_0f_0xD7: /* PMOVMSKB Gd,Em */
nextop = F8;
if((nextop&0xC0)==0xC0) {
GET_EM;
GD.dword[0] = 0;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
} else
goto _default;
_0f_0xD8: /* PSUBUSB Gm,Em */
nextop = F8;
GET_EM;
@@ -1037,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;
@@ -1059,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;
@@ -1119,6 +1218,13 @@
}
NEXT;
_0f_0xE7: /* MOVNTQ Em,Gm */
nextop = F8;
if((nextop&0xC0)==0xC0)
goto _default;
GET_EM;
EM->q = GM.q;
NEXT;
_0f_0xE8: /* PSUBSB Gm,Em */
nextop = F8;
GET_EM;
@@ -1135,7 +1241,12 @@
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
NEXT;
_0f_0xEA: /* PMINSW Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i)
GM.sw[i] = (GM.sw[i]<EM->sw[i])?GM.sw[i]:EM->sw[i];
NEXT;
_0f_0xEB: /* POR Gm, Em */
nextop = F8;
GET_EM;
@@ -1157,7 +1268,12 @@
GM.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
NEXT;
_0f_0xEE: /* PMAXSW Gm,Em */
nextop = F8;
GET_EM;
for (int i=0; i<4; ++i)
GM.sw[i] = (GM.sw[i]>EM->sw[i])?GM.sw[i]:EM->sw[i];
NEXT;
_0f_0xEF: /* PXOR Gm, Em */
nextop = F8;
GET_EM;
@@ -1215,7 +1331,15 @@
tmp32u += (GM.ub[i]>EM->ub[i])?(GM.ub[i] - EM->ub[i]):(EM->ub[i] - GM.ub[i]);
GM.q = tmp32u;
NEXT;
_0f_0xF7: /* MASKMOVQ Gm, Em */
nextop = F8;
if((nextop&0xC0)==0xC0) {
GET_EM;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80) ((uint8_t*)(R_EDI))[i] = GM.ub[i];
} else
goto _default;
NEXT;
_0f_0xF8: /* PSUBB Gm,Em */
nextop = F8;
GET_EM;
+121 -12
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,17 +43,36 @@
NEXT;
_66_0x07: /* POP ES */
emu->segs[_ES] = Pop16(emu); // no check, no use....
emu->segs_serial[_ES] = 0;
NEXT;
_66_0x0F: /* 66 0f prefix */
#include "run660f.h"
emu->old_ip = R_EIP;
R_EIP = ip-2; // don't count 66 0F yet
Run660F(emu); // implemented in Run660f.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0x1F: /* POP DS */
emu->segs[_DS] = Pop16(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
NEXT;
_66_0x26: /* ES: */
// ignored
NEXT;
opcode = F8;
goto *opcodes66[opcode];
_66_0x2E: /* CS: */
// ignored
NEXT;
opcode = F8;
goto *opcodes66[opcode];
_66_0x36: /* SS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x39:
nextop = F8;
GET_EW;
@@ -99,6 +131,27 @@
tmp8u = opcode&7;
emu->regs[tmp8u].word[0] = Pop16(emu);
NEXT;
_66_0x60: /* PUSHA */
tmp16u = R_SP;
Push16(emu, R_AX);
Push16(emu, R_CX);
Push16(emu, R_DX);
Push16(emu, R_BX);
Push16(emu, tmp16u);
Push16(emu, R_BP);
Push16(emu, R_SI);
Push16(emu, R_DI);
NEXT;
_66_0x61: /* POPA */
R_DI = Pop16(emu);
R_SI = Pop16(emu);
R_BP = Pop16(emu);
R_ESP+=2; // POP ESP
R_BX = Pop16(emu);
R_DX = Pop16(emu);
R_CX = Pop16(emu);
R_AX = Pop16(emu);
NEXT;
_66_0x66:
goto _0x66; // 0x66 0x66 => can remove one 0x66
@@ -174,13 +227,14 @@
_66_0x8C: /* MOV Ew,Seg */
nextop = F8;
GET_EW;
EW->word[0] = emu->segs[(nextop&38)>>3];
EW->word[0] = emu->segs[(nextop&0x38)>>3];
NEXT;
_66_0x8E: /* MOV Seg,Ew */
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[0];
emu->segs_serial[((nextop&0x38)>>3)] = 0;
NEXT;
_66_0x8F: /* POP Ew */
nextop = F8;
@@ -190,10 +244,16 @@
_66_0x90: /* NOP */
NEXT;
_66_0x92: /* XCHG DX,AX */
_66_0x91:
_66_0x92:
_66_0x93:
_66_0x94:
_66_0x95:
_66_0x96:
_66_0x97: /* XCHG reg,EAX */
tmp16u = R_AX;
R_AX = R_DX;
R_DX = tmp16u;
R_AX = emu->regs[opcode&7].word[0];
emu->regs[opcode&7].word[0] = tmp16u;
NEXT;
_66_0x98: /* CBW */
@@ -205,8 +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);
emu->eflags.x32 &=0xffff0000;
emu->eflags.x32 |= (Pop16(emu) & 0x3F7FD7) | 0x2;
NEXT;
_66_0xA1: /* MOV AX,Ow */
@@ -284,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;
@@ -302,21 +382,31 @@
NEXT;
_66_0xD9:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
Run66D9(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xDD:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
Run66DD(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF0: /* LOCK prefix */
emu->old_ip = R_EIP;
R_EIP = ip;
RunLock66(emu);
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_66_0xF2: /* REPNZ prefix */
_66_0xF3: /* REPZ prefix */
@@ -324,6 +414,14 @@
tmp8s = ACCESS_FLAG(F_DF)?-2:+2;
tmp32u = R_ECX;
switch(nextop) {
case 0xA4: /* REP MOVSB */
while(tmp32u) {
--tmp32u;
*(uint8_t*)R_EDI = *(uint8_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
}
break;
case 0xA5: /* REP MOVSW */
while(tmp32u) {
--tmp32u;
@@ -405,6 +503,14 @@
break;
}
NEXT;
_66_0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
NEXT;
_66_0xF9: /* STC */
CHECK_FLAGS(emu);
SET_FLAG(F_CF);
NEXT;
_66_0xFF: /* GRP 5 Ew */
nextop = F8;
@@ -416,8 +522,11 @@
case 1: /* DEC Ed */
EW->word[0] = dec16(emu, EW->word[0]);
break;
case 6:
Push16(emu, EW->word[0]);
break;
default:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 66 %02X %02X\n", opcode, nextop);
emu->quit=1;
+8 -88
View File
@@ -10,11 +10,7 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST0.f += ST(nextop&7).f;
#else
ST0.d += ST(nextop&7).d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -24,11 +20,7 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST0.f *= ST(nextop&7).f;
#else
ST0.d *= ST(nextop&7).d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -38,11 +30,7 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -52,11 +40,7 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -67,11 +51,7 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUB */
#ifdef USE_FLOAT
ST0.f -= ST(nextop&7).f;
#else
ST0.d -= ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -81,11 +61,7 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUBR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f - ST0.f;
#else
ST0.d = ST(nextop&7).d - ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -95,11 +71,7 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIV */
#ifdef USE_FLOAT
ST0.f /= ST(nextop&7).f;
#else
ST0.d /= ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -109,46 +81,26 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIVR */
#ifdef USE_FLOAT
ST0.f = ST(nextop&7).f / ST0.f;
#else
ST0.d = ST(nextop&7).d / ST0.d;
#endif
break;
default:
switch((nextop>>3)&7) {
case 0: /* FADD ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f += *(float*)ED;
#else
ST0.d += *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f += f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d += f;
#endif
}
break;
case 1: /* FMUL ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f *= *(float*)ED;
#else
ST0.d *= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f *= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d *= f;
#endif
}
break;
case 2: /* FCOM ST0, float */
@@ -156,7 +108,7 @@
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
*(uint32_t*)&f = ED->dword[0];
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
break;
@@ -165,7 +117,7 @@
if(!(((uintptr_t)ED)&3))
fpu_fcom(emu, *(float*)ED);
else {
*(uint32_t*)&f = ED->dword[0];
memcpy(&f, ED, sizeof(float));
fpu_fcom(emu, f);
}
fpu_do_pop(emu);
@@ -173,69 +125,37 @@
case 4: /* FSUB ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f -= *(float*)ED;
#else
ST0.d -= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f -= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d -= f;
#endif
}
break;
case 5: /* FSUBR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED - ST0.f;
#else
ST0.d = *(float*)ED - ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f - ST0.f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d = f - ST0.d;
#endif
}
break;
case 6: /* FDIV ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f /= *(float*)ED;
#else
ST0.d /= *(float*)ED;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f /= f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d /= f;
#endif
}
break;
case 7: /* FDIVR ST0, float */
GET_ED;
if(!(((uintptr_t)ED)&3))
#ifdef USE_FLOAT
ST0.f = *(float*)ED / ST0.f;
#else
ST0.d = *(float*)ED / ST0.d;
#endif
else {
*(uint32_t*)&f = ED->dword[0];
#ifdef USE_FLOAT
ST0.f = f / ST0.f;
#else
memcpy(&f, ED, sizeof(float));
ST0.d = f / ST0.d;
#endif
}
break;
default:
+55 -131
View File
@@ -1,5 +1,3 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch (nextop) {
case 0xC0:
@@ -31,18 +29,10 @@
break;
case 0xE0: /* FCHS */
#ifdef USE_FLOAT
ST0.f = -ST0.f;
#else
ST0.d = -ST0.d;
#endif
break;
case 0xE1: /* FABS */
#ifdef USE_FLOAT
ST0.f = fabsf(ST0.f);
#else
ST0.d = fabs(ST0.d);
#endif
break;
case 0xE4: /* FTST */
@@ -54,175 +44,128 @@
case 0xE8: /* FLD1 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 1.0f;
#else
ST0.d = 1.0;
#endif
break;
case 0xE9: /* FLDL2T */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2T;
#else
ST0.d = L2T;
#endif
break;
case 0xEA: /* FLDL2E */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = L2E;
#else
ST0.d = L2E;
#endif
break;
case 0xEB: /* FLDPI */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = PI;
#else
ST0.d = PI;
#endif
break;
case 0xEC: /* FLDLG2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LG2;
#else
ST0.d = LG2;
#endif
break;
case 0xED: /* FLDLN2 */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = LN2;
#else
ST0.d = LN2;
#endif
break;
case 0xEE: /* FLDZ */
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = 0.0f;
#else
ST0.d = 0.0;
#endif
break;
case 0xF0: /* F2XM1 */
#ifdef USE_FLOAT
ST0.f = exp2f(ST0.f) - 1.0f;
#else
ST0.d = exp2(ST0.d) - 1.0;
#endif
break;
case 0xF1: /* FYL2X */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f)*ST(1).f;
#else
ST(1).d = log2(ST0.d)*ST(1).d;
#endif
ST(1).d *= log2(ST0.d);
fpu_do_pop(emu);
break;
case 0xF2: /* FTAN */
#ifdef USE_FLOAT
ST0.f = tanf(ST0.f);
fpu_do_push(emu);
ST0.f = 1.0f;
#else
case 0xF2: /* FPTAN */
ST0.d = tan(ST0.d);
fpu_do_push(emu);
ST0.d = 1.0;
#endif
emu->sw.f.F87_C2 = 0;
break;
case 0xF3: /* FPATAN */
#ifdef USE_FLOAT
ST1.f = atan2f(ST1.f, ST0.f);
#else
ST1.d = atan2(ST1.d, ST0.d);
#endif
fpu_do_pop(emu);
break;
case 0xF4: /* FXTRACT */
#ifdef USE_FLOAT
tmp32s = (ST0.ll&0x7f700000)>>23;
tmp32s -= 127;
ST0.f /= exp2f(tmp32s);
fpu_do_push(emu);
ST0.f = tmp32s;
#else
tmp32s = (ST0.ll&0x7ff0000000000000LL)>>52;
tmp32s -= 1023;
ST0.d /= exp2(tmp32s);
ST0.d = frexp(ST0.d, &tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
#endif
break;
case 0xF8: /* FPREM */
#ifdef USE_FLOAT
tmp32s = ST0.f / ST1.f;
ST0.f -= ST1.f * tmp32s;
#else
tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
#endif
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
{
int e0, e1;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
tmp32s = e0 - e1;
}
if(tmp32s<64)
{
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
break;
case 0xF5: /* FPREM1 */
// get exponant(ST(0))-exponant(ST(1)) in temp32s
{
int e0, e1;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
tmp32s = e0 - e1;
}
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
break;
case 0xF6: /* FDECSTP */
emu->top=(emu->top-1)&7; // this will probably break a few things
break;
case 0xF7: /* FINCSTP */
emu->top=(emu->top+1)&7; // this will probably break a few things
break;
case 0xF9: /* FYL2XP1 */
#ifdef USE_FLOAT
ST(1).f = log2f(ST0.f + 1.0f)*ST(1).f;
#else
ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
#endif
ST(1).d *= log2(ST0.d + 1.0);
fpu_do_pop(emu);
break;
case 0xFA: /* FSQRT */
#ifdef USE_FLOAT
ST0.f = sqrtf(ST0.f);
#else
ST0.d = sqrt(ST0.d);
#endif
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
#ifdef USE_FLOAT
sincosf(ST1.f, &ST1.f, &ST0.f);
#else
sincos(ST1.d, &ST1.d, &ST0.d);
#endif
break;
case 0xFC: /* FRNDINT */
#ifdef USE_FLOAT
ST0.f = fpu_round(emu, ST0.f);
#else
ST0.d = fpu_round(emu, ST0.d);
#endif
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
#ifdef USE_FLOAT
ST0.f *= exp2f(truncf(ST1.f));
#else
ST0.d *= exp2(trunc(ST1.d));
#endif
break;
case 0xFE: /* FSIN */
#ifdef USE_FLOAT
ST0.f = sinf(ST0.f);
#else
ST0.d = sin(ST0.d);
#endif
break;
case 0xFF: /* FCOS */
#ifdef USE_FLOAT
ST0.f = cosf(ST0.f);
#else
ST0.d = cos(ST0.d);
#endif
break;
@@ -244,51 +187,36 @@
case 0xE6:
case 0xE7:
case 0xEF:
case 0xF5:
case 0xF6:
case 0xF7:
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FLD ST0, Ed float */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.ll = ED->dword[0];
#else
if(!(((uintptr_t)ED)&3))
ST0.d = *(float*)ED;
else {
memcpy(&f, ED->dword, sizeof(float));
memcpy(&f, ED, sizeof(float));
ST0.d = f;
}
#endif
break;
case 2: /* FST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
*(float*)ED = ST0.f;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
memcpy(ED, &f, sizeof(float));
}
#endif
break;
case 3: /* FSTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
ED->dword[0] = ST0.ll;
#else
if(!(((uintptr_t)ED)&3))
*(float*)ED = ST0.d;
else {
f = ST0.d;
memcpy(ED->dword, &f, sizeof(float));
memcpy(ED, &f, sizeof(float));
}
#endif
fpu_do_pop(emu);
break;
case 4: /* FLDENV m */
@@ -306,9 +234,6 @@
// warning, incomplete
GET_ED;
fpu_savenv(emu, (char*)ED, 0);
ED->dword[0] = emu->cw;
ED->dword[1] = emu->sw.x16;
// tagword: 2bits*8
// intruction pointer: 48bits
// data (operand) pointer: 48bits
// last opcode: 11bits save: 16bits restaured (1st and 2nd opcode only)
@@ -321,4 +246,3 @@
goto _default;
}
}
#pragma GCC diagnostic pop
+2 -30
View File
@@ -51,11 +51,7 @@
break;
case 0xE9: /* FUCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -76,19 +72,11 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f += ED->sdword[0];
#else
ST0.d += ED->sdword[0];
#endif
break;
case 1: /* FIMUL ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f *= ED->sdword[0];
#else
ST0.d *= ED->sdword[0];
#endif
break;
case 2: /* FICOM ST0, Ed int */
GET_ED;
@@ -101,35 +89,19 @@
break;
case 4: /* FISUB ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f -= ED->sdword[0];
#else
ST0.d -= ED->sdword[0];
#endif
break;
case 5: /* FISUBR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] - ST0.f;
#else
ST0.d = ED->sdword[0] - ST0.d;
#endif
ST0.d = (double)ED->sdword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f /= ED->sdword[0];
#else
ST0.d /= ED->sdword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ed int */
GET_ED;
#ifdef USE_FLOAT
ST0.f = ED->sdword[0] / ST0.f;
#else
ST0.d = ED->sdword[0] / ST0.d;
#endif
ST0.d = (double)ED->sdword[0] / ST0.d;
break;
}
}
+10 -102
View File
@@ -49,6 +49,8 @@
ST0.ll = ST(nextop&7).ll;
break;
case 0xE1: /* FDISI8087_NOP */
break;
case 0xE2: /* FNCLEX */
//Clears the floating-point exception flags (PE, UE, OE, ZE, DE, and IE),
// the exception summary status flag (ES), the stack fault flag (SF), and the busy flag (B) in the FPU status word
@@ -73,11 +75,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xF0: /* FCOMI ST0, STx */
@@ -88,14 +86,9 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
break;
case 0xE0:
case 0xE1:
case 0xE4:
case 0xE5:
case 0xE6:
@@ -103,134 +96,49 @@
goto _default;
default:
switch((nextop>>3)&7) {
case 0: /* FILD ST0, Gd */
case 0: /* FILD ST0, Ed */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = ED->sdword[0];
#else
ST0.d = ED->sdword[0];
#endif
break;
case 1: /* FISTTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
tmp32s = ST0.f; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.f, (float)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#else
tmp32s = ST0.d; // TODO: Handling of FPU Exception
if(tmp32s==0x7fffffff && isgreater(ST0.d, (double)(int32_t)0x7fffffff))
tmp32s = 0x80000000;
#endif
fpu_do_pop(emu);
ED->sdword[0] = tmp32s;
break;
case 2: /* FIST Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(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 {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
ED->sdword[0] = tmp;
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
break;
case 3: /* FISTP Ed, ST0 */
GET_ED;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fffffff) || isless(ST0.f, -(float)(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 {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floorf(ST0.f);
break;
case ROUND_Up:
ED->sdword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.f;
break;
}
volatile int32_t tmp = fpu_round(emu, ST0.d); // tmp to avoid BUS ERROR
ED->sdword[0] = tmp;
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fffffff) || isless(ST0.d, -(double)(int32_t)0x7fffffff))
ED->sdword[0] = 0x80000000;
else {
switch(emu->round) {
case ROUND_Nearest:
ED->sdword[0] = floor(ST0.d+0.5);
break;
case ROUND_Down:
ED->sdword[0] = floor(ST0.d);
break;
case ROUND_Up:
ED->sdword[0] = ceil(ST0.d);
break;
case ROUND_Chop:
ED->sdword[0] = ST0.d;
break;
}
}
#endif
fpu_do_pop(emu);
break;
case 5: /* FLD ST0, Gt */
case 5: /* FLD ST0, Et */
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
#ifdef USE_FLOAT
LD2D(&STld(0), &d);
ST0.f = d;
#else
LD2D(&STld(0), &ST(0).d);
#endif
STld(0).ref = ST0.ll;
break;
case 7: /* FSTP tbyte */
GET_ED;
if(ST0.ll!=STld(0).ref)
#ifdef USE_FLOAT
{d = ST0.f; D2LD(&d, ED);}
#else
D2LD(&ST0.d, ED);
#endif
else
memcpy(ED, &STld(0).ld, 10);
fpu_do_pop(emu);
+8 -96
View File
@@ -1,5 +1,3 @@
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
nextop = F8;
switch(nextop) {
case 0xC0:
@@ -10,11 +8,7 @@
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
break;
case 0xC8:
case 0xC9:
@@ -24,11 +18,7 @@
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
break;
case 0xD0:
case 0xD1:
@@ -38,11 +28,7 @@
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d);
#endif
break;
case 0xD8:
case 0xD9:
@@ -52,11 +38,7 @@
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // TODO: is this ok?
#endif
fpu_do_pop(emu);
break;
case 0xE0:
@@ -67,11 +49,7 @@
case 0xE5:
case 0xE6:
case 0xE7: /* FSUBR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f -ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
#endif
break;
case 0xE8:
case 0xE9:
@@ -81,11 +59,7 @@
case 0xED:
case 0xEE:
case 0xEF: /* FSUB */
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
break;
case 0xF0:
case 0xF1:
@@ -95,11 +69,7 @@
case 0xF5:
case 0xF6:
case 0xF7: /* FDIVR */
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
break;
case 0xF8:
case 0xF9:
@@ -109,54 +79,32 @@
case 0xFD:
case 0xFE:
case 0xFF: /* FDIV */
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
break;
default:
GET_ED;
switch((nextop>>3)&7) {
case 0: /* FADD ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f += d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d += *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d += d;
}
#endif
break;
case 1: /* FMUL ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f *= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d *= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d *= d;
}
#endif
break;
case 2: /* FCOM ST0, double */
if(!(((uintptr_t)ED)&7))
fpu_fcom(emu, *(double*)ED);
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
fpu_fcom(emu, d);
}
break;
@@ -164,78 +112,42 @@
if(!(((uintptr_t)ED)&7))
fpu_fcom(emu, *(double*)ED);
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
fpu_fcom(emu, d);
}
fpu_do_pop(emu);
break;
case 4: /* FSUB ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f -= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d -= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d -= d;
}
#endif
break;
case 5: /* FSUBR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED - ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d - ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED - ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d = d - ST0.d;
}
#endif
break;
case 6: /* FDIV ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f /= d;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d /= *(double*)ED;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d /= d;
}
#endif
break;
case 7: /* FDIVR ST0, double */
#ifdef USE_FLOAT
if(!(((uintptr_t)ED)&7))
ST0.f = *(double*)ED / ST0.f;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
ST0.f = d / ST0.f;
}
#else
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED / ST0.d;
else {
*(uint64_t*)&d = *(uint64_t*)ED;
memcpy(&d, ED, sizeof(double));
ST0.d = d / ST0.d;
}
#endif
break;
default:
goto _default;
+23 -42
View File
@@ -9,7 +9,8 @@
case 0xC5:
case 0xC6:
case 0xC7:
break; // not handling Tag...
fpu_do_free(emu, nextop-0xC0);
break;
case 0xD0: /* FST ST0, STx */
case 0xD1:
@@ -40,11 +41,7 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
break;
case 0xE8: /* FUCOMP ST0, STx */
case 0xE9:
@@ -54,11 +51,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcom(emu, ST(nextop&7).f);
#else
fpu_fcom(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
@@ -93,39 +86,37 @@
case 0: /* FLD double */
GET_ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
*(uint64_t*)&d = *(int64_t*)ED;
ST0.f = d;
#else
ST0.ll = *(int64_t*)ED;
#endif
if(!(((uintptr_t)ED)&7))
ST0.d = *(double*)ED;
else {
memcpy(&ST0.d, ED, sizeof(double));
}
break;
case 1: /* FISTTP ED qword */
GET_ED;
#ifdef USE_FLOAT
*(int64_t*)ED = ST0.f;
#else
*(int64_t*)ED = ST0.d;
#endif
if(!(((uintptr_t)ED)&7))
*(int64_t*)ED = ST0.d;
else {
int64_t i64 = ST0.d;
memcpy(ED, &i64, sizeof(int64_t));
}
fpu_do_pop(emu);
break;
case 2: /* FST double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
break;
case 3: /* FSTP double */
GET_ED;
#ifdef USE_FLOAT
d = ST0.f;
*(int64_t*)ED = *(uint64_t*)&d;
#else
*(int64_t*)ED = ST0.ll;
#endif
if(!(((uintptr_t)ED)&7))
*(double*)ED = ST0.d;
else {
memcpy(ED, &ST0.d, sizeof(double));
}
fpu_do_pop(emu);
break;
case 4: /* FRSTOR m108byte */
@@ -136,12 +127,7 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
d = ST(i).f;
LD2D(p, &d);
#else
LD2D(p, &ST(i).d);
#endif
p+=10;
}
}
@@ -156,12 +142,7 @@
char* p =(char*)ED;
p += 28;
for (int i=0; i<8; ++i) {
#ifdef USE_FLOAT
D2LD(&d, p);
ST(i).f = d;
#else
D2LD(&ST(i).d, p);
#endif
p+=10;
}
}
+18 -87
View File
@@ -1,55 +1,41 @@
nextop = F8;
switch (nextop) {
case 0xC1: /* FADDP ST1, ST0 */
#ifdef USE_FLOAT
ST(1).f += ST0.f;
#else
ST(1).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC0: /* FADDP STx, ST0 */
case 0xC1: /* FADDP ST1, ST0 */
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
#ifdef USE_FLOAT
ST(nextop&7).f += ST0.f;
#else
ST(nextop&7).d += ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC9: /* FMULP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f *= ST0.f;
#else
ST1.d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xC8: /* FMULP STx, ST0 */
case 0xC9: /* FMULP ST1, ST0 */
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
#ifdef USE_FLOAT
ST(nextop&7).f *= ST0.f;
#else
ST(nextop&7).d *= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7: /* FCOMP */
fpu_fcom(emu, ST(nextop&7).d);
fpu_do_pop(emu);
break;
case 0xD9: /* FCOMPP */
#ifdef USE_FLOAT
fpu_fcom(emu, ST1.f);
#else
fpu_fcom(emu, ST1.d);
#endif
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
@@ -65,33 +51,18 @@
case 0xE5:
case 0xE6:
case 0xE7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f - ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
case 0xE9: /* FSUBP ST1, ST0 */
#ifdef USE_FLOAT
ST1.f -= ST0.f;
#else
ST1.d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xE8: /* FSUBP STx, ST0 */
case 0xE9: /* FSUBP ST1, ST0 */
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
ST(nextop&7).f -= ST0.f;
#else
ST(nextop&7).d -= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xF0: /* FDIVRP STx, ST0 */
@@ -102,11 +73,7 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
ST(nextop&7).f = ST0.f / ST(nextop&7).f;
#else
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
#endif
fpu_do_pop(emu);
break;
case 0xF8: /* FDIVP STx, ST0 */
@@ -117,23 +84,11 @@
case 0xFD:
case 0xFE:
case 0xFF:
#ifdef USE_FLOAT
ST(nextop&7).f /= ST0.f;
#else
ST(nextop&7).d /= ST0.d;
#endif
fpu_do_pop(emu);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
@@ -146,51 +101,27 @@
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f += EW->sword[0];
#else
ST0.d += EW->sword[0];
#endif
break;
case 1: /* FIMUL ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f *= EW->sword[0];
#else
ST0.d *= EW->sword[0];
#endif
break;
case 4: /* FISUB ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f -= EW->sword[0];
#else
ST0.d -= EW->sword[0];
#endif
break;
case 5: /* FISUBR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] - ST0.f;
#else
ST0.d = EW->sword[0] - ST0.d;
#endif
ST0.d = (double)EW->sword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f /= EW->sword[0];
#else
ST0.d /= EW->sword[0];
#endif
break;
case 7: /* FIDIVR ST0, Ew int */
GET_EW;
#ifdef USE_FLOAT
ST0.f = EW->sword[0] / ST0.f;
#else
ST0.d = EW->sword[0] / ST0.d;
#endif
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
goto _default;
+38 -117
View File
@@ -1,5 +1,17 @@
nextop = F8;
switch (nextop) {
case 0xC0: /* FFREEP STx */
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
fpu_do_free(emu, nextop-0xC0);
fpu_do_pop(emu);
break;
case 0xE0: /* FNSTSW AX */
emu->sw.f.F87_TOP = emu->top&7;
R_AX = emu->sw.x16;
@@ -13,11 +25,7 @@
case 0xED:
case 0xEE:
case 0xEF:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d); // bad, should handle QNaN and IA interrupt
#endif
fpu_do_pop(emu);
break;
@@ -29,22 +37,10 @@
case 0xF5:
case 0xF6:
case 0xF7:
#ifdef USE_FLOAT
fpu_fcomi(emu, ST(nextop&7).f);
#else
fpu_fcomi(emu, ST(nextop&7).d);
#endif
fpu_do_pop(emu);
break;
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
@@ -92,105 +88,27 @@
GET_EW;
tmp16s = EW->sword[0];
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp16s;
#else
ST0.d = tmp16s;
#endif
break;
case 1: /* FISTTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
tmp16s = ST0.f;
#else
tmp16s = ST0.d;
#endif
EW->sword[0] = tmp16s;
fpu_do_pop(emu);
break;
case 2: /* FIST Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(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] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
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;
}
}
#endif
else
EW->sword[0] = fpu_round(emu, ST0.d);
break;
case 3: /* FISTP Ew, ST0 */
GET_EW;
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int32_t)0x7fff) || isless(ST0.f, -(float)(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] = floorf(ST0.f+0.5);
break;
case ROUND_Down:
EW->sword[0] = floorf(ST0.f);
break;
case ROUND_Up:
EW->sword[0] = ceilf(ST0.f);
break;
case ROUND_Chop:
EW->sword[0] = ST0.f;
break;
}
}
#else
if(isgreater(ST0.d, (double)(int32_t)0x7fff) || isless(ST0.d, -(double)(int32_t)0x7fff))
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;
}
}
#endif
else
EW->sword[0] = fpu_round(emu, ST0.d);
fpu_do_pop(emu);
break;
case 4: /* FBLD ST0, tbytes */
@@ -202,11 +120,7 @@
GET_ED;
tmp64s = *(int64_t*)ED;
fpu_do_push(emu);
#ifdef USE_FLOAT
ST0.f = tmp64s;
#else
ST0.d = tmp64s;
#endif
STll(0).ll = tmp64s;
STll(0).ref = ST0.ll;
break;
@@ -217,20 +131,27 @@
break;
case 7: /* FISTP i64 */
GET_ED;
if(STll(0).ref==ST(0).ll) {
*(int64_t*)ED = STll(0).ll;
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;
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 {
#ifdef USE_FLOAT
if(isgreater(ST0.f, (float)(int64_t)0x7fffffffffffffffLL) || isless(ST0.f, (float)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.f;
#else
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, (double)(int64_t)0x8000000000000000LL))
*(int64_t*)ED = 0x8000000000000000LL;
else
*(int64_t*)ED = (int64_t)ST0.d;
#endif
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);
break;
+116
View File
@@ -111,6 +111,107 @@
}
break;
case 0x7C: /* HADDPS Gx, Ex */
nextop = F8;
GET_EX;
GX.f[0] += GX.f[1];
GX.f[1] = GX.f[2] + GX.f[3];
if(EX==&GX) {
GX.f[2] = GX.f[0];
GX.f[3] = GX.f[1];
} else {
GX.f[2] = EX->f[0] + EX->f[1];
GX.f[3] = EX->f[2] + EX->f[3];
}
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
case BASE+0: \
PREFIX \
if(ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+1: \
PREFIX \
if(!ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+2: \
PREFIX \
if(ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+3: \
PREFIX \
if(!ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+4: \
PREFIX \
if(ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+5: \
PREFIX \
if(!ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+6: \
PREFIX \
if((ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+7: \
PREFIX \
if(!(ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+8: \
PREFIX \
if(ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+9: \
PREFIX \
if(!ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+0xA: \
PREFIX \
if(ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xB: \
PREFIX \
if(!ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xC: \
PREFIX \
if(ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xD: \
PREFIX \
if(ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xE: \
PREFIX \
if(ACCESS_FLAG(F_ZF) || (ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break; \
case BASE+0xF: \
PREFIX \
if(!ACCESS_FLAG(F_ZF) && (ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break;
GOCOND(0x80
, tmp32s = F32S; CHECK_FLAGS(emu);
, ip += tmp32s;
) /* 0x80 -> 0x8F Jxx */
case 0xC2: /* CMPSD Gx, Ex, Ib */
nextop = F8;
GET_EX;
@@ -129,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;
@@ -143,6 +253,12 @@
GX.q[1] = 0;
break;
case 0xF0: /* LDDQU Gx, Ex */
nextop = F8;
GET_EX;
memcpy(&GX, EX, 16);
break;
default:
goto _default;
}
+24 -2
View File
@@ -15,6 +15,28 @@
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;
GET_ED;
break;
case 0x1F: /* REP NOP */
nextop = F8;
GET_ED;
break;
case 0x2A: /* CVTSI2SS Gx, Ed */
nextop = F8;
@@ -141,7 +163,7 @@
memcpy(EX, &GX, 16); // unaligned...
break;
case 0xBC: /* TZCNT Ew,Gw */
case 0xBC: /* TZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
@@ -151,7 +173,7 @@
tmp8u = 0;
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
GD.dword[0] = tmp8u;
CONDITIONAL_SET_FLAG(tmp8u, F_ZF);
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CLEAR_FLAG(F_CF);
} else {
CLEAR_FLAG(F_ZF);
+70 -75
View File
@@ -12,9 +12,12 @@
#include "x86emu_private.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "x86trace.h"
#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,11 +63,9 @@ 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?
if(ownstack)
emu->stack = (void*)stack;
emu->stack2free = (ownstack)?(void*)stack:NULL;
emu->init_stack = (void*)stack;
emu->size_stack = stacksize;
// set default value
@@ -66,18 +74,13 @@ static void internalX86Setup(x86emu_t* emu, box86context_t *context, uintptr_t s
// fake init of segments...
emu->segs[_CS] = 0x73;
emu->segs[_DS] = emu->segs[_ES] = emu->segs[_SS] = 0x7b;
emu->segs[_FS] = 0;
emu->segs[_FS] = default_fs;
emu->segs[_GS] = 0x33;
// setup fpu regs
reset_fpu(emu);
// if trace is activated
if(context->x86trace) {
emu->dec = InitX86TraceDecoder(context);
if(!emu->dec)
printf_log(LOG_INFO, "Failed to initialize Zydis decoder and formater, no trace activated\n");
}
}
EXPORTDYN
x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, int stacksize, int ownstack)
{
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
@@ -98,101 +101,85 @@ x86emu_t *NewX86EmuFromStack(x86emu_t* emu, box86context_t *context, uintptr_t s
return emu;
}
EXPORTDYN
void SetupX86Emu(x86emu_t *emu)
{
printf_log(LOG_DEBUG, "Setup X86 Emu\n");
}
void SetTraceEmu(x86emu_t *emu, uintptr_t trace_start, uintptr_t trace_end)
void SetTraceEmu(uintptr_t start, uintptr_t end)
{
if(emu->dec) {
if (trace_end == 0) {
if(my_context->zydis) {
if (end == 0) {
printf_log(LOG_INFO, "Setting trace\n");
} else {
if(trace_end!=1) { // 0-1 is basically no trace, so don't printf it...
printf_log(LOG_INFO, "Setting trace only between %p and %p\n", (void*)trace_start, (void*)trace_end);
if(end!=1) { // 0-1 is basically no trace, so don't printf it...
printf_log(LOG_INFO, "Setting trace only between %p and %p\n", (void*)start, (void*)end);
}
}
}
emu->trace_start = trace_start;
emu->trace_end = trace_end;
trace_start = start;
trace_end = end;
}
void AddCleanup(x86emu_t *emu, void *p)
{
if(emu->clean_sz == emu->clean_cap) {
emu->clean_cap += 4;
emu->cleanups = (cleanup_t*)realloc(emu->cleanups, sizeof(cleanup_t)*emu->clean_cap);
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
emu->cleanups[emu->clean_sz].arg = 0;
emu->cleanups[emu->clean_sz++].f = p;
my_context->cleanups[my_context->clean_sz].arg = 0;
my_context->cleanups[my_context->clean_sz].a = NULL;
my_context->cleanups[my_context->clean_sz++].f = p;
}
void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
{
if(emu->clean_sz == emu->clean_cap) {
emu->clean_cap += 4;
emu->cleanups = (cleanup_t*)realloc(emu->cleanups, sizeof(cleanup_t)*emu->clean_cap);
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
emu->cleanups[emu->clean_sz].arg = 1;
emu->cleanups[emu->clean_sz].a = a;
emu->cleanups[emu->clean_sz++].f = p;
my_context->cleanups[my_context->clean_sz].arg = 1;
my_context->cleanups[my_context->clean_sz].a = a;
my_context->cleanups[my_context->clean_sz++].f = p;
}
void CallCleanup(x86emu_t *emu, void* p)
{
for(int i=emu->clean_sz-1; i>=0; --i) {
if(p==emu->cleanups[i].f) {
printf_log(LOG_DEBUG, "Calling atexit registered functions for %p mask\n", p);
for(int i=my_context->clean_sz-1; i>=0; --i) {
if(p==my_context->cleanups[i].f) {
printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
if(emu->cleanups[i].arg)
Push(emu, (uintptr_t)emu->cleanups[i].a);
PushExit(emu);
emu->ip.dword[0] = (uintptr_t)(emu->cleanups[i].f);
Run(emu, 0);
emu->quit = 0;
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
// now remove the cleanup
if(i!=emu->clean_sz-1)
memmove(emu->cleanups+i, emu->cleanups+i+1, (emu->clean_sz-i-1)*sizeof(cleanup_t));
--emu->clean_sz;
return;
if(i!=my_context->clean_sz-1)
memmove(my_context->cleanups+i, my_context->cleanups+i+1, (my_context->clean_sz-i-1)*sizeof(cleanup_t));
--my_context->clean_sz;
}
}
}
void CallAllCleanup(x86emu_t *emu)
{
/* disabling for now...
for(int i=emu->clean_sz-1; i>=0; --i) {
printf_log(LOG_DEBUG, "Calling atexit registered functions\n");
for(int i=my_context->clean_sz-1; i>=0; --i) {
printf_log(LOG_DEBUG, "Call cleanup #%d\n", i);
if(emu->cleanups[i].arg)
Push(emu, (uintptr_t)emu->cleanups[i].a);
PushExit(emu);
emu->ip.dword[0] = (uintptr_t)(emu->cleanups[i].f);
Run(emu);
emu->quit = 0;
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
}
*/
emu->clean_sz = 0;
my_context->clean_sz = 0;
}
static void internalFreeX86(x86emu_t* emu)
{
// stop trace now
if(emu->dec)
DeleteX86TraceDecoder(&emu->dec);
emu->dec = NULL;
// call atexit and fini first!
CallAllCleanup(emu);
free(emu->cleanups);
free(emu->stack);
free(emu->stack2free);
}
EXPORTDYN
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);
@@ -204,21 +191,19 @@ 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);
*emu = NULL;
}
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_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));
@@ -234,10 +219,9 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
newemu->error = emu->error;
SetTraceEmu(newemu, emu->trace_start, emu->trace_end);
// addapt R_ESP to new stack frame
uintptr_t oldst = (uintptr_t)((emu->stack)?emu->stack:emu->context->stack);
uintptr_t newst = (uintptr_t)((newemu->stack)?newemu->stack:newemu->context->stack);
// adapt R_ESP to new stack frame
uintptr_t oldst = (uintptr_t)((emu->init_stack)?emu->init_stack:emu->context->stack);
uintptr_t newst = (uintptr_t)((newemu->init_stack)?newemu->init_stack:newemu->context->stack);
newemu->regs[_SP].dword[0] = emu->regs[_SP].dword[0] + (intptr_t)(newst - oldst);
}
@@ -294,6 +278,14 @@ uint32_t GetESP(x86emu_t *emu)
{
return R_ESP;
}
void SetFS(x86emu_t *emu, uint16_t v)
{
emu->segs[_FS] = v;
}
uint16_t GetFS(x86emu_t *emu)
{
return emu->segs[_FS];
}
void ResetFlags(x86emu_t *emu)
@@ -326,11 +318,7 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
#ifdef USE_FLOAT
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].f);
#else
sprintf(tmp, "ST%d=%f", i, emu->fpu[(emu->top+i)&7].d);
#endif
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
@@ -480,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));
}
+22 -14
View File
@@ -3,7 +3,6 @@
#include "regs.h"
typedef struct zydis_dec_s zydis_dec_t;
typedef struct box86context_s box86context_t;
typedef struct i386_ucontext_s i386_ucontext_t;
@@ -11,7 +10,10 @@ typedef struct i386_ucontext_s i386_ucontext_t;
#define ERR_DIVBY0 2
#define ERR_ILLEGAL 4
typedef struct cleanup_s cleanup_t;
#ifdef DYNAREC
#define CSTACK 32
#define CSTACKMASK 31
#endif
typedef struct forkpty_s {
void* amaster;
@@ -23,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];
@@ -52,7 +54,9 @@ typedef struct x86emu_s {
uintptr_t prev2_ip, prev_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
@@ -61,29 +65,33 @@ typedef struct x86emu_s {
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
// trace
zydis_dec_t *dec;
uintptr_t trace_start, trace_end;
// 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
// cpu helpers
reg32_t zero;
reg32_t *sbiidx[8];
// atexit and fini functions
cleanup_t *cleanups;
int clean_sz;
int clean_cap;
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint32_t scratch[200];
// local stack, do be deleted when emu is freed
void* stack;
void* stack2free; // this is the stack to free (can be NULL)
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
i386_ucontext_t *uc_link; // to handle setcontext
int type; // EMUTYPE_xxx define
} x86emu_t;
#define EMUTYPE_NONE 0
#define EMUTYPE_MAIN 1
#define EMUTYPE_SIGNAL 2
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
+155 -67
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"
@@ -21,13 +24,19 @@
#include "box86context.h"
#include "librarian.h"
#include <elf.h>
#include "elfloader.h"
#include "elfs/elfloader_private.h"
typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
{
// execute atforks prepare functions, in reverse order
for (int i=emu->context->atfork_sz-1; i>=0; --i)
EmuCall(emu, emu->context->atforks[i].prepare);
for (int i=my_context->atfork_sz-1; i>=0; --i)
if(my_context->atforks[i].prepare)
EmuCall(emu, my_context->atforks[i].prepare);
int type = emu->type;
int v;
if(forktype==2) {
iFpppp_t forkpty = (iFpppp_t)emu->forkpty_info->f;
@@ -35,17 +44,21 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
emu->forkpty_info = NULL;
} else
v = fork();
if(type == EMUTYPE_MAIN)
thread_set_emu(emu);
if(v==EAGAIN || v==ENOMEM) {
// error...
} else if(v!=0) {
// execute atforks parent functions
for (int i=0; i<emu->context->atfork_sz; --i)
EmuCall(emu, emu->context->atforks[i].parent);
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].parent)
EmuCall(emu, my_context->atforks[i].parent);
} else if(v==0) {
// execute atforks child functions
for (int i=0; i<emu->context->atfork_sz; --i)
EmuCall(emu, emu->context->atforks[i].child);
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].child)
EmuCall(emu, my_context->atforks[i].child);
}
R_EAX = v;
return emu;
@@ -57,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);
@@ -65,9 +81,13 @@ void x86Int3(x86emu_t* emu)
RESET_FLAGS(emu);
wrapper_t w = (wrapper_t)addr;
addr = Fetch32(emu);
if(box86_log>=LOG_DEBUG /*&& emu->trace_end==0 && !emu->context->x86trace*/) {
/* This party can be used to trace only 1 specific lib (but it is quite slow)
elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
int have_trace = 0;
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
pthread_mutex_lock(&emu->context->mutex_trace);
int tid = syscall(SYS_gettid);
int tid = GetTID();
char buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
@@ -75,107 +95,169 @@ void x86Int3(x86emu_t* emu)
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
const char *s = GetNativeName(emu, (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
if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "glColor4f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), "glColor4f", *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12), *(float*)(R_ESP+16));
} else if(strstr(s, "glTexCoord2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), "glTexCoord2f", *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex2f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), "glVertex2f", *(float*)(R_ESP+4), *(float*)(R_ESP+8));
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "glVertex3f")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), "glVertex3f", *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
} else if(strstr(s, "__open64")==s || strstr(s, "open64")==s || strstr(s, "open64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), "open64", *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8), *(float*)(R_ESP+12));
} else if(strstr(s, "__open64")==s || strcmp(s, "open64")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "__open")==s || strstr(s, "open")==s || strstr(s, "open")==s) {
} else if(!strcmp(s, "opendir")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
perr = 1;
} else if(strstr(s, "__open")==s || strcmp(s, "open")==0) {
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(strstr(s, "fopen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), "fopen", *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} 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(strstr(s, "chdir")==s) {
} 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;
} else if(!strcmp(s, "chdir")) {
pu32=*(uint32_t**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), "chdir", pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, pu32?((pu32==(uint32_t*)1)?"/1/":(char*)pu32):"/0/");
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), "getenv", *(char**)(R_ESP+4));
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %i)", tid, *(void**)(R_ESP), "pread", *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
} else if(strstr(s, "statvfs64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), "statvfs64", *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "index")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), "index", *(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), "rindex", *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), "__xstat64", *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), "__lxstat64", *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "statvfs64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "index")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} 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, "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(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), "sem_timedwait", *(void**)(R_ESP+4), *(void**)(R_ESP+8), pu32?pu32[0]:-1, pu32?pu32[1]:-1);
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), "clock_gettime", *(uint32_t*)(R_ESP+4), *(void**)(R_ESP+8));
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;
pu32 = *(uint32_t**)(R_ESP+8);
} else if(strstr(s, "semop")==s) {
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/%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, "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, "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) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), "strcasecmp", *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, "gtk_signal_connect_full")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p, %p, %p, %p, %d, %d)", tid, *(void**)(R_ESP), "gtk_signal_connect_full", *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20), *(void**)(R_ESP+24), *(int32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32));
} else if(strstr(s, "strncasecmp")==s || strstr(s, "__strncasecmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %u)", tid, *(void**)(R_ESP), "strcasecmp", *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
} else if(strstr(s, "strcmp")==s || strstr(s, "__strcmp")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), "strcmp", *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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, "strstr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), "strstr", *(char**)(R_ESP+4), *(char**)(R_ESP+8));
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), "strlen", *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), "vsnprintf", *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
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, "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) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\"...)", tid, *(void**)(R_ESP), "vsprintf", *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} 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) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), "snprintf", *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
} 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) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), "sprintf", *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
} 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, "fprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), "fprintf", *(uint32_t*)(R_ESP+4), *(char**)(R_ESP+8));
} 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(\"%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, "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, "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), "XCreateWindow", *(void**)(R_ESP+4), *(void**)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(uint32_t*)(R_ESP+20), *(uint32_t*)(R_ESP+24), *(uint32_t*)(R_ESP+28), *(int32_t*)(R_ESP+32), *(uint32_t*)(R_ESP+36), *(void**)(R_ESP+40), *(uint32_t*)(R_ESP+44), *(void**)(R_ESP+48));
snprintf(buff, 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));
} else if(strstr(s, "XLoadQueryFont")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), "XLoadQueryFont", *(void**)(R_ESP+4), *(char**)(R_ESP+8));
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, "pthread_mutex_lock")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), "pthread_mutex_lock", *(void**)(R_ESP+4));
} else if(strstr(s, "fmodf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(!strcmp(s, "fmodf")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), "fmodf", *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(strstr(s, "fmod")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(float*)(R_ESP+4), *(float*)(R_ESP+8));
} else if(!strcmp(s, "fmod")) {
post = 4;
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), "fmod", *(double*)(R_ESP+4), *(double*)(R_ESP+12));
snprintf(buff, 255, "%04d|%p: Calling %s(%f, %f)", tid, *(void**)(R_ESP), s, *(double*)(R_ESP+4), *(double*)(R_ESP+12));
} else if(strstr(s, "SDL_GetWindowSurface")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), "SDL_GetWindowSurface", *(void**)(R_ESP+4));
snprintf(buff, 255, "%04d|%p: Calling %s(%p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4));
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} 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 {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
}
printf_log(LOG_DEBUG, "%s =>", buff);
printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
w(emu, addr); // some function never come back, so unlock the mutex first!
pthread_mutex_lock(&emu->context->mutex_trace);
@@ -187,11 +269,7 @@ void x86Int3(x86emu_t* emu)
break;
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
break;
#ifdef USE_FLOAT
case 4: snprintf(buff2, 63, " (%f)", ST0.f);
#else
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
#endif
break;
case 5: {
uint32_t* p = (uint32_t*)R_EAX;
@@ -202,15 +280,25 @@ void x86Int3(x86emu_t* emu)
}
break;
}
if(perr && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d)", errno);
printf_log(LOG_DEBUG, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
else if(perr==2 && R_EAX==0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
w(emu, addr);
}
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;
}
int GetTID()
{
return syscall(SYS_gettid);
}
+27 -24
View File
@@ -714,7 +714,7 @@ uint8_t rol8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -741,7 +741,7 @@ uint16_t rol16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -768,7 +768,7 @@ uint32_t rol32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -795,7 +795,7 @@ uint8_t ror8(x86emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -822,7 +822,7 @@ uint16_t ror16(x86emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -849,7 +849,7 @@ uint32_t ror32(x86emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
}
CHECK_FLAGS(emu);
RESET_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -891,7 +891,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
CLEAR_FLAG(F_OF);
}
} else {
res = (fill << (cnt)) | (fill >> (16 - cnt));
res = (fill << (cnt)) | (d >> (16 - cnt));
if(s==16)
cf = d & 1;
else
@@ -965,7 +965,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
}
} else {
cf = fill & (1 << (cnt - 1));
res = (fill >> cnt) | (fill << (16 - cnt));
res = (fill >> cnt) | (d << (16 - cnt));
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
@@ -1153,7 +1153,7 @@ Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv8(x86emu_t *emu, uint8_t s)
{
int32_t dvd, div, mod;
int32_t dvd, quot, mod;
RESET_FLAGS(emu);
dvd = (int16_t)R_AX;
@@ -1161,13 +1161,14 @@ void idiv8(x86emu_t *emu, uint8_t s)
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int8_t)s;
mod = dvd % (int8_t)s;
if (abs(div) > 0x7f) {
div_t p = div(dvd, (int8_t)s);
quot = p.quot;
mod = p.rem;
if (abs(quot) > 0x7f) {
INTR_RAISE_DIV0(emu);
return;
}
R_AL = (int8_t) div;
R_AL = (int8_t) quot;
R_AH = (int8_t) mod;
}
@@ -1177,25 +1178,26 @@ Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv16(x86emu_t *emu, uint16_t s)
{
int32_t dvd, div, mod;
int32_t dvd, quot, mod;
dvd = (((int32_t)R_DX) << 16) | R_AX;
if (s == 0) {
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int16_t)s;
mod = dvd % (int16_t)s;
if (abs(div) > 0x7fff) {
div_t p = div(dvd, (int16_t)s);
quot = p.quot;
mod = p.rem;
if (abs(quot) > 0x7fff) {
INTR_RAISE_DIV0(emu);
return;
}
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_SF);
CONDITIONAL_SET_FLAG(div == 0, F_ZF);
CONDITIONAL_SET_FLAG(quot == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_AX = (uint16_t)div;
R_AX = (uint16_t)quot;
R_DX = (uint16_t)mod;
}
@@ -1205,7 +1207,7 @@ Implements the IDIV instruction and side effects.
****************************************************************************/
void idiv32(x86emu_t *emu, uint32_t s)
{
int64_t dvd, div, mod;
int64_t dvd, quot, mod;
RESET_FLAGS(emu);
dvd = (((int64_t)R_EDX) << 32) | R_EAX;
@@ -1213,9 +1215,10 @@ void idiv32(x86emu_t *emu, uint32_t s)
INTR_RAISE_DIV0(emu);
return;
}
div = dvd / (int32_t)s;
mod = dvd % (int32_t)s;
if (llabs(div) > 0x7fffffff) {
lldiv_t p = lldiv(dvd, (int32_t)s);
quot = p.quot;
mod = p.rem;
if (llabs(quot) > 0x7fffffff) {
INTR_RAISE_DIV0(emu);
return;
}
@@ -1225,7 +1228,7 @@ void idiv32(x86emu_t *emu, uint32_t s)
SET_FLAG(F_ZF);
CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
R_EAX = (uint32_t)div;
R_EAX = (uint32_t)quot;
R_EDX = (uint32_t)mod;
}
+17 -11
View File
@@ -81,8 +81,6 @@ Implements the AND instruction and side effects.
****************************************************************************/
static inline uint32_t and32(x86emu_t *emu, uint32_t d, uint32_t s)
{
register uint32_t res; /* all operands in native machine order */
emu->res = d & s;
emu->df = d_and32;
@@ -161,6 +159,14 @@ Implements the INC instruction and side effects.
****************************************************************************/
static inline uint32_t inc32(x86emu_t *emu, uint32_t d)
{
if(emu->df == d_shr32) {
// workaround for some wine trickery
uint32_t cnt = emu->op2;
if (cnt > 0) {
uint32_t cc = emu->op1 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
emu->res = d + 1;
emu->op1 = d;
emu->df = d_inc32;
@@ -507,7 +513,7 @@ static inline uint32_t xor32(x86emu_t *emu, uint32_t d, uint32_t s)
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static void imul8(x86emu_t *emu, uint8_t s)
static inline void imul8(x86emu_t *emu, uint8_t s)
{
emu->df = d_imul8;
R_AX = emu->res = (int16_t)(int8_t)R_AL * (int8_t)s;
@@ -516,7 +522,7 @@ static void imul8(x86emu_t *emu, uint8_t s)
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static void imul16_eax(x86emu_t *emu, uint16_t s)
static inline void imul16_eax(x86emu_t *emu, uint16_t s)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)R_AX * (int16_t)s;
@@ -527,7 +533,7 @@ static void imul16_eax(x86emu_t *emu, uint16_t s)
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static uint16_t imul16(x86emu_t *emu, uint16_t op1, uint16_t op2)
static inline uint16_t imul16(x86emu_t *emu, uint16_t op1, uint16_t op2)
{
emu->df = d_imul16;
emu->res = (int32_t)(int16_t)op1 * (int16_t)op2;
@@ -537,7 +543,7 @@ static uint16_t imul16(x86emu_t *emu, uint16_t op1, uint16_t op2)
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_t s)
static inline void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_t s)
{
int64_t res = (int64_t)(int32_t)d * (int32_t)s;
@@ -548,7 +554,7 @@ static void imul32_direct(uint32_t *res_lo, uint32_t* res_hi,uint32_t d, uint32_
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2)
static inline uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2)
{
emu->df = d_imul32;
imul32_direct(&emu->res,&emu->op1,op1,op2);
@@ -558,7 +564,7 @@ static uint32_t imul32(x86emu_t *emu, uint32_t op1, uint32_t op2)
REMARKS:
Implements the IMUL instruction and side effects.
****************************************************************************/
static void imul32_eax(x86emu_t *emu, uint32_t s)
static inline void imul32_eax(x86emu_t *emu, uint32_t s)
{
emu->df = d_imul32;
imul32_direct(&R_EAX,&R_EDX,R_EAX,s);
@@ -569,7 +575,7 @@ static void imul32_eax(x86emu_t *emu, uint32_t s)
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static void mul8(x86emu_t *emu, uint8_t s)
static inline void mul8(x86emu_t *emu, uint8_t s)
{
emu->df = d_mul8;
R_AX = emu->res = (uint16_t)(R_AL) * s;
@@ -578,7 +584,7 @@ static void mul8(x86emu_t *emu, uint8_t s)
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static void mul16(x86emu_t *emu, uint16_t s)
static inline void mul16(x86emu_t *emu, uint16_t s)
{
emu->df = d_mul16;
emu->res = (uint32_t)R_AX * s;
@@ -589,7 +595,7 @@ static void mul16(x86emu_t *emu, uint16_t s)
REMARKS:
Implements the MUL instruction and side effects.
****************************************************************************/
static void mul32_eax(x86emu_t *emu, uint32_t s)
static inline void mul32_eax(x86emu_t *emu, uint32_t s)
{
emu->df = d_mul32;
uint64_t res = (uint64_t)R_EAX * s;
+366 -157
View File
@@ -18,6 +18,11 @@
#include "x86trace.h"
#include "x87emu_private.h"
#include "box86context.h"
#include "my_cpuid.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#endif
int my_setcontext(x86emu_t* emu, void* ucp);
@@ -26,7 +31,6 @@ int Run(x86emu_t *emu, int step)
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
reg32_t ea1;
uint8_t tmp8u, tmp8u2;
int8_t tmp8s;
uint16_t tmp16u, tmp16u2;
@@ -35,18 +39,16 @@ int Run(x86emu_t *emu, int step)
int32_t tmp32s, tmp32s2;
uint64_t tmp64u;
int64_t tmp64s;
uintptr_t ip, old_ip;
uintptr_t ip;
double d;
float f;
int64_t ll;
sse_regs_t *opex, eax1, *opx2;
sse_regs_t *opex, eax1;
mmx_regs_t *opem, eam1;
if(emu->quit)
return 0;
old_ip = 0;
//ref opcode: http://ref.x86asm.net/geek32.html#xA1
printf_log(LOG_DEBUG, "Run X86 (%p), EIP=%p, Stack=%p\n", emu, (void*)R_EIP, emu->context->stack);
#define F8 *(uint8_t*)(ip++)
@@ -63,48 +65,48 @@ int Run(x86emu_t *emu, int step)
static const void* baseopcodes[256] ={
&&_0x00_0, &&_0x00_1, &&_0x00_2, &&_0x00_3, &&_0x00_4, &&_0x00_5, &&_0x06, &&_0x07, //0x00-0x07
&&_0x08_0, &&_0x08_1, &&_0x08_2, &&_0x08_3, &&_0x08_4, &&_0x08_5, &&_default, &&_0x0F, //0x08-0x0F
&&_0x10_0, &&_0x10_1, &&_0x10_2, &&_0x10_3, &&_0x10_4, &&_0x10_5, &&_default, &&_default, //0x10-0x17
&&_0x08_0, &&_0x08_1, &&_0x08_2, &&_0x08_3, &&_0x08_4, &&_0x08_5, &&_0x0E, &&_0x0F, //0x08-0x0F
&&_0x10_0, &&_0x10_1, &&_0x10_2, &&_0x10_3, &&_0x10_4, &&_0x10_5, &&_0x16, &&_0x17, //0x10-0x17
&&_0x18_0, &&_0x18_1, &&_0x18_2, &&_0x18_3, &&_0x18_4, &&_0x18_5, &&_0x1E, &&_0x1F, //0x18-0x1F
&&_0x20_0, &&_0x20_1, &&_0x20_2, &&_0x20_3, &&_0x20_4, &&_0x20_5, &&_0x26, &&_0x27, //0x20-0x27
&&_0x28_0, &&_0x28_1, &&_0x28_2, &&_0x28_3, &&_0x28_4, &&_0x28_5, &&_0x2E, &&_0x2F, //0x28-0x2F
&&_0x30_0, &&_0x30_1, &&_0x30_2, &&_0x30_3, &&_0x30_4, &&_0x30_5, &&_default, &&_0x37, //0x30-0x37
&&_0x38, &&_0x39, &&_0x3A, &&_0x3B, &&_0x3C, &&_0x3D, &&_default, &&_0x3F, //0x38-0x3F
&&_0x30_0, &&_0x30_1, &&_0x30_2, &&_0x30_3, &&_0x30_4, &&_0x30_5, &&_0x36, &&_0x37, //0x30-0x37
&&_0x38, &&_0x39, &&_0x3A, &&_0x3B, &&_0x3C, &&_0x3D, &&_0x3E, &&_0x3F, //0x38-0x3F
&&_0x40, &&_0x41, &&_0x42, &&_0x43, &&_0x44, &&_0x45, &&_0x46, &&_0x47,
&&_0x48, &&_0x49, &&_0x4A, &&_0x4B, &&_0x4C, &&_0x4D, &&_0x4E, &&_0x4F,
&&_0x50, &&_0x51, &&_0x52, &&_0x53, &&_0x54, &&_0x55, &&_0x56, &&_0x57,
&&_0x58, &&_0x59, &&_0x5A, &&_0x5B, &&_0x5C, &&_0x5D, &&_0x5E, &&_0x5F,
&&_0x60, &&_0x61, &&_default, &&_default, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
&&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_default, &&_default, //0x68-0x6F
&&_0x60, &&_0x61, &&_0x62, &&_0x63, &&_0x64, &&_0x65, &&_0x66, &&_0x67,
&&_0x68, &&_0x69, &&_0x6A, &&_0x6B, &&_0x6C, &&_0x6D, &&_0x6E, &&_0x6F, //0x68-0x6F
&&_0x70_0, &&_0x70_1, &&_0x70_2, &&_0x70_3, &&_0x70_4, &&_0x70_5, &&_0x70_6, &&_0x70_7, //0x70-0x77
&&_0x70_8, &&_0x70_9, &&_0x70_A, &&_0x70_B, &&_0x70_C, &&_0x70_D, &&_0x70_E, &&_0x70_F, //0x78-0x7F
&&_0x80, &&_0x81, &&_default, &&_0x83, &&_0x84, &&_0x85, &&_0x86, &&_0x87,
&&_0x88, &&_0x89, &&_0x8A, &&_0x8B, &&_default, &&_0x8D, &&_0x8E, &&_0x8F,
&&_0x80, &&_0x81, &&_0x82, &&_0x83, &&_0x84, &&_0x85, &&_0x86, &&_0x87,
&&_0x88, &&_0x89, &&_0x8A, &&_0x8B, &&_0x8C, &&_0x8D, &&_0x8E, &&_0x8F,
&&_0x90, &&_0x91, &&_0x92, &&_0x93, &&_0x94, &&_0x95, &&_0x96, &&_0x97,
&&_0x98, &&_0x99, &&_default, &&_0x9B, &&_0x9C, &&_0x9D, &&_0x9E, &&_0x9F,
&&_0xA0, &&_0xA1, &&_0xA2, &&_0xA3, &&_0xA4, &&_0xA5, &&_0xA6, &&_0xA7,
&&_0xA8, &&_0xA9, &&_0xAA, &&_0xAB, &&_0xAC, &&_0xAD, &&_0xAE, &&_0xAF,
&&_0xB0, &&_0xB1, &&_0xB2, &&_0xB3, &&_0xB4, &&_0xB5, &&_0xB6, &&_0xB7,
&&_0xB8, &&_0xB9, &&_0xBA, &&_0xBB, &&_0xBC, &&_0xBD, &&_0xBE, &&_0xBF,
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_default, &&_default, &&_0xC6, &&_0xC7,
&&_0xC8, &&_0xC9, &&_default, &&_default, &&_0xCC, &&_0xCD, &&_default, &&_default, //0xC8-0xCF
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_default, &&_0xD7,
&&_0xC0, &&_0xC1, &&_0xC2, &&_0xC3, &&_0xC4, &&_0xC5, &&_0xC6, &&_0xC7,
&&_0xC8, &&_0xC9, &&_default, &&_0xCB, &&_0xCC, &&_0xCD, &&_default, &&_0xCF, //0xC8-0xCF
&&_0xD0, &&_0xD1, &&_0xD2, &&_0xD3, &&_0xD4, &&_0xD5, &&_0xD6, &&_0xD7,
&&_0xD8, &&_0xD9, &&_0xDA, &&_0xDB, &&_0xDC, &&_0xDD, &&_0xDE, &&_0xDF,
&&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_default, &&_0xE5, &&_default, &&_default,
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_default, &&_default, &&_default, &&_default,
&&_0xF0, &&_default, &&_0xF2, &&_0xF3, &&_default, &&_0xF5, &&_0xF6, &&_0xF7,
&&_0xF8, &&_0xF9, &&_default, &&_default, &&_0xFC, &&_0xFD, &&_0xFE, &&_0xFF
&&_0xE0, &&_0xE1, &&_0xE2, &&_0xE3, &&_0xE4, &&_0xE5, &&_0xE6, &&_0xE7,
&&_0xE8, &&_0xE9, &&_default, &&_0xEB, &&_0xEC, &&_0xED, &&_default, &&_default,
&&_0xF0, &&_0xF1, &&_0xF2, &&_0xF3, &&_default, &&_0xF5, &&_0xF6, &&_0xF7,
&&_0xF8, &&_0xF9, &&_0xFA, &&_0xFB, &&_0xFC, &&_0xFD, &&_0xFE, &&_0xFF
};
static const void* opcodes0f[256] = {
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17
&&_0f_0x18, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
&&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_0f_0x28, &&_0f_0x29, &&_0f_0x2A, &&_0f_0x2B, &&_0f_0x2C, &&_0f_0x2D, &&_0f_0x2E, &&_0f_0x2F,
&&_default, &&_0f_0x31, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_0f_0x38, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_0f_0x40_0, &&_0f_0x40_1, &&_0f_0x40_2, &&_0f_0x40_3, &&_0f_0x40_4, &&_0f_0x40_5, &&_0f_0x40_6, &&_0f_0x40_7,
&&_0f_0x40_8, &&_0f_0x40_9, &&_0f_0x40_A, &&_0f_0x40_B, &&_0f_0x40_C, &&_0f_0x40_D, &&_0f_0x40_E, &&_0f_0x40_F,
&&_0f_0x50, &&_0f_0x51, &&_0f_0x52, &&_0f_0x53, &&_0f_0x54, &&_0f_0x55, &&_0f_0x56, &&_0f_0x57, //0x50-0x57
@@ -117,106 +119,71 @@ int Run(x86emu_t *emu, int step)
&&_0f_0x80_8, &&_0f_0x80_9, &&_0f_0x80_A, &&_0f_0x80_B, &&_0f_0x80_C, &&_0f_0x80_D, &&_0f_0x80_E, &&_0f_0x80_F,
&&_0f_0x90_0, &&_0f_0x90_1, &&_0f_0x90_2, &&_0f_0x90_3, &&_0f_0x90_4, &&_0f_0x90_5, &&_0f_0x90_6, &&_0f_0x90_7,
&&_0f_0x90_8, &&_0f_0x90_9, &&_0f_0x90_A, &&_0f_0x90_B, &&_0f_0x90_C, &&_0f_0x90_D, &&_0f_0x90_E, &&_0f_0x90_F,
&&_default, &&_default, &&_0f_0xA2, &&_0f_0xA3, &&_0f_0xA4, &&_0f_0xA5, &&_default, &&_default, //0xA0-0xA7
&&_default, &&_default, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF,
&&_0f_0xA0, &&_0f_0xA1, &&_0f_0xA2, &&_0f_0xA3, &&_0f_0xA4, &&_0f_0xA5, &&_default, &&_default, //0xA0-0xA7
&&_0f_0xA8, &&_0f_0xA9, &&_default, &&_0f_0xAB, &&_0f_0xAC, &&_0f_0xAD, &&_0f_0xAE, &&_0f_0xAF,
&&_0f_0xB0, &&_0f_0xB1, &&_default, &&_0f_0xB3, &&_default, &&_default, &&_0f_0xB6, &&_0f_0xB7,
&&_default, &&_default, &&_0f_0xBA, &&_0f_0xBB, &&_0f_0xBC, &&_0f_0xBD, &&_0f_0xBE, &&_0f_0xBF,
&&_0f_0xC0, &&_0f_0xC1, &&_0f_0xC2, &&_default, &&_0f_0xC4, &&_0f_0xC5, &&_0f_0xC6, &&_0f_0xC7,
&&_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, &&_default, //0xD0-0xD7
&&_0f_0xD8, &&_0f_0xD9, &&_default, &&_0f_0xDB, &&_0f_0xDC ,&&_0f_0xDD, &&_default, &&_0f_0xDF, //0xD8-0xDF
&&_0f_0xE0, &&_0f_0xE1, &&_0f_0xE2, &&_0f_0xE3, &&_0f_0xE4 ,&&_0f_0xE5, &&_default, &&_default, //0xE0-0xE7
&&_0f_0xE8, &&_0f_0xE9, &&_default, &&_0f_0xEB, &&_0f_0xEC ,&&_0f_0xED, &&_default, &&_0f_0xEF, //0xE8-0xEF
&&_default, &&_0f_0xF1, &&_0f_0xF2, &&_0f_0xF3, &&_0f_0xF4 ,&&_0f_0xF5, &&_0f_0xF6, &&_default, //0xF0-0xF7
&&_default, &&_0f_0xD1, &&_0f_0xD2, &&_0f_0xD3, &&_0f_0xD4 ,&&_0f_0xD5, &&_default, &&_0f_0xD7, //0xD0-0xD7
&&_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
&&_0f_0xF8, &&_0f_0xF9, &&_0f_0xFA, &&_default, &&_0f_0xFC ,&&_0f_0xFD, &&_0f_0xFE, &&_default //0xF8-0xFF
};
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, &&_default, &&_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,
&&_66_0x50, &&_66_0x51, &&_66_0x52, &&_66_0x53, &&_66_0x54, &&_66_0x55, &&_66_0x56, &&_66_0x57, //0x50-0x57
&&_66_0x58, &&_66_0x59, &&_66_0x5A, &&_66_0x5B, &&_66_0x5C, &&_66_0x5D, &&_66_0x5E, &&_66_0x5F, //0x58-0x5F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_66_0x66, &&_default, //0x60-0x67
&&_66_0x60, &&_66_0x61, &&_default, &&_default, &&_default ,&&_default, &&_66_0x66, &&_default, //0x60-0x67
&&_66_0x68, &&_66_0x69, &&_66_0x6A, &&_66_0x6B, &&_default, &&_default, &&_default, &&_default, //0x68-0x6F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x70-0x77
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x78-0x7F
&&_default, &&_66_0x81, &&_default, &&_66_0x83, &&_default, &&_66_0x85, &&_default, &&_66_0x87,
&&_default, &&_66_0x89, &&_default, &&_66_0x8B, &&_66_0x8C, &&_default, &&_66_0x8E, &&_66_0x8F,
&&_66_0x90, &&_default, &&_66_0x92, &&_default, &&_default, &&_default, &&_default, &&_default,
&&_66_0x98, &&_66_0x99, &&_default, &&_default, &&_66_0x9C, &&_default, &&_default, &&_default, //0x98-0x9F
&&_66_0x90, &&_66_0x91, &&_66_0x92, &&_66_0x93, &&_66_0x94, &&_66_0x95, &&_66_0x96, &&_66_0x97,
&&_66_0x98, &&_66_0x99, &&_default, &&_default, &&_66_0x9C, &&_66_0x9D, &&_default, &&_default, //0x98-0x9F
&&_default, &&_66_0xA1, &&_default, &&_66_0xA3, &&_default, &&_66_0xA5, &&_default, &&_66_0xA7,
&&_default, &&_66_0xA9, &&_default, &&_66_0xAB, &&_default, &&_66_0xAD, &&_default, &&_66_0xAF, //0xA8-0xAF
&&_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,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
};
static const void* opcodes660f[256] = {
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_default,
&&_default, &&_default, &&_default, &&_6f_0xBB, &&_6f_0xBC, &&_6f_0xBD, &&_6f_0xBE, &&_default, //0xB8-0xBF
&&_default, &&_6f_0xC1, &&_6f_0xC2, &&_default, &&_6f_0xC4, &&_6f_0xC5, &&_6f_0xC6, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xC8-0xCF
&&_default, &&_6f_0xD1, &&_6f_0xD2, &&_6f_0xD3, &&_6f_0xD4, &&_6f_0xD5, &&_6f_0xD6, &&_6f_0xD7,
&&_6f_0xD8, &&_6f_0xD9, &&_default, &&_6f_0xDB, &&_6f_0xDC, &&_default, &&_6f_0xDE, &&_6f_0xDF,
&&_default, &&_6f_0xE1, &&_6f_0xE2, &&_default, &&_default, &&_6f_0xE5, &&_6f_0xE6, &&_6f_0xE7,
&&_6f_0xE8, &&_6f_0xE9, &&_6f_0xEA, &&_6f_0xEB, &&_6f_0xEC, &&_6f_0xED, &&_6f_0xEE, &&_6f_0xEF,
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
&&_default, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
&&_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);
emu->prev2_ip = emu->prev_ip;
emu->prev_ip = old_ip;
old_ip = ip;
if(emu->dec && (
(emu->trace_end == 0)
|| ((ip >= emu->trace_start) && (ip < emu->trace_end))) )
emu->prev_ip = R_EIP;
R_EIP=ip;
if(my_context->dec && (
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) )
PrintTrace(emu, ip, 0);
#define NEXT __builtin_prefetch((void*)ip, 0, 0); goto _trace;
#define NEXT goto _trace
#else
#define NEXT old_ip = ip; __builtin_prefetch((void*)ip, 0, 0); goto *baseopcodes[(opcode=F8)];
#define NEXT goto *baseopcodes[(R_EIP=ip, opcode=F8)]
#endif
#include "modrm.h"
@@ -295,17 +262,30 @@ _trace:
NEXT;
_0x07: /* POP ES */
emu->segs[_ES] = Pop(emu); // no check, no use....
emu->segs_serial[_ES] = 0;
NEXT;
_0x0E: /* PUSH CS */
Push(emu, emu->segs[_CS]);
NEXT;
_0x0F: /* More instructions */
#include "run0f.h"
NEXT;
_0x16: /* PUSH SS */
Push(emu, emu->segs[_SS]); // even if a segment is a 16bits, a 32bits push/pop is done
NEXT;
_0x17: /* POP SS */
emu->segs[_SS] = Pop(emu); // no check, no use....
emu->segs_serial[_SS] = 0;
NEXT;
_0x1E: /* PUSH DS */
Push(emu, emu->segs[_DS]); // even if a segment is a 16bits, a 32bits push/pop is done
NEXT;
_0x1F: /* POP DS */
emu->segs[_DS] = Pop(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
NEXT;
_0x26: /* ES: */
@@ -315,18 +295,24 @@ _trace:
NEXT;
_0x2E: /* CS: */
// Can also happens before a condition branch: Branch Not Taken Hint
NEXT; //ignored...
_0x2F: /* DAS */
R_AL = das8(emu, R_AL);
NEXT;
_0x36: /* SS: */
NEXT;
_0x37: /* AAA */
R_AX = aaa16(emu, R_AX);
NEXT;
_0x3E: /* DS: */
// Can also happens before a condition branch: Branch Taken Hint
NEXT;
_0x3F: /* AAS */
R_AX = aas16(emu, R_AX);
NEXT;
_0x40:
_0x41:
_0x42:
@@ -395,41 +381,43 @@ _trace:
R_ECX = Pop(emu);
R_EAX = Pop(emu);
NEXT;
_0x62: /* BOUND Gd, Ed */
nextop = F8;
GET_ED;
// ignoring the test for now
NEXT;
_0x63: /* ARPL Ew, Gw */
nextop = F8;
GET_EW;
// faking to always happy...
SET_FLAG(F_ZF);
NEXT;
_0x64: /* FS: */
switch(F8)
{
case 0xA1:
tmp32s = F32S;
R_EAX = *(uint32_t*)((emu->segs[_FS]) + tmp32s);
break;
case 0x89:
nextop = F8;
GET_ED_OFFS(emu->segs[_FS]);
ED->dword[0] = GD.dword[0];
break;
default:
UnimpOpcode(emu);
}
emu->old_ip = R_EIP;
R_EIP = ip-1;
RunFS(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x65: /* GS: */
emu->old_ip = old_ip;
R_EIP = ip;
emu->old_ip = R_EIP;
R_EIP = ip-1;
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 */
#include "run66.h"
_0x67: /* Prefix to change width of registers */
emu->old_ip = old_ip;
R_EIP = ip;
emu->old_ip = R_EIP;
R_EIP = ip-1; // don't count 0x67 yet
Run67(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
STEP
NEXT;
_0x68: /* Push Id */
@@ -452,19 +440,33 @@ _trace:
GD.dword[0] = imul32(emu, ED->dword[0], (uint32_t)tmp32s);
NEXT;
_0x6C: /* INSB */
*(int8_t*)R_EDI = 0; // faking port read
*(int8_t*)(R_EDI+GetESBaseEmu(emu)) = 0; // faking port read, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_EDI-=1;
else
R_EDI+=1;
NEXT;
_0x6D: /* INSD */
*(int32_t*)R_EDI = 0; // faking port read
*(int32_t*)(R_EDI+GetESBaseEmu(emu)) = 0; // faking port read, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_EDI-=4;
else
R_EDI+=4;
NEXT;
_0x6E: /* OUTSB */
// faking port write, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_ESI-=1;
else
R_ESI+=1;
NEXT;
_0x6F: /* OUTSD */
// faking port write, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_ESI-=4;
else
R_ESI+=4;
NEXT;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
_##BASE##_0: \
@@ -555,6 +557,7 @@ _trace:
_0x80: /* GRP Eb,Ib */
_0x82: // 0x82 and 0x80 are the same opcodes it seems?
nextop = F8;
GET_EB;
tmp8u = F8;
@@ -603,6 +606,20 @@ _trace:
NEXT;
_0x86: /* XCHG Eb,Gb */
nextop = F8;
#ifdef DYNAREC
GET_EB;
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
} else {
do {
tmp8u = arm_lock_read_b(EB);
} while(arm_lock_write_b(EB, GB));
GB = tmp8u;
}
// dynarec use need it's own mecanism
#else
GET_EB;
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
@@ -611,9 +628,29 @@ _trace:
EB->byte[0] = tmp8u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
NEXT;
_0x87: /* XCHG Ed,Gd */
nextop = F8;
#ifdef DYNAREC
GET_ED;
if((nextop&0xC0)==0xC0) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
} else {
if(((uintptr_t)ED)&3)
{
// not aligned, dont't try to "LOCK"
tmp32u = ED->dword[0];
ED->dword[0] = GD.dword[0];
GD.dword[0] = tmp32u;
} else {
// XCHG is supposed to automaticaly LOCK memory bus
GD.dword[0] = arm_lock_xchg(ED, GD.dword[0]);
}
}
#else
GET_ED;
if((nextop&0xC0)!=0xC0)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
@@ -622,6 +659,7 @@ _trace:
ED->dword[0] = tmp32u;
if((nextop&0xC0)!=0xC0)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
NEXT;
_0x88: /* MOV Eb,Gb */
nextop = F8;
@@ -643,7 +681,11 @@ _trace:
GET_ED;
GD.dword[0] = ED->dword[0];
NEXT;
_0x8C: /* MOV Ed, Seg */
nextop = F8;
GET_ED;
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
NEXT;
_0x8D: /* LEA Gd,M */
nextop = F8;
GET_ED;
@@ -653,11 +695,21 @@ _trace:
nextop = F8;
GET_EW;
emu->segs[((nextop&0x38)>>3)] = EW->word[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;
@@ -684,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 */
@@ -703,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 */
@@ -847,7 +896,20 @@ _trace:
ip = Pop(emu);
STEP
NEXT;
_0xC4: /* LES Gd,Ed */
nextop = F8;
GET_ED;
emu->segs[_ES] = ED->word[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_serial[_DS] = 0;
GD.dword[0] = *(uint32_t*)(((void*)ED)+2);
NEXT;
_0xC6: /* MOV Eb,Ib */
nextop = F8;
GET_EB;
@@ -880,8 +942,15 @@ _trace:
R_EBP = Pop(emu);
NEXT;
_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;
_0xCC: /* INT 3 */
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
x86Int3(emu);
ip = R_EIP;
@@ -890,14 +959,15 @@ _trace:
_0xCD: /* INT Ib */
nextop = F8;
if(nextop == 0x80) {
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
x86Syscall(emu);
ip = R_EIP;
if(emu->quit) goto fini;
} else {
printf_log(LOG_NONE, "Unsupported Int %02Xh\n", nextop);
emu->old_ip = old_ip;
int tid = GetTID();
printf_log(LOG_NONE, "%04d|%p: Ignoring Unsupported Int %02Xh\n", tid, (void*)ip, nextop);
emu->old_ip = R_EIP;
R_EIP = ip;
emu->quit = 1;
emu->error |= ERR_UNIMPL;
@@ -905,6 +975,13 @@ _trace:
}
NEXT;
_0xCF: /* IRET */
ip = Pop(emu);
emu->segs[_CS] = Pop(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 */
_0xD2: /* GRP2 Eb,CL */
nextop = F8;
@@ -943,7 +1020,10 @@ _trace:
_0xD5: /* AAD Ib */
R_AX = aad16(emu, R_AX, F8);
NEXT;
_0xD6:
CHECK_FLAGS(emu);
R_AL = ACCESS_FLAG(F_CF)?0xFF:0x00;
NEXT;
_0xD7: /* XLAT */
R_AL = *(uint8_t*)(R_EBX + R_AL);
NEXT;
@@ -979,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);
@@ -986,26 +1067,37 @@ _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
R_AL = 0; // nothing... should do a warning maybe?
NEXT;
_0xE5: /* IN EAX, Ib */
tmp32s = F8; // port address
R_EAX = 0; // nothing... should do a warning maybe?
NEXT;
_0xE6: /* OUT Ib, AL */
tmp32s = F8; // port address
//nothing goes out...
NEXT;
_0xE7: /* OUT Ib, EAX */
tmp32s = F8; // port address
//nothing goes out...
NEXT;
_0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, ip);
@@ -1023,15 +1115,23 @@ _trace:
ip += tmp32s;
STEP
NEXT;
_0xEC: /* IN AL, DX */
R_AL = 0; // nothing... should do a warning maybe?
NEXT;
_0xED: /* IN EAX, DX */
R_EAX = 0; // nothing... should do a warning maybe?
NEXT;
_0xF0: /* LOCK */
emu->old_ip = old_ip;
R_EIP = ip;
emu->old_ip = R_EIP;
R_EIP = ip-1; // dont't count F0 yet
RunLock(emu); // implemented in Run66.c
ip = R_EIP;
if(emu->quit) goto fini;
NEXT;
_0xF1: /* INT1 */
// does nothing for now
NEXT;
_0xF2: /* REPNZ prefix */
_0xF3: /* REPZ prefix */
nextop = F8;
@@ -1041,6 +1141,7 @@ _trace:
} else {
#include "runf20f.h"
}
STEP
NEXT;
} else if(nextop==0x66) {
nextop = F8;
@@ -1064,6 +1165,55 @@ _trace:
R_EDI += tmp8s;
}
break;
case 0xA7: /* REP(N)Z CMPSW */
tmp16u = 0;
tmp16u2 = 0;
tmp8s *= 2;
if(opcode==0xF2) {
while(tmp32u) {
--tmp32u;
tmp16u2 = *(uint16_t*)R_EDI;
tmp16u = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
if(tmp16u2==tmp16u)
break;
}
} else {
while(tmp32u) {
--tmp32u;
tmp16u2 = *(uint16_t*)R_EDI;
tmp16u = *(uint16_t*)R_ESI;
R_EDI += tmp8s;
R_ESI += tmp8s;
if(tmp16u2!=tmp16u)
break;
}
}
if(R_ECX) cmp16(emu, tmp16u, tmp16u2);
break;
case 0xAF: /* REP(N)Z SCASW */
tmp16u = 0;
tmp8s *= 2;
if(opcode==0xF2) {
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
R_EDI += tmp8s;
if(R_AX==tmp16u)
break;
}
} else {
while(tmp32u) {
--tmp32u;
tmp16u = *(uint16_t*)R_EDI;
R_EDI += tmp8s;
if(R_AX!=tmp16u)
break;
}
}
if(R_ECX) cmp16(emu, R_AX, tmp16u);
break;
default:
goto _default;
}
@@ -1072,10 +1222,58 @@ _trace:
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp32u = R_ECX;
switch(nextop) {
case 0x90: /* PAUSE */
case 0x18:
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x25:
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4A:
case 0x4B:
case 0x4C:
case 0x4D:
case 0x4E:
case 0x4F:
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7A:
case 0x7B:
case 0x7C:
case 0x7D:
case 0x7E:
case 0x7F: /* BND / NOP */
case 0x86: /* XACQUIRE/XRELEASE XCHG */
case 0x87: /* XACQUIRE/XRELEASE XCHG */
case 0x88: /* XRELEASE MOV... */
case 0x89: /* XRELEASE MOV... ignoring acquire thingy */
case 0x9C:
case 0xC3: /* yup, repz ret is valid */
case 0xE8:
case 0xE9:
case 0xEB:
case 0xF0: /* XACQUIRE/XRELEASE LOCK ... ignoring acquire thingy */
--ip;
NEXT;
case 0xC3: /* REPZ RET... yup */
ip = Pop(emu);
case 0x90: /* PAUSE */
NEXT;
case 0xA4: /* REP MOVSB */
while(tmp32u) {
@@ -1238,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]);
@@ -1266,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]);
@@ -1297,7 +1497,12 @@ _trace:
CHECK_FLAGS(emu);
SET_FLAG(F_CF);
NEXT;
_0xFA: /* CLI */
CLEAR_FLAG(F_IF); //not really handled...
NEXT;
_0xFB: /* STI */
SET_FLAG(F_IF);
NEXT;
_0xFC: /* CLD */
CLEAR_FLAG(F_DF);
NEXT;
@@ -1306,6 +1511,7 @@ _trace:
NEXT;
_0xFE: /* GRP 5 Eb */
nextop = F8;
tmp32u2 = ip;
GET_EB;
switch((nextop>>3)&7) {
case 0: /* INC Eb */
@@ -1315,9 +1521,9 @@ _trace:
EB->byte[0] = dec8(emu, EB->byte[0]);
break;
default:
emu->old_ip = old_ip;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
emu->old_ip = R_EIP;
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;
@@ -1325,6 +1531,7 @@ _trace:
NEXT;
_0xFF: /* GRP 5 Ed */
nextop = F8;
tmp32u2 = ip;
GET_ED;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
@@ -1334,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 = old_ip;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode %02X %02X\n", opcode, nextop);
emu->old_ip = R_EIP;
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;
@@ -1355,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 = old_ip;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->old_ip = R_EIP;
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;
@@ -1373,12 +1581,13 @@ _trace:
}
break;
case 6: /* Push Ed */
Push(emu, ED->dword[0]);
tmp32u = ED->dword[0];
Push(emu, tmp32u); // avoid potential issue with push [esp+...]
break;
default:
emu->old_ip = old_ip;
R_EIP = ip;
printf_log(LOG_NONE, "Illegal Opcode 0x%02X 0x%02X\n", opcode, nextop);
emu->old_ip = R_EIP;
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;
@@ -1386,13 +1595,13 @@ _trace:
NEXT;
_default:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
UnimpOpcode(emu);
goto fini;
#ifdef DYNAREC
stepout:
emu->old_ip = old_ip;
emu->old_ip = R_EIP;
R_EIP = ip;
return 0;
#endif
+868 -86
View File
File diff suppressed because it is too large. Load diff
+445 -60
View File
@@ -1,6 +1,90 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "debug.h"
#include "box86stack.h"
#include "x86emu.h"
#include "x86run.h"
#include "x86emu_private.h"
#include "x86run_private.h"
#include "x86primop.h"
#include "x86trace.h"
#include "box86context.h"
#define F8 *(uint8_t*)(ip++)
#define F8S *(int8_t*)(ip++)
#define F16 *(uint16_t*)(ip+=2, ip-2)
#define F16S *(int16_t*)(ip+=2, ip-2)
#define F32 *(uint32_t*)(ip+=4, ip-4)
#define F32S *(int32_t*)(ip+=4, ip-4)
#define PK(a) *(uint8_t*)(ip+a)
#include "modrm.h"
void Run660F(x86emu_t *emu)
{
uintptr_t ip = R_EIP+2; //skip 66 0F
uint8_t opcode;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
int8_t tmp8s;
uint16_t tmp16u;
int16_t tmp16s;
uint32_t tmp32u;
int32_t tmp32s;
sse_regs_t *opex, eax1, *opx2;
mmx_regs_t *opem;
static const void* opcodes660f[256] = {
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_6f_0x10, &&_6f_0x11, &&_6f_0x12, &&_6f_0x13, &&_6f_0x14, &&_6f_0x15, &&_6f_0x16, &&_6f_0x17,
&&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_default, &&_6f_0x1F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
&&_6f_0x28, &&_6f_0x29, &&_6f_0x2A, &&_default, &&_6f_0x2C, &&_6f_0x2D, &&_6f_0x2E, &&_6f_0x2F,
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x30-0x37
&&_6f_0x38, &&_default, &&_6f_0x3A, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x38-0x3F
&&_6f_0x40_0, &&_6f_0x40_1, &&_6f_0x40_2, &&_6f_0x40_3, &&_6f_0x40_4, &&_6f_0x40_5, &&_6f_0x40_6, &&_6f_0x40_7,
&&_6f_0x40_8, &&_6f_0x40_9, &&_6f_0x40_A, &&_6f_0x40_B, &&_6f_0x40_C, &&_6f_0x40_D, &&_6f_0x40_E, &&_6f_0x40_F,
&&_6f_0x50, &&_6f_0x51, &&_default, &&_default, &&_6f_0x54, &&_6f_0x55, &&_6f_0x56, &&_6f_0x57,
&&_6f_0x58, &&_6f_0x59, &&_6f_0x5A, &&_6f_0x5B, &&_6f_0x5C, &&_6f_0x5D, &&_6f_0x5E, &&_6f_0x5F,
&&_6f_0x60, &&_6f_0x61, &&_6f_0x62, &&_6f_0x63, &&_6f_0x64, &&_6f_0x65, &&_6f_0x66, &&_6f_0x67,
&&_6f_0x68, &&_6f_0x69, &&_6f_0x6A, &&_6f_0x6B, &&_6f_0x6C, &&_6f_0x6D, &&_6f_0x6E, &&_6f_0x6F,
&&_6f_0x70, &&_6f_0x71, &&_6f_0x72, &&_6f_0x73, &&_6f_0x74, &&_6f_0x75, &&_6f_0x76, &&_default,
&&_default, &&_default, &&_default, &&_default, &&_6f_0x7C, &&_default, &&_6f_0x7E, &&_6f_0x7F, //0x78-0x7F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x80-0x87
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x88-0x8F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x90-0x97
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x98-0x9F
&&_default, &&_default, &&_default, &&_6f_0xA3, &&_6f_0xA4, &&_6f_0xA5, &&_default, &&_default,
&&_default, &&_default, &&_default, &&_6f_0xAB, &&_6f_0xAC, &&_6f_0xAD, &&_default, &&_6f_0xAF,
&&_default, &&_6f_0xB1, &&_default, &&_6f_0xB3, &&_default, &&_default, &&_6f_0xB6, &&_6f_0xB7,
&&_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
&&_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,
&&_default, &&_6f_0xF1, &&_6f_0xF2, &&_6f_0xF3, &&_6f_0xF4, &&_6f_0xF5, &&_6f_0xF6, &&_6f_0xF7,
&&_6f_0xF8, &&_6f_0xF9, &&_6f_0xFA, &&_6f_0xFB, &&_6f_0xFC, &&_6f_0xFD, &&_6f_0xFE, &&_default
};
#define NEXT goto _fini
opcode = F8;
goto *opcodes660f[opcode];
_default:
emu->old_ip = R_EIP;
R_EIP = ip;
UnimpOpcode(emu);
goto _fini;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
_6f_##BASE##_0: \
PREFIX \
@@ -104,12 +188,18 @@
_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;
@@ -207,17 +297,127 @@
_6f_0x38: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: // PSHUFB
case 0x00: /* PSHUFB */
nextop = F8;
GET_EX;
eax1 = GX;
for (int i=0; i<15; ++i) {
for (int i=0; i<16; ++i) {
if(EX->ub[i]&128)
GX.ub[i] = 0;
else
GX.ub[i] = eax1.ub[EX->ub[i]&15];
}
break;
case 0x01: /* PHADDW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sw[i] = GX.sw[i*2+0]+GX.sw[i*2+1];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i)
GX.sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
}
break;
case 0x02: /* PHADDD Gx, Ex */
nextop = F8;
GET_EX;
GX.sd[0] += GX.sd[1];
GX.sd[1] = GX.sd[2] + GX.sd[3];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
GX.sd[2] = EX->sd[0] + EX->sd[1];
GX.sd[3] = EX->sd[2] + EX->sd[3];
}
break;
case 0x03: /* PHADDSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
tmp32s = GX.sw[i*2+0]+GX.sw[i*2+1];
GX.sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
GX.sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x04: /* PMADDUBSW Gx,Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
tmp32s = (int32_t)(GX.ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX.ub[i*2+1])*EX->sb[i*2+1];
GX.sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x05: /* PHSUBW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sw[i] = GX.sw[i*2+0] - GX.sw[i*2+1];
if(&GX == EX) {
GX.q[1] = GX.q[0];
} else {
for (int i=0; i<4; ++i)
GX.sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
}
break;
case 0x08: /* PSIGNB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
GX.sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
break;
case 0x09: /* PSIGNW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i)
GX.sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
break;
case 0x0A: /* PSIGND Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i)
GX.sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
break;
case 0x0B: /* PMULHRSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
tmp32s = ((((int32_t)(GX.sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
GX.uw[i] = tmp32s&0xffff;
}
break;
case 0x1C: /* PABSB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i) {
GX.sb[i] = abs(EX->sb[i]);
}
break;
case 0x1D: /* PABSW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i) {
GX.sw[i] = abs(EX->sw[i]);
}
break;
case 0x1E: /* PABSD Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
GX.sd[i] = abs(EX->sd[i]);
}
break;
default:
goto _default;
}
@@ -226,31 +426,42 @@
_6f_0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F: // PALIGNR
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
if(tmp8u>31)
{EX->q[0] = EX->q[1] = 0;}
else if(tmp8u>15) {
{GX.q[0] = GX.q[1] = 0;}
else
#if 0
if(tmp8u>15) {
tmp8u=(tmp8u-16)*8;
if (tmp8u < 64) {
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u);
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u);
} else {
GX.q[0] = EX->q[1] >> (tmp8u - 64);
GX.q[0] = GX.q[1] >> (tmp8u - 64);
GX.q[1] = 0;
}
} else {
tmp8u*=8;
if (tmp8u < 64) {
GX.q[0] = (GX.q[0] >> tmp8u) | (GX.q[1] << (64 - tmp8u));
GX.q[1] = (GX.q[1] >> tmp8u) | (EX->q[0] << (64-tmp8u));
GX.q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
GX.q[1] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64-tmp8u));
} else {
GX.q[0] = GX.q[1] >> (tmp8u - 64) | (EX->q[0] << (tmp8u));
GX.q[1] = (EX->q[0] << (64-tmp8u)) | (EX->q[1] >> (tmp8u - 64));
tmp8u -= 64;
GX.q[0] = (EX->q[1] >> tmp8u) | (GX.q[0] << (64 - tmp8u));
GX.q[1] = (GX.q[0] >> tmp8u) | (GX.q[1] >> (64 - tmp8u));
}
}
#else
{
for (int i=0; i<16; ++i, ++tmp8u)
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX.ub[tmp8u-16]):EX->ub[tmp8u];
GX.q[0] = eax1.q[0];
GX.q[1] = eax1.q[1];
}
#endif
break;
default:
goto _default;
@@ -354,18 +565,26 @@
_6f_0x60: /* PUNPCKLBW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=7; i>0; --i)
for(int i=7; i>0; --i) // 0 is untouched
GX.ub[2 * i] = GX.ub[i];
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = EX->ub[i];
if(&GX==EX)
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = GX.ub[2 * i];
else
for(int i=0; i<8; ++i)
GX.ub[2 * i + 1] = EX->ub[i];
NEXT;
_6f_0x61: /* PUNPCKLWD Gx,Ex */
nextop = F8;
GET_EX;
for(int i=3; i>0; --i)
GX.uw[2 * i] = GX.uw[i];
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = EX->uw[i];
if(&GX==EX)
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = GX.uw[2 * i];
else
for(int i=0; i<4; ++i)
GX.uw[2 * i + 1] = EX->uw[i];
NEXT;
_6f_0x62: /* PUNPCKLDQ Gx,Ex */
nextop = F8;
@@ -377,10 +596,16 @@
_6f_0x63: /* PACKSSWB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
if(&GX==EX) {
for(int i=0; i<8; ++i)
GX.sb[i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<8; ++i)
GX.sb[i] = (GX.sw[i]<-128)?-128:((GX.sw[i]>127)?127:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
}
NEXT;
_6f_0x64: /* PCMPGTB Gx,Ex */
nextop = F8;
@@ -400,13 +625,19 @@
for(int i=0; i<4; ++i)
GX.ud[i] = (GX.sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
NEXT;
_6f_0x67: /* PACKUSWB */
_6f_0x67: /* PACKUSWB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
if(&GX==EX) {
for(int i=0; i<8; ++i)
GX.ub[i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<8; ++i)
GX.ub[i] = (GX.sw[i]<0)?0:((GX.sw[i]>0xff)?0xff:GX.sw[i]);
for(int i=0; i<8; ++i)
GX.ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
}
NEXT;
_6f_0x68: /* PUNPCKHBW Gx,Ex */
nextop = F8;
@@ -429,20 +660,25 @@
_6f_0x6A: /* PUNPCKHDQ Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
// no copy needed if &GX==EX
GX.ud[0] = GX.ud[2];
GX.ud[2] = GX.ud[3];
GX.ud[1] = EX->ud[2];
GX.ud[2] = GX.ud[3];
GX.ud[3] = EX->ud[3];
NEXT;
_6f_0x6B: /* PACKSSDW Gx,Ex */
nextop = F8;
GET_EX;
if(EX==&GX) {eax1 = GX; EX = &eax1;} // copy is needed
for(int i=0; i<4; ++i)
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
for(int i=0; i<4; ++i)
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
if(&GX==EX) {
for(int i=0; i<4; ++i)
GX.sw[i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
GX.q[1] = GX.q[0];
} else {
for(int i=0; i<4; ++i)
GX.sw[i] = (GX.sd[i]<-32768)?-32768:((GX.sd[i]>32767)?32767:GX.sd[i]);
for(int i=0; i<4; ++i)
GX.sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
}
NEXT;
_6f_0x6C: /* PUNPCKLQDQ Gx,Ex */
nextop = F8;
@@ -598,6 +834,17 @@
GX.ud[i] = (GX.ud[i]==EX->ud[i])?0xffffffff:0;
NEXT;
_6f_0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] += GX.d[1];
if(EX==&GX) {
GX.d[1] = GX.d[0];
} else {
GX.d[1] = EX->d[0] + EX->d[1];
}
NEXT;
_6f_0x7E: /* MOVD Ed, Gx */
nextop = F8;
GET_ED;
@@ -623,7 +870,10 @@
_6f_0xA5: /* SHLD Ew,Gw,CL */
nextop = F8;
GET_EW;
tmp8u = (opcode==0xA4)?(F8):R_CL;
if(opcode==0xA4)
tmp8u = F8;
else
tmp8u = R_CL;
EW->word[0] = shld16(emu, EW->word[0], GW.word[0], tmp8u);
NEXT;
@@ -642,7 +892,10 @@
_6f_0xAD: /* SHRD Ew,Gw,CL */
nextop = F8;
GET_EW;
tmp8u = (opcode==0xAC)?(F8):R_CL;
if(opcode==0xAC)
tmp8u = F8;
else
tmp8u = R_CL;
EW->word[0] = shrd16(emu, EW->word[0], GW.word[0], tmp8u);
NEXT;
@@ -679,7 +932,79 @@
GET_EB;
GW.word[0] = EB->byte[0];
NEXT;
_6f_0xB7: /* MOVZX Gw,Ew */
nextop = F8;
GET_EW;
GW.word[0] = EW->word[0]; // yeah, the ZX is useless here
NEXT;
_6f_0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4: /* BT Ew,Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
break;
case 5: /* BTS Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else
EW->word[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
break;
case 6: /* BTR Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(ED))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
break;
case 7: /* BTC Ew, Ib */
CHECK_FLAGS(emu);
GET_EW;
tmp8u = F8;
if((nextop&0xC0)!=0xC0)
{
EW=(reg32_t*)(((uint16_t*)(EW))+(tmp8u>>4));
}
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
break;
default:
goto _default;
}
NEXT;
_6f_0xBB: /* BTC Ew,Gw */
CHECK_FLAGS(emu);
nextop = F8;
@@ -773,6 +1098,23 @@
GX.q[1] = eax1.q[1];
NEXT;
_6f_0xC8:
_6f_0xC9:
_6f_0xCA:
_6f_0xCB:
_6f_0xCC:
_6f_0xCD:
_6f_0xCE:
_6f_0xCF: /* BSWAP reg16 */
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;
@@ -808,7 +1150,7 @@
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.sw[i] * EX->sw[i];
GX.sw[i] = tmp32s;
GX.sw[i] = tmp32s&0xffff;
}
NEXT;
_6f_0xD6: /* MOVQ Ex,Gx */
@@ -820,18 +1162,21 @@
NEXT;
_6f_0xD7: /* PMOVMSKB Gd,Ex */
nextop = F8;
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
if((nextop&0xC0)==0xC0) {
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD.dword[0] |= (1<<i);
NEXT;
} else
goto _default;
_6f_0xD8: /* PSUBUSB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.ub[i] - EX->ub[i];
GX.ub[i] = (tmp16s<0)?0:((tmp16s>255)?255:tmp16s);
GX.ub[i] = (tmp16s<0)?0:tmp16s;
}
NEXT;
_6f_0xD9: /* PSUBUSW Gx,Ex */
@@ -839,10 +1184,15 @@
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.uw[i] - EX->uw[i];
GX.uw[i] = (tmp32s<0)?0:((tmp32s>0xffff)?0xffff:tmp32s);
GX.uw[i] = (tmp32s<0)?0:tmp32s;
}
NEXT;
_6f_0xDA: /* PMINUB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
if(EX->ub[i]<GX.ub[i]) GX.ub[i] = EX->ub[i];
NEXT;
_6f_0xDB: /* PAND Gx,Ex */
nextop = F8;
GET_EX;
@@ -857,7 +1207,14 @@
GX.ub[i] = (tmp16s>255)?255:tmp16s;
}
NEXT;
_6f_0xDD: /* PADDUSW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX.uw[i] + EX->uw[i];
GX.uw[i] = (tmp32s>65535)?65535:tmp32s;
}
NEXT;
_6f_0xDE: /* PMAXUB Gx, Ex */
nextop = F8;
GET_EX;
@@ -867,23 +1224,43 @@
_6f_0xDF: /* PANDN Gx,Ex */
nextop = F8;
GET_EX;
GX.q[0] = (~GX.q[0]) & EX->q[0];
GX.q[1] = (~GX.q[1]) & EX->q[1];
GX.q[0] = (~(GX.q[0])) & EX->q[0];
GX.q[1] = (~(GX.q[1])) & EX->q[1];
NEXT;
_6f_0xE0: /* PAVGB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i)
GX.ub[i] = ((uint16_t)GX.ub[i] + EX->ub[i] + 1)>>1;
NEXT;
_6f_0xE1: /* PSRAW Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>15)?16:EX->ub[0];
for (int i=0; i<8; ++i) GX.sw[i] >>= tmp8u;
for (int i=0; i<8; ++i)
GX.sw[i] >>= tmp8u;
NEXT;
_6f_0xE2: /* PSRAD Gx, Ex */
nextop = F8;
GET_EX;
tmp8u=(EX->q[0]>31)?32:EX->ub[0];
for (int i=0; i<4; ++i) GX.sd[i] >>= tmp8u;
for (int i=0; i<4; ++i)
GX.sd[i] >>= tmp8u;
NEXT;
_6f_0xE3: /* PAVGW Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<8; ++i)
GX.uw[i] = ((uint32_t)GX.uw[i] + EX->uw[i] + 1)>>1;
NEXT;
_6f_0xE4: /* PMULHUW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i) {
tmp32u = (uint32_t)GX.uw[i] * EX->uw[i];
GX.uw[i] = (tmp32u>>16)&0xffff;
}
NEXT;
_6f_0xE5: /* PMULHW Gx, Ex */
nextop = F8;
GET_EX;
@@ -899,7 +1276,7 @@
GX.sd[1] = EX->d[1];
GX.q[1] = 0;
NEXT;
_6f_0xE7: /* MOVNTDQ Ex, Gx */
_6f_0xE7: /* MOVNTDQ Ex, Gx */
nextop = F8;
GET_EX;
EX->q[0] = GX.q[0];
@@ -910,7 +1287,7 @@
GET_EX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX.sb[i] - EX->sb[i];
GX.ub[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
GX.sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
}
NEXT;
_6f_0xE9: /* PSUBSW Gx,Ex */
@@ -1023,12 +1400,17 @@
opx2->ub[i] = GX.ub[i];
}
NEXT;
_6f_0xF8: /* PSUBB Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
GX.sb[i] -= EX->sb[i];
NEXT;
_6f_0xF9: /* PSUBW Gx,Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
GX.uw[i] -= EX->uw[i];
GX.sw[i] -= EX->sw[i];
NEXT;
_6f_0xFA: /* PSUBD Gx,Ex */
nextop = F8;
@@ -1064,5 +1446,8 @@
GX.sd[2] += EX->sd[2];
GX.sd[3] += EX->sd[3];
NEXT;
_fini:
R_EIP = ip;
return;
}
+217 -109
View File
@@ -22,6 +22,7 @@
#ifdef HAVE_TRACE
#include "x86trace.h"
#endif
#include "x86tls.h"
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
@@ -31,9 +32,9 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
//TODO: register rtld_fini
//TODO: register fini
// let's cheat and set all args...
Push(emu, (uint32_t)emu->context->envv);
Push(emu, (uint32_t)emu->context->argv);
Push(emu, (uint32_t)emu->context->argc);
Push(emu, (uint32_t)my_context->envv);
Push(emu, (uint32_t)my_context->argv);
Push(emu, (uint32_t)my_context->argc);
if(init) {
PushExit(emu);
R_EIP=(uint32_t)*init;
@@ -43,7 +44,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
return 0;
emu->quit = 0;
}
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", emu->context->argc, emu->context->argv, emu->context->envv, main);
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
PushExit(emu);
R_EIP=(uint32_t)main;
@@ -53,36 +54,30 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
return 0;
}
const char* GetNativeName(x86emu_t* emu, void* p)
const char* GetNativeName(void* p)
{
static char unknown[10] = "???";
const char *ret = GetNameOffset(emu->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;
}
uintptr_t pltResolver = ~0;
void PltResolver(x86emu_t* emu, uint32_t id, uintptr_t ofs)
{
printf_log(LOG_INFO, "PltResolver: Ofs=%p, Id=%d (IP=%p, ESP+4=%p)", (void*)ofs, id, *(void**)(R_ESP), *(void**)(R_ESP+4));
emu->quit=1;
}
void UpdateFlags(x86emu_t *emu)
{
uint32_t cc;
@@ -537,6 +532,152 @@ void UpdateFlags(x86emu_t *emu)
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_AF);
break;
case d_cmp8:
CLEAR_FLAG(F_CF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_cmp16:
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_cmp32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_tst8:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_tst16:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_tst32:
CLEAR_FLAG(F_OF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CLEAR_FLAG(F_CF);
break;
case d_adc8:
CONDITIONAL_SET_FLAG(emu->res & 0x100, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_adc16:
CONDITIONAL_SET_FLAG(emu->res & 0x10000, F_CF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_adc32:
if(emu->res == (emu->op1+emu->op2)) {
lo = (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
} else {
lo = 1 + (emu->op1 & 0xFFFF) + (emu->op2 & 0xFFFF);
}
hi = (lo >> 16) + (emu->op1 >> 16) + (emu->op2 >> 16);
CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
cc = (emu->op2 & emu->op1) | ((~emu->res) & (emu->op2 | emu->op1));
CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
break;
case d_sbb8:
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_sbb16:
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_sbb32:
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_rol8:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 7)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_rol16:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 15)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_rol32:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG((emu->res + (emu->res >> 31)) & 1, F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & 0x1, F_CF);
break;
case d_ror8:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 7), F_CF);
break;
case d_ror16:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 15), F_CF);
break;
case d_ror32:
if(emu->op2 == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
}
CONDITIONAL_SET_FLAG(emu->res & (1 << 31), F_CF);
break;
case d_unknown:
printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_EIP);
break;
@@ -544,132 +685,99 @@ void UpdateFlags(x86emu_t *emu)
RESET_FLAGS(emu);
}
void PackFlags(x86emu_t* emu)
uintptr_t GetSegmentBaseEmu(x86emu_t* emu, int seg)
{
#define GO(A) emu->packed_eflags.f.F__##A = emu->flags[F_##A];
GO(CF);
GO(res1);
GO(PF);
GO(res2);
GO(AF);
GO(res3);
GO(ZF);
GO(SF);
GO(TF);
GO(IF);
GO(DF);
GO(OF);
GO(IOPL);
GO(NT);
GO(dummy);
GO(RF);
GO(VM);
GO(AC);
GO(VIF);
GO(VIP);
GO(ID);
#undef GO
}
void UnpackFlags(x86emu_t* emu)
{
#define GO(A) emu->flags[F_##A] = emu->packed_eflags.f.F__##A;
GO(CF);
GO(res1);
GO(PF);
GO(res2);
GO(AF);
GO(res3);
GO(ZF);
GO(SF);
GO(TF);
GO(IF);
GO(DF);
GO(OF);
GO(IOPL);
GO(NT);
GO(dummy);
GO(RF);
GO(VM);
GO(AC);
GO(VIF);
GO(VIP);
GO(ID);
#undef GO
if(emu->segs_serial[seg] != emu->context->sel_serial) {
emu->segs_offs[seg] = (uintptr_t)GetSegmentBase(emu->segs[seg]);
emu->segs_serial[seg] = emu->context->sel_serial;
}
return emu->segs_offs[seg];
}
uintptr_t GetGSBaseEmu(x86emu_t* emu)
const char* getAddrFunctionName(uintptr_t addr)
{
return (uintptr_t)GetGSBase(emu->context);
static char ret[1000];
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
if(addr==start)
sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
else
sprintf(ret, "%s/%s + %d", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
} else
sprintf(ret, "???");
return ret;
}
void printFunctionAddr(uintptr_t nextaddr, const char* text)
{
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
if(nextaddr==start)
printf_log(LOG_NONE, " (%s%s/%s)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname);
else
printf_log(LOG_NONE, " (%s%s/%s + %d)", text, ElfName(FindElfAddress(my_context, nextaddr)), symbname, nextaddr - start);
}
}
#ifdef HAVE_TRACE
extern uint64_t start_cnt;
#define PK(a) *(uint8_t*)(ip+a)
#define PK32(a) *(uint32_t*)(uint8_t*)(ip+a)
static void printFunctionAddr(x86emu_t* emu, uintptr_t nextaddr, const char* text)
{
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(emu->context, nextaddr), (void*)nextaddr, &start, &sz);
if(symbname && nextaddr>=start && nextaddr<(start+sz)) {
if(nextaddr==start)
printf_log(LOG_NONE, " (%s%s)", text, symbname);
else
printf_log(LOG_NONE, " (%s%s + 0x%x)", text, symbname, nextaddr - start);
}
}
#define PK(a) (*(uint8_t*)(ip+a))
#define PK32(a) (*(int32_t*)((uint8_t*)(ip+a)))
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
{
if(start_cnt) --start_cnt;
if(!start_cnt && emu->dec && (
(emu->trace_end == 0)
|| ((ip >= emu->trace_start) && (ip < emu->trace_end))) ) {
pthread_mutex_lock(&emu->context->mutex_trace);
if(!start_cnt && my_context->dec && (
(trace_end == 0)
|| ((ip >= trace_start) && (ip < trace_end))) ) {
int tid = syscall(SYS_gettid);
pthread_mutex_lock(&my_context->mutex_trace);
#ifdef DYNAREC
if((emu->context->trace_tid != tid) || (emu->context->trace_dynarec!=dynarec)) {
if((my_context->trace_tid != tid) || (my_context->trace_dynarec!=dynarec)) {
printf_log(LOG_NONE, "Thread %04d| (%s) |\n", tid, dynarec?"dyn":"int");
emu->context->trace_tid = tid;
emu->context->trace_dynarec = dynarec;
my_context->trace_tid = tid;
my_context->trace_dynarec = dynarec;
}
#else
if(emu->context->trace_tid != tid) {
if(my_context->trace_tid != tid) {
printf_log(LOG_NONE, "Thread %04d|\n", tid);
emu->context->trace_tid = tid;
my_context->trace_tid = tid;
}
#endif
printf_log(LOG_NONE, "%s", DumpCPURegs(emu, ip));
if(PK(0)==0xcc && PK(1)=='S' && PK(2)=='C') {
uint32_t a = *(uint32_t*)(ip+3);
if(a==0) {
printf_log(LOG_NONE, "0x%p: Exit x86emu\n", (void*)ip);
printf_log(LOG_NONE, "%p: Exit x86emu\n", (void*)ip);
} else {
printf_log(LOG_NONE, "0x%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(emu, *(void**)(ip+7)));
printf_log(LOG_NONE, "%p: Native call to %p => %s\n", (void*)ip, (void*)a, GetNativeName(*(void**)(ip+7)));
}
} else {
printf_log(LOG_NONE, "%s", DecodeX86Trace(emu->dec, ip));
printf_log(LOG_NONE, "%s", DecodeX86Trace(my_context->dec, ip));
uint8_t peek = PK(0);
if(peek==0xC3 || peek==0xC2) {
printf_log(LOG_NONE, " => %p", *(void**)(R_ESP));
printFunctionAddr(emu, *(uintptr_t*)(R_ESP), "=> ");
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
} else if(peek==0x55) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
printFunctionAddr(emu, ip, "here: ");
printFunctionAddr(ip, "here: ");
} else if(peek==0xE8) { // Call
uintptr_t nextaddr = ip + PK32(1);
printFunctionAddr(emu, nextaddr, "=> ");
uintptr_t nextaddr = ip + 5 + PK32(1);
printFunctionAddr(nextaddr, "=> ");
} else if(peek==0xFF) {
if(PK(1)==0x25) {
uintptr_t nextaddr = ip + PK32(2);
printFunctionAddr(emu, nextaddr, "=> ");
uintptr_t nextaddr = ip + 6 + PK32(2);
printFunctionAddr(nextaddr, "=> ");
}
}
printf_log(LOG_NONE, "\n");
}
pthread_mutex_unlock(&emu->context->mutex_trace);
pthread_mutex_unlock(&my_context->mutex_trace);
}
}
+34 -5
View File
@@ -122,6 +122,33 @@ static inline reg32_t* GetEw16(x86emu_t *emu, uint32_t v)
}
}
static inline reg32_t* GetEw16off(x86emu_t *emu, uint32_t v, uintptr_t offset)
{
uint32_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)];
} else {
uint32_t base = 0;
switch(m&7) {
case 0: base = R_BX+R_SI; break;
case 1: base = R_BX+R_DI; break;
case 2: base = R_BP+R_SI; break;
case 3: base = R_BP+R_DI; break;
case 4: base = R_SI; break;
case 5: base = R_DI; break;
case 6: base = R_BP; break;
case 7: base = R_BX; break;
}
switch((m>>6)&3) {
case 0: if(m==6) base = Fetch16(emu); break;
case 1: base += Fetch8s(emu); break;
case 2: base += Fetch16s(emu); break;
// case 3 is C0..C7, already dealt with
}
return (reg32_t*)(base+offset);
}
}
static inline mmx_regs_t* GetEm(x86emu_t *emu, uint32_t v)
{
uint32_t m = v&0xC7; // filter Ed
@@ -173,18 +200,20 @@ void Run660F(x86emu_t *emu);
void Run66D9(x86emu_t *emu); // x87
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)
#define GetESBaseEmu(emu) GetSegmentBaseEmu(emu, _ES)
uintptr_t GetGSBaseEmu(x86emu_t* emu);
const char* GetNativeName(x86emu_t* emu, void* p);
const char* GetNativeName(void* p);
#ifdef HAVE_TRACE
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec);
Loaded 100 of 361 files, more files were not shown because too many files have changed in this diff. Show more