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

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

* [MAIN] Revert default log level

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

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

* [ANDROID]Fix Termux installation path

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

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

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

* Add fstatat

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

No files matched your search

+3
View File
@@ -23,6 +23,9 @@ on:
- RPI4
- RPI4ARM64
- SD845
- SD888
- ADLINK
- PHYTIUM
build_type:
description: 'Build type'
required: true
+2 -2
View File
@@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, SD888, ADLINK, PHYTIUM, ANDROID]
type: [Release, Trace]
os: [ubuntu-latest]
@@ -60,7 +60,7 @@ jobs:
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DNOLOADADDR=1" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DARM_DYNAREC=ON -DNOLOADADDR=1" >> $GITHUB_ENV
else
sudo apt-get -y install gcc-arm-linux-gnueabihf
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
+130 -21
View File
@@ -19,11 +19,14 @@ 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(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(SD888 "Set to ON if targeting a Snapragon 888 based device" ${SD888})
option(ADLINK "Set to ON if targeting an ADLink AmpereAltra based device" ${ADLINK})
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
option(ARM64 "Set to ON if targeting a generic ARM64 based device" ${ARM64})
option(BAD_SIGNAL "Set to ON to activate the workaround for incoherent si_info on SIGSEGV" ${BAD_SIGNAL})
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(TERMUX "Set to ON if targeting an Android device with Termux" ${TERMUX})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
@@ -32,7 +35,7 @@ option(NOGIT "Set to ON if not building from a git clone repo (like when buildin
option(NO_LIB_INSTALL "Set ON to not install a few x86 libs that are used by many program" ${NO_LIB_INSTALL})
option(NO_CONF_INSTALL "Set ON to not install config files" ${NO_CONF_INSTALL})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR ARM64 OR RK3588)
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR ARM64 OR RK3588)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -40,8 +43,13 @@ if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE O
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
endif()
if(TERMUX)
set(ANDROID ON CACHE BOOL "")
set(TERMUX_PATH "/data/data/com.termux/files")
endif()
if(ANDROID)
set(NOLOADADDR ON CACHE BOOL "")
set(BAD_SIGNAL ON CACHE BOOL "")
endif()
option(LD80BITS "Set to ON if host device have 80bits long double (i.e. i386)" ${LD80BITS})
option(NOALIGN "Set to ON if host device doesn't need re-align (i.e. i386)" ${NOALIGN})
@@ -70,8 +78,10 @@ string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "arm" _arm)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armv8l" _armv8l)
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A OR RK3588 OR ARM64))
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI3ARM64 OR RPI4ARM64 OR PHYTIUM OR SD845 OR SD888 OR ADLINK OR A64 OR LX2160A OR RK3588 OR ARM64))
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
@@ -137,6 +147,14 @@ elseif(SD845)
add_definitions(-DSD845)
add_definitions(-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.2-a+simd+crypto -mtune=cortex-a75.cortex-a55 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(SD888)
add_definitions(-DSD888)
add_definitions(-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -march=armv8.4-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ADLINK)
add_definitions(-DADLINK)
add_definitions(-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -mcpu=neoverse-n1 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(A64)
add_definitions(-DA64)
add_definitions(-marm -march=armv8-a+crc+simd+crypto -mcpu=cortex-a53+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
@@ -178,13 +196,18 @@ elseif(LX2160A)
add_definitions(-DLX2160A)
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ANDROID)
add_definitions(-DANDROID)
elseif(ARM_DYNAREC)
#if DYNAREC is selected alone, without any arch
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
if(NOT ANDROID)
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
endif()
endif()
if(ANDROID)
add_definitions(-DANDROID)
endif()
if(TERMUX)
add_definitions(-DTERMUX)
endif()
if(BAD_SIGNAL)
add_definitions(-DBAD_SIGNAL)
endif()
@@ -299,6 +322,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/librarian/dictionnary.c"
"${BOX86_ROOT}/src/librarian/symbols.c"
"${BOX86_ROOT}/src/librarian/globalsymbols.c"
"${BOX86_ROOT}/src/emu/x86compstrings.c"
"${BOX86_ROOT}/src/emu/x86emu.c"
"${BOX86_ROOT}/src/emu/x86run_private.c"
"${BOX86_ROOT}/src/emu/x86syscall.c"
@@ -334,6 +358,7 @@ set(INTERPRETER
"${BOX86_ROOT}/src/emu/x86run660f.c"
"${BOX86_ROOT}/src/emu/x86run66d9.c"
"${BOX86_ROOT}/src/emu/x86run66dd.c"
"${BOX86_ROOT}/src/emu/x86run66f20f.c"
"${BOX86_ROOT}/src/emu/x86run67.c"
"${BOX86_ROOT}/src/emu/x86run6766.c"
"${BOX86_ROOT}/src/emu/x86rund8.c"
@@ -354,6 +379,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibbsd.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibx11.c"
@@ -413,6 +439,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX86_ROOT}/src/wrapped/wrappedalure.c"
"${BOX86_ROOT}/src/wrapped/wrappedalut.c"
"${BOX86_ROOT}/src/wrapped/wrappedopencl.c"
"${BOX86_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX86_ROOT}/src/wrapped/wrappedudev1.c"
@@ -467,6 +494,7 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator3.c"
"${BOX86_ROOT}/src/wrapped/wrappedayatanaappindicator3.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
@@ -519,6 +547,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibfuse.c"
"${BOX86_ROOT}/src/wrapped/wrappedatomic.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibpcre.c"
)
if(ANDROID)
list(APPEND WRAPPEDS
@@ -548,7 +578,7 @@ add_custom_command(
OUTPUT "${BOX86_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX86_ROOT}/rebuild_wrappers.py"
"${BOX86_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "--"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "POWERPCLE" "ANDROID" "TERMUX" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX86_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
@@ -666,7 +696,11 @@ else()
endif()
if(ARM_DYNAREC)
if(ANDROID)
if(TERMUX)
target_link_libraries(${BOX86} dynarec interpreter m dl android-sysv-semaphore android-spawn)
else()
target_link_libraries(${BOX86} dynarec interpreter m dl)
endif()
else()
target_link_libraries(${BOX86} dynarec interpreter m dl rt pthread resolv)
endif()
@@ -688,6 +722,11 @@ add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
if(ANDROID)
if(TERMUX)
target_link_libraries(${BOX86} dynarec interpreter m dl android-complex-math android-sysv-semaphore android-spawn )
else()
target_link_libraries(${BOX86} dynarec interpreter m dl)
endif()
target_link_libraries(${BOX86} c m dl)
else()
#target_link_libraries(${BOX86} c m dl rt pthread resolv)
@@ -701,30 +740,58 @@ endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
if(NOT NOLOADADDR)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,--image-base,${BOX86_ELF_ADDRESS}")
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS}")
endif()
else()
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS -rdynamic)
endif()
else()
target_link_options(${BOX86} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(${BOX86} PUBLIC -Wl,--image-base,${BOX86_ELF_ADDRESS})
else()
target_link_options(${BOX86} PUBLIC -Wl,-Ttext-segment,${BOX86_ELF_ADDRESS})
endif()
endif()
endif()
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
if(NOT TERMUX)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
else()
install(TARGETS ${BOX86}
RUNTIME DESTINATION ${TERMUX_PATH}/usr/bin)
endif()
if(NOT NO_CONF_INSTALL)
configure_file(system/box86.conf.cmake system/box86.conf)
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
if(NOT TERMUX)
install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION /etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION /etc/)
else()
#install(FILES ${CMAKE_BINARY_DIR}/system/box86.conf DESTINATION ${TERMUX_PATH}/usr/etc/binfmt.d/)
install(FILES ${CMAKE_SOURCE_DIR}/system/box86.box86rc DESTINATION ${TERMUX_PATH}/usr/etc/)
endif()
endif()
if(NOT NO_LIB_INSTALL)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
if(NOT TERMUX)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION /usr/lib/i386-linux-gnu/)
else()
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libunwind.so.8 DESTINATION ${TERMUX_PATH}/usr/lib/i386-linux-gnu/)
endif()
endif()
endif()
@@ -742,7 +809,11 @@ set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "ptitSeb")
set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION "Box86 - Linux Userspace x86 Emulator with a twist")
if(TERMUX)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libandroid-sysv-semaphore, libandroid-spawn")
else()
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
endif()
set(CPACK_PACKAGE_HOMEPAGE_URL, "https://box86.org")
file(STRINGS "${BOX86_ROOT}/src/box86version.h" TEMP_STRING REGEX "BOX86_MAJOR\\s*")
string(REGEX REPLACE "BOX86_MAJOR" "" TEMP_STRING ${TEMP_STRING})
@@ -756,16 +827,29 @@ string(REGEX MATCH "[0-9]" BOX86_REVISION ${TEMP_STRING})
set(CPACK_PACKAGE_VERSION_MAJOR ${BOX86_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${BOX86_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${BOX86_REVISION})
if(NOT TERMUX)
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
if(_aarch64 OR _armhf)
endif()
if(_aarch64 OR _armhf OR _arm OR _armv8l)
if(TERMUX)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm")
else()
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "armhf")
endif()
elseif(_x86_64 OR _x86)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386")
else()
#probably wrong...
execute_process(COMMAND "dpkg --print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
endif()
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Linux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
if(TERMUX)
set(CPACK_PACKAGING_INSTALL_PREFIX "${TERMUX_PATH}/usr")
endif()
if(NOT TERMUX)
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_${CMAKE_SYSTEM_NAME}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
else()
set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVISION}_Termux-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
endif()
INCLUDE(CPack)
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
@@ -872,20 +956,45 @@ add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
add_test(NAME multiple_dlopen COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test21 -D TEST_OUTPUT=tmpfile21.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME aes COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
endforeach()
add_test(NAME sse_optimized COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17_o2 -D TEST_OUTPUT=tmpfile17_o2.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17_o2.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
set_tests_properties(sse_optimized PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0;BOX86_DYNAREC_FASTROUND=0")
add_test(bswap ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test23 -D TEST_OUTPUT=tmpfile23.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref23.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
#add_test(feround ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
# -D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test24 -D TEST_OUTPUT=tmpfile24.txt
# -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref24.txt
# -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(sse4_2 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test25 -D TEST_OUTPUT=tmpfile25.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref25.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif(BOX86LIB)
+35
View File
@@ -1,3 +1,38 @@
box86 (0.3.4) unstable; urgency=low
* X86Libs: Updated libstdc++ & libgcc_s
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* ElfLoader: rework how elf memory is handled
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support for ADLink Ampere Altra
* OS: Added profile to build for Android and Termux.
* => Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
* => Some work also to reduce the memory footprint
-- Sebastien Chevalier <[email protected]> Thu, 15 Dec 2023 17:30:33 -0100
box86 (0.3.2) unstable; urgency=low
* Better syscall handling
* Fixed some wrapped functions, added some others
* Introduced another wrapper helper
* Added some more opcodes
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
* Added support of FASTNAN for some more opcodes
* Reduced memory footprint
* Added BOX86_NOSANDBOX (adds an argument to the command line)
* Added an ukrainian translation
* => Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
-- Sebastien Chevalier <[email protected]> Thu, 10 Mar 2023 10:20:33 -0500
box86 (0.3.0) unstable; urgency=low
* Added rcfile handling: box86 now read "/etc/box86.box86rc" and "~/.box86rc" and apply per process parameters
+31
View File
@@ -1,3 +1,34 @@
v0.3.4
======
* X86Libs: Updated libstdc++ & libgcc_s
* X86Libs: Use x86 vrsion of libunwind (it's needed by wine)
* Dynarec: Fixed some flags propagation issues inside blocks
* Dynarec: Improved Strong Memory Model emulation, introducing a 3rd level
* CPU: Remoworked how INT, priviliged opcodes and teh Trace flags works
* CPU: Added full support for SSE4.2
* ElfLoader: rework how elf memory is handled
* Emulation: Better handling of Signal (also handling SIGMAX correctly)
* Emulation: Better support for POKEUSER/PEEKUSER (helps Windows Unity games)
* Wrapping: More libs and some fixes in function wrapping (gtk3, vulkan...)
* Wrapping: Removed faked libunwind wrapping
* Hardware: Added more profile, with support for ADLink Ampere Altra
* OS: Added profile to build for Android and Termux.
=> Mostly a stability update with improved elfloader again, and added SSE 4.2 support (still need to work on the Dynarec part of this)
=> Some work also to reduce the memory footprint
v0.3.2
======
* Better syscall handling
* Fixed some wrapped functions, added some others
* Introduced another wrapper helper
* Added some more opcodes
* Added a cosimulation mode (to compare the behaviour of the dynarec against the interpreter)
* Added support of FASTNAN for some more opcodes
* Reduced memory footprint
* Added BOX86_NOSANDBOX (adds an argument to the command line)
* Added an ukrainian translation
=> Mostly a stability update with improved elfloader, fixed opcodes and refined profiles
v0.3.0
======
* Added rcfile handling: box86 now read `/etc/box86.box86rc` and `~/.box86rc` and apply per process parameters
+10 -2
View File
@@ -100,11 +100,13 @@ As most Allwinner A64 devices run an AARCH64 OS, you'll need an `armhf` multiarc
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for Snapdragon 845
#### for Snapdragon
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
or
`mkdir build; cd build; cmake .. -DSD888=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Depending how old/recent you SD is. As most Snapdragon devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Phytium
@@ -115,6 +117,12 @@ As most Phytium (D2000 or FT2000/4) devices run an AARCH64 OS, you'll need an `a
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for ADLink AmpereAltra
`mkdir build; cd build; cmake .. -DADLINK=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j`
As ADLINK AmpereAltra computers run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Other ARM64 64bits Linux platform
`mkdir build; cd build; cmake .. -DARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
+8 -8
View File
@@ -2,7 +2,7 @@
Linux Userspace x86 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
@@ -28,8 +28,8 @@ Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
> Compilation instructions can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](https://github.com/ptitSeb/box86/blob/master/docs/X86WINE.md)
----
@@ -80,15 +80,15 @@ Notes about Box86 configuration
----
Box86 now have configurations files. There are 2 files loaded. `/etc/box4.box86rc` and `~/.box86rc`. Both files have the same syntax, and is basicaly an ini files. Section in square brakets define the process name, and the rest is the env. var. to set. Looke at [Usage](USAGE.md) for detail on what parameters can be put. Box86 comes with a default file that should be installed for better stability. The file in in `system/box86.box86rc` and should be installed to `/etc/box86.box86rc` If, for some reasons, you don't want to install that file here, at least copy it to `~/.box86rc` or some game may not function correctly.
Note that the priority is: `~/.bashrc` > `/etc/box86.box86rc` > command line
So, your settings in `~/.bashrc` may override the setting from your command line...
Note that the priority is: `~/.box86rc` > `/etc/box86.box86rc` > command line
So, your settings in `~/.box86rc` may override the setting from your command line...
----
Notes about Unity game emulation
----
Running Unity games shoudl generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Running Unity games should generaly work now, but you should also note that many Unity3D games require OpenGL 3+ which can be tricky to provide on ARM SBC (single-board computers) for now.
Hint: on Pi4, use `MESA_GL_VERSION_OVERRIDE=3.2` and with Panfrost use `PAN_MESA_DEBUG=gl3` to use higher profile if the game starts then quits before showing anything.
----
@@ -134,8 +134,8 @@ I want to thank everyone who has contributed to box86 development.
There are many ways to contribute: code, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, icecream95, M-HT
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/), [CubeCoders Limited](http://cubecoders.com/)
* For their hardware contribution: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/), [AYN](https://www.ayntec.com/)
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
And I also thank the many other people who participated even once in the project.
+2 -2
View File
@@ -2,7 +2,7 @@
Linux用户空间的x86应用模拟器
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
@@ -127,7 +127,7 @@ Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序
以下感谢不分先后:
* 代码贡献:rajdakin, icecream95, M-HT
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 硬件捐赠:[ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
我还要感谢很多人,即使他们只参与了一次本项目。
+143
View File
@@ -0,0 +1,143 @@
![Official logo](img/Box86Logo.png "Official Logo")
Емулятор простіра користувача x86_64 із родзинкою
[Дивитись журнал змін](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Українська](https://github.com/ptitSeb/box86/blob/master/docs/README_UK.md) | [Повідомити про помилку](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=main) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
Box86 дозволяє запускати x86 Linux програми (наприклад, ігри) на системах Linux відмінних від x86, наприклад ARM (хост-система має мати 32-розрядний порядок редагування).
Вам *ПОТРІБНА* 32-розрядна підсистема для запуску та створення Box86. Box86 марний лише на 64-розрядних системах. Крім того, вам *ПОТРІБЕН* 32-розрядний інструментарій для створення Box86. Ланцюжок інструментів, який підтримує лише 64-розрядні версії, не компілює Box86, і ви отримаєте помилки (зазвичай на aarch64 ви отримуєте що «-marm» не розпізнається, і вам знадобиться середовище з мультиархітектурою або chroot).
Оскільки Box86 використовує рідні версії деяких «системних» бібліотек, таких як libc, libm, SDL і OpenGL, його легко інтегрувати та використовувати з більшістю програм, а продуктивність у багатьох випадках може бути напрочуд високою. Подивіться на цей стендовий аналіз для прикладу [тут](https://box86.org/index.php/2021/06/game-performances/). Це також означає, що вам знадобиться 32-бітний простір користувача на 64-бітній ОС, наприклад `armhf` поверх `aarch64` 64-бітної ОС.
Більшість x86-ігор потребують OpenGL, тому на платформах ARM може знадобитися таке рішення, як [gl4es](https://github.com/ptitSeb/gl4es). (Деякі платформи ARM підтримують лише OpenGL ES і/або їх реалізація OpenGL хитра. (див. OpenGL на Android))
Box86 інтегрується з DynaRec (динамічний рекомпілятор) для платформ ARM64 і RV64 забезпечуючи підвищення швидкості в 5-10 разів, ніж використання лише інтерпретатора. Деякі високорівневі відомості про те, як працює DynaRec, можна знайти [тут](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Багато ігор просто працюють без особливих налаштувань, наприклад: WorldOfGoo, Airline Tycoon Deluxe і FTL. Багато ігор GameMaker Linux також працюють нормально. (є довгий список, серед них UNDERTALE, A Risk of Rain і Cook Serve Delicious). Ігри Unity3D також працюють добре, але вимога OpenGL може бути проблемою на деяких платформах ARM.
Якщо ви серйозно ставитеся до розробки Box86, вам слід встановити ccache та створити Box86 з ним. (Використовуйте, наприклад, ccmake.)
Щоб увімкнути TRACE (тобто скидання в stdout усіх окремих виконаних інструкцій x86 із дампом регістрів), вам також знадобиться [бібліотека Zydis](https://github.com/zyantific/zydis), доступна у вашій системі.
Деякі внутрішні коди операцій x86 використовують частини «Бібліотеки емулятора Realmode X86», дивіться [x86primop.c](../src/emu/x86primop.c) для детальної інформації про авторські права.
----
Компіляція/Встановлення
----
> Інструкцію зі складання Box86 можна знайти [тут](COMPILE.md).\
> Інструкцію з встановлення Wine для Box86 можна знайти [тут](X86WINE.md).
----
Ось 6 відео, перші 2 відео – це відео "Airline Tycoon Deluxe" і "Heretic 2", які працюють на GigaHertz OpenPandora (друге використовує Dynarec), а наступні 2 відео – це відео "Bit.Trip.Runner" і "Neverwinter Night", які працюють на ODroid XU4 (без dynarec), а останні 2 відео на Pi4: Shovel Knight (відео від @ITotalJustice) і Freedom Planet (відео від @djazz), також без Dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
Ви можете знайти багато інших відео про Box86 у YouTube каналах [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) або [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA).
Список сумісності доступний тут: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
Логотип і піктограма зроблені @grayduck, дякую!
Зауважте, що цей проект не слід плутати з [86box](https://github.com/86Box/86Box), гарним емулятором "повної системи", що спеціалізується на ранньому (до відносно недавньому) апаратному забезпеченні ПК.
----
Використання
----
Є кілька змінних середовища для керування поведінкою Box86.
Дивіться [тут](USAGE.md) для перегляду всіх змінних середовища та того, що вони роблять.
Примітка: Dynarec від Box86 використовує механізм із захистом пам’яті та обробником сигналу помилки сегментів для обробки JIT коду. Простіше кажучи, якщо ви хочете використовувати GDB для налагодження запущеної програми, яка використовує JIT-код (наприклад, mono/Unity3D), ви все одно матимете багато «звичайних» помилок сегментів. Пропонується використовувати щось на зразок `handle SIGSEGV nostop` в GDB, щоб не зупинятися на кожній помилці сегмента, і, можливо, поставити точку зупину всередині `my_memprotectionhandler` в `signals.c`, якщо ви хочете перехопити помилки сегментів.
----
Історія версій/Журнал змін
----
Історія версій доступна [тут](docs/CHANGELOG.md).
----
Примітки щодо 64-розрядних платформ
----
Оскільки Box86 працює шляхом прямого перекладу викликів функцій із x86 на хост-систему, хост-система (на якій працює Box86) повинна мати 32-розрядні бібліотеки. Box86 не містить 32-біт <-> 64-біт перекладу. Отже, щоб запустити Box86, наприклад, на платформі ARM64, вам потрібно буде зібрати Box86 для 32-бітної ARM, а також потрібно мати chroot з 32-бітними бібліотеками.
Якщо ви дивитесь на 64-розрядну версію box86, подивіться на [Box64](https://github.com/ptitSeb/box64): він може запускати двійкові файли x86_64 на 64-розрядних платформах. Але зауважте, що вам все одно потрібен Box86 (і 32-розрядний chroot) для запуску бінарних файлів x86 (як це також трапляється в реальному Linux x86_64, для запуску якого потрібні бібліотеки x86 і двійковий файл в multiarch).
----
Примітки щодо конфігурації Box86
----
Box86 тепер має конфігураційні файли. Завантажуються 2 файли: `/etc/box4.box86rc` і `~/.box86rc`. Обидва файли мають однаковий синтаксис і в основному є файлами ini. Розділ у квадратних дужках визначає назву процесу, а решта — встановлють змінну середовища. Подивіться на [використання](docs/USAGE.md), щоб дізнатися, які параметри можна використовувати. Box86 поставляється з файлом за замовчуванням, який слід інсталювати для кращої стабільності. Файл знаходиться в `system/box86.box86rc` і має бути встановлено в `/etc/box86.box86rc`. Якщо з певних причин ви не хочете встановлювати цей файл у `/etc`, принаймні скопіюйте його в `~/.box86rc` або гра може не працювати належним чином. Зауважте, що пріоритетом є: `~/.bashrc` > `/etc/box86.box86rc` > командний рядок
Таким чином, ваші налаштування в `~/.bashrc` можуть замінити налаштування з вашого командного рядка...
----
Примітки щодо емуляції ігор Unity
----
Запуск ігор Unity має працювати, але ви також повинні зауважити, що для багатьох ігор Unity3D потрібен OpenGL 3+, який може бути складно забезпечити на ARM SBC (одноплатних комп’ютерах). Крім того, багато нових ігор Unity3D (наприклад, KSP) використовують стиснуті текстури BC7, які не підтримуються багатьма інтегрованими GPU ARM.
Підказка: в Pi4 використовуйте `MESA_GL_VERSION_OVERRIDE=3.2`, а в Panfrost — `PAN_MESA_DEBUG=gl3`, щоб використовувати вищий профіль, якщо гра запускається, а потім завершується, перш ніж щось показує.
----
Примітки щодо Steam
----
Linux версія Steam тепер може працювати з Box86, але вам також потрібен Box64, щоб його можна було повністю використовувати.
Рекомендується запускати Steam у small режимі, оскільки він використовує менше пам’яті, але steamwebhelper (64-бітний процес) усе одно завантажуватиметься, навіть якщо він не використовується.
Екран входу не може працювати без steamwebhelper, і буде показувати лише порожні вікна без належного налаштування box64 у системі.
Зауважте, що Steam використовуватиме багато пам’яті та ледве поміститься в систему з 4 ГБ оперативної пам’яті. Він більше не працюватиме в системі з меншим об’ємом пам’яті (як обхідний шлях, створіть файл підкачки, увійдіть і поставте прапорець «запам’ятати мене», використовуйте box64rc, щоб вимкнути steamwebhelper і запускати лише в малому режимі без підкачки після першого входу в систему)
Останнє зауваження: Steam BigPicture працюватиме, але також потрібен steamwebhelper (і box64) і багато пам’яті. Він не запуститься в системі лише з 4 ГБ оперативної пам’яті без файлу підкачки.
- Якщо у вас виникли проблеми зі встановленням Steam, ви можете знайти `install_steam.sh` у кореневій папці сховища box86. Цей простий скрипт завантажить і встановить Steam у вашу домашню папку, а потім створить ярлик steam у `/usr/local/bin` (для цього він запитає дозвіл sudo). Просто використовуйте `steam` для запуску після встановлення. Зауважте, що інсталяція, яка знаходиться в папці Home, працюватиме лише для одного користувача. Не використовуйте цей скрипт, якщо вам потрібна багатокористувацька інсталяція.
- Щоб уникнути повідомлення «libc.so.6 відсутній», ви можете використовувати `STEAMOS=1` і `STEAM_RUNTIME=1` як змінні середовища (воно автоматично з’являється, якщо ви використовували сценарій `install_steam.sh`)
Щоб вимкнути `steamwebhelper`, коли Box64 встановлений і працює, створіть (або відредагуйте) `~/.box64rc` і додайте у ньому:
```
[steamwebhelper]
BOX64_EXIT=1
```
І тоді `steamwebhelper` буде вимкнено. Прокоментуйте `#` ці 2 рядки, щоб увімкнути його знову.
----
Примітки щодо Wine
----
Wine тепер підтримується. Інтегровани програми Wine працює як і багато програм та ігор для Windows. Не забувайте, що більшість ігор для Windows використовують Direct3D, для цього може знадобитися повний драйвер OpenGL і якомога більш високий профіль (і gl4es з бекендом ES2 наразі мають проблеми з Wine).
Примітка: якщо ви плануєте використовувати box86 з Wine на Raspberry Pi 3 або ранішої версії, ці моделі використовують ОС за замовчуванням, яка має ядро ​​з розділенням 2/2 (тобто 2G місця для програми користувача та 2 Г місця для ядра). Це несумісно з програмами Wine, яким потрібен доступ до пам’яті > 2 Гб адреси. Тож вам потрібно буде переналаштувати ядро ​​для розділення 3G/1G.
----
Примітки щодо Vulkan
----
Box86 вже використовує Vulkan. Якщо у вашій системі є 32-розрядний драйвер Vulkan, Box86 використовуватиме його за потреби. Профіль 1.0, 1.1, 1.2 і 1.3, з деякими розширеннями, має бути в порядку. DXVK, включаючи 2.0, працює. Я знаю, що деякі демонстраційні версії працюють на Pi4 (демонстраційні версії Sascha Willems для x86 працюють так само, як якщо б створювати безпосередньо на armhf). Зауважте, що драйвер Vulkan для Pi4 наразі НЕ підтримує DXVK (обгортка Wine DirectX->Vulkan). Це не проблема Box86, у драйвері відсутні розширення (підтримка апаратного забезпечення) та кілька інших речей, через які DXVK не працює на pi4. З боку Panfrost, PanVK трохи молодий, і я ще не тестував DXVK з ним.
----
Останнє слово
----
Я хочу подякувати всім, хто зробив внесок у розвиток box86.
Є багато способів зробити свій внесок: код, фінанси, апаратне забезпечення та реклама!
Отже, без особливого порядку, я хочу подякувати:
* За основний внесок у код: rajdakin, icecream95, M-HT
* За великий фінансовий внесок: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* За внесок у апаратне забезпечення: [ADLink](https://www.adlinktech.com/Products/Computer_on_Modules/COM-HPC-Server-Carrier-and-Starter-Kit/Ampere_Altra_Developer_Platform?lang=en), [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [Команда TwisterOS](https://twisteros.com/)
* За постійну рекламу Box86: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[Команда TwisterOS](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
І я також дякую багатьом іншим людям, які хоч раз брали участь у проекті.
(Якщо ви використовуєте Box86 у своєму проекті, будь ласка, не забудьте згадати про це!)
+39 -2
View File
@@ -146,8 +146,9 @@ Define Box86's Dynarec max allowed forward value when building Block.
#### BOX86_DYNAREC_STRONGMEM *
Enable/Disable simulation of Strong Memory model
* 0 : Don't try anything special (Default.)
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
* 1 : Enable some Memory Barrier when writting to memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : All 1. plus a memory barrier on every write to memory using MOV
* 3 : All 2. plus Memory Barrier when reading from memory and on some SSE/SSE2 opcodes too
#### BOX86_DYNAREC_X87DOUBLE *
Force the use of Double for x87 emulation
@@ -185,11 +186,21 @@ Detect MonoBleedingEdge and apply conservative settings
* 0 : Don't detect MonoBleedingEdge
* 1 : Detect MonoBleedingEdge, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_DYNAREC_JVM *
Detect libjvm and apply conservative settings
* 0 : Don't detect libjvm
* 1 : Detect libjvm, and apply BIGBLOCK=0 STRONGMEM=1 if detected (Default)
#### BOX86_DYNAREC_WAIT *
Behavior with FillBlock is not availble (FillBlock build Dynarec blocks and is not multithreaded)
* 0 : Dynarec will not wait for FillBlock to ready and use Interpreter instead (might speedup a bit massive multithread or JIT programs)
* 1 : Dynarec will wait for FillBlock to be ready (Default)
#### BOX86_DYNAREC_MISSING *
Dynarec print the missing opcodes
* 0 : not print the missing opcode (Default, unless DYNAREC_LOG>=1 or DYNAREC_DUMP>=1 is used)
* 1 : Will print the missing opcodes
#### BOX86_SSE_FLUSHTO0 *
Handling of SSE Flush to 0 flags
* 0 : Just track the flag (Default)
@@ -200,6 +211,21 @@ Handling of x87 80bits long double
* 0 : Try to handle 80bits long double as precise as possible (Default)
* 1 : Handle them as double
#### BOX86_LIBCEF *
Detect libcef and apply malloc_hack settings
* 0 : Don't detect libcef
* 1 : Detect libcef, and apply MALLOC_HACK=2 if detected (Default)
#### BOX86_SDL2_JGUID *
Need a workaround for SDL_GetJoystickGUIDInfo function for wrapped SDL2
* 0 : Don't use any workaround
* 1 : Use a workaround for program that use the private SDL_GetJoystickGUIDInfo function with 1 missing argument
#### BOX86_MUTEX_ALIGNED *
Will mutex are used as-is or wrapped to handle unaligned used
* 0 : Mutex will be wrapped in case unaligned mutexes are used (Default)
* 1 : Do no wrap mutex and use them as-is (faster, but might crash with SEGBUS error)
#### BOX86_LIBGL *
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -249,6 +275,11 @@ Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX86_FUTEX_WAITV *
Use of the new fuext_waitc syscall
* 0 : Do not try to use it, return unsupported (Default for BAD_SIGNAL build)
* 1 : let program use the syscall if the host system support it (Default for other build)
#### BOX86_ENV
* XXX=yyyy
will add XXX=yyyy env. var.
@@ -293,6 +324,12 @@ Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
* 2 : Launch `gdbserver` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process, and go in an endless loop, waiting.
Use `gdb /PATH/TO/box86` and then `target remote 127.0.0.1:1234` to connect to the gdbserver (or use actual IP if not on the machine). After that, the procedure is the same as with ` BOX86_JITGDB=1`.
This mode can be usefullwhen programs redirect all console output to a file (like Unity3D Games)
* 3 : Launch `lldb` when a segfault, bus error or illegal instruction signal is trapped, attached to the offending process and go in an endless loop, waiting.
#### BOX86_NORCFILES
If the env var exist, no rc files (like /etc/box86.box86rc and ~/.box86rc) will be loaded
#### BOX86_NOSANDBOX
* 0 : Nothing special
* 1 : Added "--no-sandbox" to command line arguments (usefull for chrome based programs)
+1 -1
View File
@@ -42,7 +42,7 @@ rm ~/wine.tgz # clean up
# Install shortcuts (make launcher & symlinks. Credits: grayduck, Botspot)
echo -e '#!/bin/bash\nsetarch linux32 -L '"$HOME/wine/bin/wine "'"$@"' | sudo tee -a /usr/local/bin/wine >/dev/null # Create a script to launch wine programs as 32bit only
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could aslo just make a symlink, but box86 only works for 32bit apps at the moment
#sudo ln -s ~/wine/bin/wine /usr/local/bin/wine # You could also just make a symlink, but box86 only works for 32bit apps at the moment
sudo ln -s ~/wine/bin/wineboot /usr/local/bin/wineboot
sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
+4 -2
View File
@@ -22,7 +22,7 @@ echo "#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
export DBUS_FATAL_WARNINGS=0
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
~/steam/bin/steam $@" > steam
# make script executable and move
chmod +x steam
@@ -35,7 +35,9 @@ if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
sudo apt update # update package lists with the newly added arch
# install the libraries that Steam requires
sudo apt install libc6:armhf libncurses5:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf
sudo apt install libc6:armhf libsdl2-2.0-0:armhf libsdl2-image-2.0-0:armhf libsdl2-mixer-2.0-0:armhf libsdl2-ttf-2.0-0:armhf libopenal1:armhf libpng16-16:armhf libfontconfig1:armhf libxcomposite1:armhf libbz2-1.0:armhf libxtst6:armhf libsm6:armhf libice6:armhf libgl1:armhf libxinerama1:armhf libxdamage1:armhf
# this one is not there all the time, so just try it...
sudo apt install libncurses5:armhf
# install mesa for armhf if already installed
if dpkg-query -W libgl1-mesa-dri 2>/dev/null; then
+1 -1
View File
@@ -1834,7 +1834,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
+39 -14
View File
@@ -679,12 +679,12 @@ class Clauses:
return isinstance(o, Clauses) and (self.clauses == o.clauses)
JumbledFunctions = CustOrderedDictList[Clause, Function]
FilesSpecific = Dict[Filename, FileSpec]
FileSpecifics = Dict[Filename, FileSpec]
SortedGlobals = CustOrderedDictList[Clauses, FunctionType]
SortedRedirects = CustOrderedDictList[Clauses, FunctionType]
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FilesSpecific]:
def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions, FileSpecifics]:
"""
readFiles
@@ -693,7 +693,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
gbls: JumbledFunctions = CustOrderedDictList()
redirects: JumbledFunctions = CustOrderedDictList()
filespecs: FilesSpecific = {}
filespecs: FileSpecifics = {}
symbols: Dict[str, Filename] = {}
need_halt: bool = False
@@ -751,6 +751,8 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("gstinterfaces010","gstaudio")\
or match("gstreamer010","gstreamer") \
or match("appindicator","appindicator3")\
or match("appindicator","ayatanaappindicator3")\
or match("appindicator3","ayatanaappindicator3")\
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
@@ -880,7 +882,7 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
return gbls, redirects, filespecs
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FilesSpecific) \
def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespecs: FileSpecifics) \
-> Tuple[SortedGlobals, SortedRedirects]:
# First sort file specific stuff
for fn in filespecs:
@@ -944,13 +946,13 @@ def sortArrays(gbl_funcs: JumbledFunctions, red_funcs: JumbledFunctions, filespe
redirects[red_vals[funtype]].append(funtype)
redirects.sort(key=Clauses.splitdef)
def fail(): assert(False)
def fail(): assert False
for clauses in redirects:
redirects[clauses].sort(key=lambda v: fail() if v.redirected is None else v.splitchar() + v.redirected.splitchar())
return gbls, redirects
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filesspec: FilesSpecific) -> Optional[str]:
def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filespecs: FileSpecifics) -> Optional[str]:
# Check if there was any new functions compared to last run
functions_list: str = ""
for clauses in gbls:
@@ -960,18 +962,18 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
for v in redirects[clauses]:
assert(v.redirected is not None)
functions_list = functions_list + "#" + str(clauses) + " " + v.orig + " -> " + v.redirected.orig + "\n"
for filename in sorted(filesspec.keys()):
for filename in sorted(filespecs.keys()):
functions_list = functions_list + filename + ":\n"
for st in filesspec[filename].structs:
struct = filesspec[filename].structs[st]
for st in filespecs[filename].structs:
struct = filespecs[filename].structs[st]
functions_list = functions_list + \
"% " + st + " " + struct.name + " " + struct.repl + "\n"
for _bare in filesspec[filename].typedefs:
for _bare in filespecs[filename].typedefs:
functions_list = functions_list + "- " + _bare.orig + ":\n"
for fn in filesspec[filename].typedefs[_bare]:
for fn in filespecs[filename].typedefs[_bare]:
if fn.no_dlsym: continue
functions_list = functions_list + " - " + fn.name + "\n"
for funtype in filesspec[filename].structsuses:
for funtype in filespecs[filename].structsuses:
assert(funtype.redirected is not None)
functions_list = functions_list + "% " + funtype.orig + " -> " + funtype.redirected.orig + "\n"
@@ -992,7 +994,7 @@ def checkRun(root: str, gbls: SortedGlobals, redirects: SortedRedirects, filessp
return functions_list
def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobals, redirects: SortedRedirects, \
filespecs: FilesSpecific) -> None:
filespecs: FileSpecifics) -> None:
# Files header and guard
files_header = {
"wrapper.c": """
@@ -1148,6 +1150,13 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
for fhdr in files_header:
files_guard[fhdr] = trim(files_guard[fhdr])
# TODO: put the informations below in a structure (like in box64, where
# typedefs & co. are stored in an ABI-specific structure)
return_x87: str = "DKdf"
if any(c not in FileSpec.values for c in return_x87):
raise NotImplementedError("Invalid character")
# Typedefs
# E v c w i I C W u U f d D K l L p V O S 2 P G N M s
tdtypes = ["x86emu_t*", "void", "int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "_2uint_struct_t", "void*", "void*", "...", "...", "void*"]
@@ -1309,6 +1318,22 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
if not clauses.empty():
file.write("#endif\n")
# Finally, write predicate functions
# isRetX87Wrapper
file.write("\nint isRetX87Wrapper(wrapper_t fun) {\n")
for clauses in gbls:
empty = True
for funtype in gbls[clauses]:
if funtype.orig[0] in return_x87: # TODO: put this in a function (functions would request the ABI for more info)
if empty and (not clauses.empty()):
file.write("#if " + str(clauses) + "\n")
empty = False
file.write("\tif (fun == &" + funtype.orig + ") return 1;\n")
if not empty:
file.write("#endif\n")
file.write("\treturn 0;\n}\n")
file.write(files_guard["wrapper.c"].format(lbr="{", rbr="}", version=ver))
# Rewrite the wrapper.h file:
@@ -1398,6 +1423,6 @@ if __name__ == '__main__':
if v == "--":
limit.append(i)
Define.defines = list(map(DefineType, sys.argv[2:limit[0]]))
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.10") != 0:
if main(sys.argv[1], sys.argv[limit[0]+1:], "2.0.0.11") != 0:
exit(2)
exit(0)
+63 -22
View File
@@ -79,13 +79,15 @@ void free_tlsdatasize(void* p)
tlsdatasize_t *data = (tlsdatasize_t*)p;
box_free(data->ptr);
box_free(p);
if(my_context)
pthread_setspecific(my_context->tlskey, NULL);
}
int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
void* tid = (void*)GetTID();
#define GO(A, B) \
i = (arm_lock_storeifref2(&A, NULL, tid)==tid); \
@@ -140,6 +142,7 @@ static void init_mutexes(box86context_t* context)
{
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
arm_lock_stored(&context->mutex_dyndump, 0);
arm_lock_stored(&context->mutex_once, 0);
arm_lock_stored(&context->mutex_once2, 0);
@@ -147,6 +150,20 @@ static void init_mutexes(box86context_t* context)
arm_lock_stored(&context->mutex_tls, 0);
arm_lock_stored(&context->mutex_thread, 0);
arm_lock_stored(&context->mutex_bridge, 0);
#else
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_dyndump, &attr);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutex_init(&context->mutex_bridge, &attr);
pthread_mutexattr_destroy(&attr);
#endif
pthread_mutex_init(&context->mutex_lock, NULL);
#else
pthread_mutexattr_t attr;
@@ -212,7 +229,7 @@ box86context_t *NewBox86Context(int argc)
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
context->deferedInit = 1;
context->deferredInit = 1;
#endif
context->sel_serial = 1;
@@ -222,8 +239,6 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// Cannot use Bridge name as the map is not initialized yet
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
@@ -243,7 +258,7 @@ box86context_t *NewBox86Context(int argc)
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
pthread_key_create(&context->tlskey, free_tlsdatasize);
pthread_key_create(&context->tlskey, NULL/*free_tlsdatasize*/);
InitFTSMap(context);
@@ -251,6 +266,8 @@ box86context_t *NewBox86Context(int argc)
context->canary[/*getrand(4)*/0] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at GS:0x14, value:%08X\n", *(uint32_t*)context->canary);
context->globdata = NewMapSymbols();
initAllHelpers(context);
return context;
@@ -271,6 +288,7 @@ void FreeBox86Context(box86context_t** context)
box86context_t* ctx = *context; // local copy to do the cleanning
//clean_current_emuthread(); // cleaning main thread seems a bad idea
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib, NULL);
if(ctx->maplib)
@@ -293,8 +311,8 @@ void FreeBox86Context(box86context_t** context)
if(ctx->zydis)
DeleteX86Trace(ctx);
if(ctx->deferedInitList)
box_free(ctx->deferedInitList);
if(ctx->deferredInitList)
box_free(ctx->deferredInitList);
/*box_free(ctx->argv);*/
@@ -341,7 +359,6 @@ void FreeBox86Context(box86context_t** context)
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
pthread_setspecific(ctx->tlskey, NULL);
}
pthread_key_delete(ctx->tlskey);
@@ -355,26 +372,25 @@ void FreeBox86Context(box86context_t** context)
}
}
free_neededlib(&ctx->neededlibs);
free_neededlib(ctx->neededlibs);
ctx->neededlibs = NULL;
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
FreeMapSymbols(&ctx->globdata);
finiAllHelpers(ctx);
#ifdef DYNAREC
pthread_mutex_destroy(&ctx->mutex_lock);
#else
#ifndef USE_CUSTOM_MUTEX
pthread_mutex_destroy(&ctx->mutex_once);
pthread_mutex_destroy(&ctx->mutex_once2);
pthread_mutex_destroy(&ctx->mutex_trace);
pthread_mutex_destroy(&ctx->mutex_tls);
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
pthread_mutex_destroy(&ctx->mutex_lock);
#endif
pthread_mutex_destroy(&ctx->mutex_lock);
freeCycleLog(ctx);
@@ -382,20 +398,45 @@ void FreeBox86Context(box86context_t** context)
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
int idx = ctx->elfsize;
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
int idx = 0;
while(idx<ctx->elfsize && ctx->elfs[idx]) idx++;
if(idx == ctx->elfsize) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
} else {
ctx->elfs[idx] = head;
}
ctx->elfs[idx] = head;
ctx->elfsize++;
printf_log(LOG_DEBUG, "Adding \"%s\" as #%d in elf collection\n", ElfName(head), idx);
return idx;
}
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head) {
if(GetTLSBase(head)) {
// should remove the tls info
int tlsbase = GetTLSBase(head);
/*if(tlsbase == -ctx->tlssize) {
// not really correct, but will do for now
ctx->tlssize -= GetTLSSize(head);
if(!(++ctx->sel_serial))
++ctx->sel_serial;
}*/
}
for(int i=0; i<ctx->elfsize; ++i)
if(ctx->elfs[i] == head) {
ctx->elfs[i] = NULL;
return;
}
}
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
// should in fact first try to map a hole, but rewinding all elfs and checking filled space, like with the mapmem utilities
context->tlssize += tlssize;
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 3
#define BOX86_REVISION 1
#define BOX86_REVISION 4
#endif //__BOX86_VERSION_H_
+171 -70
View File
@@ -23,6 +23,7 @@
#include <sys/mman.h>
#include "custommem.h"
#include "threads.h"
//#define TRACE_MEMSTAT
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/dynablock_private.h"
@@ -34,7 +35,6 @@
// init inside dynablocks.c
static mmaplist_t *mmaplist = NULL;
//#define TRACE_MEMSTAT
#ifdef TRACE_MEMSTAT
static size_t jmptbl_allocated = 0, jmptbl_allocated1 = 0;
#endif
@@ -44,6 +44,8 @@ static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
// lock addresses
KHASH_SET_INIT_INT(lockaddress)
static kh_lockaddress_t *lockaddress = NULL;
#endif
#ifdef USE_CUSTOM_MUTEX
static uint32_t mutex_prot;
static uint32_t mutex_blocks;
#else
@@ -57,7 +59,7 @@ static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags b
static uint8_t hotpages[MEMPROT_SIZE] = {0};
#endif
#ifdef TRACE_MEMSTAT
static uint64_t memprot_allocated = 0, memprot_max_allocated = 0;
static uint32_t memprot_allocated = 0, memprot_max_allocated = 0;
#endif
static int inited = 0;
@@ -67,7 +69,8 @@ typedef struct mapmem_s {
struct mapmem_s *next;
} mapmem_t;
static mapmem_t *mapmem = NULL;
static mapmem_t *mapallmem = NULL;
static mapmem_t *mmapmem = NULL;
typedef struct blocklist_s {
void* block;
@@ -76,7 +79,7 @@ typedef struct blocklist_s {
void* first;
} blocklist_t;
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
#define MMAPSIZE (64*1024) // allocate 64kb sized blocks
static int n_blocks = 0; // number of blocks for custom malloc
static int c_blocks = 0; // capacity of blocks for custom malloc
@@ -169,6 +172,8 @@ static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
}
}
#define THRESHOLD (128-2*sizeof(blockmark_t))
static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
{
(void)block;
@@ -178,25 +183,26 @@ static void* allocBlock(void* block, void *sub, size_t size, void** pstart)
s->next.fill = 1;
// check if a new mark is worth it
if(s->next.size>size+2*sizeof(blockmark_t))
if(s->next.size>size+2*sizeof(blockmark_t)+THRESHOLD) {
size_t old_size = s->next.size;
s->next.size = size;
blockmark_t *m = NEXT_BLOCK(s); // this is new n
m->prev.fill = 1;
if(n!=m) {
// new mark
blockmark_t *m = NEXT_BLOCK(s);
m->prev.fill = 1;
m->prev.size = s->next.size;
m->next.fill = 0;
m->next.size = ((uintptr_t)n - (uintptr_t)m) - sizeof(blockmark_t);
m->next.size = old_size - (size + sizeof(blockmark_t));
n->prev.fill = 0;
n->prev.size = m->next.size;
n = m;
} else {
n->prev.fill = 1;
}
if(pstart && sub==*pstart) {
// get the next free block
m = (blockmark_t*)*pstart;
while(m->next.fill)
m = NEXT_BLOCK(m);
*pstart = (void*)m;
while(n->next.fill)
n = NEXT_BLOCK(n);
*pstart = (void*)n;
}
return (void*)((uintptr_t)sub + sizeof(blockmark_t));
}
@@ -210,7 +216,7 @@ static size_t freeBlock(void *block, void* sub, void** pstart)
s->next.fill = 0;
n->prev.fill = 0;
// check if merge with previous
if (s->prev.x32 && !s->prev.fill) {
if (m!=s && s->prev.x32 && !s->prev.fill) {
// remove s...
m->next.size += s->next.size + sizeof(blockmark_t);
n->prev.size = m->next.size;
@@ -246,7 +252,7 @@ static int expandBlock(void* block, void* sub, size_t newsize)
if((size_t)(s->next.size + n->next.size + sizeof(blockmark_t)) < newsize)
return 0; // free space too short
// ok, doing the alloc!
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<2*sizeof(blockmark_t))
if((s->next.size+n->next.size+sizeof(blockmark_t))-newsize<THRESHOLD+2*sizeof(blockmark_t))
s->next.size += n->next.size+sizeof(blockmark_t);
else
s->next.size = newsize+sizeof(blockmark_t);
@@ -285,10 +291,10 @@ int printBlockCoherent(int i)
if(p_blocks[i].first && p_blocks[i].first!=first) {printf_log(LOG_NONE, "First %p and stored first %p differs for block %d\n", first, p_blocks[i].first, i); ret = 0;}
// check if maxfree is correct, with no hint
size_t maxfree = getMaxFreeBlock(m, p_blocks[i].size, NULL);
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree without hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree); ret = 0;}
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree without hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree, i); ret = 0;}
// check if maxfree from first is correct
maxfree = getMaxFreeBlock(m, p_blocks[i].size, p_blocks[i].first);
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree with hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree); ret = 0;}
if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree with hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree, i); ret = 0;}
// check chain
blockmark_t* last = (blockmark_t*)(((uintptr_t)m)+p_blocks[i].size-sizeof(blockmark_t));
while(m<last) {
@@ -327,8 +333,6 @@ void testAllBlocks()
printf_log(LOG_NONE, "Total %d blocks, for %zd allocated memory, max_free %zd, toatal fragmented free %zd\n", n_blocks, total, max_free, fragmented_free);
}
#define THRESHOLD (128-2*sizeof(blockmark_t))
static size_t roundSize(size_t size)
{
if(!size)
@@ -341,7 +345,6 @@ static size_t roundSize(size_t size)
return size;
}
#ifdef TRACE_MEMSTAT
static size_t customMalloc_allocated = 0;
#endif
@@ -504,7 +507,7 @@ dynablock_t* FindDynablockFromNativeAddress(void* p)
}
#ifdef TRACE_MEMSTAT
static uint64_t dynarec_allocated = 0;
static uint32_t dynarec_allocated = 0;
#endif
uintptr_t AllocDynarecMap(size_t size)
{
@@ -642,6 +645,16 @@ void addDBFromAddressRange(uintptr_t addr, size_t size)
// do nothing, dynablock are allowed based on memory protection flags
}
int isJmpTableEmpty(uintptr_t *tbl)
{
if(tbl == box86_jmptbl_default)
return 0;
for(int i=0; i<1<<JMPTABL_SHIFT; ++i)
if(tbl[i]!=(uintptr_t)arm_next)
return 0;
return 1;
}
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
{
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
@@ -657,6 +670,23 @@ void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
MarkRangeDynablock(db, addr, size);
}
}
if(destroy) {
// remove only if the page is destroyed
start_addr = addr;
end = addr+size;
while (start_addr<end) {
uintptr_t* tbl;
if(isJmpTableEmpty((tbl=box86_jmptbl[start_addr>>JMPTABL_SHIFT]))) {
if(arm_lock_storeifref(&box86_jmptbl[start_addr>>JMPTABL_SHIFT], box86_jmptbl_default, tbl)==box86_jmptbl_default) {
box_free(tbl);
#ifdef TRACE_MEMSTAT
jmptbl_allocated -= (1<<JMPTABL_SHIFT)*sizeof(uintptr_t);
#endif
}
}
start_addr += 1<<JMPTABL_SHIFT;
}
}
}
static uintptr_t *create_jmptbl(uintptr_t idx0, uintptr_t idx1)
@@ -670,7 +700,7 @@ static uintptr_t *create_jmptbl(uintptr_t idx0, uintptr_t idx1)
#ifdef TRACE_MEMSTAT
else {
jmptbl_allocated += (1<<JMPTABL_SHIFT)*sizeof(uintptr_t);
++jmptbl_allocated;
++jmptbl_allocated1;
}
#endif
}
@@ -770,16 +800,15 @@ void protectDB(uintptr_t addr, uintptr_t size)
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
uint32_t dyn = prot&PROT_DYN;
uint32_t mapped = prot&PROT_MMAP;
if(!prot)
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
prot&=~PROT_CUSTOM;
if(!(dyn&PROT_NOPROT)) {
if(prot&PROT_WRITE) {
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i] = prot|mapped|PROT_DYNAREC; // need to use atomic exchange?
memprot[i] = prot|PROT_DYNAREC; // need to use atomic exchange?
} else
memprot[i] = prot|mapped|PROT_DYNAREC_R;
memprot[i] = prot|PROT_DYNAREC_R;
}
}
mutex_unlock(&mutex_prot);
@@ -800,7 +829,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size, int mark)
prot&=~PROT_DYN;
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_MMAP);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot);
memprot[i] = prot; // need to use atomic exchange?
} else if(prot&PROT_DYNAREC_R)
memprot[i] = prot&~PROT_CUSTOM;
@@ -827,7 +856,7 @@ int isprotectedDB(uintptr_t addr, size_t size)
#endif
void printMapMem()
void printMapMem(mapmem_t* mapmem)
{
mapmem_t* m = mapmem;
while(m) {
@@ -836,10 +865,12 @@ void printMapMem()
}
}
void addMapMem(uintptr_t begin, uintptr_t end)
void addMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
if(begin<box86_pagesize)
begin = box86_pagesize;
begin &=~(box86_pagesize-1);
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
// sanitize values
@@ -875,10 +906,12 @@ void addMapMem(uintptr_t begin, uintptr_t end)
}
// all done!
}
void removeMapMem(uintptr_t begin, uintptr_t end)
void removeMapMem(mapmem_t* mapmem, uintptr_t begin, uintptr_t end)
{
if(!mapmem)
return;
if(begin<box86_pagesize)
begin = box86_pagesize;
begin &=~(box86_pagesize-1);
end = (end&~(box86_pagesize-1))+(box86_pagesize-1); // full page
// sanitize values
@@ -925,13 +958,12 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
mutex_lock(&mutex_prot);
addMapMem(addr, addr+size-1);
addMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t old_prot = memprot[i];
uint32_t dyn=(old_prot&PROT_DYN);
uint32_t mapped=(old_prot&PROT_MMAP);
if(!(dyn&PROT_NOPROT)) {
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
@@ -940,7 +972,7 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
dyn = PROT_DYNAREC_R;
}
}
memprot[i] = prot|dyn|mapped;
memprot[i] = prot|dyn;
}
mutex_unlock(&mutex_prot);
}
@@ -949,7 +981,7 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
mutex_lock(&mutex_prot);
addMapMem(addr, addr+size-1);
addMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
@@ -960,7 +992,30 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot)
{
setProtection(addr, size, prot|PROT_MMAP);
if(!size)
return;
size = (size+box86_pagesize-1)&~(box86_pagesize-1); // round size
mutex_lock(&mutex_prot);
addMapMem(mmapmem, addr, addr+size-1);
mutex_unlock(&mutex_prot);
if(prot)
setProtection(addr, size, prot);
else {
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
mutex_unlock(&mutex_prot);
}
}
void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot)
{
if(prot)
setProtection(addr, size, prot);
else {
mutex_lock(&mutex_prot);
addMapMem(mapallmem, addr, addr+size-1);
mutex_unlock(&mutex_prot);
}
}
void refreshProtection(uintptr_t addr)
@@ -981,14 +1036,12 @@ void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
mutex_lock(&mutex_prot);
addMapMem(addr, addr+size-1);
addMapMem(mapallmem, addr, addr+size-1);
mutex_unlock(&mutex_prot);
}
#ifdef DYNAREC
int IsInHotPage(uintptr_t addr) {
if(addr>=(1LL<<48))
return 0;
int idx = (addr>>MEMPROT_SHIFT);
if(!hotpages[idx])
return 0;
@@ -1034,7 +1087,7 @@ void loadProtectionFromMap()
(void)ret;
char r, w, x;
uintptr_t s, e;
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
if(sscanf(buf, "%x-%x %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
}
@@ -1046,7 +1099,8 @@ void loadProtectionFromMap()
void freeProtection(uintptr_t addr, uintptr_t size)
{
mutex_lock(&mutex_prot);
removeMapMem(addr, addr+size-1);
removeMapMem(mmapmem, addr, addr+size-1);
removeMapMem(mapallmem, addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
@@ -1061,56 +1115,92 @@ uint32_t getProtection(uintptr_t addr)
mutex_lock(&mutex_prot);
uint32_t ret = memprot[idx];
mutex_unlock(&mutex_prot);
return ret&~PROT_MMAP;
return ret;
}
int getMmapped(uintptr_t addr)
{
mutex_lock(&mutex_prot);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
uint32_t ret = memprot[idx];
mutex_unlock(&mutex_prot);
return (ret&PROT_MMAP)?1:0;
mapmem_t* m = mmapmem;
if(addr<box86_pagesize) return 0;
while(m) {
uintptr_t begin = m->begin;
uintptr_t end = m->end;
if(addr>=begin && addr<=end)
return 1;
if(addr<begin)
return 0;
m = m->next;
}
return 0;
}
#define LOWEST (void*)0x10000
#define MEDIAN (void*)0x40000000
static void* findBlockHinted(void* hint, size_t size)
static void* findBlockHinted(void* hint, size_t size, uintptr_t mask)
{
mapmem_t* m = mapmem;
mapmem_t* m = mapallmem;
uintptr_t h = (uintptr_t)hint;
if(!mask) mask = 0xffff;
while(m) {
// granularity 0x10000
uintptr_t addr = (m->end+1+0xffff)&~0xffff;
uintptr_t addr = m->end+1;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
// check hint and available size
if(addr<=h && end>=h && end-h+1>=size)
return hint;
if(addr>=h && end-addr+1>=size)
return (void*)addr;
uintptr_t aaddr = (addr+mask)&~mask;
if(aaddr>=h && end>aaddr && end-aaddr+1>=size)
return (void*)aaddr;
if(end>=0xc0000000 && h<0xc0000000)
return NULL;
m = m->next;
}
return NULL;
}
void* findBlockNearHint(void* hint, size_t size)
{ void* ret = findBlockHinted(hint, size);
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask)
{ void* ret = findBlockHinted(hint, size, mask);
return ret?ret:hint;
}
void* find32bitBlock(size_t size)
{
void* ret = findBlockHinted(MEDIAN, size);
if(!ret) ret = findBlockHinted(LOWEST, size);
void* ret = findBlockHinted(MEDIAN, size, 0);
if(!ret) ret = findBlockHinted(LOWEST, size, 0);
return ret;
}
void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask)
{
static void* startingpoint = (void*)0x60000000;
void* mainaddr = (void*)0x30000000;
void* ret = findBlockHinted(mainbin?mainaddr:startingpoint, size, mask);
if(!ret) ret = findBlockHinted(LOWEST, size, mask);
if(!mainbin)
startingpoint = (void*)(((uintptr_t)startingpoint+size+0x200000)&~0xfffff);
return ret;
}
int isBlockFree(void* hint, size_t size)
{
mapmem_t* m = mapallmem;
uintptr_t h = (uintptr_t)hint;
while(m) {
uintptr_t addr = m->end+1;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
if(addr<=h && end>=h && end-h+1>=size)
return 1;
if(addr>h)
return 0;
m = m->next;
}
return 0;
}
int unlockCustommemMutex()
{
int ret = 0;
int i = 0;
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
void* tid = (void*)GetTID();
#define GO(A, B) \
i = (arm_lock_storeifref2(&A, NULL, (void*)tid)==tid); \
@@ -1143,7 +1233,7 @@ void relockCustommemMutex(int locks)
static void init_mutexes(void)
{
#ifdef DYNAREC
#ifdef USE_CUSTOM_MUTEX
arm_lock_stored(&mutex_blocks, 0);
arm_lock_stored(&mutex_prot, 0);
#else
@@ -1151,6 +1241,7 @@ static void init_mutexes(void)
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
pthread_mutex_init(&mutex_prot, &attr);
pthread_mutexattr_destroy(&attr);
#endif
@@ -1181,10 +1272,14 @@ void init_custommem_helper(box86context_t* ctx)
lockaddress = kh_init(lockaddress);
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
// init mapmem list
mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mapmem->begin = 0x0;
mapmem->end = (uintptr_t)LOWEST - 1;
// init mapallmem list
mapallmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mapallmem->begin = 0x0;
mapallmem->end = (uintptr_t)LOWEST - 1;
// init mmapmem list
mmapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mmapmem->begin = 0x0;
mmapmem->end = (uintptr_t)box86_pagesize - 1;
loadProtectionFromMap();
}
@@ -1192,18 +1287,18 @@ void fini_custommem_helper(box86context_t *ctx)
{
(void)ctx;
#ifdef TRACE_MEMSTAT
uintptr_t njmps = 0, njmps_in_lv1_max = 0;
for (uintptr_t idx1 = 0; idx1 < (1 << JMPTABL_SHIFT); ++idx1) {
size_t njmps = 0, njmps_in_lv1_max = 0;
for (size_t idx1 = 0; idx1 < (1 << JMPTABL_SHIFT); ++idx1) {
if (box86_jmptbl[idx1] == box86_jmptbl_default) continue;
uintptr_t njmps_in_cur_lv1 = 0;
for (uintptr_t idx0 = 0; idx0 < (1 << JMPTABL_SHIFT); ++idx0) {
size_t njmps_in_cur_lv1 = 0;
for (size_t idx0 = 0; idx0 < (1 << JMPTABL_SHIFT); ++idx0) {
if (box86_jmptbl[idx1][idx0] == (uintptr_t)arm_next) continue;
++njmps;
++njmps_in_cur_lv1;
}
if (njmps_in_cur_lv1 > njmps_in_lv1_max) njmps_in_lv1_max = njmps_in_cur_lv1;
}
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lld kio\n- customMalloc: %lld kio\n- memprot: %lld kio (peak at %lld kio)\n- jump table: %lld kio (%lld level 1 table allocated, for %lld jumps, with at most %lld per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, memprot_allocated / 1024, memprot_max_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
printf_log(LOG_INFO, "Allocation:\n- dynarec: %lu kio\n- customMalloc: %zu kio\n- memprot: %lu kio (peak at %ld kio)\n- jump table: %zu kio (%zu level 1 table allocated, for %zu jumps, with at most %zu per level 1)\n", dynarec_allocated / 1024, customMalloc_allocated / 1024, memprot_allocated / 1024, memprot_max_allocated / 1024, jmptbl_allocated / 1024, jmptbl_allocated1, njmps, njmps_in_lv1_max);
#endif
if(!inited)
return;
@@ -1245,12 +1340,18 @@ void fini_custommem_helper(box86context_t *ctx)
box_free(p_blocks[i].block);
#endif
box_free(p_blocks);
#ifndef DYNAREC
#ifndef USE_CUSTOM_MUTEX
pthread_mutex_destroy(&mutex_blocks);
pthread_mutex_destroy(&mutex_prot);
#endif
while(mapmem) {
mapmem_t *tmp = mapmem;
mapmem = mapmem->next;
while(mapallmem) {
mapmem_t *tmp = mapallmem;
mapallmem = mapallmem->next;
box_free(tmp);
}
while(mmapmem) {
mapmem_t *tmp = mmapmem;
mmapmem = mmapmem->next;
box_free(tmp);
}
}
+38
View File
@@ -222,6 +222,8 @@ Op is 20-27
// add dst, src1, src2, lsr #imm
#define ADD_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
#define ADD_REG_LSR_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT((cond) | 0x00800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
#define ADC_IMM8(dst, src, imm8) \
EMIT(0xe2a00000 | ((dst) << 12) | ((src) << 16) | brIMM(imm8) )
// add.s dst, src, #(imm8)
@@ -591,8 +593,12 @@ Op is 20-27
// Count leading 0 bit of Rm, store result in Rd
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
// Count leading 0 bit of Rm, store result in Rd with cond
#define CLZ_COND(cond, Rd, Rm) EMIT(cond | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
// Reverse bits of Rm, store result in Rd
#define RBIT(Rd, Rm) EMIT(c__ | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
// Reverse bits of Rm, store result in Rd with cond
#define RBIT_COND(cond, Rd, Rm) EMIT(cond | 0b01101111<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0011<<4 | (Rm))
#define PLD_gen(U, R, Rn, Imm5, type, Rm) (0b1111<<28 | 0b0111<<24 | (U)<<23 | (R)<<22 | 0b01<<20 | (Rn)<<16 | 0b1111<<12 | (Imm5)<<7 | (type)<<5 | (Rm))
// Preload Cache Rn+Rm
@@ -602,7 +608,21 @@ Op is 20-27
#define DMB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0101<<4 | (opt))
// Data memory barrier Inner Sharable
#ifdef PANDORA
// The Pandora is single core and ordered, DMB is not usefull here so just emit nothing
#define DMB_ISH()
#else
#define DMB_ISH() EMIT(DMB_gen(0b1011))
#endif
#define DSB_gen(opt) (0b1111<<28 | 0b01010111<<20 | 0b1111<<16 | 0b1111<<12 | 0b0000<<8 | 0b0100<<4 | (opt))
// Data memory barrier Inner Sharable
#ifdef PANDORA
// The Pandora is single core and ordered, DSB is not usefull here so just emit nothing
#define DSB_ISH()
#else
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#endif
#define SWP_gen(cond, B, Rn, Rt, Rt2) (cond | 0b0001<<24 | (B)<<22 | (Rn)<<16 | (Rt)<<12 | 0b1001<<4 | (Rt2))
// SWAP (atomic) [Rn]->Rt2 / Rt->[Rn], Rt can be same as Rt2
@@ -628,11 +648,15 @@ Op is 20-27
#define VMRS(Rt) EMIT(c__ | (0b1110<<24) | (0b1111<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm register
#define VMSR(Rt) EMIT(c__ | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm register with cond
#define VMSR_cond(cond, Rt) EMIT(cond | (0b1110<<24) | (0b1110<<20) | (0b0001<<16) | ((Rt)<<12) | (0b1010<<8) | (0b0001<<4) | (0b0000))
// Move to FPSCR from Arm flags APSR
#define VMRS_APSR() VMRS(15)
// Move between Rt to Sm
#define VMOVtoV(Sm, Rt) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
// Move between Rt to Sm with condition
#define VMOVtoVcond(cond, Sm, Rt) EMIT(cond | (0b1110<<24) | (0b000<<21) | (0<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
// Move between Sm to Rt
#define VMOVfrV(Rt, Sm) EMIT(c__ | (0b1110<<24) | (0b000<<21) | (1<<20) | ((((Sm)&0b11110)>>1)<<16) | ((Rt)<<12) | (0b1010<<8) | (((Sm)&1)<<7) |(0b00<<6) | (1<<4))
@@ -1095,6 +1119,7 @@ Op is 20-27
#define VMULL_U32_U16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_S64_S32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_U64_U32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_P64(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 1, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMUL_NEON_gen(op, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (op)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1001<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VMULQ_32(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@@ -1392,4 +1417,17 @@ Op is 20-27
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// AES
#define AESD_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESD(Dd, Dm) EMIT(AESD_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESE_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESE(Dd, Dm) EMIT(AESE_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESIMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESIMC(Dd, Dm) EMIT(AESIMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESMC(Dd, Dm) EMIT(AESMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#endif //__ARM_EMITTER_H__
+3 -3
View File
@@ -335,9 +335,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
+1 -2
View File
@@ -131,6 +131,7 @@ arm_lock_storeifref_loop:
beq arm_lock_storeifref_loop
mov r0, r1
arm_lock_storeifref_exit:
dmb ish
bx lr
arm_lock_decifnot0b:
@@ -174,13 +175,11 @@ arm_lock_incif0b_0:
bx lr
arm_lock_stored:
dmb ish
str r1, [r0]
dmb ish
bx lr
arm_lock_storeb:
dmb ish
strb r1, [r0]
dmb ish
bx lr
+4 -4
View File
@@ -159,7 +159,7 @@ const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
char tmp[7];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
@@ -3049,7 +3049,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3064,7 +3064,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
@@ -3080,7 +3080,7 @@ const char* arm_print(uint32_t opcode) {
int param1_1 = (opcode >> 5) & 0x1;
int param2_1 = (opcode >> 4) & 0x1;
char align[4];
char align[5];
if (param2_1 == 1) {
sprintf(align, ":%d", 16 << size);
} else {
+13 -3
View File
@@ -177,11 +177,21 @@ dynablock_t *AddNewDynablock(uintptr_t addr)
}
//TODO: move this to dynrec_arm.c and track allocated structure to avoid memory leak
static __thread struct __jmp_buf_tag dynarec_jmpbuf;
#ifdef ANDROID
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
static __thread JUMPBUFF dynarec_jmpbuf;
#ifdef ANDROID
#define DYN_JMPBUF dynarec_jmpbuf
#else
#define DYN_JMPBUF &dynarec_jmpbuf
#endif
void cancelFillBlock()
{
longjmp(&dynarec_jmpbuf, 1);
longjmp(DYN_JMPBUF, 1);
}
/*
@@ -214,7 +224,7 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
// fill the block
block->x86_addr = (void*)addr;
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
if(sigsetjmp(DYN_JMPBUF, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
FreeDynablock(block, 0);
if(need_lock)
+93 -158
View File
@@ -46,27 +46,26 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
}
#endif
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1);
dynablock_t* block = NULL;
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1);
} else
block = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
printf_log(LOG_INFO, "Jmp address has alternate: %p", (void*)addr);
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1);
}
if(!block) {
#ifdef HAVE_TRACE
if(LOG_INFO<=box86_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
}
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
#ifdef HAVE_TRACE
if(LOG_INFO<=box86_dynarec_log) {
dynablock_t* db = FindDynablockFromNativeAddress(x2);
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)x2);
dynarec_log(LOG_INFO, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p(elf=%s))\n", (void*)addr, x2, db, db?(void*)getX86Address(db, (uintptr_t)x2-4):NULL, h?ElfName(h):"(none)");
}
#endif
//tableupdate(arm_epilog, addr, table);
return arm_epilog;
}
if(!block->done) {
// not finished yet... leave linker
@@ -82,125 +81,75 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
}
#endif
#ifdef ANDROID
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
void DynaCall(x86emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
int jmpbuf_reset = 0;
int skip = 0;
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaCall %d, fs=0x%x\n", skip, ejb->emu->segs[_FS]);
addr = R_EIP; // not sure if it should still be inside DynaCall!
#ifdef DYNAREC
if(box86_dynarec_test) {
if(emu->test.clean)
x86test_check(emu, R_EIP);
emu->test.clean = 0;
}
#endif
if(skip!=2)
skip = 0;
}
}
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
// save defered flags
defered_flags_t old_df = emu->df;
uint32_t old_op1 = emu->op1;
uint32_t old_op2 = emu->op2;
uint32_t old_res = emu->res;
// uc_link
i386_ucontext_t* old_uc_link = emu->uc_link;
emu->uc_link = NULL;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
DynaRun(emu);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
emu->uc_link = old_uc_link;
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
// restore defered flags
emu->df = old_df;
emu->op1 = old_op1;
emu->op2 = old_op2;
emu->res = old_res;
// and the old registers
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
EmuCall(emu, addr);
#ifdef DYNAREC
else {
uint32_t old_esp = R_ESP;
uint32_t old_ebx = R_EBX;
uint32_t old_edi = R_EDI;
uint32_t old_esi = R_ESI;
uint32_t old_ebp = R_EBP;
uint32_t old_eip = R_EIP;
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
current = block;
if(!block || !block->block || !block->done) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
if(box86_dynarec_test)
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_EIP;
}
}
}
}
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
emu->longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
R_ESI = old_esi;
R_EBP = old_ebp;
R_ESP = old_esp;
R_EIP = old_eip; // and set back instruction pointer
}
}
#endif
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
}
int my_setcontext(x86emu_t* emu, void* ucp);
int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
emu_jmpbuf_t *ejb = NULL;
JUMPBUFF jmpbuf[1] = {0};
int skip = 0;
#ifdef DYNAREC
int jmpbuf_reset = 1;
#endif
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
if(!ejb->jmpbuf_ok) {
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
int a;
#ifdef DYNAREC
jmpbuf_reset = 1;
#endif
if((skip=sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))) {
printf_log(LOG_DEBUG, "Setjmp DynaRun %d, fs=0x%x\n", skip, ejb->emu->segs[_FS]);
JUMPBUFF *old_jmpbuf = emu->jmpbuf;
emu->flags.jmpbuf_ready = 0;
while(!(emu->quit)) {
if(!emu->jmpbuf || (emu->flags.need_jmpbuf && emu->jmpbuf!=jmpbuf)) {
emu->jmpbuf = jmpbuf;
emu->flags.jmpbuf_ready = 1;
#ifdef ANDROID
if((skip=sigsetjmp(*(JUMPBUFF*)emu->jmpbuf, 1)))
#else
if((skip=sigsetjmp(emu->jmpbuf, 1)))
#endif
{
printf_log(LOG_DEBUG, "Setjmp DynaRun\n");
#ifdef DYNAREC
if(box86_dynarec_test) {
if(emu->test.clean)
@@ -208,60 +157,46 @@ int DynaRun(x86emu_t* emu)
emu->test.clean = 0;
}
#endif
if(skip!=2)
skip = 0;
}
}
}
#ifdef DYNAREC
if(!box86_dynarec)
#endif
return Run(emu, 0);
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = (skip==2)?NULL:DBGetBlock(emu, R_EIP, 1);
current = block;
if(emu->flags.need_jmpbuf)
emu->flags.need_jmpbuf = 0;
#ifndef DYNAREC
Run(emu, 0);
#else
if(!box86_dynarec)
Run(emu, 0);
else {
dynablock_t* block = (skip || ACCESS_FLAG(F_TF))?NULL:DBGetBlock(emu, R_EIP, 1);
if(!block || !block->block || !block->done) {
skip = 0;
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
dynarec_log(LOG_DEBUG, "%04d|Running Interpreter @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
if(box86_dynarec_test)
emu->test.clean = 0;
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (hash=0x%x) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->hash, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
#endif
}
if(emu->fork) {
int forktype = emu->fork;
emu->quit = 0;
emu->fork = 0;
emu = x86emu_fork(emu, forktype);
if(emu->type == EMUTYPE_MAIN) {
ejb = GetJmpBuf();
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
else if(emu->quit && emu->uc_link) {
if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
}
}
#endif
if(emu->flags.need_jmpbuf)
emu->quit = 0;
}
// clear the setjmp
if(ejb && jmpbuf_reset)
ejb->jmpbuf_ok = 0;
return 0;
#endif
emu->jmpbuf = old_jmpbuf;
}
+89 -39
View File
@@ -74,7 +74,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 64;
dyn->next = (uintptr_t*)customRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
dyn->next = (uintptr_t*)dynaRealloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -95,6 +95,21 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
}
return best;
}
void add_jump(dynarec_arm_t *dyn, int ninst) {
// add slots
if(dyn->jmp_sz == dyn->jmp_cap) {
dyn->jmp_cap += 64;
dyn->jmps = (int*)dynaRealloc(dyn->jmps, dyn->jmp_cap*sizeof(int));
}
dyn->jmps[dyn->jmp_sz++] = ninst;
}
int get_first_jump(dynarec_arm_t *dyn, int next) {
for(int i=0; i<dyn->jmp_sz; ++i)
if(dyn->insts[dyn->jmps[i]].x86.jmp == next)
return i;
return -2;
}
#define PK(A) (*((uint8_t*)(addr+(A))))
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
{
@@ -279,6 +294,13 @@ static void fillPredecessors(dynarec_arm_t* dyn)
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
}
}
// remove "has_next" from orphean branch
for(int i=0; i<dyn->size-1; ++i) {
if(!dyn->insts[i].x86.has_next) {
if(dyn->insts[i+1].x86.has_next && !dyn->insts[i+1].pred_sz)
dyn->insts[i+1].x86.has_next = 0;
}
}
// second the "has_next"
for(int i=0; i<dyn->size-1; ++i) {
if(dyn->insts[i].x86.has_next) {
@@ -286,7 +308,7 @@ static void fillPredecessors(dynarec_arm_t* dyn)
++dyn->insts[i+1].pred_sz;
}
}
dyn->predecessor = (int*)customMalloc(pred_sz*sizeof(int));
dyn->predecessor = (int*)dynaMalloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -303,8 +325,6 @@ static void fillPredecessors(dynarec_arm_t* dyn)
dyn->insts[j].pred[dyn->insts[j].pred_sz++] = i;
}
}
}
// updateNeed goes backward, from last intruction to top
@@ -330,9 +350,8 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
if(dyn->insts[ninst].x86.may_set)
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
// Consume X_PEND if relevant
if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
need &=~X_PEND;
else if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
need &=~X_PEND; // Consume X_PEND if relevant
need |= dyn->insts[ninst].x86.use_flags;
if(dyn->insts[ninst].x86.need_before == need)
return ninst - 1;
@@ -347,9 +366,9 @@ static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
else
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
}
if(!ok)
return ninst - 1;
--ninst;
if(!ok)
return ninst;
}
return ninst;
}
@@ -363,9 +382,9 @@ void CancelBlock(int need_lock)
dynarec_arm_t* helper = (dynarec_arm_t*)current_helper;
current_helper = NULL;
if(helper) {
customFree(helper->next);
customFree(helper->insts);
customFree(helper->predecessor);
dynaFree(helper->next);
dynaFree(helper->insts);
dynaFree(helper->predecessor);
if(helper->dynablock && helper->dynablock->actual_block) {
FreeDynarecMap((uintptr_t)helper->dynablock->actual_block);
helper->dynablock->actual_block = NULL;
@@ -440,13 +459,9 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm_t*)customCalloc(helper.cap, sizeof(instruction_arm_t));
helper.insts = (instruction_arm_t*)dynaCalloc(helper.cap, sizeof(instruction_arm_t));
// pass 0, addresses, x86 jump addresses, overall size of the block
uintptr_t end = arm_pass0(&helper, addr);
// no need for next anymore
customFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
@@ -465,26 +480,57 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
protectDB(addr, end-addr); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x86.addr==j)
k=i2;
for(int ii=0; ii<helper.jmp_sz; ++ii) {
int i = helper.jmps[ii];
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end || j==helper.insts[i].x86.addr) {
if(j==helper.insts[i].x86.addr) // if there is a loop on some opcode, make the block "always to tested"
helper.always_test = 1;
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
int search = ((j>=helper.insts[0].x86.addr) && j<helper.insts[0].x86.addr+helper.isize)?1:0;
int imin = 0;
int imax = helper.size-1;
int i2 = helper.size/2;
// dichotomy search
while(search) {
if(helper.insts[i2].x86.addr == j) {
k = i2;
search = 0;
} else if(helper.insts[i2].x86.addr>j) {
imax = i2;
i2 = (imax+imin)/2;
} else {
imin = i2;
i2 = (imax+imin)/2;
}
if(search && (imax-imin)<2) {
search = 0;
if(helper.insts[imin].x86.addr==j)
k = imin;
else if(helper.insts[imax].x86.addr==j)
k = imax;
}
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
}
/*for(int i2=0; i2<helper.size && k==-1; ++i2) {
if(helper.insts[i2].x86.addr==j)
k=i2;
}*/
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
}
}
// no need for next and jmps anymore
dynaFree(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
dynaFree(helper.jmps);
helper.jmp_sz = helper.jmp_cap = 0;
helper.jmps = NULL;
// fill predecessors with the jump address
fillPredecessors(&helper);
@@ -517,7 +563,6 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
block->actual_block = actual_p;
helper.arm_start = (uintptr_t)p;
helper.jmp_next = (uintptr_t)next+sizeof(void*);
helper.insts_size = 0; // reset
helper.instsize = (instsize_t*)instsize;
*(dynablock_t**)actual_p = block;
// pass 3, emit (log emit native opcode)
@@ -527,15 +572,17 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
size_t oldarmsize = helper.arm_size;
size_t oldinstsize = helper.insts_size;
helper.arm_size = 0;
helper.insts_size = 0; // reset
arm_pass3(&helper, addr);
// keep size of instructions for signal handling
block->instsize = instsize;
// ok, free the helper now
customFree(helper.insts);
dynaFree(helper.insts);
helper.insts = NULL;
helper.instsize = NULL;
customFree(helper.predecessor);
dynaFree(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
@@ -553,7 +600,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// Check if something changed, to abbort if it as
if((block->hash != hash)) {
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%ld)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
dynarec_log(LOG_DEBUG, "Warning, a block changed while being processed hash(%p:%zu)=%x/%x\n", block->x86_addr, block->x86_size, block->hash, hash);
AddHotPage(addr);
CancelBlock(0);
return NULL;
@@ -572,8 +619,11 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
CancelBlock(0);
return NULL;
}
if(insts_rsize/sizeof(instsize_t)<helper.insts_size) {
printf_log(LOG_NONE, "BOX86: Warning, ists_size difference in block between pass2 (%zu) and pass3 (%zu), allocated: %zu\n", oldinstsize, helper.insts_size, insts_rsize/sizeof(instsize_t));
}
if(!isprotectedDB(addr, end-addr)) {
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%ld, marking as need_test\n", block->x86_addr, block->x86_size);
dynarec_log(LOG_DEBUG, "Warning, block unprotected while being processed %p:%zu, marking as need_test\n", block->x86_addr, block->x86_size);
AddHotPage(addr);
block->dirty = 1;
//protectDB(addr, end-addr);
+300 -168
View File
@@ -27,6 +27,10 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
int isRetX87Wrapper(wrapper_t fun);
void emit_signal(x86emu_t* emu, int sig, void* addr, int code);
void emit_div0(x86emu_t* emu, void* addr, int code);
uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
@@ -1000,7 +1004,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("(LOCK)XCHG Eb, Gb");
// Do the swap
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x14);
ed = (nextop&7);
eb1 = xEAX+(ed&3);
@@ -1027,7 +1031,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x87:
INST_NAME("(LOCK)XCHG Ed, Gd");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGD;
GETED;
if(gd!=ed) {
@@ -1077,7 +1081,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
gd = gb1; // no need to extract
}
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)>>2); // L or H
@@ -1092,7 +1096,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Ed, Gd");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
@@ -1106,7 +1110,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
gd = (nextop&0x38)>>3;
gb1 = xEAX+(gd&3);
gb2 = ((gd&4)>>2);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -1117,10 +1121,6 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = wback;
}
} else {
if(box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
SMDMB();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
SMREADLOCK(lock);
LDRB_IMM9(x14, wback, fixedaddress);
@@ -1132,7 +1132,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Gd, Ed");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
@@ -1144,7 +1144,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Ed, Seg");
nextop=F8;
MOV32(x3, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
if((nextop&0xC0)==0xC0) { // reg <= seg
if(MODREG) { // reg <= seg
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
@@ -1157,7 +1157,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LEA Gd, Ed");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg? that's an invalid operation
if(MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0, NULL);
@@ -1169,7 +1169,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
@@ -1189,7 +1189,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x8F:
INST_NAME("POP Ed");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7));
} else {
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
@@ -1245,6 +1245,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
AND_REG_LSL_IMM5(xFlags, xFlags, x1, 0);
ORR_IMM8(xFlags, xFlags, 2, 0);
SET_DFNONE(x1);
if(box86_wine || 1) { // should this be done all the time?
TSTS_IMM8_ROR(xFlags, 0x1, 12); // 0x100 == F_TF
B_NEXT(cEQ);
// go to epilog, TF should trigger at end of next opcode, so using Interpretor only
jump_to_epilog(dyn, addr, 0, ninst);
}
break;
case 0x9E:
INST_NAME("SAHF");
@@ -1264,6 +1270,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV AL, Ob");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDRB_IMM9(x2, x2, 0);
BFI(xEAX, x2, 0, 8);
break;
@@ -1271,33 +1279,41 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV EAX, Od");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDR_IMM9(xEAX, x2, 0);
break;
case 0xA2:
INST_NAME("MOV Ob, AL");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
STRB_IMM9(xEAX, x2, 0);
SMWRITE();
SMWRITELOCK(lock);
break;
case 0xA3:
INST_NAME("MOV Od, EAX");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
STR_IMM9(xEAX, x2, 0);
SMWRITE();
SMWRITELOCK(lock);
break;
case 0xA4:
INST_NAME("MOVSB");
GETDIR(x3, 1);
SMREAD();
LDRBAI_REG_LSL_IMM5(x1, xESI, x3, 0);
STRBAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
SMWRITE();
break;
case 0xA5:
INST_NAME("MOVSD");
GETDIR(x3, 4);
SMREAD();
LDRAI_REG_LSL_IMM5(x1, xESI, x3, 0);
STRAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
SMWRITE();
break;
case 0xA6:
INST_NAME("CMPSB");
@@ -1334,11 +1350,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("STOSB");
GETDIR(x3, 1);
STRBAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
SMWRITE();
break;
case 0xAB:
INST_NAME("STOSD");
GETDIR(x3, 4);
STRAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
SMWRITE();
break;
case 0xAC:
INST_NAME("LODSB");
@@ -1444,49 +1462,42 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
case 6:
INST_NAME("SHL Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32(x14, u8); UFLAG_OP2(x14)
};
UFLAG_OP1(ed);
MOV_REG_LSL_IMM5(ed, ed, u8);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl8);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEB(x1);
u8 = (F8)&0x1f;
emit_shl8c(dyn, ninst, ed, u8, x2, x14);
EBBACK;
} else {
FAKEED;
F8;
}
break;
case 5:
INST_NAME("SHR Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32(x14, u8); UFLAG_OP2(x14)
};
UFLAG_OP1(ed);
if(u8) {
MOV_REG_LSR_IMM5(ed, ed, u8);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEB(x1);
u8 = (F8)&0x1f;
emit_shr8c(dyn, ninst, ed, u8, x2, x14);
EBBACK;
} else {
FAKEED;
F8;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr8);
break;
case 7:
INST_NAME("SAR Eb, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETSEB(x1);
u8 = (F8)&0x1f;
UFLAG_IF{
MOV32(x14, u8); UFLAG_OP2(x14)
};
UFLAG_OP1(ed);
if(u8) {
MOV_REG_ASR_IMM5(ed, ed, u8);
if(geted_ib(dyn, addr, ninst, nextop)&0x1f) {
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEB(x1);
u8 = (F8)&0x1f;
emit_sar8c(dyn, ninst, ed, u8, x2, x14);
EBBACK;
} else {
FAKEED;
F8;
}
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar8);
break;
}
break;
@@ -1617,7 +1628,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC6:
INST_NAME("MOV Eb, Ib");
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= u8
if(MODREG) { // reg <= u8
u8 = F8;
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
@@ -1635,7 +1646,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("MOV Ed, Id");
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
if(MODREG) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
@@ -1666,6 +1677,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SKIPTEST(x14);
MESSAGE(LOG_DEBUG, "Exit x86 Emu\n");
MOV32(x14, ip+1+2);
SMEND();
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
MOVW(x1, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, quit));
@@ -1674,6 +1686,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
SKIPTEST(x14);
SMEND();
x87_forget(dyn, ninst, x3, x14, 0);
if((box86_log<2) && !cycle_log) { // call the wrapper directly
uintptr_t ncall[2]; // to avoid BUSERROR!!!
@@ -1709,9 +1722,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, offsetof(box86context_t, signals[SIGTRAP]));
LDR_REG_LSL_IMM5(x3, x1, x2, 0);
CMPS_IMM8(x3, 0);
B_NEXT(cNE);
B_NEXT(cEQ);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
MOV32(xEIP, addr);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
MOV32(x1, SIGTRAP);
CALL_(raise, -1, 0);
MOV32(x2, addr);
MOV32(x3, 128);
CALL(emit_signal, -1, 0);
break;
}
break;
@@ -1737,7 +1755,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
jump_to_epilog(dyn, 0, xEIP, ninst);
} else {
INST_NAME("INT Ib");
if(box86_wine && u8==0x2D) {
if(box86_wine && u8==0x2D && 0) {
MESSAGE(LOG_DEBUG, "Hack for wine/int 2d\n");
} else {
DEFAULT;
@@ -1754,115 +1772,68 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*ok = 0;
break;
case 0xD0:
case 0xD2:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
if(opcode==0xD0) {
INST_NAME("ROL Eb, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
} else {
INST_NAME("ROL Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization ROL 8b\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
CALL_(rol8, x1, (1<<x3));
EBBACK;
}
INST_NAME("ROL Eb, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
break;
case 1:
if(opcode==0xD0) {
INST_NAME("ROR Eb, 1");
MOVW(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
} else {
INST_NAME("ROR Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
SETFLAGS(X_OF|X_CF, SF_SET);
MESSAGE(LOG_DUMP, "Need Optimization ROR 8b\n");
GETEB(x1);
CALL_(ror8, x1, (1<<x3));
EBBACK;
}
INST_NAME("ROR Eb, 1");
MOVW(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
break;
case 2:
if(opcode==0xD0) {INST_NAME("RCL Eb, 1");} else {INST_NAME("RCL Eb, CL");}
INST_NAME("RCL Eb, 1");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
MOVW(x2, 1);
GETEB(x1);
CALL_(rcl8, x1, (1<<x3));
EBBACK;
break;
case 3:
if(opcode==0xD0) {INST_NAME("RCR Eb, 1");} else {INST_NAME("RCR Eb, CL");}
INST_NAME("RCR Eb, 1");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
MOVW(x2, 1);
GETEB(x1);
CALL_(rcr8, x1, (1<<x3));
EBBACK;
break;
case 4:
case 6:
if(opcode==0xD0) {
INST_NAME("SHL Eb, 1");
MOVW(x2, 1);
} else {
INST_NAME("SHL Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHL Eb, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEB(x1);
UFLAG_OP12(ed, x2)
MOV_REG_LSL_REG(ed, ed, x2);
emit_shl8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl8);
break;
case 5:
if(opcode==0xD0) {
INST_NAME("SHR Eb, 1");
MOVW(x2, 1);
} else {
INST_NAME("SHR Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHR Eb, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEB(x1);
UFLAG_OP12(ed, x2)
MOV_REG_LSR_REG(ed, ed, x2);
emit_shr8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr8);
break;
case 7:
if(opcode==0xD0) {
INST_NAME("SAR Eb, 1");
MOVW(x2, 1);
} else {
INST_NAME("SAR Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SAR Eb, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEB(x1);
UFLAG_OP12(ed, x2)
MOV_REG_ASR_REG(ed, ed, x2);
emit_sar8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar8);
break;
}
break;
case 0xD1:
nextop = F8;
switch((nextop>>3)&7) {
@@ -1943,6 +1914,125 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
}
break;
case 0xD2:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Eb, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x7);
RSB_IMM8(x2, x2, 8);
GETEB(x1);
BFI(ed, ed, 8, 8);
MOV_REG_LSR_REG(ed, ed, x2);
EBBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 7);
MOV_REG_LSR_IMM5_COND(cEQ, x3, ed, 7);
ADD_REG_LSL_IMM5_COND(cEQ, x3, x3, ed, 0);
BFI_COND(cEQ, xFlags, x3, F_OF, 1);
BFI(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Eb, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x7);
GETEB(x1);
BFI(ed, ed, 8, 8);
MOV_REG_LSR_REG(ed, ed, x2);
EBBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 1);
MOV_REG_LSR_IMM5_COND(cEQ, x2, ed, 6); // x2 = d>>30
XOR_REG_LSR_IMM8_COND(cEQ, x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
BFI_COND(cEQ, xFlags, x2, F_OF, 1);
MOV_REG_LSR_IMM5(x2, ed, 7);
BFI(xFlags, x2, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 2:
INST_NAME("RCL Eb, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEB(x1);
CALL_(rcl8, x1, (1<<x3));
EBBACK;
break;
case 3:
INST_NAME("RCR Eb, CL");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEB(x1);
CALL_(rcr8, x1, (1<<x3));
EBBACK;
break;
case 4:
case 6:
INST_NAME("SHL Eb, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEB(x1);
emit_shl8(dyn, ninst, ed, x2, x2, x14);
EBBACK;
break;
case 5:
INST_NAME("SHR Eb, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEB(x1);
emit_shr8(dyn, ninst, ed, x2, x2, x14);
EBBACK;
break;
case 7:
INST_NAME("SAR Eb, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETSEB(x1);
emit_sar8(dyn, ninst, ed, x2, x2, x14);
EBBACK;
break;
}
break;
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
@@ -2195,8 +2285,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, addr);
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
SKIPTEST(x14);
// calling a native function
x87_forget(dyn, ninst, x3, x14, 0);
if(isRetX87Wrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2))) {
// return value will be on the stack, so the stack depth needs to be updated
x87_purgecache(dyn, ninst, 0, x3, x14, x1);
}
if((box86_log<2) && !cycle_log && dyn->insts[ninst].natcall) { // call the wrapper directly
uintptr_t ncall[2];
memcpy(ncall, (void*)(dyn->insts[ninst].natcall+2), 2*sizeof(void*)); // the wrapper + function
@@ -2266,11 +2360,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("JMP Ib");
i32 = F8S;
}
JUMP(addr+i32, 0);
JUMP((uintptr_t)getAlternate((void*)(addr+i32)), 0);
if(dyn->insts[ninst].x86.jmp_insts==-1) {
// out of the block
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
jump_to_next(dyn, addr+i32, 0, ninst);
jump_to_next(dyn, (uintptr_t)getAlternate((void*)(addr+i32)), 0, ninst);
} else {
// inside the block
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
@@ -2285,9 +2379,20 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
*ok = 0;
break;
case 0xEE:
INST_NAME("OUT dx, al");
//ignored!
case 0xEC: /* IN AL, DX */
case 0xED: /* IN EAX, DX */
case 0xEE: /* OUT DX, AL */
case 0xEF: /* OUT DX, EAX */
INST_NAME(opcode==0xEC?"IN AL, DX":(opcode==0xED?"IN EAX, DX":(opcode==0xEE?"OUT DX? AL":"OUT DX, EAX")));
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
MOV32(xEIP, ip);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_priv, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0xF0:
@@ -2311,11 +2416,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3, 2);
SMREAD();
MARK;
LDRHAI_REG_LSL_IMM5(x1, xESI, x3);
STRHAI_REG_LSL_IMM5(x1, xEDI, x3);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
break;
case 0xAB:
INST_NAME("REP STOSW");
@@ -2326,6 +2433,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRHAI_REG_LSL_IMM5(xEAX, xEDI, x3);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
break;
case 0xAF:
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
@@ -2404,11 +2512,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,1);
SMREAD();
MARK;
LDRBAI_REG_LSL_IMM5(x1, xESI, x3, 0);
STRBAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
// done
break;
case 0xA5:
@@ -2416,11 +2526,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,4);
SMREAD();
MARK;
LDRAI_REG_LSL_IMM5(x1, xESI, x3, 0);
STRAI_REG_LSL_IMM5(x1, xEDI, x3, 0);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
// done
break;
case 0xA6:
@@ -2482,6 +2594,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRBAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
break;
case 0xAB:
INST_NAME("REP STOSD");
@@ -2492,6 +2605,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STRAI_REG_LSL_IMM5(xEAX, xEDI, x3, 0);
SUBS_IMM8(xECX, xECX, 1);
B_MARK(cNE);
SMWRITE();
break;
case 0xAC:
INST_NAME("REP LODSB");
@@ -2590,7 +2704,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("NOT Eb");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -2611,12 +2725,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
INST_NAME("MUL AL, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, d_mul8);
GETEB(x1);
UBFX(x2, xEAX, 0, 8);
MUL(x1, x1, x2);
BFI(xEAX, x1, 0, 16);
UFLAG_RES(x1);
UFLAG_DF(x2, d_mul8);
break;
case 5:
INST_NAME("IMUL AL, Eb");
@@ -2675,52 +2789,66 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
INST_NAME("MUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, d_mul32);
GETED;
UMULL(xEDX, xEAX, xEAX, ed);
UFLAG_RES(xEAX);
UFLAG_OP1(xEDX);
UFLAG_DF(x2, d_mul32);
break;
case 5:
INST_NAME("IMUL EAX, Ed");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x2, d_imul32);
GETED;
SMULL(xEDX, xEAX, xEAX, ed);
UFLAG_RES(xEAX);
UFLAG_OP1(xEDX);
UFLAG_DF(x2, d_imul32);
break;
case 6:
INST_NAME("DIV Ed");
SETFLAGS(X_ALL, SF_SET);
if(arm_div && ninst && dyn->insts
if(ninst && dyn->insts && (nextop==0xF0)
&& dyn->insts[ninst-1].x86.addr
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
SET_DFNONE(x2); // flags are undefined
GETED;
UDIV(x2, xEAX, ed); // x1 = xEAX / ed
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x1*ed)
MOV_REG(xEAX, x2);
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0xB8
&& *(uint32_t*)(dyn->insts[ninst-1].x86.addr+1)==0) {
// hack for some protection that check a divide by zero actualy trigger a div0 exception
MESSAGE(LOG_INFO, "Divide by 0 hack\n");
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
MOV32(xEIP, addr);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
MOV_REG(x1, xEIP);
MOV32(x2, 0);
CALL(emit_div0, -1, 0);
} else {
GETEDH(x1);
if(arm_div) {
CMPS_IMM8(xEDX, 0);
B_MARK(cEQ);
}
if(ed!=x1) {MOV_REG(x1, ed);}
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(div32, -1, 0);
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
if(arm_div) {
B_NEXT(c__);
MARK;
UDIV(x2, xEAX, ed); // x2 = xEAX / ed
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x2*ed)
MOV_REG(xEAX, x2);
if(arm_div && ninst && dyn->insts
&& dyn->insts[ninst-1].x86.addr
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
SET_DFNONE(x2); // flags are undefined
GETED;
UDIV(x2, xEAX, ed); // x1 = xEAX / ed
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x1*ed)
MOV_REG(xEAX, x2);
} else {
GETEDH(x1);
if(arm_div) {
CMPS_IMM8(xEDX, 0);
B_MARK(cEQ);
}
if(ed!=x1) {MOV_REG(x1, ed);}
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
CALL(div32, -1, 0);
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
if(arm_div) {
B_NEXT(c__);
MARK;
UDIV(x2, xEAX, ed); // x2 = xEAX / ed
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x2*ed)
MOV_REG(xEAX, x2);
SET_DFNONE(x2); // flags are undefined
}
}
}
break;
@@ -2778,13 +2906,17 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORRS_IMM8(xFlags, xFlags, 1, 0);
break;
case 0xFA:
INST_NAME("CLI");
BFC(xFlags, F_IF, 1);
break;
case 0xFB:
INST_NAME("STI");
MOVW(x1, 1);
BFI(xFlags, x1, F_IF, 1);
INST_NAME(opcode==0xFA?"STI":"CLI");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
MOV32(xEIP, ip);
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_priv, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 0xFC:
INST_NAME("CLD");
@@ -2837,7 +2969,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF((box86_dynarec_safeflags>1) ||
PASS2IF((box86_dynarec_safeflags>1) ||
((ninst && dyn->insts[ninst-1].x86.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x86.set_flags)), 1)
{
+127 -63
View File
@@ -28,7 +28,7 @@
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETEX(a, w) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
@@ -40,7 +40,7 @@
gd = (nextop&0x38)>>3; \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
#define GETEM(a) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
} else { \
SMREAD(); \
@@ -111,7 +111,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -133,7 +133,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -150,7 +150,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x12:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
INST_NAME("MOVHLPS Gx,Ex");
GETGX(v0, 1);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
@@ -169,7 +169,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
INST_NAME("MOVLPS Ex,Gx");
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
VMOVD(v1, v0);
} else {
@@ -192,7 +192,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, q0);
} else q1 = q0;
@@ -203,7 +203,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, q0);
} else q1 = q0;
@@ -212,7 +212,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x16:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
INST_NAME("MOVLHPS Gx,Ex");
GETGX(v0, 1);
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
@@ -229,7 +229,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
INST_NAME("MOVHPS Ex,Gx");
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
VMOVD(v1, v0+1);
} else {
@@ -249,7 +249,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x18:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
INST_NAME("NOP (multibyte)");
} else
switch((nextop>>3)&7) {
@@ -282,7 +282,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVAPS Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -298,7 +298,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -312,7 +312,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
@@ -327,7 +327,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -340,7 +340,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -355,7 +355,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -388,7 +388,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v1<16)
d0 = v1;
@@ -466,7 +466,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVBE Gd, Ed");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
REV(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
@@ -479,12 +479,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVBE Ed, Gd");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
REV(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
REV(x1, gd);
STR_IMM9(gd, ed, fixedaddress);
STR_IMM9(x1, ed, fixedaddress);
SMWRITE();
}
break;
@@ -523,7 +523,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETFLAGS; \
nextop=F8; \
GETGD; \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
ed = xEAX+(nextop&7); \
MOV_REG_COND(YES, gd, ed); \
} else { \
@@ -625,7 +625,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGD;
XOR_REG_LSL_IMM5(gd, gd, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
// EX is an xmm reg
GETEX(q0, 0);
VMOVfrV_D(x1, x2, q0);
@@ -663,6 +663,8 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
#if 0
// the approximate is not precise enough and and some incorrect behavior
v2 = fpu_get_scratch_quad(dyn);
v1 = fpu_get_scratch_quad(dyn);
// Newton-Raphson: Xn+1 = Xn*(3-d*Xn²)/2 converge to 1/sqrt(d) with X0 = result of VSQRTE
@@ -695,6 +697,33 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMULQ_F32(v0, v2, q0); // v0 = X2*d ~ SQRT(d)
}
#else
if((q0<15) && (v0<15)) {
d0 = q0;
d1 = v0;
} else {
s0 = fpu_get_scratch_quad(dyn);
// source ok or not
if(q0<15) {
d0 = q0;
} else {
VMOVQ(s0, q0);
d0 = s0;
}
if(v0<15)
d1 = v0;
else
d1 = s0;
}
for(int i=0; i<4; ++i) {
VSQRT_F32(d1*2+i, d0*2+i);
}
if(v0<15) {
//done
} else {
VMOVQ(v0, d1);
}
#endif
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
@@ -702,8 +731,22 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
v0 = fpu_get_scratch_quad(dyn);
if(q1==q0 || !box86_dynarec_fastnan)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = q1;
VRSQRTEQ_F32(v0, q0);
VMULQ_F32(v1, v0, q0);
VRSQRTSQ_F32(v1, v1, v0);
VMULQ_F32(q1, v1, v0);
if(!box86_dynarec_fastnan) {
VCEQQ_F32(v1, q1, q1); // 00 is nan
VANDQ(q1, q1, v1); // if nan, remove
VBICQ(v0, v0, v1); // if nan, keep
VORRQ(q1, q1, v0);
}
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
@@ -711,8 +754,15 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
q1 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(q0 == q1)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = q1;
v0 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v0, q0);
VRECPSQ_F32(v1, v0, q0);
VMULQ_F32(q1, v0, v1);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
@@ -859,7 +909,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -870,7 +920,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -881,7 +931,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -923,7 +973,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
q0 = fpu_get_scratch_quad(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
VMOVD(q0+1, d1);
} else {
@@ -938,7 +988,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -950,7 +1000,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -962,7 +1012,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(d0);
GETEM(d1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = fpu_get_scratch_double(dyn);
VMOVD(v0, d1);
} else v0 = d1;
@@ -997,7 +1047,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVQ Gm, Em");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
VMOVD(v0, v1);
@@ -1013,7 +1063,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
gd = (nextop&0x38)>>3;
i32 = -1;
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
u8 = F8;
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
// use stack as temporary storage
@@ -1058,7 +1108,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLW Em, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
@@ -1081,7 +1131,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 4:
INST_NAME("PSRAW Em, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
@@ -1100,7 +1150,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("PSLLW Em, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
SMREAD();
@@ -1228,7 +1278,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVD Ed, Gm");
nextop = F8;
GETGM(v0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX + (nextop&7);
VMOVfrDx_32(ed, v0, 0);
} else {
@@ -1242,7 +1292,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVQ Em, Gm");
nextop = F8;
GETGM(v0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, nextop&7);
VMOVD(v1, v0);
} else {
@@ -1381,7 +1431,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop=F8; \
MOVW_COND(NO, x3, 0); \
MOVW_COND(YES, x3, 1); \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
ed = (nextop&7); \
eb1 = xEAX+(ed&3); \
eb2 = ((ed&4)>>2); \
@@ -1508,7 +1558,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
@@ -1564,7 +1614,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1631,7 +1681,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MESSAGE(LOG_DUMP, "Need Optimization\n");
// A purge is probably not needed, just a full refresh
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
@@ -1643,7 +1693,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FXRSTOR Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
@@ -1664,7 +1714,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("STMXCSR Md");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
LDR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
} else {
@@ -1677,7 +1727,20 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("XRSTOR Ed (not implemented");
FAKEED;
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
STM(xEmu, (1<<xEAX)|(1<<xECX)|(1<<xEDX)|(1<<xEBX)|(1<<xESP)|(1<<xEBP)|(1<<xESI)|(1<<xEDI)|(1<<xFlags));
STR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
CALL(arm_ud, -1, 0);
LDR_IMM9(xEIP, xEmu, offsetof(x86emu_t, ip));
jump_to_epilog(dyn, 0, xEIP, ninst);
*need_epilog = 0;
*ok = 0;
break;
case 7:
INST_NAME("CLFLUSH Ed");
MESSAGE(LOG_DUMP, "Need Optimization?\n");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL_(arm_clflush, -1, 0);
break;
default:
DEFAULT;
@@ -1747,7 +1810,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1779,7 +1842,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVZX Gd, Eb");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
@@ -1794,7 +1857,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVZX Gd, Ew");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
UXTH(gd, ed, 0);
} else {
@@ -1812,7 +1875,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
@@ -1832,7 +1895,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1864,7 +1927,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1896,7 +1959,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1936,7 +1999,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -2008,7 +2071,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVSX Gd, Eb");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
@@ -2023,7 +2086,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVSX Gd, Ew");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
SXTH(gd, ed, 0);
} else {
@@ -2048,11 +2111,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGD;
GETED;
MOV_REG(x1, gd);
if(gd!=ed) {
MOV_REG(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, x1, x3, x14);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0xC2:
@@ -2091,7 +2155,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// ignoring "NTI"
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd); // doesn't exist
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
@@ -2102,7 +2166,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PINSRW Gm,Ed,Ib");
nextop = F8;
GETGM(d0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
u8 = (F8)&3;
ed = xEAX+(nextop&7);
VMOVtoDx_16(d0, u8, ed);
@@ -2117,7 +2181,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("PEXTRW Gd,Em,Ib");
nextop = F8;
gd = xEAX+((nextop&0x38)>>3);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEM(d0);
u8 = (F8)&3;
VMOVfrDx_U16(gd, d0, u8);
@@ -2380,7 +2444,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xD7:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
INST_NAME("PMOVMSKB Gd, Em");
GETEM(d0);
gd = xEAX+((nextop&0x38)>>3);
@@ -2524,7 +2588,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOVNTQ Em, Gm");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
DEFAULT;
} else {
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
+57 -12
View File
@@ -29,7 +29,8 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, u8;
uint8_t wback, u8, wb1, wb2;
uint8_t gb1, gb2, eb1, eb2;
int fixedaddress;
MAYUSE(j32);
@@ -46,6 +47,17 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_add32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x20:
INST_NAME("AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGB(x2);
GETEBO(x14);
emit_and8(dyn, ninst, x1, x2, x14, x2);
EBBACK;
break;
case 0x2B:
INST_NAME("SUB Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -86,6 +98,13 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x64:
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x65:
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x67:
// reduced EA size...
opcode = F8;
@@ -95,7 +114,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -112,7 +131,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
@@ -125,7 +144,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
@@ -165,7 +184,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
@@ -182,13 +201,36 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
}
break;
case 0x88:
INST_NAME("MOV Eb, Gb");
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
gd = (nextop&0x38)>>3;
gb2 = ((gd&4)>>2);
gb1 = xEAX+(gd&3);
if(gb2) {
gd = x3;
UXTB(gd, gb1, gb2);
} else {
gd = gb1; // no need to extract
}
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = ((ed&4)<<1); // L or H
BFI(eb1, gd, eb2, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STRB_REG_LSL_IMM5(gd, ed, x14, 0);
SMWRITE2();
}
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
@@ -202,7 +244,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
@@ -215,7 +257,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ed");
grab_fsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
@@ -224,6 +266,9 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SMWRITE2();
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA0:
INST_NAME("MOV AL, FS:Id");
@@ -288,7 +333,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
if(MODREG) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
@@ -321,7 +366,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
@@ -336,7 +381,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6: // Push Ed
INST_NAME("PUSH FS:Ed");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
+16 -6
View File
@@ -172,6 +172,13 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_cmp32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x64:
addr = dynarecFS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x65:
addr = dynarecGS(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x69:
INST_NAME("IMUL Gd, GS:Ed, Id");
SETFLAGS(X_ALL, SF_PENDING);
@@ -369,7 +376,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
@@ -383,7 +390,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
SMREAD();
@@ -396,7 +403,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP GS:Ed");
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
@@ -405,6 +412,9 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SMWRITE2();
}
break;
case 0x90:
INST_NAME("NOP");
break;
case 0xA1:
INST_NAME("MOV EAX, GS:Id");
@@ -444,7 +454,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV GS:Eb, Ib");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= u8
if(MODREG) { // reg <= u8
u8 = F8;
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
@@ -463,7 +473,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= i32
if(MODREG) { // reg <= i32
i32 = F32S;
ed = xEAX+(nextop&7);
MOV32(ed, i32);
@@ -650,7 +660,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH GS:Ed");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
+229 -133
View File
@@ -18,6 +18,7 @@
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "custommem.h"
#include "dynarec_arm_helper.h"
#include "dynarec_arm_functions.h"
@@ -47,8 +48,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADD Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
GETSGW(x2);
GETSEW(x1);
emit_add16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -56,16 +57,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
GETSGW(x1);
GETSEW(x2);
emit_add16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
i32 = F16S;
SXTH(x1, xEAX, 0);
emit_add16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -123,8 +124,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
GETSGW(x2);
GETSEW(x1);
emit_adc16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -133,8 +134,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
GETSGW(x1);
GETSEW(x2);
emit_adc16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
@@ -142,8 +143,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
i32 = F16S;
SXTH(x1, xEAX, 0);
emit_adc16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -153,8 +154,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
GETSGW(x2);
GETSEW(x1);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -164,7 +165,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
GETSEW(x2);
emit_sbb16(dyn, ninst, x1, x2, x14, x3, 0);
GWBACK;
break;
@@ -172,9 +173,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
i16 = F16;
UXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
i32 = F16S;
SXTH(x1, xEAX, 0);
emit_sbb16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x1E:
@@ -219,8 +220,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1);
GETSGW(x2);
GETSEW(x1);
emit_sub16(dyn, ninst, x1, x2, x14, x3, (wb1 && (wback==x3))?1:0);
EWBACK;
break;
@@ -228,16 +229,16 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2);
GETSGW(x1);
GETSEW(x2);
emit_sub16(dyn, ninst, x1, x2, x3, x14, 0);
GWBACK;
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTH(x1, xEAX, 0);
i32 = F16S;
SXTH(x1, xEAX, 0);
emit_sub16c(dyn, ninst, x1, i32, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
@@ -388,13 +389,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("IMUL Gw,Ew,Iw");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETEW(x1);
i16 = F16S;
MOVW(x2, i16);
SMULBB(x2, ed, x2);
UFLAG_RES(x2);
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 0x6A:
INST_NAME("PUSH Ib");
@@ -406,13 +407,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("IMUL Gw,Ew,Ib");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
GETEW(x1);
i16 = F8S;
MOVW(x2, i16);
SMULBB(x2, ed, x2);
UFLAG_RES(x2);
BFI(xEAX+((nextop&0x38)>>3), x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 0x81:
@@ -507,7 +508,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x87:
INST_NAME("(LOCK) XCHG Ew, Gw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGD;
UXTH(x14, gd, 0);
ed = xEAX + (nextop&7);
@@ -541,7 +542,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Ew, Gw");
nextop = F8;
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -556,7 +557,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Gw, Ew");
nextop = F8;
GETGD; // don't need GETGW neither
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
@@ -573,7 +574,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
LDRH_REG(x1, xEmu, x2);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
BFI(ed, x1, 0, 16);
} else {
@@ -586,7 +587,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x8E:
INST_NAME("MOV Seg,Ew");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
@@ -649,7 +650,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV, AX, Od");
u32 = F32;
MOV32(x2, u32);
SMREAD();
if(isLockAddress(u32)) lock=1; else lock = 0;
SMREADLOCK(lock);
LDRH_IMM8(x2, x2, 0);
BFI(xEAX, x2, 0, 16);
break;
@@ -657,8 +659,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("MOV Od, AX");
u32 = F32;
MOV32(x2, u32);
if(isLockAddress(u32)) lock=1; else lock = 0;
STRH_IMM8(xEAX, x2, 0);
SMWRITE();
SMWRITELOCK(lock);
break;
case 0xA5:
INST_NAME("MOVSW");
@@ -723,21 +726,29 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
CALL_(rol16, x1, (1<<x3));
EWBACK;
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_rol16c(dyn, ninst, x1, u8&15, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 1:
INST_NAME("ROR Ew, Ib");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1);
u8 = F8;
MOVW(x2, u8);
CALL_(ror16, x1, (1<<x3));
EWBACK;
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_ror16c(dyn, ninst, x1, u8&15, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 2:
INST_NAME("RCL Ew, Ib");
@@ -762,39 +773,42 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_LSL_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_shl16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 5:
INST_NAME("SHR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
u8 = F8;
emit_shr16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1);
u8 = F8;
MOVW(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
MOV_REG_ASR_REG(ed, ed, x2);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
if(geted_ib(dyn, addr, ninst, nextop)&31) {
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETSEW(x1);
u8 = F8;
emit_sar16c(dyn, ninst, x1, u8&31, x2, x14);
EWBACK;
} else {
FAKEED;
F8;
}
break;
}
break;
@@ -802,7 +816,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC7:
INST_NAME("MOV Ew, Iw");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u16 = F16;
MOVW(x1, u16);
@@ -816,101 +830,178 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xD1:
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
if(opcode==0xD1) {
INST_NAME("ROL Ew, 1");
MOVW(x2, 1);
} else {
INST_NAME("ROL Ew, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROL Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
CALL_(rol16, x1, (1<<x3));
emit_rol16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
case 1:
if(opcode==0xD1) {
INST_NAME("ROR Ew, 1");
MOVW(x2, 1);
} else {
INST_NAME("ROR Ew, CL");
AND_IMM8(x2, xECX, 0x1f);
}
SETFLAGS(X_OF|X_CF, SF_SET);
INST_NAME("ROR Ew, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEW(x1);
CALL_(ror16, x1, (1<<x3));
emit_ror16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
case 2:
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
INST_NAME("RCL Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
MOVW(x2, 1);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
EWBACK;
break;
case 3:
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
INST_NAME("RCR Ew, 1");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
MOVW(x2, 1);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
EWBACK;
break;
case 4:
case 6:
if(opcode==0xD1) {
INST_NAME("SHL Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SHL Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHL Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_LSL_REG(ed, ed, x14);
emit_shl16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
if(opcode==0xD1) {
INST_NAME("SHR Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SHR Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SHR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_LSR_REG(ed, ed, x14);
emit_shr16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
break;
case 7:
if(opcode==0xD1) {
INST_NAME("SAR Ew, 1");
MOVW(x14, 1);
} else {
INST_NAME("SAR Ew, CL");
AND_IMM8(x14, xECX, 0x1f);
}
SETFLAGS(X_ALL, SF_PENDING);
INST_NAME("SAR Ew, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETSEW(x1);
UFLAG_OP12(ed, x14)
MOV_REG_ASR_REG(ed, ed, x14);
emit_sar16c(dyn, ninst, x1, 1, x2, x14);
EWBACK;
break;
}
break;
case 0xD3:
nextop = F8;
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x0f);
RSB_IMM8(x2, x2, 16);
GETEW(x1);
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 15);
ADD_REG_LSR_IMM5_COND(cEQ, x3, ed, ed, 15);
BFI_COND(cEQ, xFlags, x3, F_OF, 1);
BFI(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Ew, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
TSTS_IMM8(xECX, 0x1f);
B_NEXT(cEQ);
}
AND_IMM8(x2, xECX, 0x0f);
GETEW(x1);
ORR_REG_LSL_IMM5(ed, ed, ed, 16);
MOV_REG_LSR_REG(ed, ed, x2);
EWBACK;
UFLAG_IF { // calculate flags directly
CMPS_IMM8(x2, 1);
MOV_REG_LSR_IMM5_COND(cEQ, x2, ed, 14); // x2 = d>>14
XOR_REG_LSR_IMM8_COND(cEQ, x2, x2, x2, 1); // x2 = ((d>>14) ^ ((d>>14)>>1))
BFI_COND(cEQ, xFlags, x2, F_OF, 1);
MOV_REG_LSR_IMM5(x2, ed, 15);
BFI(xFlags, x2, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 2:
INST_NAME("RCL Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcl16, x1, (1<<x3));
EWBACK;
break;
case 3:
INST_NAME("RCR Ew, CL");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEW(x1);
CALL_(rcr16, x1, (1<<x3));
EWBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEW(x1);
emit_shl16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
break;
case 5:
INST_NAME("SHR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETEW(x1);
emit_shr16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
break;
case 7:
INST_NAME("SAR Ew, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(box86_dynarec_safeflags>1)
MAYSETFLAGS();
UFLAG_IF {
ANDS_IMM8(x2, xECX, 0x1f);
B_NEXT(cEQ);
} else {
AND_IMM8(x2, xECX, 0x1f);
}
GETSEW(x1);
emit_sar16(dyn, ninst, x1, x2, x2, x14);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_sar16);
break;
}
break;
@@ -1058,13 +1149,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5:
INST_NAME("IMUL AX, Ew");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_DF(x1, d_imul16);
GETEW(x1);
SMULBB(x2, xEAX, ed);
UFLAG_RES(x2);
BFI(xEAX, x2, 0, 16);
MOV_REG_LSR_IMM5(x2, x2, 16);
BFI(xEDX, x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 6:
INST_NAME("DIV Ew");
@@ -1128,6 +1219,11 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
case 6:
INST_NAME("PUSH Ew");
GETEW(x1);
PUSH16(x1, xESP);
break;
default:
DEFAULT;
}
+332 -56
View File
@@ -21,10 +21,11 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
#include "emu/x86compstrings.h"
// Get EX as a quad
#define GETEX(a, w) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
SMREAD(); \
@@ -35,12 +36,18 @@
#define GETGX(a, w) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETGX_empty(a) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
#define GETG gd = (nextop&0x38)>>3
uintptr_t dynarec660F(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, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t eb1, eb2;
@@ -66,7 +73,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVUPD Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -87,7 +94,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -105,7 +112,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVLPD Gx, Eq");
nextop = F8;
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
@@ -126,7 +133,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVLPD Eq, Gx");
nextop = F8;
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
@@ -147,7 +154,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("UNPCKLPD Gx, Ex");
nextop = F8;
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
@@ -161,7 +168,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(v0, 1);
VMOVD(v0, v0+1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1+1);
} else {
@@ -174,7 +181,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVHPD Gx, Ed");
nextop = F8;
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
@@ -195,7 +202,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVHPD Ed, Gx");
nextop = F8;
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
@@ -223,7 +230,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVAPD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -239,7 +246,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -255,7 +262,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -286,7 +293,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(q0, 1);
q1 = fpu_get_scratch_quad(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -460,6 +467,108 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S32(q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX_empty(q0);
AESIMC(q0, q1);
} else {
GETEX(q1, 0);
GETGX_empty(q0);
if(q0!=q1) {
VMOVQ(q0, q1);
}
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesimc, -1, 0);
}
break;
case 0xDC:
INST_NAME("AESENC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
AESMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aese, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDD:
INST_NAME("AESENCLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aeselast, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDE:
INST_NAME("AESDEC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
AESIMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesd, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDF:
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesdlast, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
default:
DEFAULT;
}
@@ -484,6 +593,163 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VEXTQ_8(q0, q1, q0, u8);
}
break;
case 0x16:
INST_NAME("PEXTRD Ed, Gx, Ib");
nextop = F8;
GETGX(q0, 0);
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
VMOVfrDx_32(ed, q0+((u8&2)>>1), u8&1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
VST1LANE_32(q0+((u8&2)>>1), wback, u8&1);
SMWRITE2();
}
break;
case 0x20:
INST_NAME("PINSRB Gx, ED, Ib");
nextop = F8;
GETGX(q0, 1);
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
VMOVtoDx_8(q0+((u8&8)>>3), u8&7, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
VLD1LANE_8(q0+((u8&8)>>3), wback, u8&7);
SMWRITE2();
}
break;
case 0x22:
INST_NAME("PINSRD Gx, ED, Ib");
nextop = F8;
GETGX(q0, 1);
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
VMOVtoDx_32(q0+((u8&2)>>1), u8&1, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
VLD1LANE_32(q0+((u8&2)>>1), wback, u8&1);
SMWRITE2();
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
if(arm_pmull) {
GETGX(q0, 1);
GETEX(q1, 0);
u8 = F8;
switch (u8&0b00010001) {
case 0b00000000:
VMULL_P64(q0, q0, q1);
break;
case 0b00010001:
VMULL_P64(q0, q0+1, q1+1);
break;
case 0b00000001:
VMULL_P64(q0, q0+1, q1);
break;
case 0b00010000:
VMULL_P64(q0, q0, q1+1);
break;
}
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
if(MODREG) {
ed = nextop&7;
sse_forget_reg(dyn, ninst, ed, x1);
MOV32(x2, ed);
} else {
MOV32(x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x2) {
MOV_REG(x2, ed);
}
}
MOV32(x1, gd); // gx
u8 = F8;
MOV32(x3, u8);
CALL(arm_pclmul, -1, 0);
}
break;
case 0x63:
INST_NAME("PCMPISTRI Gx, Ex, Ib");
SETFLAGS(X_OF|X_CF|X_AF|X_ZF|X_SF|X_PF, SF_SET);
nextop = F8;
GETG;
if(!sse_reflect_reg(dyn, ninst, gd, x2)) {
u32 = offsetof(x86emu_t, xmm[gd]);
if(!(u32&3) && (u32>>2)<256) {
ADD_IMM8_ROR(x2, xEmu, u32>>2, 15);
} else {
MOV32(x2, u32);
ADD_REG_LSL_IMM5(x2, xEmu, x2, 0);
}
}
if(MODREG) {
ed = (nextop&7);
if(!sse_reflect_reg(dyn, ninst, ed, x1)) {
u32 = offsetof(x86emu_t, xmm[ed]);
if(!(u32&3) && (u32>>2)<256) {
ADD_IMM8_ROR(x1, xEmu, u32>>2, 15);
} else {
MOV32(x1, u32);
ADD_REG_LSL_IMM5(x1, xEmu, x1, 0);
}
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
}
u8 = F8;
MOV32(x3, u8);
CALL(sse42_compare_string_implicit_len, x1, 0);
CMPS_IMM8(x1, 0);
MOVW_COND(cEQ, xECX, (u8&1)?8:16);
if(u8&0b1000000) {
CLZ_COND(cNE, xECX, x1);
RSB_COND_IMM8(cNE, xECX, xECX, 31);
} else {
RBIT_COND(cNE, xECX, x1);
CLZ_COND(cNE, xECX, xECX);
}
break;
case 0xDF:
INST_NAME("AESKEYGENASSIST Gx, Ex, Ib"); // AES-NI
nextop = F8;
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd); // gx
if(MODREG) {
ed = nextop&7;
sse_forget_reg(dyn, ninst, ed, x2);
MOV32(x2, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x2) {
MOV_REG(x2, ed);
}
}
u8 = F8;
MOV32(x3, u8);
CALL(arm_aeskeygenassist, -1, 0);
break;
default:
DEFAULT;
}
@@ -494,7 +760,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETFLAGS; \
nextop=F8; \
GETGD; \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
ed = xEAX+(nextop&7); \
} else { \
SMREAD(); \
@@ -602,7 +868,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETEX(q0, 0);
gd = xEAX+((nextop&0x38)>>3);
if((nextop&0xC0)==0xC0)
if(MODREG)
q1 = fpu_get_scratch_quad(dyn);
else
q1 = q0;
@@ -727,11 +993,21 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q1 = v1;
// need rounding!
//VCVTQ_S32_F32(v0, v1);
u8 = sse_setround(dyn, ninst, x1, x2, x14);
VCVTR_S32_F32(q0*2+0, q1*2+0);
VCVTR_S32_F32(q0*2+1, q1*2+1);
VCVTR_S32_F32(q0*2+2, q1*2+2);
VCVTR_S32_F32(q0*2+3, q1*2+3);
if(!box86_dynarec_fastround)
u8 = sse_setround_reset(dyn, ninst, x1, x2, x14);
else
u8 = sse_setround(dyn, ninst, x1, x2, x14);
for(int i=0; i<4; ++i) {
VCVTR_S32_F32(q0*2+i, q1*2+i);
if(!box86_dynarec_fastround) {
VMRS(x3); // get the FPCSR reg and test FPU exception (IO only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
MOV_IMM_COND(cNE, x1, 0b10, 1); // 0x80000000
VMOVtoVcond(cNE, q0*2+i, x1);
BIC_IMM8_COND(cNE, x3, x3, 1, 0); // reset FPU
VMSR_cond(cNE, x3);
}
}
if(q0!=v0) {
VMOVQ(v0, q0);
}
@@ -936,7 +1212,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
@@ -950,7 +1226,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGX(q0, 1);
VMOVD(q0, q0+1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(q0+1, q1+1);
} else {
@@ -972,7 +1248,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDQA Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -988,7 +1264,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
i32 = -1;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
@@ -1119,7 +1395,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLW Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1142,7 +1418,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 4:
INST_NAME("PSRAW Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1161,7 +1437,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 6:
INST_NAME("PSLLW Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1192,7 +1468,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLD Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1215,7 +1491,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 4:
INST_NAME("PSRAD Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1234,7 +1510,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 6:
INST_NAME("PSLLD Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1264,7 +1540,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLQ Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1287,7 +1563,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 3:
INST_NAME("PSRLDQ Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1312,7 +1588,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 6:
INST_NAME("PSLLQ Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1335,7 +1611,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 7:
INST_NAME("PSLLDQ Ex, Ib");
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
SMREAD();
@@ -1389,7 +1665,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX + (nextop&7);
VMOVfrDx_32(ed, v0, 0);
} else {
@@ -1403,7 +1679,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDQA Ex,Gx");
nextop = F8;
GETGX(v0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -1419,7 +1695,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SET_DFNONE(x1);
nextop = F8;
GETGD; // there is an AND below, so 32bits is the same (no need for GETGW)
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7); // no need for extract
} else {
SMREAD();
@@ -1461,7 +1737,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SET_DFNONE(x1);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
@@ -1511,8 +1787,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("IMUL Gw,Ew");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
UFLAG_DF(x1, d_imul16);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
@@ -1523,6 +1798,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SMULBB(x2, gd, ed);
UFLAG_RES(x2);
BFI((xEAX+((nextop&0x38)>>3)), x2, 0, 16);
UFLAG_DF(x1, d_imul16);
break;
case 0xB3:
@@ -1531,7 +1807,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SET_DFNONE(x1);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
@@ -1560,7 +1836,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVZX Gw, Eb");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
@@ -1576,7 +1852,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVZX Gw, Ew");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX + (nextop&7);
UXTH(x1, ed, 0);
} else {
@@ -1594,7 +1870,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("BT Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
SMREAD();
@@ -1614,7 +1890,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("BTS Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1645,7 +1921,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("BTR Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1676,7 +1952,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("BTC Ew, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -1712,7 +1988,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
SET_DFNONE(x1);
nextop = F8;
GETGD; // there is an AND below, to 32bits is the same
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
@@ -1771,7 +2047,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSX Gw, Eb");
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
@@ -1844,7 +2120,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PINSRW Gx,Ed,Ib");
nextop = F8;
GETGX(v0, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
u8 = (F8)&7;
ed = xEAX+(nextop&7);
VMOVtoDx_16(v0+(u8/4), u8&3, ed);
@@ -1859,7 +2135,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PEXTRW Gd,Ex,Ib");
nextop = F8;
gd = xEAX+((nextop&0x38)>>3);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEX(v0, 0);
u8 = (F8)&7;
VMOVfrDx_U16(gd, v0+(u8/4), (u8&3));
@@ -1973,7 +2249,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVQ Ex,Gx");
nextop = F8;
GETGX(q0, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVD(q1, q0);
VEOR(q1+1, q1+1, q1+1);
@@ -1994,7 +2270,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
break;
case 0xD7:
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
INST_NAME("PMOVMSKB Gd, Ex");
GETEX(q0, 0);
gd = xEAX+((nextop&0x38)>>3);
@@ -2165,7 +2441,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -2280,7 +2556,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q0 = fpu_get_scratch_quad(dyn);
VMOVQ(q0, v0);
VTRN_32(q0, q0+1); // transpose GX
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else {
@@ -2317,7 +2593,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VLD1Q_8(v0, xEDI); // hopefully it's always aligned?
if((nextop&0xC0)==0xC0)
if(MODREG)
v1 = fpu_get_scratch_quad(dyn); // need to preserve the register
else
v1 = q1;
+9 -9
View File
@@ -41,7 +41,6 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x81:
case 0x83:
nextop = F8;
SMDMB();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
@@ -50,8 +49,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = xEAX+(nextop&7);
emit_add16c(dyn, ninst, ed, i16, x3, x14);
@@ -69,9 +67,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -84,8 +82,8 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0); // put the whole value
SMDMB();
}
SMDMB();
}
break;
default:
@@ -101,7 +99,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0: // INC Ew
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEW(x1);
emit_inc16(dyn, ninst, ed, x3, x14);
EWBACK(x1);
@@ -118,9 +116,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
@@ -133,13 +131,14 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
SMDMB();
}
}
break;
case 1: //DEC Ew
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETEW(x1);
emit_dec32(dyn, ninst, ed, x3, x14);
EWBACK(x1);
@@ -156,9 +155,9 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -171,6 +170,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
SMDMB();
}
}
break;
+4 -4
View File
@@ -50,7 +50,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD; // don't need GETGW here
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(ed, gd, 0, 16);
@@ -67,7 +67,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
if(MODREG) { // reg <= reg
ed = xEAX+(nextop&7);
if(ed!=gd) {
BFI(gd, ed, 0, 16);
@@ -83,7 +83,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("POP FS:Ew16");
nextop=F8;
grab_fsdata(dyn, addr, ninst, x14);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
POP1(xEAX+(nextop&7)); // 67 ignored
} else {
addr = geted16(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0);
@@ -123,7 +123,7 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 6: // Push Ed
INST_NAME("PUSH FS:Ew");
if((nextop&0xC0)==0xC0) { // reg
if(MODREG) { // reg
DEFAULT;
} else { // mem <= i32
SMREAD();
+14 -8
View File
@@ -319,15 +319,21 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 9, 2); //C1 C2 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
if(PK(0)==0xdd && PK(1)==0xd8) {
MESSAGE(LOG_DUMP, "Optimized next DD D8 fstp st0, st0, not emiting 1\n");
u8 = F8;
u8 = F8;
} else {
VMOV_i_64(v2, 0b01110000);
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
} else {
VMOV_i_64(v2, 0b01110000);
}
}
break;
case 0xF3:
+1 -1
View File
@@ -923,7 +923,7 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
void emit_dec8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
SET_DF(s3, d_dec8);
} else IFX(X_ZF|X_OF|X_AF|X_SF|X_PF) {
SET_DFNONE(s3);
+697 -46
View File
@@ -154,7 +154,17 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
}
IFX(X_ZF|X_CF) {
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_ZF) {
MOVS_REG_LSR_REG(s1, s1, s2);
} else {
MOV_REG_LSR_REG(s1, s1, s2);
@@ -162,25 +172,14 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF|X_CF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
}
IFX(X_ZF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -203,7 +202,21 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
}
return;
}
IFX(X_ZF|X_CF) {
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, F_CF, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, F_CF, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_ZF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
MOV_REG_LSR_IMM5(s1, s1, c);
@@ -211,26 +224,14 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF|X_CF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
}
IFX(X_ZF) {
BIC_IMM8(xFlags, xFlags, (1<<F_ZF), 0);
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -274,6 +275,565 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
MOV_REG_LSR_IMM5(s3, s1, 31);
BFI(xFlags, s3, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF | X_OF) {
RSB_IMM8(s4, s2, 8);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
MOV_REG_LSL_REG(s1, s1, s2);
IFX(X_ZF) {
ANDS_IMM8(s1, s1, 0xff);
} else IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
MOV32(s4, 1);
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);}
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c<8) {
IFX(X_CF|X_OF) {
MOV_REG_LSR_IMM5(s3, s1, 8-c);
BFI(xFlags, s3, F_CF, 1);
}
MOV_REG_LSL_IMM5(s1, s1, c);
IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 7);}
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
} else {
IFX(X_CF) {
MOV_REG_LSL_IMM5(s3, s1, c-1);
MOV_REG_LSR_IMM5(s4, s3, 7);
BFI(xFlags, s4, F_CF, 1);
}
MOVW(s1, 0);
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFC(xFlags, F_SF, 1);
}
IFX(X_PF | X_ZF) {
MOVW(s3, 1);
IFX(X_ZF) {
BFI(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFI(xFlags, s3, F_PF, 1);
}
}
}
}
// emit SHR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 7);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
MOV_REG_LSR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, 0, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_OF, 1);
}
}
MOV_REG_LSR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR8 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_ASR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
MOV_REG_ASR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
MOV_REG_ASR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
MOV_REG_ASR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_IMM8(s1, 0xff);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 7);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF | X_OF) {
RSB_IMM8(s4, s2, 16);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
MOV_REG_LSL_REG(s1, s1, s2);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOV32(s4, 1);
BFI_COND(cEQ, xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
IFX(X_SF) {} else {MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 15);}
XOR_REG_LSL_IMM5_COND(cEQ, s4, s4, xFlags, 0); // CF is set if OF is asked
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shl16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c<16) {
IFX(X_CF|X_OF) {
MOV_REG_LSR_IMM5(s3, s1, 16-c);
BFI(xFlags, s3, F_CF, 1);
}
MOV_REG_LSL_IMM5(s1, s1, c);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {MOV_REG_LSR_IMM5(s4, s1, 15);}
XOR_REG_LSL_IMM5(s4, s4, xFlags, 0); // CF is set if OF is asked
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
} else {
IFX(X_CF) {
MOV_REG_LSL_IMM5(s3, s1, c-1);
MOV_REG_LSR_IMM5(s4, s3, 15);
BFI(xFlags, s4, F_CF, 1);
}
MOVW(s1, 0);
IFX(X_OF) {
BFC(xFlags, F_OF, 1);
}
IFX(X_SF) {
BFC(xFlags, F_SF, 1);
}
IFX(X_PF | X_ZF) {
MOVW(s3, 1);
IFX(X_ZF) {
BFI(xFlags, s3, F_ZF, 1);
}
IFX(X_PF) {
BFI(xFlags, s3, F_PF, 1);
}
}
}
}
// emit SHR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1); // if s2==1
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 16);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
MOV_REG_LSR_REG(s1, s1, s2);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SHR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_shr16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
if(c==1) {
BFI(xFlags, s1, 0, 1);
} else {
MOV_REG_LSR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_OF, 1);
}
}
MOV_REG_LSR_IMM5(s1, s1, c);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR16 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
SUB_IMM8(s4, s2, 1);
MOV_REG_ASR_REG(s4, s1, s4);
BFI(xFlags, s4, 0, 1);
}
MOV_REG_ASR_REG(s1, s1, s2);
UBFX(s1, s1, 0, 16);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
CMPS_IMM8(s2, 1);
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
if(!c)
return;
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_sar16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
IFX(X_CF) {
MOV_REG_ASR_IMM5(s3, s1, c-1);
BFI(xFlags, s3, 0, 1);
}
MOV_REG_ASR_IMM5(s1, s1, c);
IFX(X_PEND | X_ZF) {
UXTH(s1, s1, 0);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
TSTS_REG_LSL_IMM5(s1, s1, 0);
MOVW_COND(cNE, s4, 0);
MOVW_COND(cEQ, s4, 1);
BFI(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 15);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_OF)
if(c==1) {
BFC(xFlags, F_OF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
@@ -366,6 +926,12 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
return;
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
}
IFX(X_CF) {
MOVS_REG_LSR_IMM5(s1, s1, c);
} else {
@@ -394,9 +960,11 @@ void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 30);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
MOV_REG_LSR_IMM5(s4, s1, 31);
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
@@ -425,6 +993,12 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
return;
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 32-c);
BFI(xFlags, s3, F_CF, 1);
@@ -436,9 +1010,9 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
}
IFX(X_OF) {
if(c==1) {
UBFX(s3, s1, (31-c), 1);
XOR_IMM8_COND(cCS, s3, s3, 1);
BFI(xFlags, s3, F_OF, 1);
MOV_REG_LSR_IMM5(s4, s1, 31);
XOR_REG_LSR_IMM8(s4, s4, xFlags, F_OF); // set if sign changed
BFI(xFlags, s4, F_OF, 1);
} else {
BFC(xFlags, F_OF, 1);
}
@@ -474,7 +1048,7 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shr32
SET_DF(s4, d_shr32);
SET_DF(s4, d_shrd32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
@@ -484,6 +1058,10 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
IFX(X_CF) {
MOVS_REG_LSR_REG(s1, s1, s3);
} else {
@@ -513,8 +1091,8 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
IFX(X_OF) {
CMPS_IMM8(s3, 31); // 32-c
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 30);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, s4, 1);
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
@@ -531,7 +1109,7 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shl32
SET_DF(s4, d_shl32);
SET_DF(s4, d_shld32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
@@ -544,6 +1122,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
B_NEXT(cEQ);
IFX(X_OF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_OF, 1); // store sign for later use
}
IFX(X_CF) {
RSB_IMM8(s4, s3, 32);
MOV_REG_LSR_REG(s4, s1, s4);
@@ -555,13 +1137,10 @@ void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MOV_REG_LSL_REG(s1, s1, s3);
}
IFX(X_OF) {
MOVW_COND(cCS, s4, 1);
MOVW_COND(cCC, s4, 0);
CMPS_IMM8(s3, 1);
ORR_REG_LSR_IMM5_COND(cEQ, s4, s4, s1, 30);
CMPS_IMM8(s3, 31); // 32-c
MOV_REG_LSR_IMM5_COND(cEQ, s4, s1, 31);
XOR_REG_LSR_IMM8_COND(cEQ, s4, s4, xFlags, F_OF);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
//else
BFC_COND(cNE, xFlags, F_OF, 1);
}
RSB_IMM8(s3, s3, 32);
IFX(X_ZF) {
@@ -602,8 +1181,8 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
return;
}
if(c&7) {
BFI(s1, s1, 24, 8); // duplicate the value for rotate left
MOV_REG_ROR_IMM5(s1, s1, 32-(c&7));
BFI(s1, s1, 8, 8);
MOV_REG_LSR_IMM5(s1, s1, 8-(c&7));
}
//AND_IMM8(s1, s1, 0xff);
IFX(X_PEND) {
@@ -614,7 +1193,7 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
IFX(X_OF) {
if(c==1) {
ADD_REG_LSR_IMM5(s3, s1, s1, 7);
XOR_REG_LSR_IMM8(s3, s1, s1, 7);
BFI(xFlags, s3, F_OF, 1);
}
}
@@ -638,7 +1217,7 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
if(c&7) {
BFI(s1, s1, 8, 8); // duplicate the value for Rotate right
MOV_REG_ROR_IMM5(s1, s1, c&7);
MOV_REG_LSR_IMM5(s1, s1, c&7);
}
IFX(X_PEND) {
AND_IMM8(s1, s1, 0xff);
@@ -656,3 +1235,75 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
}
}
// emit ROL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_rol16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&15) {
BFI(s1, s1, 16, 16);
MOV_REG_LSR_IMM5(s1, s1, 16-(c&15));
}
IFX(X_PEND) {
UBFX(s1, s1, 0, 16);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
BFI(xFlags, s1, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
XOR_REG_LSR_IMM8(s3, s1, s1, 15);
BFI(xFlags, s3, F_OF, 1);
}
}
}
// emit ROR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_ror16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
return;
}
if(c&15) {
BFI(s1, s1, 16, 16); // duplicate the value for Rotate right
MOV_REG_LSR_IMM5(s1, s1, c&15);
}
IFX(X_PEND) {
UBFX(s1, s1, 0, 16);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
MOV_REG_LSR_IMM5(s3, s1, 15);
BFI(xFlags, s3, F_CF, 1);
}
IFX(X_OF) {
if(c==1) {
MOV_REG_LSR_IMM5(s4, s1, 14);
XOR_REG_LSR_IMM8(s4, s4, s4, 1);
BFI(xFlags, s4, F_OF, 1);
}
}
}
+75 -104
View File
@@ -42,8 +42,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -66,8 +65,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -85,8 +83,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK OR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -111,8 +108,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -132,8 +128,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -157,8 +152,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -178,8 +172,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -203,8 +196,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -222,8 +214,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK AND Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -248,8 +239,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -268,8 +258,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -292,8 +281,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -311,8 +299,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK XOR Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GETGB(x2);
wback = (nextop&7);
wb2 = (wback>>2);
@@ -337,8 +324,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
} else {
@@ -368,8 +354,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_add32c(dyn, ninst, ed, i32, x3, x14);
@@ -409,8 +394,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_or32c(dyn, ninst, ed, i32, x3, x14);
@@ -430,8 +414,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
@@ -451,8 +434,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
@@ -471,8 +453,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_and32c(dyn, ninst, ed, i32, x3, x14);
@@ -491,12 +472,11 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(!fixedaddress) {
@@ -532,12 +512,11 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(opcode==0x81) i32 = F32S; else i32 = F8S;
ed = xEAX+(nextop&7);
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
@@ -552,7 +531,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
GETEDH(x1);
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F32S; else i32 = F8S;
@@ -566,7 +544,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed wy a locked write)
// generic case, no lock needed, the value is only read (note that on x86 locked read is always followed by a locked write)
#define GO(A) \
case A+0x02: \
case A+0x03: \
@@ -585,17 +563,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SMDMB();
--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:
SMDMB();
--addr;
break;
case 0x0F:
nextop = F8;
@@ -603,9 +570,8 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xB0:
INST_NAME("LOCK CMPXCHG Eb, Gb");
SETFLAGS(X_ALL, SF_SET_PENDING);
SMDMB();
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -649,8 +615,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
// same as no lock, all in regs...
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
@@ -721,8 +686,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -736,30 +700,26 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
AND_IMM8(x2, gd, 0x1f);
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to end of instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
BIC_REG_LSL_REG(ed, ed, x14, x2);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
SMDMB();
break;
case 0xBA:
nextop = F8;
SMDMB();
switch((nextop>>3)&7) {
case 4:
INST_NAME("(LOCK) BT Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0, LOCK_LOCK);
@@ -778,26 +738,21 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK BTS Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8&0x1f);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
u8 = F8&0x1f;
ed = x1;
MOVW(gd, u8&0x1f);
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cNE); // bit already set, jump to next instruction
MOVW(x14, 1);
XOR_REG_LSL_REG(ed, ed, x14, x2);
BFI(ed, x14, u8, 1);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
@@ -809,26 +764,46 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("LOCK BTR Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
gd = x2;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8;
MOVW(gd, u8&0x1f);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
u8 = F8&0x1f;
ed = x1;
MOVW(gd, u8&0x1f);
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_REG(x14, ed, x2);
ANDS_IMM8(x14, x14, 1);
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
B_MARK3(cEQ); // bit already clear, jump to next instruction
//MOVW(x14, 1); // already 0x01
XOR_REG_LSL_REG(ed, ed, x14, x2);
BFC(ed, u8, 1);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
}
MARK3;
break;
case 7:
INST_NAME("LOCK BTC Ed, Ib");
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
if(MODREG) {
ed = xEAX+(nextop&7);
u8 = F8&0x1f;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8&0x1f;
ed = x1;
MARKLOCK;
LDREX(ed, wback);
}
MOV_REG_LSR_IMM5(x14, ed, u8);
BFI(xFlags, x14, F_CF, 1);
MOV32(x14, 1);
XOR_REG_LSL_IMM5(ed, ed, x14, u8);
if(wback) {
STREX(x14, ed, wback);
CMPS_IMM8(x14, 0);
@@ -847,8 +822,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SET_DFNONE(x1);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
@@ -879,7 +853,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
SMDMB();
GETGB(x1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xEAX+(wback&3);
@@ -909,8 +883,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
SMDMB();
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
if(gd!=ed) {
XOR_REG_LSL_IMM5(gd, gd, ed, 0); // swap gd, ed
@@ -964,7 +937,6 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
SMDMB();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
@@ -1010,8 +982,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
default:
// dafault to NO LOCK
addr-=2;
DEFAULT;
}
break;
@@ -1023,7 +994,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x14);
} else {
@@ -1039,9 +1010,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1054,13 +1025,14 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0);
SMDMB();
}
}
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x14);
} else {
@@ -1076,9 +1048,9 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STREX(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
SMDMB();
}
if(!fixedaddress) {
SMDMB();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
@@ -1091,19 +1063,18 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STR_IMM9(x1, wback, 0);
SMDMB();
}
}
break;
default:
// default to NO LOCK
addr-=2;
DEFAULT;
}
SMDMB();
break;
default:
// default to NO LOCK
--addr;
DEFAULT;
}
return addr;
+10 -10
View File
@@ -24,7 +24,7 @@
// Get Ex as a double, not a quad (warning, x2 and x3 may get used)
#define GETEX(a, w) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7,w);\
} else { \
parity = getedparity(dyn, ninst, addr, nextop, 3); \
@@ -68,7 +68,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0, d0);
@@ -87,7 +87,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
VMOVD(d0, v0);
} else {
@@ -102,7 +102,7 @@ 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;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, d0);
@@ -133,7 +133,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -165,7 +165,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -328,7 +328,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -364,7 +364,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -434,7 +434,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -460,7 +460,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
+14 -14
View File
@@ -24,7 +24,7 @@
// Get Ex as a single, not a quad, with b a intermediary double
#define GETEX(a, b) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
b = sse_get_reg(dyn, ninst, x1, nextop&7,0);\
if(b<16) \
a = b; \
@@ -81,7 +81,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
@@ -121,7 +121,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
if(v0<16)
d0 = v0;
@@ -156,7 +156,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSLDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -173,7 +173,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVSHDUP Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -223,7 +223,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
@@ -268,7 +268,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
GETGD;
s0 = fpu_get_scratch_single(dyn);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v0<16)
d0 = v0;
@@ -420,7 +420,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0x5B:
INST_NAME("CVTTPS2DQ Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -523,7 +523,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVDQU Gx,Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
@@ -543,7 +543,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
SMREAD();
@@ -579,7 +579,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVQ Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVD(v0, v1);
@@ -596,7 +596,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
@@ -666,7 +666,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX_empty(v0);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VEORQ(v0, v0, v0); // usefull?
VMOV_64(v0, v1);
@@ -688,7 +688,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
if(v1<16)
v0 = v1;
+230 -38
View File
@@ -69,12 +69,24 @@ void arm_fxtract(x86emu_t* emu)
}
void arm_fprem(x86emu_t* emu)
{
int64_t tmp64s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)floor(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(floor((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
void arm_frndint(x86emu_t* emu)
{
@@ -176,6 +188,18 @@ void arm_ud(x86emu_t* emu)
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
}
void arm_priv(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
}
void arm_singlestep(x86emu_t* emu)
{
emu->test.test = 0;
emit_signal(emu, SIGTRAP, (void*)R_EIP, 2);
}
void arm_fsave(x86emu_t* emu, uint8_t* ed)
{
fpu_savenv(emu, (char*)ed, 0);
@@ -202,15 +226,185 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int64_t tmp64s = lrint(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
int e0, e1;
int64_t ll;
frexp(ST0.d, &e0);
frexp(ST1.d, &e1);
int32_t tmp32s = e0 - e1;
if(tmp32s<64)
{
ll = (int64_t)round(ST0.d/ST1.d);
ST0.d = ST0.d - (ST1.d*ll);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = (ll&1)?1:0;
emu->sw.f.F87_C3 = (ll&2)?1:0;
emu->sw.f.F87_C0 = (ll&4)?1:0;
} else {
ll = (int64_t)(trunc((ST0.d/ST1.d))/exp2(tmp32s - 32));
ST0.d = ST0.d - ST1.d*ll*exp2(tmp32s - 32);
emu->sw.f.F87_C2 = 1;
}
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void arm_aesimc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void arm_aesmc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void arm_aesdlast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
void arm_aeselast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void arm_aesd(x86emu_t* emu, int xmm)
{
arm_aesdlast(emu, xmm);
arm_aesimc(emu, xmm);
}
void arm_aese(x86emu_t* emu, int xmm)
{
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8)
{
sse_regs_t *EX = ((uintptr_t)p>8)?((sse_regs_t*)p):&emu->xmm[(uintptr_t)p];
sse_regs_t *GX = &emu->xmm[gx];
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8)
{
int ex = (((uintptr_t)p)<8)?((uintptr_t)p):-1;
sse_regs_t *EX = (ex==-1)?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
int g = (u8&1)?1:0;
int e = (u8&0b10000)?1:0;
uint64_t result[2] = {0};
uint64_t op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i)) {
result[0] ^= (EX->q[e]<<i);
if(i)
result[1] ^= (EX->q[e]>>(64-i));
}
GX->q[0] = result[0];
GX->q[1] = result[1];
}
void arm_clflush(x86emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
@@ -698,6 +892,12 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
}
return addr;
}
// return Ib on a mod/rm opcode without emiting anything
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
addr = fakeed(dyn, addr, ninst, nextop);
return F8;
}
#undef F8
#undef F32
@@ -747,35 +947,27 @@ static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
return 1;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending==SF_PENDING || dyn->insts[ninst].f_exit.pending==SF_SET_PENDING)
return 0;
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
return 0;
}
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int ret = 0;
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
+13
View File
@@ -23,12 +23,24 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
void arm_aesd(x86emu_t* emu, int xmm);
void arm_aese(x86emu_t* emu, int xmm);
void arm_aesdlast(x86emu_t* emu, int xmm);
void arm_aeselast(x86emu_t* emu, int xmm);
void arm_aesimc(x86emu_t* emu, int xmm);
void arm_aeskeygenassist(x86emu_t* emu, int gx, void* p, uint32_t u8);
void arm_pclmul(x86emu_t* emu, int gx, void* p, uint32_t u8);
void arm_clflush(x86emu_t* emu, void* p);
int64_t arm_fist64_0(double d);
int64_t arm_fist64_1(double d);
int64_t arm_fist64_2(double d);
int64_t arm_fist64_3(double d);
void arm_ud(x86emu_t* emu);
void arm_priv(x86emu_t* emu);
void arm_singlestep(x86emu_t* emu);
#define FPUFIRST 8
@@ -79,6 +91,7 @@ int getNominalPred(dynarec_arm_t* dyn, int ninst);
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
uint8_t geted_ib(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
+58 -11
View File
@@ -40,6 +40,9 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
if(hint>0 && hint<xEAX) scratch = hint;
if(hint==xEIP) scratch = hint; // allow this one as a scratch and return register
MAYUSE(scratch);
if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
@@ -177,8 +180,8 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
uint32_t m = nextop&0xC7;
uint32_t n = (m>>6)&3;
int32_t offset = 0;
if(!n && m==6) {
offset = F16;
if(!n && (m&7)==6) {
offset = F16S;
MOVW(ret, offset);
} else {
switch(n) {
@@ -1049,8 +1052,10 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
if(ret==-1) // nothing to do
return;
MESSAGE(LOG_DUMP, "\tForget x87 Cache for ST%d\n", st);
int reg = dyn->n.x87reg[ret];
#if STEP == 1
neoncache_promote_double(dyn, ninst, st);
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F)
neoncache_promote_double(dyn, ninst, st);
#endif
// prepare offset to fpu => s1
ADD_IMM8(s1, xEmu, offsetof(x86emu_t, x87));
@@ -1062,11 +1067,17 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
AND_IMM8(s2, s2, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(s2, s1, s2, 3); // fpu[(emu->top+i)&7] lsl 3 because fpu are double, so 8 bytes
VSTR_64(dyn->n.x87reg[ret], s2, 0); // save the value
if(dyn->n.neoncache[reg].t==NEON_CACHE_ST_F) {
// this should not happens
VCVT_F64_F32(0, reg*2); // use D0 as scratch...
VSTR_64(0, s2, 0);
} else {
VSTR_64(reg, s2, 0); // save the value
}
MESSAGE(LOG_DUMP, "\t--------Forget x87 Cache for ST%d\n", st);
// and forget that cache
fpu_free_reg_double(dyn, dyn->n.x87reg[ret]);
dyn->n.neoncache[dyn->n.x87reg[ret]].v = 0;
fpu_free_reg_double(dyn, reg);
dyn->n.neoncache[reg].v = 0;
dyn->n.x87cache[ret] = -1;
dyn->n.x87reg[ret] = -1;
}
@@ -1336,6 +1347,26 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
dyn->n.ssecache[a].write = 1; // it will be write...
return dyn->n.ssecache[a].reg;
}
// forget neon register for a SSE reg
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1)
{
if(dyn->n.ssecache[a].v==-1)
return;
if(dyn->n.neoncache[dyn->n.ssecache[a].reg+0-FPUFIRST].t == NEON_CACHE_XMMW) {
int offs = offsetof(x86emu_t, xmm[a]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
VST1Q_64(dyn->n.ssecache[a].reg, s1);
}
fpu_free_reg_quad(dyn, dyn->n.ssecache[a].reg);
dyn->n.ssecache[a].v = -1;
return;
}
// purge the SSE cache only(needs 1 scratch registers)
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
{
@@ -1394,6 +1425,24 @@ static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
}
}
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1)
{
if(dyn->n.ssecache[a].v==-1)
return 0;
if(dyn->n.ssecache[a].write) {
int offs = offsetof(x86emu_t, xmm[a]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
VST1Q_32(dyn->n.ssecache[a].reg, s1);
return 1;
}
return 0;
}
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
{
// only need to push 16-31...
@@ -1846,7 +1895,7 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = 0;
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)?1:0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
@@ -1864,12 +1913,10 @@ static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
else
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
else if(dyn->insts[jmp].f_entry.dfnone!=dyn->f.dfnone)
go = 1;
break;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
go = 1;
if(go) {
if(dyn->f.pending!=SF_PENDING) {
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
+63 -12
View File
@@ -27,29 +27,34 @@
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
#define MODREG ((nextop&0xC0)==0xC0)
// Strong mem emulation helpers
// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
// Squence of Write will trigger a DMB on "last" write if strongmem is 1
#define SMREAD_MIN 2
#define SMWRITE_MIN 1
// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
// Opcode will read
#define SMREAD() if(!dyn->smread && box86_dynarec_strongmem>1) {SMDMB();}
#define SMREAD() if((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
// Opcode will read with option forced lock
#define SMREADLOCK(lock) if(lock || (!dyn->smread && box86_dynarec_strongmem>1)) {SMDMB();}
// Opcode migh read (depend on nextop)
#define SMREADLOCK(lock) if((lock) || ((dyn->smread==0) && (box86_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
// Opcode might read (depend on nextop)
#define SMMIGHTREAD() if(!MODREG) {SMREAD();}
// Opcode has wrote
#define SMWRITE() dyn->smwrite=1
// Opcode has wrote (strongmem>1 only)
#define SMWRITE2() if(box86_dynarec_strongmem>1) dyn->smwrite=1
#define SMWRITE2() if(box86_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
// Opcode has wrote with option forced lock
#define SMWRITELOCK(lock) if(lock) {SMDMB();} else dyn->smwrite=1
// Opcode migh have wrote (depend on nextop)
#define SMWRITELOCK(lock) if(lock || (box86_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
// Opcode might have wrote (depend on nextop)
#define SMMIGHTWRITE() if(!MODREG) {SMWRITE();}
// Start of sequence
#define SMSTART() SMEND()
// End of sequence
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
#define SMEND() if(dyn->smwrite && box86_dynarec_strongmem) {if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1
#define SMDMB() if(box86_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
//LOCK_* define
#define LOCK_LOCK (int*)1
@@ -120,6 +125,8 @@
}
// GETGW extract x86 register in gd, that is i
#define GETGW(i) gd = xEAX+((nextop&0x38)>>3); UXTH(i, gd, 0); gd = i;
// GETSGW extract x86 signed register in gd, that is i
#define GETSGW(i) gd = xEAX+((nextop&0x38)>>3); SXTH(i, gd, 0); gd = i;
//GETEWW will use i for ed, and can use w for wback.
#define GETEWW(w, i) if((nextop&0xC0)==0xC0) { \
wback = xEAX+(nextop&7);\
@@ -335,7 +342,17 @@
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
#define SET_DF(S, N) \
if(N) { \
MOVW(S, N);\
STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); \
if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x86.need_after && !(dyn->insts[ninst].x86.need_after&X_PEND)) { \
CALL_(UpdateFlags, -1, 0); \
dyn->f.pending = SF_SET; \
SET_NODF(); \
} \
dyn->f.dfnone=0;\
} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
@@ -377,7 +394,7 @@
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
#define JUMP(A, C) SMEND()
#endif
#ifndef BARRIER
#define BARRIER(A)
@@ -512,10 +529,24 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define emit_shr32 STEPNAME(emit_shr32)
#define emit_shr32c STEPNAME(emit_shr32c)
#define emit_sar32c STEPNAME(emit_sar32c)
#define emit_shl8 STEPNAME(emit_shl8)
#define emit_shl8c STEPNAME(emit_shl8c)
#define emit_shr8 STEPNAME(emit_shr8)
#define emit_shr8c STEPNAME(emit_shr8c)
#define emit_sar8 STEPNAME(emit_sar8)
#define emit_sar8c STEPNAME(emit_sar8c)
#define emit_shl16 STEPNAME(emit_shl16)
#define emit_shl16c STEPNAME(emit_shl16c)
#define emit_shr16 STEPNAME(emit_shr16)
#define emit_shr16c STEPNAME(emit_shr16c)
#define emit_sar16 STEPNAME(emit_sar16)
#define emit_sar16c STEPNAME(emit_sar16c)
#define emit_rol32c STEPNAME(emit_rol32c)
#define emit_rol8c STEPNAME(emit_rol8c)
#define emit_ror32c STEPNAME(emit_ror32c)
#define emit_ror8c STEPNAME(emit_ror8c)
#define emit_rol16c STEPNAME(emit_rol16c)
#define emit_ror16c STEPNAME(emit_ror16c)
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
@@ -545,6 +576,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define sse_reflect_reg STEPNAME(sse_reflect_reg)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
@@ -648,10 +681,24 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_shr32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shr16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shr16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
@@ -740,6 +787,10 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// forget an SSE reg
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
// sync reg with emu for sse reg (return 1 if reflect was done, s1 = &xmm[a] then)
int sse_reflect_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
// common coproc helpers
// reset the cache
+25 -12
View File
@@ -187,21 +187,24 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
reset_n = -2;
for(int ii=0; ii<ninst; ++ii)
if(dyn->insts[ii].x86.jmp == next) {
reset_n = ii;
ii=ninst;
}
// and pred table is not ready yet
reset_n = get_first_jump(dyn, next);
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
} else if(next && (next-addr)<box86_dynarec_forward && (getProtection(next)&PROT_READ)/*box86_dynarec_bigblock>=stopblock*/) {
if(!((box86_dynarec_bigblock<stopblock) && !isJumpTableDefault((void*)next))) {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
if(dyn->forward) {
if(next<dyn->forward_to)
dyn->forward_to = next;
reset_n = -2;
ok = 1;
} else {
dyn->forward = addr;
dyn->forward_to = next;
dyn->forward_size = dyn->size;
dyn->forward_ninst = ninst;
reset_n = -2;
ok = 1;
}
}
}
}
@@ -217,6 +220,16 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->insts[ninst].x86.need_after |= X_PEND;
++ninst;
}
if(dyn->forward) {
// stopping too soon
dyn->size = dyn->forward_size;
ninst = dyn->forward_ninst+1;
addr = dyn->forward;
dyn->forward = 0;
dyn->forward_to = 0;
dyn->forward_size = 0;
dyn->forward_ninst = 0;
}
#endif
}
++ninst;
+3 -3
View File
@@ -16,13 +16,13 @@
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#define JUMP(A, C) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define JUMP(A, C) add_jump(dyn, ninst); add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_arm_t*)customRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
dyn->insts = (instruction_arm_t*)dynaRealloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2);\
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
@@ -40,7 +40,7 @@
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump || box86_dynarec_missing) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped @ %s (%s:%u) because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, __FUNCTION__, __FILE__, __LINE__, PKip(0), \
PKip(1), PKip(2), PKip(3), \
+5
View File
@@ -97,6 +97,9 @@ typedef struct dynarec_arm_s {
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
int* jmps; // variable array of jump instructions
int jmp_sz;
int jmp_cap;
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
@@ -112,6 +115,8 @@ typedef struct dynarec_arm_s {
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
void add_jump(dynarec_arm_t *dyn, int ninst);
int get_first_jump(dynarec_arm_t *dyn, int next);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
+13
View File
@@ -44,4 +44,17 @@ typedef struct instruction_x86_s {
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
//#define USE_CUSTOM_MEM
#ifdef USE_CUSTOM_MEM
#define dynaMalloc customMalloc
#define dynaCalloc customCalloc
#define dynaRealloc customRealloc
#define dynaFree customFree
#else
#define dynaMalloc box_malloc
#define dynaCalloc box_calloc
#define dynaRealloc box_realloc
#define dynaFree box_free
#endif
#endif //__DYNAREC_PRIVATE_H_
+3 -3
View File
@@ -233,9 +233,9 @@ NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 0 size 1 @<1> Rm @ param=1 char align[4
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 0 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> 1 1 1 1 @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 0 @<4> Rm @ set uint8_t temp = (2 << size) - 1@ set uint8_t temp2 = param & temp@ temp2=0=param>>1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 8 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ @ VLD1<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[4] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 0 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> 1 1 1 1 @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd 1 1 0 1 size @<1> @<1> Rm @ param2_1=1 char align[5] !@ %@ sprintf(align, ":%d", 16 << size)@ align[0] = '\0'@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[], \vecname[0x21 + param1_1 + d]\[]}, [<Rn>\align\], <Rm>
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 0 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]!
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> 1 1 1 1 @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\]
NEON 1 1 1 1 0 1 0 0 1 D 1 0 Rn Vd size 0 1 @<4> Rm @ size=0b00=0b01 uint8_t temp temp,1,1,3@ set uint8_t temp2 = param & temp@ temp2=0=1 char align[5] !@ %@ align[0] = '\0'@ sprintf(align, ":%d", 16 << size)@ sprintf(align, "???")@ set uint8_t x = param >> (size + 1)@ set int spacing = size ? ((param >> size) & 1) : 0@ @ VLD2<c>.\%d8 &l&l size\ {\vecname[0x20 + d]\[\%dx\], \vecname[0x21 + d + spacing]\[\%dx\]}, [<Rn>\align\], <Rm>
+3 -1
View File
@@ -45,7 +45,9 @@ const char* DumpSection(Elf32_Shdr *s, char* SST) {
GO(SHT_GNU_ATTRIBUTES);
GO(SHT_GNU_HASH);
GO(SHT_GNU_LIBLIST);
GO(SHT_CHECKSUM);
#ifndef TERMUX
GO(SHT_CHECKSUM);
#endif
GO(SHT_LOSUNW);
//GO(SHT_SUNW_move);
GO(SHT_SUNW_COMDAT);
+500 -364
View File
File diff suppressed because it is too large. Load diff
+28 -6
View File
@@ -8,9 +8,21 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
#include <elf.h>
#include "elfloader.h"
struct elfheader_s {
typedef struct multiblock_s {
void* p;
uintptr_t offs;
uintptr_t paddr;
uintptr_t align;
size_t size;
size_t asize;
uint8_t flags;
} multiblock_t;
typedef struct elfheader_s {
char* name;
char* path; // Resolved path to file
char* soname; // soname of the elf
uint16_t numPHEntries;
Elf32_Phdr *PHEntries;
uint16_t numSHEntries;
@@ -34,8 +46,10 @@ struct elfheader_s {
Elf32_Verdef* VerDef;
int szVerDef;
int e_type;
uint32_t flags;
intptr_t delta; // should be 0
void* image;
uintptr_t entrypoint;
uintptr_t initentry;
@@ -66,6 +80,9 @@ struct elfheader_s {
int textsz;
uintptr_t bss;
int bsssz;
uintptr_t ehframe;
uintptr_t ehframe_end;
uintptr_t ehframehdr;
uintptr_t paddr;
uintptr_t vaddr;
@@ -83,20 +100,25 @@ struct elfheader_s {
int init_done;
int fini_done;
int refcnt; // ref count for the elf
int malloc_hook_2; // this elf hook malloc, hacking it
char* memory; // char* and not void* to allow math on memory pointer
void** multiblock;
uintptr_t* multiblock_offs;
uint32_t* multiblock_size;
multiblock_t* multiblocks;
int multiblock_n;
library_t *lib;
needed_libs_t *neededlibs;
needed_libs_t *needed;
FILE* file;
int fileno;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
};
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
} elfheader_t;
#define R_386_NONE 0
#define R_386_32 1
+90 -2
View File
@@ -242,8 +242,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#ifndef ANDROID
if(val)
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
#endif
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
@@ -273,6 +275,10 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->VerDef = (Elf32_Verdef*)ptr;
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
case DT_FLAGS:
h->flags = val;
printf_dump(LOG_DEBUG, "The DT_FLAGS is 0x%x\n", h->flags);
break;
}
}
if(h->rel) {
@@ -351,6 +357,17 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->bsssz = h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame");
if(ii) {
h->ehframe = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->ehframe_end = h->ehframe + h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .eh_frame section is at address %p..%p\n", (void*)h->ehframe, (void*)h->ehframe_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".eh_frame_hdr");
if(ii) {
h->ehframehdr = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_dump(LOG_DEBUG, "The .eh_frame_hdr section is at address %p\n", (void*)h->ehframehdr);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
@@ -399,3 +416,74 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index)
}
return NULL;
}
int GetVersionIndice(elfheader_t* h, const char* vername)
{
if(!vername)
return 0;
if(h->VerDef) {
Elf32_Verdef *def = (Elf32_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
Elf32_Verdaux *aux = (Elf32_Verdaux*)((uintptr_t)def + def->vd_aux);
if(!strcmp(h->DynStr+aux->vda_name, vername))
return def->vd_ndx;
def = def->vd_next?((Elf32_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
}
return 0;
}
int GetNeededVersionCnt(elfheader_t* h, const char* libname)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname))
return ver->vn_cnt;
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return 0;
}
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx)
{
if(!libname)
return 0;
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
char *filename = h->DynStr + ver->vn_file;
Elf32_Vernaux *aux = (Elf32_Vernaux*)((uintptr_t)ver + ver->vn_aux);
if(!strcmp(filename, libname)) {
for(int j=0; j<ver->vn_cnt; ++j) {
if(j==idx)
return h->DynStr+aux->vna_name;
aux = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
return NULL; // idx out of bound, return NULL...
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
}
return NULL;
}
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver)
{
if(!libname || !ver)
return 0;
int n = GetNeededVersionCnt(h, libname);
if(!n)
return 0;
for(int i=0; i<n; ++i) {
const char* vername = GetNeededVersionString(h, libname, i);
if(vername && !strcmp(ver, vername))
return 1;
}
return 0;
}
+15 -14
View File
@@ -21,6 +21,7 @@
#endif
// ModRM utilities macros
#define MODREG ((nextop&0xC0)==0xC0)
#define getecommon(A, T) \
if(!(nextop&0xC0)) { \
if((nextop&7)==4) { \
@@ -107,7 +108,7 @@
case 7: base = R_BX; break; \
} \
switch((m>>6)&3) { \
case 0: if(m==6) base = F16; break; \
case 0: if(m&7==6) base = F16S; break; \
case 1: base += F8S; break; \
case 2: base += F16S; break; \
} \
@@ -116,11 +117,11 @@
#define geteb(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommon(A, reg32_t)
#define testeb(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else { \
reg32_t* ret; \
@@ -131,19 +132,19 @@
A = (reg32_t*)test->mem;\
}
#define getebo(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = (reg32_t*)&emu->regs[(nextop&3)].byte[((nextop&0x4)>>2)]; \
} else getecommono(A, reg32_t, O)
#define geted(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon(A, reg32_t)
#define getedo(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommono(A, reg32_t, O)
#define tested(A, SZ, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else {\
reg32_t* ret; \
@@ -154,11 +155,11 @@
A = (reg32_t*)test->mem;\
}
#define getem(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->mmx[(nextop&7)]; \
} else getecommon(A, mmx87_regs_t)
#define testem(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->mmx[(nextop&7)]; \
} else {\
mmx87_regs_t* ret; \
@@ -169,11 +170,11 @@
A = (mmx87_regs_t*)test->mem;\
}
#define getex(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->xmm[(nextop&7)]; \
} else getecommon(A, sse_regs_t)
#define testex(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->xmm[(nextop&7)]; \
} else {\
sse_regs_t* ret; \
@@ -184,15 +185,15 @@
A = (sse_regs_t*)test->mem;\
}
#define getew16(A) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16(A, reg32_t)
#define getew16o(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else getecommon16o(A, reg32_t, O)
#define testtew16(A, O) \
if((nextop&0xC0)==0xC0) { \
if(MODREG) { \
A = &emu->regs[(nextop&7)]; \
} else { \
reg32_t* ret; \
+120
View File
@@ -0,0 +1,120 @@
#include <stdint.h>
#include "box86stack.h"
#include "x86emu.h"
#include "x86run_private.h"
#include "x86emu_private.h"
#include "x86compstrings.h"
static int overrideIfDataInvalid(sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, int j, int i, int imm8)
{
int valid1 = (i<lreg);
int valid2 = (j<lmem);
if(!valid1 && !valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01: return 0;
case 0b10:
case 0b11: return 1;
}
if(!valid1 && valid2)
switch((imm8>>2)&3) {
case 0b00:
case 0b01:
case 0b10: return 0;
case 0b11: return 1;
}
if(valid1 && !valid2)
return 0;
switch((imm8>>2)&3) {
case 0b01: // range
switch (imm8&3) {
case 0b00: // ub
return (i&1)?((reg->ub[i]>=mem->ub[j])):((reg->ub[i]<=mem->ub[j]));
case 0b01: // uw
return (i&1)?((reg->uw[i]>=mem->uw[j])):((reg->uw[i]<=mem->uw[j]));
case 0b10: // sb
return (i&1)?((reg->sb[i]>=mem->sb[j])):((reg->sb[i]<=mem->sb[j]));
case 0b11: // sw
return (i&1)?((reg->sw[i]>=mem->sw[j])):((reg->sw[i]<=mem->sw[j]));
}
break;
default: // the others
switch (imm8&1) {
case 0: // byte
return (reg->ub[i] == mem->ub[j]);
case 1: // word
return (reg->uw[i] == mem->uw[j]);
}
}
}
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* mem, int lmem, sse_regs_t* reg, int lreg, uint8_t imm8)
{
// get number of packed byte/word
int n_packed = (imm8&1)?8:16;
if(lreg<0) lreg = -lreg;
if(lmem<0) lmem = -lmem;
if(lreg>n_packed) lreg = n_packed;
if(lmem>n_packed) lmem = n_packed;
// aggregate to intres1
uint32_t intres1 = 0;
switch((imm8>>2)&3) {
case 0b00: //Equal any
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8)<<j;
}
break;
case 0b01: // Range
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed; i+=2) {
intres1 |= (overrideIfDataInvalid(mem, lmem, reg, lreg, j, i, imm8) & overrideIfDataInvalid(mem, lmem, reg, lreg, j, i+1, imm8))<<j;
}
break;
case 0b10: // Equal each
for(int i=0; i<n_packed; ++i) {
intres1 |= overrideIfDataInvalid(mem, lmem, reg, lreg, i, i, imm8)<<i;
}
break;
case 0b11: // Equal ordered
intres1 = (1<<n_packed)-1;
for(int j=0; j<n_packed; ++j)
for(int i=0; i<n_packed-j; ++i) {
int k = i+j;
intres1 &= (((1<<n_packed)-1)^(1<<j)) | overrideIfDataInvalid(mem, lmem, reg, lreg, k, i, imm8)<<j;
}
break;
}
// build intres2
uint32_t intres2 = intres1;
switch((imm8>>4)&3) {
case 0b01: intres2 ^= ((1<<n_packed)-1); break;
case 0b11: intres2 ^= ((1<<lmem)-1); break;
}
// and now set the flags
RESET_FLAGS(emu);
CONDITIONAL_SET_FLAG(intres2, F_CF);
CONDITIONAL_SET_FLAG(lmem<n_packed, F_ZF);
CONDITIONAL_SET_FLAG(lreg<n_packed, F_SF);
CONDITIONAL_SET_FLAG(intres2&1, F_OF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_PF);
return intres2;
}
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* mem, sse_regs_t* reg, uint8_t imm8)
{
int lmem = 0;
int lreg = 0;
// get lmem and lreg
if(imm8&1) {
while(lmem<8 && mem->uw[lmem]) ++lmem;
while(lreg<8 && reg->uw[lreg]) ++lreg;
} else {
while(lmem<16 && mem->ub[lmem]) ++lmem;
while(lreg<16 && reg->ub[lreg]) ++lreg;
}
return sse42_compare_string_explicit_len(emu, mem, lmem, reg, lreg, imm8);
}
+13
View File
@@ -0,0 +1,13 @@
#ifndef __X86_CMPSTRINGS_H__
#define __X86_CMPSTRINGS_H__
#include <stdint.h>
#include "regs.h"
typedef struct x86emu_s x86emu_t;
uint32_t sse42_compare_string_explicit_len(x86emu_t* emu, sse_regs_t* a, int la, sse_regs_t* b, int lb, uint8_t imm8);
uint32_t sse42_compare_string_implicit_len(x86emu_t* emu, sse_regs_t* a, sse_regs_t* b, uint8_t imm8);
#endif //__X86_CMPSTRINGS_H__
+4 -6
View File
@@ -422,8 +422,6 @@ void UnimpOpcode(x86emu_t* emu)
tid, (void*)emu->old_ip, Peek(emu, -1),
Peek(emu, 0), Peek(emu, 1), Peek(emu, 2), Peek(emu, 3),
Peek(emu, 4), Peek(emu, 5), Peek(emu, 6), Peek(emu, 7));
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
void EmuCall(x86emu_t* emu, uintptr_t addr)
@@ -440,9 +438,9 @@ void EmuCall(x86emu_t* emu, uintptr_t addr)
Run(emu, 0);
emu->quit = 0; // reset Quit flags...
emu->df = d_none;
if(emu->quitonlongjmp && emu->longjmp) {
if(emu->quitonlongjmp==1)
emu->longjmp = 0; // don't change anything because of the longjmp
if(emu->flags.quitonlongjmp && emu->flags.longjmp) {
if(emu->flags.quitonlongjmp==1)
emu->flags.longjmp = 0; // don't change anything because of the longjmp
} else {
R_EBX = old_ebx;
R_EDI = old_edi;
@@ -501,8 +499,8 @@ uint64_t ReadTSC(x86emu_t* emu)
uint64_t ret;
__asm__ volatile("rdtsc" : "=A"(ret));
return ret;
#if 0
#elif defined(__ARM_ARCH)
#if 0
#if (__ARM_ARCH >= 6)
static int init = 1;
if(init) {
+20 -4
View File
@@ -34,6 +34,21 @@ typedef struct x86test_s {
uint8_t mem[16];
} x86test_t;
typedef struct emu_flags_s {
uint32_t need_jmpbuf:1; // need a new jmpbuff for signal handling
uint32_t quitonlongjmp:2; // quit if longjmp is called
uint32_t quitonexit:2; // quit if exit/_exit is called
uint32_t longjmp:1; // if quit because of longjmp
uint32_t jmpbuf_ready:1; // the jmpbuf in the emu is ok and don't need refresh
} emu_flags_t;
#ifdef ANDROID
#include <setjmp.h>
#define JUMPBUFF sigjmp_buf
#else
#define JUMPBUFF struct __jmp_buf_tag
#endif
typedef struct x86emu_s {
// cpu
reg32_t regs[8];
@@ -63,17 +78,17 @@ typedef struct x86emu_s {
uintptr_t prev2_ip, prev_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uint16_t segs[6];
uint16_t dummy_seg6, dummy_seg7; // to stay aligned
uintptr_t segs_offs[6]; // computed offset associate with segment
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// emu control
int quit;
int error;
int fork; // quit because need to fork
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int longjmp; // if quit because of longjmp
forkpty_t* forkpty_info;
emu_flags_t flags;
x86test_t test; // used for dynarec testing
// parent context
box86context_t *context;
@@ -86,6 +101,7 @@ typedef struct x86emu_s {
void* stack2free; // this is the stack to free (can be NULL)
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
JUMPBUFF* jmpbuf;
i386_ucontext_t *uc_link; // to handle setcontext
+3 -3
View File
@@ -67,7 +67,7 @@ x86emu_t* x86emu_fork(x86emu_t* emu, int forktype)
R_EAX = v;
return emu;
}
void emit_signal(x86emu_t* emu, int sig, void* addr, int code); // in signals.c
extern int errno;
void x86Int3(x86emu_t* emu)
{
@@ -350,8 +350,8 @@ void x86Int3(x86emu_t* emu)
}
return;
}
if(0 && my_context->signals[SIGTRAP])
raise(SIGTRAP);
if(1 && my_context->signals[SIGTRAP])
emit_signal(emu, SIGTRAP, (void*)R_EIP, 128);
else
printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_EIP);
//emu->quit = 1;
+19 -29
View File
@@ -484,10 +484,8 @@ uint8_t rcl8(x86emu_t *emu, uint8_t d, uint8_t s)
CONDITIONAL_SET_FLAG(cf, F_CF);
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized this expression since it appears to
be causing OF to be misset */
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 7)) & 0x1, F_OF);
}
return (uint8_t)res;
@@ -513,8 +511,8 @@ uint16_t rcl16(x86emu_t *emu, uint16_t d, uint8_t s)
res |= 1 << (cnt - 1);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 15)) & 0x1, F_OF);
}
return (uint16_t)res;
}
@@ -539,8 +537,8 @@ uint32_t rcl32(x86emu_t *emu, uint32_t d, uint8_t s)
res |= 1 << (cnt - 1);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
F_OF);
if(cnt == 1)
CONDITIONAL_SET_FLAG((cf ^ (res >> 31)) & 0x1, F_OF);
}
return res;
}
@@ -592,6 +590,11 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
(i.e. packed bit array or unpacked.)
*/
ocf = ACCESS_FLAG(F_CF) != 0;
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized... */
CONDITIONAL_SET_FLAG((ocf ^ (d >> 7)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
@@ -620,13 +623,6 @@ uint8_t rcr8(x86emu_t *emu, uint8_t d, uint8_t s)
}
/* set the new carry flag, based on the variable "cf" */
CONDITIONAL_SET_FLAG(cf, F_CF);
/* OVERFLOW is set *IFF* cnt==1, then it is the
xor of CF and the most significant bit. Blecck. */
/* parenthesized... */
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
F_OF);
}
}
return (uint8_t)res;
}
@@ -648,6 +644,8 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
if (cnt == 1) {
cf = d & 0x1;
ocf = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG((ocf ^ (d >> 15)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
mask = (1 << (16 - cnt)) - 1;
@@ -657,10 +655,6 @@ uint16_t rcr16(x86emu_t *emu, uint16_t d, uint8_t s)
res |= 1 << (16 - cnt);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
F_OF);
}
}
return (uint16_t)res;
}
@@ -682,6 +676,8 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
if (cnt == 1) {
cf = d & 0x1;
ocf = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG((ocf ^ (d >> 31)) & 0x1,
F_OF);
} else
cf = (d >> (cnt - 1)) & 0x1;
mask = (1 << (32 - cnt)) - 1;
@@ -692,10 +688,6 @@ uint32_t rcr32(x86emu_t *emu, uint32_t d, uint8_t s)
res |= 1 << (32 - cnt);
}
CONDITIONAL_SET_FLAG(cf, F_CF);
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
F_OF);
}
}
return res;
}
@@ -885,8 +877,7 @@ uint16_t shld16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
(ACCESS_FLAG(F_CF) != 0)), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -927,8 +918,7 @@ uint32_t shld32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
(ACCESS_FLAG(F_CF) != 0)), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -959,7 +949,7 @@ uint16_t shrd16 (x86emu_t *emu, uint16_t d, uint16_t fill, uint8_t s)
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 15)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
@@ -1005,7 +995,7 @@ uint32_t shrd32 (x86emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
res = d;
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
CONDITIONAL_SET_FLAG(((res ^ d) >> 31)&1, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
+89 -78
View File
@@ -65,10 +65,12 @@ int Run(x86emu_t *emu, int step)
if(emu->quit)
return 0;
if(addr==0) {
emu->quit = 1;
printf_log(LOG_INFO, "%04d|Ask to run at NULL, quit silently\n", GetTID());
print_cycle_log(LOG_INFO);
return 0;
// emu->quit = 1;
// printf_log(LOG_INFO, "%04d|Ask to run at NULL, quit silently\n", GetTID());
// print_cycle_log(LOG_INFO);
// return 0;
// Some program, like C# Vara.exe, need to trigger that segfault to actually run... (ticket #830à)
printf_log(LOG_INFO, "%04d|Ask to run at NULL, will segfault\n", GetTID());
}
//ref opcode: http://ref.x64asm.net/geek32.html#xA1
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)addr, (void*)R_ESP);
@@ -91,12 +93,14 @@ x86emurun:
opcode = F8;
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
while((opcode==0xF2) || (opcode==0xF3) || (opcode==0x3E)) {
switch (opcode) {
case 0xF2: rep = 1; break;
case 0xF3: rep = 2; break;
case 0x3E: /* ignored*/ break;
}
opcode = F8;
}
while((opcode==0x3E)) //Branch Taken Hint ignored
opcode = F8;
switch(opcode) {
@@ -421,46 +425,14 @@ x86emurun:
GD.dword[0] = imul32(emu, ED->dword[0], (uint32_t)tmp32s);
break;
case 0x6C: /* INSB */
tmp32u = rep?R_ECX:1;
while(tmp32u--) {
*(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;
}
if(rep)
R_ECX = 0;
break;
case 0x6D: /* INSD */
tmp32u = rep?R_ECX:1;
while(tmp32u--) {
*(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;
}
if(rep)
R_ECX = 0;
break;
case 0x6E: /* OUTSB */
// faking port write, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_ESI-=rep?R_ECX:1;
else
R_ESI+=1?R_ECX:1;
if(rep)
R_ECX = 0;
break;
case 0x6F: /* OUTSD */
// faking port write, using explicit ES segment
if(ACCESS_FLAG(F_DF))
R_ESI-=(rep?R_ECX:1)*4;
else
R_ESI+=(rep?R_ECX:1)*4;
if(rep)
R_ECX = 0;
#ifndef TEST_INTERPRETER
// this is a privilege opcode
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
@@ -598,7 +570,7 @@ x86emurun:
nextop = F8;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
GET_EB;
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
if(MODREG) { // reg / reg: no lock
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
@@ -624,7 +596,7 @@ x86emurun:
nextop = F8;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
GET_ED;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
@@ -674,7 +646,7 @@ x86emurun:
case 0x8C: /* MOV Ed, Seg */
nextop = F8;
GET_ED;
if((nextop&0xC0)==0xC0)
if(MODREG)
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
else
ED->word[0] = emu->segs[((nextop&0x38)>>3)];
@@ -694,7 +666,7 @@ x86emurun:
break;
case 0x8F: /* POP Ed */
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
emu->regs[(nextop&7)].dword[0] = Pop(emu);
} else {
tmp32u = Pop(emu); // this order allows handling POP [ESP] and variant
@@ -866,6 +838,7 @@ x86emurun:
}
if(R_ECX) cmp32(emu, tmp32u2, tmp32u3);
R_ECX = tmp32u;
break;
case 2:
tmp32u2 = 0;
tmp32u3 = 0;
@@ -881,6 +854,7 @@ x86emurun:
}
if(R_ECX) cmp32(emu, tmp32u2, tmp32u3);
R_ECX = tmp32u;
break;
}
break;
case 0xA8: /* TEST AL, Ib */
@@ -1063,6 +1037,12 @@ x86emurun:
break;
case 0xC4: /* LES Gd,Ed */
nextop = F8;
if(MODREG) {
UnimpOpcode(emu);
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
GET_ED;
emu->segs[_ES] = *(__uint16_t*)(((char*)ED)+4);
emu->segs_serial[_ES] = 0;
@@ -1070,6 +1050,12 @@ x86emurun:
break;
case 0xC5: /* LDS Gd,Ed */
nextop = F8;
if(MODREG) {
UnimpOpcode(emu);
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
GET_ED;
emu->segs[_DS] = *(__uint16_t*)(((char*)ED)+4);
emu->segs_serial[_DS] = 0;
@@ -1137,7 +1123,7 @@ x86emurun:
printf_log(LOG_DEBUG, "INT 2D called\n");
} else {
#ifndef TEST_INTERPRETER
emit_signal(emu, SIGSEGV, (void*)R_EIP, 0);
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
if(emu->quit) goto fini;
STEP;
#endif
@@ -1147,8 +1133,9 @@ x86emurun:
case 0xCE: /* INTO */
emu->old_ip = R_EIP;
#ifndef TEST_INTERPRETER
emit_signal(emu, SIGFPE, (void*)R_EIP, FPE_INTOVF);
if(emu->quit) goto fini;
CHECK_FLAGS(emu);
if(ACCESS_FLAG(F_OF))
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
@@ -1355,30 +1342,26 @@ x86emurun:
STEP2;
break;
case 0xE4: /* IN AL, Ib */
tmp32s = F8; // port address
R_AL = 0; // nothing... should do a warning maybe?
break;
case 0xE5: /* IN EAX, Ib */
tmp32s = F8; // port address
R_EAX = 0; // nothing... should do a warning maybe?
break;
case 0xE6: /* OUT Ib, AL */
tmp32s = F8; // port address
//nothing goes out...
break;
case 0xE7: /* OUT Ib, EAX */
tmp32s = F8; // port address
//nothing goes out...
#ifndef TEST_INTERPRETER
// this is a privilege opcode
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, addr);
addr += tmp32s;
addr = (uintptr_t)getAlternate((void*)addr);
STEP2;
break;
case 0xE9: /* JMP Id */
tmp32s = F32S; // jmp is relative
addr += tmp32s;
addr = (uintptr_t)getAlternate((void*)addr);
STEP2;
break;
@@ -1388,13 +1371,14 @@ x86emurun:
STEP2;
break;
case 0xEC: /* IN AL, DX */
R_AL = 0; // nothing... should do a warning maybe?
break;
case 0xED: /* IN EAX, DX */
R_EAX = 0; // nothing... should do a warning maybe?
break;
case 0xEE: /* OUT DX, AL */
//nothing goes out...
case 0xEF: /* OUT DX, EAX */
#ifndef TEST_INTERPRETER
// this is a privilege opcode
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
case 0xF0: /* LOCK */
@@ -1417,10 +1401,10 @@ x86emurun:
break;
case 0xF4: /* HLT */
// this is a privilege opcode... should an error be called instead?
#ifndef TEST_INTERPRETER
sched_yield();
STEP2;
// this is a privilege opcode
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
case 0xF5: /* CMC */
@@ -1450,9 +1434,13 @@ x86emurun:
imul8(emu, EB->byte[0]);
break;
case 6: /* DIV Eb */
if(!EB->byte[0])
emit_div0(emu, (void*)R_EIP, 0);
div8(emu, EB->byte[0]);
break;
case 7: /* IDIV Eb */
if(!EB->byte[0])
emit_div0(emu, (void*)R_EIP, 0);
idiv8(emu, EB->byte[0]);
break;
}
@@ -1479,9 +1467,13 @@ x86emurun:
imul32_eax(emu, ED->dword[0]);
break;
case 6: /* DIV Ed */
if(!ED->dword[0])
emit_div0(emu, (void*)R_EIP, 0);
div32(emu, ED->dword[0]);
break;
case 7: /* IDIV Ed */
if(!ED->dword[0])
emit_div0(emu, (void*)R_EIP, 0);
idiv32(emu, ED->dword[0]);
break;
}
@@ -1496,10 +1488,12 @@ x86emurun:
SET_FLAG(F_CF);
break;
case 0xFA: /* CLI */
CLEAR_FLAG(F_IF); //not really handled...
break;
case 0xFB: /* STI */
SET_FLAG(F_IF);
#ifndef TEST_INTERPRETER
// this is a privilege opcode
emit_signal(emu, SIGSEGV, (void*)R_EIP, 128);
STEP;
#endif
break;
case 0xFC: /* CLD */
CLEAR_FLAG(F_DF);
@@ -1553,7 +1547,7 @@ x86emurun:
GET_ED_;
Push(emu, R_CS);
Push(emu, addr);
addr = ED->dword[0];
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
R_CS = (ED+1)->word[0];
goto fini; // in case there is a change of CS
}
@@ -1573,7 +1567,7 @@ x86emurun:
goto fini;
} else {
GET_ED_;
addr = ED->dword[0];
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
R_CS = (ED+1)->word[0];
STEP2;
}
@@ -1597,15 +1591,32 @@ x86emurun:
unimp = 1;
goto fini;
}
#ifndef TEST_INTERPRETER
if(ACCESS_FLAG(F_TF)) {
R_EIP = addr;
emit_signal(emu, SIGTRAP, (void*)addr, 1);
if(emu->quit) goto fini;
}
#endif
R_EIP = addr;
}
fini:
#ifndef TEST_INTERPRETER
// check the TRACE flag before going to out, in case it's a step by step scenario
if(!emu->quit && !emu->fork && !emu->uc_link && ACCESS_FLAG(F_TF)) {
R_EIP = addr;
emit_signal(emu, SIGTRAP, (void*)addr, 1);
if(emu->quit) goto fini;
}
#endif
#ifndef TEST_INTERPRETER
printf_log(LOG_DEBUG, "End of X86 run (%p), RIP=%p, Stack=%p, unimp=%d, emu->fork=%d, emu->uc_link=%p, emu->quit=%d\n", emu, (void*)R_EIP, (void*)R_ESP, unimp, emu->fork, emu->uc_link, emu->quit);
if(unimp) {
emu->quit = 1;
UnimpOpcode(emu);
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
emu->quit=1;
emu->error |= ERR_UNIMPL;
}
// fork handling
if(emu->fork) {
@@ -1619,7 +1630,7 @@ fini:
goto x86emurun;
}
// setcontext handling
else if(emu->uc_link) {
else if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
addr = R_EIP;
+19 -7
View File
@@ -23,6 +23,7 @@
#include "signals.h"
#ifdef DYNAREC
#include "../dynarec/arm_lock_helper.h"
#include "custommem.h"
#endif
#include "modrm.h"
@@ -52,6 +53,10 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
#ifdef TEST_INTERPRETER
x86emu_t *emu = test->emu;
#endif
#ifdef TERMUX
extern int isinff(float);
extern int isnanf(float);
#endif
opcode = F8;
@@ -63,13 +68,13 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
case 0: /* SLDT Ew */
GET_EW;
EW->word[0] = 0;
if((nextop&0xC0)==0xC0)
if(MODREG)
EW->word[1] = 0;
break;
case 1: /* STR Ew */
GET_EW;
EW->word[0] = 0x7f; // dummy return
if((nextop&0xC0)==0xC0)
if(MODREG)
EW->word[1] = 0;
break;
case 4: //VERR
@@ -144,7 +149,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
case 0x12:
nextop = F8;
GET_EX;
if((nextop&0xC0)==0xC0) /* MOVHLPS Gx,Ex */
if(MODREG) /* MOVHLPS Gx,Ex */
GX.q[0] = EX->q[1];
else
GX.q[0] = EX->q[0]; /* MOVLPS Gx,Ex */
@@ -182,7 +187,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
case 0x18: /* PREFETCHh Ed */
nextop = F8;
GET_ED_;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
} else
switch((nextop>>3)&7) {
case 0: //PREFETCHnta
@@ -1059,6 +1064,13 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
applyFlushTo0(emu);
#endif
break;
case 7: /* CLFLUSH Ed */
GET_ED_(0);
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
if(box86_dynarec)
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
#endif
break;
default:
return 0;
}
@@ -1376,7 +1388,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
case 0xD7: /* PMOVMSKB Gd,Em */
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GET_EM;
GD.dword[0] = 0;
for (int i=0; i<8; ++i)
@@ -1492,7 +1504,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
case 0xE7: /* MOVNTQ Em,Gm */
nextop = F8;
if((nextop&0xC0)==0xC0)
if(MODREG)
return 0;
GET_EM;
EM->q = GM.q;
@@ -1605,7 +1617,7 @@ uintptr_t Run0F(x86emu_t *emu, uintptr_t addr, int *step)
break;
case 0xF7: /* MASKMOVQ Gm, Em */
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GET_EM;
for (int i=0; i<8; ++i)
if(EM->ub[i]&0x80) ((uint8_t*)(R_EDI))[i] = GM.ub[i];
+25 -9
View File
@@ -75,7 +75,12 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
GD.dword[0] = adc32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x21: /* AND Ed,Gd */
case 0x20: /* AND Seg:Eb,Gb */
nextop = F8;
GET_EB_OFFS(tlsdata);
EB->byte[0] = and8(emu, EB->byte[0], GB);
break;
case 0x21: /* AND Seg:Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
ED->dword[0] = and32(emu, ED->dword[0], GD.dword[0]);
@@ -165,13 +170,18 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
return addr-1;
case 0x64: /* FS: */
// so just ignore that GS: prefix then
#ifdef TEST_INTERPRETER
return Test64(test, _FS, addr-1); // put FS back
#else
return Run64(emu, _FS, addr-1); // put FS back
#endif
case 0x65: /* GS: */
#ifdef TEST_INTERPRETER
return Test64(test, _GS, addr);
#else
return Run64(emu, _GS, addr);
#endif
break;
case 0x66:
#ifdef TEST_INTERPRETER
return Test6466(test, tlsdata, addr);
@@ -250,7 +260,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
nextop = F8;
#if defined(DYNAREC) && !defined(TEST_INTERPRETER)
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)==0xC0) {
if(MODREG) {
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
@@ -268,16 +278,20 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
}
#else
GET_ED_OFFS(tlsdata);
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
tmp32u = GD.dword[0];
GD.dword[0] = ED->dword[0];
ED->dword[0] = tmp32u;
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x88: /* MOV Seg:Eb,Gb */
nextop = F8;
GET_EB_OFFS(tlsdata);
EB->byte[0] = GB;
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
@@ -309,6 +323,8 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
GET_ED_OFFS(tlsdata);
ED->dword[0] = Pop(emu);
break;
case 0x90: /* NOP */
break;
case 0x9C: /* PUSHFD */
// Segment override if for memory loc, no stack segment
@@ -424,7 +440,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
} else {
Push16(emu, R_CS);
Push(emu, addr);
addr = ED->dword[0];
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
R_CS = (ED+1)->word[0];
}
break;
@@ -438,7 +454,7 @@ uintptr_t Run64(x86emu_t *emu, int seg, uintptr_t addr)
emu->error |= ERR_ILLEGAL;
return 0;
} else {
addr = ED->dword[0];
addr = (uintptr_t)getAlternate((void*)ED->dword[0]);
R_CS = (ED+1)->word[0];
}
break;
+15 -5
View File
@@ -99,11 +99,21 @@ uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr)
break;
case 0x0F: /* 66 0f prefix */
#ifdef TEST_INTERPRETER
return Test660F(test, addr);
#else
return Run660F(emu, addr);
#endif
switch(rep) {
case 2: return 0;
case 1:
#ifdef TEST_INTERPRETER
return Test66F20F(test, addr);
#else
return Run66F20F(emu, addr);
#endif
default:
#ifdef TEST_INTERPRETER
return Test660F(test, addr);
#else
return Run660F(emu, addr);
#endif
}
case 0x1E: /* PUSH DS */
Push16(emu, emu->segs[_DS]);
+477 -7
View File
@@ -15,6 +15,28 @@
#include "box86context.h"
#include "modrm.h"
#include "x86compstrings.h"
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
#ifdef TEST_INTERPRETER
uintptr_t Test660F(x86test_t *test, uintptr_t addr)
@@ -33,14 +55,63 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
int32_t tmp32s;
sse_regs_t *opex, eax1, *opx2;
mmx87_regs_t *opem;
float tmpf;
double tmpd;
#ifndef NOALIGN
int is_nan;
#endif
// AES opcodes constants
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
#ifdef TERMUX
extern int isinff(float);
extern int isnanf(float);
#endif
opcode = F8;
switch(opcode) {
@@ -403,6 +474,15 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
}
break;
case 0x10: /* PBLENDVB Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<16; ++i) {
if(emu->xmm[0].ub[i]&0x80)
GX.ub[i] = EX->ub[i];
}
break;
case 0x14: /* BLENDVPS Gx, Ex */
nextop = F8;
GET_EX;
@@ -411,6 +491,14 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.ud[i] = EX->ud[i];
}
break;
case 0x15: /* BLENDVPD Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<2; ++i) {
if(emu->xmm[0].q[i]&0x8000000000000000LL)
GX.q[i] = EX->q[i];
}
break;
case 0x17: // PTEST GX, EX
nextop = F8;
@@ -418,6 +506,10 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!((GX.q[0]&EX->q[0])|(GX.q[1]&EX->q[1])), F_ZF);
CONDITIONAL_SET_FLAG(!(((~GX.q[0])&EX->q[0])|((~GX.q[1])&EX->q[1])), F_CF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
CLEAR_FLAG(F_PF);
break;
case 0x1C: /* PABSB Gx, Ex */
@@ -479,6 +571,36 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.sq[i] = EX->sd[i];
break;
case 0x28: /* PMULDQ Gx, Ex */
nextop = F8;
GET_EX;
GX.sq[1] = ((int64_t)GX.sd[2])*(int64_t)EX->sd[2];
GX.sq[0] = ((int64_t)GX.sd[0])*(int64_t)EX->sd[0];
break;
case 0x29: /* PCMPEQQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = (GX.sq[i]==EX->sq[i])?-1LL:0LL;
break;
case 0x2A: /* MOVNTDQA Gx, Ex */
nextop = F8;
GET_EX;
GX.q[0] = EX->q[0];
GX.q[1] = EX->q[1];
break;
case 0x2B: /* PACKUSDW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
GX.uw[i] = (GX.sd[i]<0)?0:((GX.sd[i]>65535)?65535:GX.sd[i]);
if(&GX==EX)
GX.q[1] = GX.q[0];
else
for(int i=0; i<4; ++i)
GX.uw[i+4] = (EX->sd[i]<0)?0:((EX->sd[i]>65535)?65535:EX->sd[i]);
break;
case 0x30: /* PMOVZXBW Gx, Ex */
nextop = F8;
GET_EX;
@@ -516,6 +638,19 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.q[i] = EX->ud[i];
break;
case 0x37: /* PCMPGTQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = (GX.sq[i]>EX->sq[i])?-1LL:0LL;
break;
case 0x38: /* PMINSB Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
if(GX.sb[i]>EX->sb[i])
GX.sb[i] = EX->sb[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GET_EX;
@@ -523,7 +658,27 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
if(GX.sd[i]>EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
case 0x3A: /* PMINUW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
if(GX.uw[i]>EX->uw[i])
GX.uw[i] = EX->uw[i];
break;
case 0x3B: /* PMINUD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.ud[i]>EX->ud[i])
GX.ud[i] = EX->ud[i];
break;
case 0x3C: /* PMAXSB Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<16; ++i)
if(GX.sb[i]<EX->sb[i])
GX.sb[i] = EX->sb[i];
break;
case 0x3D: /* PMAXSD Gx, Ex */
nextop = F8;
GET_EX;
@@ -531,7 +686,20 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
if(GX.sd[i]<EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
case 0x3E: /* PMAXUW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<8; ++i)
if(GX.uw[i]<EX->uw[i])
GX.uw[i] = EX->uw[i];
break;
case 0x3F: /* PMAXUD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.ud[i]<EX->ud[i])
GX.ud[i] = EX->ud[i];
break;
case 0x40: /* PMULLD Gx, Ex */
nextop = F8;
GET_EX;
@@ -539,13 +707,136 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.sd[i] *= EX->sd[i];
}
break;
case 0x41: /* PHMINPOSUW Gx, Ex */
nextop = F8;
GET_EX;
tmp16u = EX->uw[0];
tmp16s = 0;
for(int i=1; i<8; ++i) {
if(EX->uw[i]<tmp16u) {
tmp16u = EX->uw[i];
tmp16s = i;
}
}
GX.q[1] = 0;
GX.uw[0] = tmp16u;
GX.uw[1] = tmp16s;
GX.ud[1] = 0;
break;
case 0xDB: /* AESIMC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← InvMixColumns( STATE );
if (EX == &GX) {
for(int i=0; i<16; ++i)
eax1.ub[i] = EX->ub[i];
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
} else {
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
}
}
break;
case 0xDC: /* AESENC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = subbytes[eax1.ub[i]];
//STATE ← MixColumns( STATE );
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
GX.ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
GX.ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDD: /* AESENCLAST Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
GX.ub[i] = subbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDE: /* AESDEC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = invsubbytes[eax1.ub[i]];
//STATE ← InvMixColumns( STATE );
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDF: /* AESDECLAST Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
GX.ub[i] = invsubbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xF0: /* MOVBE Gw, Ew */
nextop = F8;
GET_ED;
GD.word[0] = __builtin_bswap16(ED->word[0]);
break;
case 0xF1: /* MOVBE Ew, Gw */
nextop = F8;
GET_ED;
ED->word[0] = __builtin_bswap16(GD.word[0]);
break;
default:
return 0;
}
break;
case 0x3A: // these are some SSE3 opcodes
case 0x3A: // these are some SSE3 & SSE4.x opcodes
opcode = F8;
switch(opcode) {
case 0x08: // roundps GX, EX, u8
@@ -644,7 +935,24 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
break;
}
break;
case 0x0C: /* PBLENDPS Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
for (int i=0; i<4; ++i) {
if(tmp8u&(1<<i))
GX.ud[i] = EX->ud[i];
}
break;
case 0x0D: /* PBLENDPD Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
for (int i=0; i<2; ++i) {
if(tmp8u&(1<<i))
GX.q[i] = EX->q[i];
}
break;
case 0x0E: /* PBLENDW Gx, Ex, Ib */
nextop = F8;
GET_EX;
@@ -669,12 +977,36 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
}
break;
case 0x14: // PEXTRB ED, GX, u8
nextop = F8;
GET_ED;
tmp8u = F8;
if(MODREG)
ED->dword[0] = GX.ub[tmp8u&0x0f];
else
ED->byte[0] = GX.ub[tmp8u&0x0f];
break;
case 0x15: // PEXTRW Ew,Gx,Ib
nextop = F8;
GET_ED;
tmp8u = F8;
if(MODREG)
ED->dword[0] = GX.uw[tmp8u&7]; // 16bits extract, 0 extended
else
ED->word[0] = GX.uw[tmp8u&7];
break;
case 0x16: // PEXTRD ED, GX, u8
nextop = F8;
GET_ED;
tmp8u = F8;
ED->dword[0] = GX.ud[tmp8u&3];
break;
case 0x17: // EXTRACTPS ED, GX, u8
nextop = F8;
GET_ED;
tmp8u = F8;
ED->dword[0] = GX.ud[tmp8u&3];
break;
case 0x20: // PINSRB GX, Ed, Ib
nextop = F8;
@@ -686,7 +1018,7 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
nextop = F8;
GET_EX;
tmp8u = F8;
if((nextop&0xC0)==0xC0) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
GX.ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
for(int i=0; i<4; ++i)
if(tmp8u&(1<<i))
@@ -699,6 +1031,144 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.ud[tmp8u&0x3] = ED->dword[0];
break;
case 0x40: /* DPPS Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
tmpf = 0.0f;
for(int i=0; i<4; ++i)
if(tmp8u&(1<<(i+4)))
tmpf += GX.f[i]*EX->f[i];
for(int i=0; i<4; ++i)
GX.f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
break;
case 0x41: /* DPPD Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
tmpd = 0.0;
if(tmp8u&(1<<(4+0)))
tmpd += GX.d[0]*EX->d[0];
if(tmp8u&(1<<(4+1)))
tmpd += GX.d[1]*EX->d[1];
GX.d[0] = (tmp8u&(1<<(0)))?tmpd:0.0;
GX.d[1] = (tmp8u&(1<<(1)))?tmpd:0.0;
break;
case 0x42: /* MPSADBW Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
{
int src = tmp8u&3;
int dst = (tmp8u>>2)&1;
int b[11];
for (int i=0; i<11; ++i)
b[i] = GX.ub[dst*4+i];
for(int i=0; i<8; ++i) {
int tmp = abs(b[i+0]-EX->ub[src*4+0]);
tmp += abs(b[i+1]-EX->ub[src*4+1]);
tmp += abs(b[i+2]-EX->ub[src*4+2]);
tmp += abs(b[i+3]-EX->ub[src*4+3]);
GX.uw[i] = tmp;
}
}
break;
case 0x44: /* PCLMULQDQ Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
{
int g = (tmp8u&1)?1:0;
int e = (tmp8u&0b10000)?1:0;
uint64_t result[2] = { 0 };
for (int i=0; i<64; ++i)
if(GX.q[g]&(1LL<<i)) {
result[0] ^= (EX->q[e]<<i);
if(i)
result[1] ^= (EX->q[e]>>(64-i));
}
GX.q[0] = result[0];
GX.q[1] = result[1];
}
break;
case 0x60: /* PCMPESTRM */
nextop = F8;
GET_EX;
tmp8u = F8;
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
GX.q[1] = GX.q[0] = 0;
GX.uw[0] = tmp32u;
}
break;
case 0x61: /* PCMPESTRI */
nextop = F8;
GET_EX;
tmp8u = F8;
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, &GX, R_EAX, tmp8u);
if(!tmp32u)
R_ECX = (tmp8u&1)?8:16;
else if(tmp8u&0b1000000)
R_ECX = 31-__builtin_clz(tmp32u);
else
R_ECX = __builtin_ffs(tmp32u) - 1;
break;
case 0x62: /* PCMPISTRM */
nextop = F8;
GET_EX;
tmp8u = F8;
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) GX.ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) GX.uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
GX.q[1] = GX.q[0] = 0;
GX.uw[0] = tmp32u;
}
break;
case 0x63: /* PCMPISTRI */
nextop = F8;
GET_EX;
tmp8u = F8;
tmp32u = sse42_compare_string_implicit_len(emu, EX, &GX, tmp8u);
if(!tmp32u)
R_ECX = (tmp8u&1)?8:16;
else if(tmp8u&0b1000000)
R_ECX = 31-__builtin_clz(tmp32u);
else
R_ECX = __builtin_ffs(tmp32u) - 1;
break;
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
nextop = F8;
GET_EX;
tmp32u = F8;
for (int i = 4; i < 8; ++i)
GX.ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX.ub[i] = subbytes[EX->ub[i]];
GX.ud[0] = GX.ud[1];
tmp8u = GX.ub[4];
GX.ud[1] = GX.ud[1] >> 8;
GX.ub[7] = tmp8u;
GX.ud[1] ^= tmp32u;
GX.ud[2] = GX.ud[3];
tmp8u = GX.ub[12];
GX.ud[3] = GX.ud[3] >> 8;
GX.ub[15] = tmp8u;
GX.ud[3] ^= tmp32u;
break;
default:
return 0;
}
@@ -1520,12 +1990,12 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
nextop = F8;
GET_EX;
EX->q[0] = GX.q[0];
if((nextop&0xC0)==0xC0)
if(MODREG)
EX->q[1] = 0;
break;
case 0xD7: /* PMOVMSKB Gd,Ex */
nextop = F8;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
GET_EX;
GD.dword[0] = 0;
for (int i=0; i<16; ++i)
+2 -2
View File
@@ -29,8 +29,8 @@ uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr)
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
nextop = F8;
switch(nextop) {
case 0xC0:
case 0xC1:
+2 -2
View File
@@ -29,8 +29,8 @@ uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr)
x86emu_t* emu = test->emu;
#endif
uint8_t opcode = F8;
switch(opcode) {
nextop = F8;
switch(nextop) {
case 0xC0:
case 0xC1:
+74
View File
@@ -0,0 +1,74 @@
#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"
#include "modrm.h"
#include "x86compstrings.h"
#ifdef TEST_INTERPRETER
uintptr_t Test66F20F(x86test_t *test, uintptr_t addr)
#else
uintptr_t Run66F20F(x86emu_t *emu, uintptr_t addr)
#endif
{
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;
mmx87_regs_t *opem;
float tmpf;
double tmpd;
#ifdef TEST_INTERPRETER
x86emu_t* emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
case 0x38: // SSE 4.x
opcode = F8;
switch(opcode) {
case 0xF1: // CRC32 Gd, Ew
nextop = F8;
GET_EW;
for(int j=0; j<2; ++j) {
GD.dword[0] ^= EW->byte[j];
for (int i = 0; i < 8; i++) {
if (GD.dword[0] & 1)
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
else
GD.dword[0] = (GD.dword[0] >> 1);
}
}
break;
default:
return 0;
}
break;
default:
return 0;
}
return addr;
}
+40 -4
View File
@@ -24,6 +24,7 @@
#include "x86trace.h"
#endif
#include "x86tls.h"
#include "x86emu.h"
#define PARITY(x) (((emu->x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
@@ -456,6 +457,8 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
if(emu->op2==1)
CLEAR_FLAG(F_OF);
}
} else {
if (emu->op1&0x80) {
@@ -479,6 +482,8 @@ void UpdateFlags(x86emu_t *emu)
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);
if(emu->op2==1)
CLEAR_FLAG(F_OF);
}
} else {
if (emu->op1&0x8000) {
@@ -501,6 +506,8 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
if(emu->op2==1)
CLEAR_FLAG(F_OF);
}
break;
case d_shr8:
@@ -514,7 +521,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 6), F_OF);
CONDITIONAL_SET_FLAG(emu->op1 & 0x80, F_OF);
}
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (emu->op2-1)) & 0x1, F_CF);
@@ -534,7 +541,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 14), F_OF);
CONDITIONAL_SET_FLAG(emu->op1 & 0x8000, F_OF);
}
} else {
CLEAR_FLAG(F_CF);
@@ -553,7 +560,35 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
}
if (cnt == 1) {
CONDITIONAL_SET_FLAG(XOR2(emu->res >> 30), F_OF);
CONDITIONAL_SET_FLAG(emu->op1 & 0x80000000, F_OF);
}
break;
case d_shrd32:
cnt = emu->op2;
if (cnt > 0) {
cc = emu->op1 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, 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);
if (cnt == 1) {
CONDITIONAL_SET_FLAG((emu->op1 ^ emu->res) & 0x80000000, F_OF);
}
}
break;
case d_shld32:
cnt = emu->op2;
if (cnt > 0) {
cc = emu->op1 & (1 << (32 - cnt));
CONDITIONAL_SET_FLAG(cc, 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);
if (cnt == 1) {
CONDITIONAL_SET_FLAG((emu->op1 ^ emu->res) & 0x80000000, F_OF);
} else {
CLEAR_FLAG(F_OF);
}
}
break;
case d_sub8:
@@ -882,6 +917,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
} else if(peek==0x55) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "top:");
printFunctionAddr(ip, "here: ");
} else if(peek==0xE8) { // Call
uintptr_t nextaddr = ip + 5 + PK32(1);
@@ -890,7 +926,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
const uint8_t pk1 = PK(1);
if(((pk1>>3)&7)==2 || ((pk1>>3)&7)==4) { // jmp/call near
uintptr_t nextaddr = (uintptr_t)getAlternate((void*)evalED(emu, ip+1));
printf_log(LOG_NONE, " => %p", nextaddr);
printf_log(LOG_NONE, " => %p", (void*)nextaddr);
printFunctionAddr(nextaddr, " / ");
}
}
+2
View File
@@ -212,6 +212,7 @@ uintptr_t Run6466(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Run6467(x86emu_t *emu, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Run66(x86emu_t *emu, int rep, uintptr_t addr);
uintptr_t Run660F(x86emu_t *emu, uintptr_t addr);
uintptr_t Run66F20F(x86emu_t *emu, uintptr_t addr);
uintptr_t Run6664(x86emu_t *emu, int seg, uintptr_t addr);
uintptr_t Run66D9(x86emu_t *emu, uintptr_t addr);
uintptr_t Run66DD(x86emu_t *emu, uintptr_t addr);
@@ -241,6 +242,7 @@ uintptr_t Test6466(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Test6467(x86test_t *test, uintptr_t tlsdata, uintptr_t addr);
uintptr_t Test66(x86test_t *test, int rep, uintptr_t addr);
uintptr_t Test660F(x86test_t *test, uintptr_t addr);
uintptr_t Test66F20F(x86test_t *test, uintptr_t addr);
uintptr_t Test6664(x86test_t *test, int seg, uintptr_t addr);
uintptr_t Test66D9(x86test_t *test, uintptr_t addr);
uintptr_t Test66DD(x86test_t *test, uintptr_t addr);
-9
View File
@@ -554,15 +554,6 @@ uintptr_t RunF0(x86emu_t *emu, uintptr_t addr)
case 0x86: /* XCHG Eb,Gb */
case 0x87: /* XCHG Ed,Gd */
return addr-1; // let the normal XCHG execute, it have integrated LOCK
case 0x90: // This is xchg reg, reg, so let's ignore the LOCK prefix...
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
return addr-1;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
+36
View File
@@ -103,6 +103,42 @@ uintptr_t RunF20F(x86emu_t *emu, uintptr_t addr, int *step)
break;
}
break;
case 0x38: // more opcodes
opcode = F8;
switch(opcode) {
case 0xF0: // CRC32 Gd, Eb
nextop = F8;
GET_EB;
GD.dword[0] ^= EB->byte[0];
for (int i = 0; i < 8; i++) {
if (GD.dword[0] & 1)
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
else
GD.dword[0] = (GD.dword[0] >> 1);
}
break;
case 0xF1: // CRC32 Gd, Ed
nextop = F8;
GET_ED;
for(int j=0; j<4; ++j) {
GD.dword[0] ^= ED->byte[j];
for (int i = 0; i < 8; i++) {
if (GD.dword[0] & 1)
GD.dword[0] = (GD.dword[0] >> 1) ^ 0x82f63b78;
else
GD.dword[0] = (GD.dword[0] >> 1);
}
}
break;
default:
return 0;
}
break;
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
GET_EX;
+19
View File
@@ -42,6 +42,11 @@ uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
x86emu_t*emu = test->emu;
#endif
#ifdef TERMUX
extern int isinff(float);
extern int isnanf(float);
#endif
opcode = F8;
switch(opcode) {
@@ -215,6 +220,20 @@ uintptr_t RunF30F(x86emu_t *emu, uintptr_t addr)
memcpy(EX, &GX, 16); // unaligned...
break;
case 0xB8: /* POPCNT Gd,Ed */
nextop = F8;
GET_ED;
GD.dword[0] = __builtin_popcount(ED->dword[0]);
RESET_FLAGS(emu);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
CLEAR_FLAG(F_ZF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_CF);
CLEAR_FLAG(F_PF);
CONDITIONAL_SET_FLAG(GD.dword[0]==0, F_ZF);
break;
case 0xBC: /* TZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
+315 -278
View File
@@ -51,6 +51,7 @@ int32_t my___sendmmsg(x86emu_t* emu, int32_t fd, void* msgvec, uint32_t vlen, ui
#endif
#endif
typedef struct x86_sigaction_s x86_sigaction_t;
typedef struct x86_sigaction_restorer_s x86_sigaction_restorer_t;
int32_t my_getrandom(x86emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
@@ -67,6 +68,7 @@ int32_t my_epoll_ctl(x86emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void*
int32_t my_epoll_wait(x86emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout);
#endif
int my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
int my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize);
int32_t my_execve(x86emu_t* emu, const char* path, char* const argv[], char* const envp[]);
void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
@@ -105,6 +107,7 @@ int my_socketcall(x86emu_t* emu, int n, unsigned long *args) {
printf_log(LOG_DEBUG, "BOX86 Error on Syscall 102: Unknown Soket command %d\n", n);
ret = -EINVAL;
}
return ret;
};
#endif
@@ -116,181 +119,184 @@ int my_fcntl(x86emu_t* emu, int fd, int cmd, ... /* arg */ );
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
typedef struct scwrap_s {
uint32_t x86s;
int nats;
int nbpars;
} scwrap_t;
scwrap_t syscallwrap[] = {
{ 2, __NR_fork, 1 }, // should wrap this one, because of the struct pt_regs (the only arg)?
//{ 3, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
//{ 4, __NR_write, 3 }, // same
//{ 5, __NR_open, 3 }, // flags need transformation
//{ 6, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
[2] ={ __NR_fork, 1 }, // should wrap this one, because of the struct pt_regs (the only arg)?
//[3] ={ __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
//[4] ={ __NR_write, 3 }, // same
//[5] ={ __NR_open, 3 }, // flags need transformation
//[6] ={ __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
#ifdef __NR_waitpid
{ 7, __NR_waitpid, 3 },
[7] ={ __NR_waitpid, 3 },
#endif
{ 10, __NR_unlink, 1 },
{ 12, __NR_chdir, 1 },
[10] { __NR_unlink, 1 },
[12] { __NR_chdir, 1 },
#ifdef __NR_time
{ 13, __NR_time, 1 },
[13] { __NR_time, 1 },
#endif
{ 15, __NR_chmod, 2 },
{ 19, __NR_lseek, 3 },
{ 20, __NR_getpid, 0 },
{ 24, __NR_getuid, 0 },
{ 33, __NR_access, 2 },
{ 37, __NR_kill, 2 },
{ 38, __NR_rename, 2 },
{ 39, __NR_mkdir, 2 },
{ 40, __NR_rmdir, 1 },
{ 41, __NR_dup, 1 },
{ 42, __NR_pipe, 1 },
//{ 45, __NR_brk, 1 },
{ 47, __NR_getgid, 0 },
{ 49, __NR_geteuid, 0 },
{ 50, __NR_getegid, 0 },
{ 54, __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5
//{ 55, __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD
{ 60, __NR_umask, 1 },
{ 63, __NR_dup2, 2 },
{ 64, __NR_getppid, 0 },
{ 66, __NR_setsid, 0 },
{ 75, __NR_setrlimit, 2 },
[15] { __NR_chmod, 2 },
[19] { __NR_lseek, 3 },
[20] { __NR_getpid, 0 },
[24] { __NR_getuid, 0 },
#ifdef __NR_alarm
[27] { __NR_alarm, 1 },
#endif
[33] { __NR_access, 2 },
[37] { __NR_kill, 2 },
[38] { __NR_rename, 2 },
[39] { __NR_mkdir, 2 },
[40] { __NR_rmdir, 1 },
[41] { __NR_dup, 1 },
[42] { __NR_pipe, 1 },
//[45] { __NR_brk, 1 },
[47] { __NR_getgid, 0 },
[49] { __NR_geteuid, 0 },
[50] { __NR_getegid, 0 },
[54] { __NR_ioctl, 3 }, // should be wrapped to allow SA_RESTART handling by libc, but syscall is only 3 arguments, ioctl can be 5
//[55] { __NR_fcntl, 3 }, // wrapped to allow filter of F_SETFD
[60] { __NR_umask, 1 },
[63] { __NR_dup2, 2 },
[64] { __NR_getppid, 0 },
[66] { __NR_setsid, 0 },
//[67] { __NR_sigaction, 3 },
[75] { __NR_setrlimit, 2 },
#ifdef __NR_getrlimit
{ 76, __NR_getrlimit, 2 },
[76] { __NR_getrlimit, 2 },
#endif
{ 77, __NR_getrusage, 2 },
{ 78, __NR_gettimeofday, 2 },
{ 83, __NR_symlink, 2 },
[77] { __NR_getrusage, 2 },
[78] { __NR_gettimeofday, 2 },
[80] { __NR_getgroups, 2 },
[83] { __NR_symlink, 2 },
#ifdef __NR_select
{ 82, __NR_select, 5 },
[82] { __NR_select, 5 },
#endif
{ 85, __NR_readlink, 3 },
//{ 91, __NR_munmap, 2 },
{ 94, __NR_fchmod, 2 },
{ 99, __NR_statfs, 2 },
[85] { __NR_readlink, 3 },
//[91] { __NR_munmap, 2 },
[94] { __NR_fchmod, 2 },
[99] { __NR_statfs, 2 },
#ifdef __NR_socketcall
{ 102, __NR_socketcall, 2 },
[102] { __NR_socketcall, 2 },
#endif
{ 104, __NR_setitimer, 3 },
{ 105, __NR_getitimer, 2 },
[104] { __NR_setitimer, 3 },
[105] { __NR_getitimer, 2 },
#ifdef __NR_newstat
{ 106, __NR_newstat, 2 },
[106] { __NR_newstat, 2 },
#else
{ 106, __NR_stat, 2 },
[106] { __NR_stat, 2 },
#endif
#ifdef __NR_newlstat
{ 107, __NR_newlstat, 2 },
[107] { __NR_newlstat, 2 },
#else
{ 107, __NR_lstat, 2 },
[107] { __NR_lstat, 2 },
#endif
#ifdef __NR_newfstat
{ 108, __NR_newfstat, 2 },
[108] { __NR_newfstat, 2 },
#else
{ 108, __NR_fstat, 2 },
[108] { __NR_fstat, 2 },
#endif
#ifdef __NR_olduname
{ 109, __NR_olduname, 1 },
[109] { __NR_olduname, 1 },
#endif
#ifdef __NR_iopl
{ 110, __NR_iopl, 1 },
[110] { __NR_iopl, 1 },
#endif
{ 114, __NR_wait4, 4 }, //TODO: check struct rusage alignment
[114] { __NR_wait4, 4 }, //TODO: check struct rusage alignment
#ifdef __NR_ipc
{ 117, __NR_ipc, 6 },
[117] { __NR_ipc, 6 },
#endif
//{ 119, __NR_sigreturn, 0},
//{ 120, __NR_clone, 5 }, // need works
//{ 122, __NR_uname, 1 },
//{ 123, __NR_modify_ldt },
//{ 125, __NR_mprotect, 3 },
{ 136, __NR_personality, 1 },
{ 140, __NR__llseek, 5 },
{ 141, __NR_getdents, 3 },
{ 142, __NR__newselect, 5 },
{ 143, __NR_flock, 2 },
{ 144, __NR_msync, 3 },
{ 145, __NR_readv, 3 },
{ 146, __NR_writev, 3 },
{ 148, __NR_fdatasync, 1 },
{ 149, __NR__sysctl, 1 }, // need wrapping?
{ 156, __NR_sched_setscheduler, 3 },
{ 157, __NR_sched_getscheduler, 1 },
{ 158, __NR_sched_yield, 0 },
{ 162, __NR_nanosleep, 2 },
{ 164, __NR_setresuid, 3 },
//{ 168, __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc
{ 172, __NR_prctl, 5 },
//{ 173, __NR_rt_sigreturn, 0 },
{ 175, __NR_rt_sigprocmask, 4 },
{ 179, __NR_rt_sigsuspend, 2 },
{ 183, __NR_getcwd, 2 },
{ 184, __NR_capget, 2},
{ 185, __NR_capset, 2},
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
{ 191, __NR_ugetrlimit, 2 },
// { 192, __NR_mmap2, 6},
//{ 195, __NR_stat64, 2 }, // need proprer wrap because of structure size change
//{ 196, __NR_lstat64, 2 }, // need proprer wrap because of structure size change
//{ 197, __NR_fstat64, 2 }, // need proprer wrap because of structure size change
//[119] { __NR_sigreturn, 0},
//[120] { __NR_clone, 5 }, // need works
//[122] { __NR_uname, 1 },
//[123] { __NR_modify_ldt },
//[125] { __NR_mprotect, 3 },
[126] { __NR_sigprocmask, 3 },
[136] { __NR_personality, 1 },
[140] { __NR__llseek, 5 },
[141] { __NR_getdents, 3 },
[142] { __NR__newselect, 5 },
[143] { __NR_flock, 2 },
[144] { __NR_msync, 3 },
[145] { __NR_readv, 3 },
[146] { __NR_writev, 3 },
[148] { __NR_fdatasync, 1 },
[149] { __NR__sysctl, 1 }, // need wrapping?
[156] { __NR_sched_setscheduler, 3 },
[157] { __NR_sched_getscheduler, 1 },
[158] { __NR_sched_yield, 0 },
[162] { __NR_nanosleep, 2 },
[164] { __NR_setresuid, 3 },
//[168] { __NR_poll, 3 }, // wrapped to allow SA_RESTART wrapping by libc
[172] { __NR_prctl, 5 },
//[173] { __NR_rt_sigreturn, 0 },
[175] { __NR_rt_sigprocmask, 4 },
[179] { __NR_rt_sigsuspend, 2 },
[183] { __NR_getcwd, 2 },
[184] { __NR_capget, 2},
[185] { __NR_capset, 2},
[186] { __NR_sigaltstack, 2 }, // neeed wrap or something?
[191] { __NR_ugetrlimit, 2 },
// [192] { __NR_mmap2, 6},
//[195] { __NR_stat64, 2 }, // need proprer wrap because of structure size change
//[196] { __NR_lstat64, 2 }, // need proprer wrap because of structure size change
//[197] { __NR_fstat64, 2 }, // need proprer wrap because of structure size change
#ifndef POWERPCLE
{ 199, __NR_getuid32, 0 },
{ 200, __NR_getgid32, 0 },
{ 201, __NR_geteuid32, 0 },
{ 202, __NR_getegid32, 0 },
{ 208, __NR_setresuid32, 3 },
{ 209, __NR_getresuid32, 3 },
{ 210, __NR_setresgid32, 3 },
{ 211, __NR_getresgid32, 3 },
[199] { __NR_getuid32, 0 },
[200] { __NR_getgid32, 0 },
[201] { __NR_geteuid32, 0 },
[202] { __NR_getegid32, 0 },
[208] { __NR_setresuid32, 3 },
[209] { __NR_getresuid32, 3 },
[210] { __NR_setresgid32, 3 },
[211] { __NR_getresgid32, 3 },
#else
// PowerPC uses the same syscalls for 32/64 bit processes.
{ 199, __NR_getuid, 0 },
{ 200, __NR_getgid, 0 },
{ 201, __NR_geteuid, 0 },
{ 202, __NR_getegid, 0 },
{ 208, __NR_setresuid, 3 },
{ 209, __NR_getresuid, 3 },
{ 210, __NR_setresgid, 3 },
{ 211, __NR_getresgid, 3 },
[199] { __NR_getuid, 0 },
[200] { __NR_getgid, 0 },
[201] { __NR_geteuid, 0 },
[202] { __NR_getegid, 0 },
[208] { __NR_setresuid, 3 },
[209] { __NR_getresuid, 3 },
[210] { __NR_setresgid, 3 },
[211] { __NR_getresgid, 3 },
#endif
{ 220, __NR_getdents64, 3 },
//{ 221, __NR_fcntl64, 3 },
{ 224, __NR_gettid, 0 },
{ 240, __NR_futex, 6 },
{ 241, __NR_sched_setaffinity, 3 },
{ 242, __NR_sched_getaffinity, 3 },
{ 252, __NR_exit_group, 1 },
[220] { __NR_getdents64, 3 },
//[221] { __NR_fcntl64, 3 },
[224] { __NR_gettid, 0 },
[240] { __NR_futex, 6 },
[241] { __NR_sched_setaffinity, 3 },
[242] { __NR_sched_getaffinity, 3 },
[252] { __NR_exit_group, 1 },
#ifdef NOALIGN
{ 254, __NR_epoll_create, 1 },
{ 255, __NR_epoll_ctl, 4 },
{ 256, __NR_epoll_wait, 4 },
[254] { __NR_epoll_create, 1 },
[255] { __NR_epoll_ctl, 4 },
[256] { __NR_epoll_wait, 4 },
#endif
{ 265, __NR_clock_gettime, 2 },
{ 266, __NR_clock_getres, 2 },
//{ 270, __NR_tgkill, 3 },
{ 271, __NR_utimes, 2 },
{ 291, __NR_inotify_init, 0},
{ 292, __NR_inotify_add_watch, 3},
{ 293, __NR_inotify_rm_watch, 2},
{ 311, __NR_set_robust_list, 2 },
{ 312, __NR_get_robust_list, 4 },
{ 318, __NR_getcpu, 3},
{ 328, __NR_eventfd2, 2},
[265] { __NR_clock_gettime, 2 },
[266] { __NR_clock_getres, 2 },
//[270] { __NR_tgkill, 3 },
[271] { __NR_utimes, 2 },
[291] { __NR_inotify_init, 0},
[292] { __NR_inotify_add_watch, 3},
[293] { __NR_inotify_rm_watch, 2},
[311] { __NR_set_robust_list, 2 },
[312] { __NR_get_robust_list, 4 },
[318] { __NR_getcpu, 3},
[328] { __NR_eventfd2, 2},
#ifdef NOALIGN
{ 329, __NR_epoll_create1, 1 },
[329] { __NR_epoll_create1, 1 },
#endif
{ 331, __NR_pipe2, 2},
{ 332, __NR_inotify_init1, 1},
[331] { __NR_pipe2, 2},
[332] { __NR_inotify_init1, 1},
#ifdef __NR_getrandom
{ 355, __NR_getrandom, 3 },
[355] { __NR_getrandom, 3 },
#endif
#ifdef __NR_memfd_create
{ 356, __NR_memfd_create, 2},
#endif
#ifdef __NR_futex_waitv
{ 449, __NR_futex_waitv, 5},
[356] { __NR_memfd_create, 2},
#endif
//[449] { __NR_futex_waitv, 5},
};
struct mmap_arg_struct {
@@ -405,27 +411,25 @@ void EXPORT x86Syscall(x86emu_t *emu)
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p", (void*)R_EIP, s, s, (void*)R_EBX, (void*)R_ECX, (void*)R_EDX, (void*)R_ESI, (void*)R_EDI);
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
for (int i=0; i<cnt; i++) {
if(syscallwrap[i].x86s == s) {
int sc = syscallwrap[i].nats;
switch(syscallwrap[i].nbpars) {
case 0: *(int32_t*)&R_EAX = syscall(sc); break;
case 1: *(int32_t*)&R_EAX = syscall(sc, R_EBX); break;
case 2: if(s==33) {printf_log(LOG_DEBUG, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX); break;
case 3: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
case 4: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
case 5: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
case 6: *(int32_t*)&R_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break;
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
emu->quit = 1;
return;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
return;
if(s<cnt && syscallwrap[s].nats) {
int sc = syscallwrap[s].nats;
switch(syscallwrap[s].nbpars) {
case 0: S_EAX = syscall(sc); break;
case 1: S_EAX = syscall(sc, R_EBX); break;
case 2: if(s==33) {printf_log(LOG_DEBUG, " => sys_access(\"%s\", %d)\n", (char*)R_EBX, R_ECX);}; S_EAX = syscall(sc, R_EBX, R_ECX); break;
case 3: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX); break;
case 4: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI); break;
case 5: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI); break;
case 6: S_EAX = syscall(sc, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP); break;
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[s].nbpars);
emu->quit = 1;
return;
}
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
return;
}
switch (s) {
case 1: // sys_exit
@@ -435,32 +439,32 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = R_EBX; // faking the syscall here, we don't want to really terminate the thread now
break;
case 3: // sys_read
R_EAX = (uint32_t)read((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = read(S_EBX, (void*)R_ECX, (size_t)R_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 4: // sys_write
R_EAX = (uint32_t)write((int)R_EBX, (void*)R_ECX, (size_t)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = write(S_EBX, (void*)R_ECX, (size_t)R_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 5: // sys_open
if(s==5) {printf_log(LOG_DEBUG, " => sys_open(\"%s\", %d, %d)", (char*)R_EBX, of_convert(R_ECX), R_EDX);};
//R_EAX = (uint32_t)open((void*)R_EBX, of_convert(R_ECX), R_EDX);
R_EAX = (uint32_t)my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
//S_EAX = open((void*)R_EBX, of_convert(R_ECX), R_EDX);
S_EAX = my_open(emu, (void*)R_EBX, of_convert(R_ECX), R_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 6: // sys_close
R_EAX = (uint32_t)close((int)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = close(S_EBX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef __NR_waitpid
case 7: //sys_waitpid
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, (int)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
R_EAX = waitpid((pid_t)R_EBX, (int*)R_ECX, S_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 11: // sys_execve
@@ -471,43 +475,55 @@ void EXPORT x86Syscall(x86emu_t *emu)
printf_log(LOG_DEBUG, " => sys_execve(\"%s\", %p(\"%s\", \"%s\", \"%s\"...), %p)\n", prog, argv, (argv && argv[0])?argv[0]:"nil", (argv && argv[0] && argv[1])?argv[1]:"nil", (argv && argv[0] && argv[1] && argv[2])?argv[2]:"nil", envv);
R_EAX = my_execve(emu, (const char*)R_EBX, (void*)R_ECX, (void*)R_EDX);
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef __NR_time
case 13: // sys_time (it's deprecated and remove on ARM EABI it seems)
R_EAX = time(NULL);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
#ifndef __NR_alarm
case 27:
R_EAX = alarm(R_EBX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 45: // sys_brk
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 54: // sys_ioctl
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = ioctl(S_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 55: // sys_fcntl
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = my_fcntl(emu, S_EBX, S_ECX, R_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 67: // sys_sigaction
S_EAX = my_syscall_sigaction(emu, R_EBX, (x86_sigaction_restorer_t*)R_ECX, (x86_sigaction_restorer_t*)R_EDX, R_ESI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef __NR_getrlimit
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
R_EAX = getrlimit(R_EBX, (void*)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
#ifndef __NR_select
case 82: // select
R_EAX = select(R_EBX, (fd_set*)R_ECX, (fd_set*)R_EDX, (fd_set*)R_ESI, (struct timeval*)R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 90: // old_mmap
@@ -515,19 +531,19 @@ void EXPORT x86Syscall(x86emu_t *emu)
struct mmap_arg_struct *st = (struct mmap_arg_struct*)R_EBX;
R_EAX = (uintptr_t)my_mmap(emu, (void*)st->addr, st->len, st->prot, st->flags, st->fd, st->offset);
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 91: // munmap
R_EAX = my_munmap(emu, (void*)R_EBX, (unsigned long)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef __NR_socketcall
case 102:
R_EAX = my_socketcall(emu, R_EBX, (unsigned long *)R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
#ifndef __NR_olduname
@@ -543,8 +559,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
memcpy(old->version, un.version, 9);
strcpy(old->machine, "i686");
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
}
break;
#endif
@@ -555,9 +571,9 @@ void EXPORT x86Syscall(x86emu_t *emu)
#endif
#ifndef __NR_ipc
case 117: // ipc
R_EAX = (uint32_t)my_ipc(R_EBX, (int)R_ECX, (int)R_EDX, (int)R_ESI, (void*)R_EDI, (long)R_EBP);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = my_ipc(R_EBX, S_ECX, S_EDX, S_ESI, (void*)R_EDI, (long)R_EBP);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 119: // sys_sigreturn
@@ -569,8 +585,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
if((R_EBX&~0xff)==0x4100) {
// this is a case of vfork...
R_EAX = my_vfork(emu);
if(R_EAX==0xffffffff)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1)
S_EAX = -errno;
} else {
if(R_ECX)
{
@@ -606,12 +622,12 @@ void EXPORT x86Syscall(x86emu_t *emu)
my_context->stack_clone_used = 1;
}
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
R_EAX = (uint32_t)ret;
S_EAX = ret;
}
else
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
}
break;
case 122: // uname
@@ -627,23 +643,23 @@ void EXPORT x86Syscall(x86emu_t *emu)
strcpy(old->machine, "i686");
}
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 123: // SYS_modify_ldt
R_EAX = my_modify_ldt(emu, R_EBX, (thread_area_t*)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 125: // mprotect
R_EAX = my_mprotect(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 168: // sys_poll
R_EAX = (uint32_t)poll((void*)R_EBX, R_ECX, (int)R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = poll((void*)R_EBX, R_ECX, S_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 173: // sys_rt_sigreturn
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
@@ -651,19 +667,19 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 174: // sys_rt_sigaction
//printf_log(LOG_NONE, "Warning, Ignoring sys_rt_sigaction(0x%02X, %p, %p)\n", R_EBX, (void*)R_ECX, (void*)R_EDX);
R_EAX = my_syscall_sigaction(emu, R_EBX, (void*)R_ECX, (void*)R_EDX, R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 190: // vfork
{
int r = my_vfork(emu);
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 192: // mmap2
R_EAX = (uint32_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
S_EAX = (intptr_t)my_mmap64(emu, (void*)R_EBX, (unsigned long)R_ECX, R_EDX, R_ESI, R_EDI, R_EBP);
break;
case 195: // stat64
{
@@ -673,8 +689,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 196: // lstat64
{
@@ -684,8 +700,8 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 197: // fstat64
{
@@ -695,65 +711,73 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = r;
}
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 221: // sys_fcntl64
R_EAX = (uint32_t)my_fcntl(emu, (int)R_EBX, (int)R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
S_EAX = my_fcntl(emu, S_EBX, S_ECX, R_EDX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 243: // set_thread_area
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef NOALIGN
case 254: // epoll_create
R_EAX = my_epoll_create(emu, (int)R_EBX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
R_EAX = my_epoll_create(emu, S_EBX);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 255: // epoll_ctl
R_EAX = my_epoll_ctl(emu, (int)R_EBX, (int)R_ECX, (int)R_EDX, (void*)R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
R_EAX = my_epoll_ctl(emu, S_EBX, S_ECX, S_EDX, (void*)R_ESI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
case 256: // epoll_wait
R_EAX = my_epoll_wait(emu, (int)R_EBX, (void*)R_ECX, (int)R_EDX, (int)R_ESI);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
R_EAX = my_epoll_wait(emu, S_EBX, (void*)R_ECX, S_EDX, S_ESI);
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 270: // tgkill
R_EAX = syscall(__NR_tgkill, R_EBX, R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#ifndef NOALIGN
case 329: // epoll_create1
R_EAX = my_epoll_create1(emu, of_convert(R_EBX));
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
#ifndef __NR_getrandom
case 355: // getrandom
R_EAX = my_getrandom(emu, (void*)R_EBX, R_ECX, R_EDX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
R_EAX = my_memfd_create(emu, (void*)R_EBX, R_ECX);
if(R_EAX==0xffffffff && errno>0)
R_EAX = (uint32_t)-errno;
if(S_EAX==-1 && errno>0)
S_EAX = -errno;
break;
#endif
case 449:
#ifdef __NR_futex_waitv
if(box86_futex_waitv)
S_EAX = syscall(R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
else
#endif
S_EAX = -ENOSYS;
break;
default:
printf_log(LOG_INFO, "Warning: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
R_EAX = (uint32_t)-ENOSYS;
S_EAX = -ENOSYS;
return;
}
printf_log(LOG_DEBUG, " => 0x%x\n", R_EAX);
@@ -764,56 +788,60 @@ void EXPORT x86Syscall(x86emu_t *emu)
#define u32(n) *(uint32_t*)stack(n)
#define p(n) *(void**)stack(n)
uint32_t EXPORT my_syscall(x86emu_t *emu)
long EXPORT my_syscall(x86emu_t *emu)
{
static uint32_t warned = 0;
uint32_t s = u32(0);
printf_log(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
for (int i=0; i<cnt; i++) {
if(syscallwrap[i].x86s == s) {
int sc = syscallwrap[i].nats;
switch(syscallwrap[i].nbpars) {
case 0: return syscall(sc);
case 1: return syscall(sc, u32(4));
case 2: return syscall(sc, u32(4), u32(8));
case 3: return syscall(sc, u32(4), u32(8), u32(12));
case 4: return syscall(sc, u32(4), u32(8), u32(12), u32(16));
case 5: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20));
case 6: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20), u32(24));
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[i].nbpars);
emu->quit = 1;
return 0;
}
if(s<cnt && syscallwrap[s].nats) {
int sc = syscallwrap[s].nats;
switch(syscallwrap[s].nbpars) {
case 0: return syscall(sc);
case 1: return syscall(sc, u32(4));
case 2: return syscall(sc, u32(4), u32(8));
case 3: return syscall(sc, u32(4), u32(8), u32(12));
case 4: return syscall(sc, u32(4), u32(8), u32(12), u32(16));
case 5: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20));
case 6: return syscall(sc, u32(4), u32(8), u32(12), u32(16), u32(20), u32(24));
default:
printf_log(LOG_NONE, "ERROR, Unimplemented syscall wrapper (%d, %d)\n", s, syscallwrap[s].nbpars);
emu->quit = 1;
return 0;
}
}
switch (s) {
case 1: // __NR_exit
emu->quit = 1;
return u32(4); // faking the syscall here, we don't want to really terminate the program now
return i32(4); // faking the syscall here, we don't want to really terminate the program now
case 3: // sys_read
return (uint32_t)read(i32(4), p(8), u32(12));
return read(i32(4), p(8), u32(12));
case 4: // sys_write
return (uint32_t)write(i32(4), p(8), u32(12));
return write(i32(4), p(8), u32(12));
case 5: // sys_open
return my_open(emu, p(4), of_convert(u32(8)), u32(12));
case 6: // sys_close
return (uint32_t)close(i32(4));
return close(i32(4));
case 11: // execve
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
return my_execve(emu, p(4), p(8), p(12));
#ifndef __NR_alarm
case 27:
return alarm(R_EBX);
#endif
case 45: // brk
return (uintptr_t)ElfSetBrk(p(4));
return (intptr_t)ElfSetBrk(p(4));
case 67: // sys_sigaction
return my_syscall_sigaction(emu, u32(4), (x86_sigaction_restorer_t*)p(8), (x86_sigaction_restorer_t*)p(12), u32(16));
case 91: // munmap
return (uint32_t)my_munmap(emu, p(4), u32(8));
return my_munmap(emu, p(4), u32(8));
#ifndef __NR_socketcall
case 102:
return my_socketcall(emu, i32(4), (unsigned long *)p(8));
#endif
#ifndef __NR_ipc
case 117: // ipc
return (uint32_t)my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
return my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
#endif
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
@@ -853,19 +881,19 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
}
// x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), u32(4), newemu, p(12), p(16), p(20));
return (uint32_t)ret;
return ret;
}
else
return (uint32_t)syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
return syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
break;
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 125: // mprotect
return (uint32_t)my_mprotect(emu, p(4), u32(8), i32(12));
return my_mprotect(emu, p(4), u32(8), i32(12));
case 174: // sys_rt_sigaction
return (uint32_t)my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
return my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
case 192: // mmap2
return (uint32_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
return (intptr_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
case 243: // set_thread_area
return my_set_thread_area((thread_area_t*)p(4));
#ifndef NOALIGN
@@ -892,12 +920,22 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
#endif
#ifndef __NR_getrandom
case 355: // getrandom
return (uint32_t)my_getrandom(emu, p(4), u32(8), u32(12));
return my_getrandom(emu, p(4), u32(8), u32(12));
#endif
#ifndef __NR_memfd_create
case 356: // memfd_create
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
return my_memfd_create(emu, (void*)R_EBX, R_ECX);
#endif
case 449:
#ifdef __NR_futex_waitv
if(box86_futex_waitv)
return syscall(__NR_futex_waitv, u32(4), u32(8), u32(12), u32(16), u32(20));
else
#endif
{
errno = ENOSYS;
return -1;
}
default:
if(!(warned&(1<<s))) {
printf_log(LOG_INFO, "Warning: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
@@ -906,5 +944,4 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
errno = ENOSYS;
return -1;
}
return 0;
}
+3 -1
View File
@@ -217,7 +217,9 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
mutex_lock(&context->mutex_tls);
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
if(sizeTLSData(oldata->tlssize)!=sizeTLSData(context->tlssize) || (oldata->n_elfs/0xff)!=(context->elfsize/0xff)) {
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
if(sizeTLSData(oldata->tlssize)) {
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
}
tlsdatasize_t *data = setupTLSData(context);
// copy the relevent old part, in case something changed
memcpy((void*)((uintptr_t)data->data-oldata->tlssize), (void*)((uintptr_t)oldata->data-oldata->tlssize), oldata->tlssize);
+1
View File
@@ -305,6 +305,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
p->ControlWord = emu->cw.x16;
p->StatusWord = emu->sw.x16;
p->MxCsr = emu->mxcsr.x32;
p->MxCsr_Mask = 0;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
tags |= (emu->p_regs[i].tag==0b11)?0:(1<<(i*2));
+42 -18
View File
@@ -7,6 +7,10 @@
#ifdef DYNAREC
#include "dynarec/arm_lock_helper.h"
#endif
#ifdef DYNAREC
// disabling for now, seems to have a negative impact on performances
//#define USE_CUSTOM_MUTEX
#endif
typedef struct elfheader_s elfheader_t;
typedef struct cleanup_s cleanup_t;
@@ -17,6 +21,7 @@ typedef struct bridge_s bridge_t;
typedef struct dlprivate_s dlprivate_t;
typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct kh_defaultversion_s kh_defaultversion_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct library_s library_t;
typedef struct linkmap_s linkmap_t;
typedef struct kh_fts_s kh_fts_t;
@@ -56,9 +61,16 @@ void free_tlsdatasize(void* p);
typedef struct needed_libs_s {
int cap;
int size;
library_t **libs;
char** names;
library_t** libs;
int nb_done;
} needed_libs_t;
void free_neededlib(needed_libs_t* needed); // defined in library.c
void free_neededlib(needed_libs_t* needed);
needed_libs_t* new_neededlib(int n);
needed_libs_t* copy_neededlib(needed_libs_t* needed);
void add1_neededlib(needed_libs_t* needed);
void add1lib_neededlib(needed_libs_t* needed, library_t* lib, const char* name);
typedef struct base_segment_s {
uintptr_t base;
@@ -100,7 +112,8 @@ typedef struct box86context_s {
int elfcap;
int elfsize; // number of elf loaded
needed_libs_t neededlibs; // needed libs for main elf
needed_libs_t *neededlibs; // needed libs for main elf
needed_libs_t *preload;
uintptr_t ep; // entry point
@@ -109,7 +122,8 @@ typedef struct box86context_s {
lib_t *maplib; // lib and symbols handling
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
dic_t *versym; // dictionnary of versionned symbols
dic_t *versym; // dictionnary of versioned symbols
kh_mapsymbols_t *globdata; // GLOBAL_DAT relocation for COPY mapping in main elf
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
bridge_t *system; // other bridges
@@ -120,8 +134,6 @@ typedef struct box86context_s {
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
vkprocaddress_t vkprocaddress;
#ifndef DYNAREC
@@ -133,6 +145,7 @@ typedef struct box86context_s {
pthread_mutex_t mutex_bridge;
pthread_mutex_t mutex_lock;
#else
#ifdef USE_CUSTOM_MUTEX
uint32_t mutex_once;
uint32_t mutex_once2;
uint32_t mutex_trace;
@@ -140,6 +153,15 @@ typedef struct box86context_s {
uint32_t mutex_thread;
uint32_t mutex_bridge;
uint32_t mutex_dyndump;
#else
pthread_mutex_t mutex_once;
pthread_mutex_t mutex_once2;
pthread_mutex_t mutex_trace;
pthread_mutex_t mutex_tls;
pthread_mutex_t mutex_thread;
pthread_mutex_t mutex_bridge;
pthread_mutex_t mutex_dyndump;
#endif
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
int trace_dynarec;
pthread_mutex_t mutex_lock; // this is for the Test interpreter
@@ -157,10 +179,10 @@ typedef struct box86context_s {
void* sdl2allocrw; // AllocRW/FreeRW functions from SDL2
void* sdl2freerw;
int deferedInit;
elfheader_t **deferedInitList;
int deferedInitSz;
int deferedInitCap;
int deferredInit;
elfheader_t **deferredInitList;
int deferredInitSz;
int deferredInitCap;
pthread_key_t tlskey; // then tls key to have actual tlsdata
void* tlsdata; // the initial global tlsdata
@@ -169,9 +191,9 @@ typedef struct box86context_s {
uintptr_t *auxval_start;
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
cleanup_t *cleanups; // atexit functions
int clean_sz;
int clean_cap;
#ifndef NOALIGN
kh_fts_t *ftsmap;
#endif
@@ -185,10 +207,10 @@ typedef struct box86context_s {
uint8_t canary[4];
uintptr_t signals[MAX_SIGNAL];
uintptr_t restorer[MAX_SIGNAL];
int onstack[MAX_SIGNAL];
int is_sigaction[MAX_SIGNAL];
uintptr_t signals[MAX_SIGNAL+1];
uintptr_t restorer[MAX_SIGNAL+1];
int onstack[MAX_SIGNAL+1];
int is_sigaction[MAX_SIGNAL+1];
x86emu_t *emu_sig; // the emu with stack used for signal handling (must be separated from main ones)
int no_sigsegv;
int no_sigill;
@@ -201,7 +223,7 @@ typedef struct box86context_s {
int current_line;
} box86context_t;
#ifndef DYNAREC
#ifndef USE_CUSTOM_MUTEX
#define mutex_lock(A) pthread_mutex_lock(A)
#define mutex_trylock(A) pthread_mutex_trylock(A)
#define mutex_unlock(A) pthread_mutex_unlock(A)
@@ -224,6 +246,8 @@ void print_cycle_log(int loglevel);
// return the index of the added header
int AddElfHeader(box86context_t* ctx, elfheader_t* head);
// remove an elf from list (but list is never reduced, so there can be holes)
void RemoveElfHeader(box86context_t* ctx, elfheader_t* head);
// return the tlsbase (negative) for the new TLS partition created (no partition index is stored in the context)
int AddTLSPartition(box86context_t* context, int tlssize);
+1 -1
View File
@@ -14,7 +14,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
uintptr_t CheckBridged(bridge_t* bridge, void* fnc);
int IsBridge(void* func);
uintptr_t AddCheckBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N);
uintptr_t AddAutomaticBridge(x86emu_t* emu, bridge_t* bridge, wrapper_t w, void* fnc, int N, const char* name);
void* GetNativeFnc(uintptr_t fnc);
void* GetNativeFncOrFnc(uintptr_t fnc);
+7 -3
View File
@@ -5,11 +5,15 @@
typedef struct x86emu_s x86emu_t;
uint32_t RunFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint32_t RunFunction(uintptr_t fnc, int nargs, ...);
// using a fmt description
uint32_t RunFunctionFmt(uintptr_t fnc, const char* fmt, ...);
// use thread local emu to run the function (context is unused now)
uint64_t RunFunction64(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint64_t RunFunction64(uintptr_t fnc, int nargs, ...);
// using a fmt description and returning a 64bit value
uint64_t RunFunctionFmt64(uintptr_t fnc, const char* fmt, ...);
// use emu state to run function
uint32_t RunFunctionWithEmu(x86emu_t *emu, int QuitOnLongJump, uintptr_t fnc, int nargs, ...);
uint32_t RunSafeFunction(box86context_t *context, uintptr_t fnc, int nargs, ...);
uint32_t RunSafeFunction(uintptr_t fnc, int nargs, ...);
#endif //__CALLBACK_H__
+5 -3
View File
@@ -40,13 +40,13 @@ uintptr_t getJumpAddress(uintptr_t addr);
#define PROT_DYNAREC 0x80
#define PROT_DYNAREC_R 0x40
#define PROT_NOPROT 0x20
#define PROT_MMAP 0x10
#define PROT_DYN (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_MMAP | PROT_NOPROT)
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R | PROT_NOPROT)
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
void setProtection_mmap(uintptr_t addr, size_t size, uint32_t prot);
void setProtection_elf(uintptr_t addr, size_t size, uint32_t prot);
void freeProtection(uintptr_t addr, size_t size);
void refreshProtection(uintptr_t addr);
uint32_t getProtection(uintptr_t addr);
@@ -61,7 +61,9 @@ int AreaInHotPage(uintptr_t start, uintptr_t end);
void AddHotPage(uintptr_t addr);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
void* findBlockNearHint(void* hint, size_t size, uintptr_t mask);
void* find32bitBlockElf(size_t size, int mainbin, uintptr_t mask);
int isBlockFree(void* hint, size_t size);
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
int unlockCustommemMutex();
+17 -2
View File
@@ -27,17 +27,26 @@ extern int box86_dynarec_hotpage;
extern int box86_dynarec_wait;
extern int box86_dynarec_fastpage;
extern int box86_dynarec_bleeding_edge;
extern int box86_dynarec_missing;
extern int box86_dynarec_test;
extern int box86_dynarec_jvm;
extern int box86_dynarec_tbb;
#ifdef ARM
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
extern int arm_div;
extern int arm_aes;
extern int arm_pmull;
#endif
#endif
extern int box86_libcef;
extern int box86_sdl2_jguid;
extern int dlsym_error; // log dlsym error
extern int cycle_log; // if using rolling logs
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int box86_nosandbox;
extern int box86_malloc_hack;
extern int box86_sse_flushto0;
extern int box86_x87_no80bits;
extern int allow_missing_libs;
@@ -45,11 +54,14 @@ extern int box86_prefer_wrapped;
extern int box86_prefer_emulated;
extern int box86_steam;
extern int box86_wine;
extern int box86_musl;
extern int box86_nopulse; // disabling the use of wrapped pulseaudio
extern int box86_nogtk; // disabling the use of wrapped gtk
extern int box86_novulkan; // disabling the use of wrapped vulkan
extern int box86_futex_waitv;
extern int box86_mapclean;
extern int box86_showsegv;
extern int box86_mutex_aligned;
extern int allow_missing_symbols;
extern uintptr_t trace_start, trace_end;
extern char* trace_func;
@@ -60,6 +72,7 @@ extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal
extern uint32_t default_fs;
extern int jit_gdb; // launch gdb when a segfault is trapped
extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
extern int box86_isglibc234; // is the program linked with glibc 2.34+
extern int box86_x11threads;
extern int box86_x11glx;
extern char* box86_libGL;
@@ -93,8 +106,10 @@ void init_malloc_hook();
#define box_calloc calloc
#define box_free free
#define box_memalign memalign
#define box_strdup strdup
#define box_realpath realpath
#else
extern size_t(*box_malloc_usable_size)(void*);
extern size_t(*box_malloc_usable_size)(const void*);
extern void* __libc_malloc(size_t);
extern void* __libc_realloc(void*, size_t);
extern void* __libc_calloc(size_t, size_t);
@@ -105,8 +120,8 @@ extern void* __libc_memalign(size_t, size_t);
#define box_calloc __libc_calloc
#define box_free __libc_free
#define box_memalign __libc_memalign
#endif
extern char* box_strdup(const char* s);
extern char* box_realpath(const char* path, char* ret);
#endif
#endif //__DEBUG_H_
+26 -19
View File
@@ -9,66 +9,73 @@ typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_defaultversion_s kh_defaultversion_t;
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
#endif
// Open an elfheader. Transfert control of f to elfheader also!
elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
void FreeElfHeader(elfheader_t** head);
const char* ElfName(elfheader_t* head);
const char* ElfPath(elfheader_t* head);
void ElfAttachLib(elfheader_t* head, library_t* lib);
// return 0 if OK
int CalcLoadAddr(elfheader_t* head);
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
int AllocLoadElfMemory(box86context_t* context, elfheader_t* head, int mainbin);
void FreeElfMemory(elfheader_t* head);
int LoadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head);
int RelocateElf(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
int RelocateElfPlt(lib_t* maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, uint32_t* stackalign);
int isElfHasNeededVer(elfheader_t* head, const char* libname, elfheader_t* verneeded);
int RelocateElf(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, int bindnow, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, size_t* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu);
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, int local, int bindnow, box86context_t *box86, x86emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RefreshElfTLS(elfheader_t* h);
void RunElfInit(elfheader_t* h, x86emu_t* emu);
void RunElfFini(elfheader_t* h, x86emu_t* emu);
void RunDeferedElfInit(x86emu_t* emu);
void RunElfInit(elfheader_t* h, x86emu_t *emu);
void RunElfFini(elfheader_t* h, x86emu_t *emu);
void RunDeferredElfInit(x86emu_t *emu);
void MarkElfInitDone(elfheader_t* h);
void* GetBaseAddress(elfheader_t* h);
void* GetElfDelta(elfheader_t* h);
uint32_t GetBaseSize(elfheader_t* h);
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
elfheader_t* FindElfAddress(box86context_t* context, uintptr_t addr);
int IsAddressInElfSpace(const elfheader_t* h, uintptr_t addr);
elfheader_t* FindElfAddress(box86context_t *context, uintptr_t addr);
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
int32_t GetTLSBase(elfheader_t* h);
uint32_t GetTLSSize(elfheader_t* h);
void* GetTLSPointer(box86context_t* context, elfheader_t* h);
void* GetDTatOffset(box86context_t* context, int index, int offset);
#ifdef DYNAREC
dynablock_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr);
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr);
#endif
void ResetSpecialCaseMainElf(elfheader_t* h);
void CreateMemorymapFile(box86context_t* context, int fd);
void* GetDynamicSection(elfheader_t* h);
void* ElfGetBrk(elfheader_t* h);
void* ElfSetBrk(void* newbrk);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
const char* GetSymbolVersion(elfheader_t* h, int version);
const char* GetParentSymbolVersion(elfheader_t* h, int index);
const char* VersionnedName(const char* name, int ver, const char* vername);
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
const char* VersionedName(const char* name, int ver, const char* vername);
int SameVersionedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
int GetVersionIndice(elfheader_t* h, const char* vername);
int GetNeededVersionCnt(elfheader_t* h, const char* libname);
const char* GetNeededVersionString(elfheader_t* h, const char* libname, int idx);
int GetNeededVersionForLib(elfheader_t* h, const char* libname, const char* ver);
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h);
kh_defaultversion_t* GetGlobalDefaultVersion(elfheader_t* h);
kh_defaultversion_t* GetWeakDefaultVersion(elfheader_t* h);
void* GetNativeSymbolUnversionned(void* lib, const char* name);
void* GetNativeSymbolUnversioned(void* lib, const char* name);
void AddMainElfToLinkmap(elfheader_t* lib);
#endif //__ELF_LOADER_H_
+2
View File
@@ -10,8 +10,10 @@ void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
// NCurse / TInfo
void my_checkGlobalTInfo();
void my_updateGlobalTInfo(void);
// getopt
void my_checkGlobalOpt();
void my_updateGlobalOpt(void);
#endif //_GLOBAL_SYMBOLS_H_
+16 -8
View File
@@ -10,28 +10,36 @@ typedef struct dlprivate_s dlprivate_t;
typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
typedef struct elfheader_s elfheader_t;
typedef struct box86context_s box86context_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapoffsets_s kh_mapoffsets_t;
typedef char* cstr_t;
lib_t *NewLibrarian(box86context_t* context, int ownlibs);
void FreeLibrarian(lib_t **maplib, x86emu_t* emu);
dlprivate_t *NewDLPrivate();
dlprivate_t *NewDLPrivate(void);
void FreeDLPrivate(dlprivate_t **lib);
box86context_t* GetLibrarianContext(lib_t* maplib);
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86context_t* box86, x86emu_t* emu);
library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
void promoteLocalLibGlobal(library_t* lib);
int isLibLocal(library_t* lib);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver);
void MapLibRemoveLib(lib_t* maplib, library_t* lib);
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref);
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t *local_maplib, int isweak, const char* symname);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib);
+11 -10
View File
@@ -15,25 +15,26 @@ typedef struct elfheader_s elfheader_t;
#define LIB_EMULATED 1
#define LIB_UNNKNOW -1
library_t *NewLibrary(const char* path, box86context_t* box86);
library_t *NewLibrary(const char* path, box86context_t* box86, elfheader_t* verneeded);
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x86emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, int bindnow, x86emu_t* emu);
int ReloadLibrary(library_t* lib, x86emu_t* emu);
void InactiveLibrary(library_t* lib);
void Free1Library(library_t **lib, x86emu_t* emu);
char* GetNameLib(library_t *lib);
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int *weak, int version, const char* vername, int local);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local);
needed_libs_t* GetNeededLibs(library_t* lib);
int GetNeededLibN(library_t* lib);
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
char** GetNeededLibsNames(library_t* lib);
int GetNeededLibsN(library_t* lib);
library_t* GetNeededLib(library_t* lib, int idx);
lib_t* GetMaplib(library_t* lib);
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped)
elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped)
void* GetHandle(library_t* lib); // NULL if not wrapped
void IncRefCount(library_t* lib, x86emu_t* emu);
int DecRefCount(library_t** lib, x86emu_t* emu); // might unload the lib!
int GetRefCount(library_t* lib);
#endif //__LIBRARY_H_
void SetDlOpenIdx(library_t* lib, int dlopen);
#endif //__LIBRARY_H_
+17 -1
View File
@@ -345,4 +345,20 @@ typedef struct my_GValue_s
} my_GValue_t;
void alignNGValue(my_GValue_t* v, void* value, int n);
void unalignNGValue(void* value, my_GValue_t* v, int n);
void unalignNGValue(void* value, my_GValue_t* v, int n);
// longjmp / setjmp
typedef struct jump_buff_i386_s {
uint32_t save_ebx;
uint32_t save_esi;
uint32_t save_edi;
uint32_t save_ebp;
uint32_t save_esp;
uint32_t save_eip;
} jump_buff_i386_t;
typedef struct __jmp_buf_tag_s {
jump_buff_i386_t __jmpbuf;
int __mask_was_saved;
sigset_t __saved_mask;
} __jmp_buf_tag_t;
+24 -2
View File
@@ -7,7 +7,7 @@ enum {
};
enum {
_CS, _DS, _SS, _ES, _FS, _GS
_ES, _CS, _SS, _DS, _FS, _GS
};
@@ -96,7 +96,9 @@ typedef enum {
d_rcr8,
d_rcr16,
d_rcr32,
d_unknown //46
d_shld32,
d_shrd32,
d_unknown //66
} defered_flags_t;
#pragma pack(push, 1)
@@ -289,6 +291,26 @@ typedef union {
#define R_ES emu->segs[_ES]
#define R_FS emu->segs[_FS]
#define R_GS emu->segs[_GS]
#define S_EAX emu->regs[_AX].sdword[0]
#define S_EBX emu->regs[_BX].sdword[0]
#define S_ECX emu->regs[_CX].sdword[0]
#define S_EDX emu->regs[_DX].sdword[0]
#define S_EDI emu->regs[_DI].sdword[0]
#define S_ESI emu->regs[_SI].sdword[0]
#define S_ESP emu->regs[_SP].sdword[0]
#define S_EBP emu->regs[_BP].sdword[0]
#define S_AX emu->regs[_AX].sword[0]
#define S_BX emu->regs[_BX].sword[0]
#define S_CX emu->regs[_CX].sword[0]
#define S_DX emu->regs[_DX].sword[0]
#define S_DI emu->regs[_DI].sword[0]
#define S_SI emu->regs[_SI].sword[0]
#define S_SP emu->regs[_SP].sword[0]
#define S_BP emu->regs[_BP].sword[0]
#define S_AL emu->regs[_AX].sbyte[0]
#define S_AH emu->regs[_AX].sbyte[1]
#define S_CX emu->regs[_CX].sword[0]
#define S_CL emu->regs[_CX].sbyte[0]
#define ACCESS_FLAG(F) emu->eflags.f._##F
#define SET_FLAG(F) emu->eflags.f._##F = 1
+1
View File
@@ -38,5 +38,6 @@ void init_signal_helper(box86context_t* context);
void fini_signal_helper();
void emit_signal(x86emu_t* emu, int sig, void* addr, int code);
void emit_div0(x86emu_t* emu, void* addr, int code);
#endif //__SIGNALS_H__
+4 -2
View File
@@ -9,12 +9,14 @@ typedef struct versymbols_s versymbols_t;
KHASH_MAP_DECLARE_STR(mapsymbols, versymbols_t)
kh_mapsymbols_t* NewMapSymbols();
kh_mapsymbols_t* NewMapSymbols(void);
void FreeMapSymbols(kh_mapsymbols_t** map);
// replace if already there
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver);
// Update addr and sz of existing symbols
void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz);
// don't add if already there
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver);
@@ -23,7 +25,7 @@ const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs,
// default version handling
KHASH_MAP_DECLARE_STR(defaultversion, const char*)
kh_defaultversion_t* NewDefaultVersion();
kh_defaultversion_t* NewDefaultVersion(void);
void FreeDefaultVersion(kh_defaultversion_t** def);
void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char* vername);
+2 -9
View File
@@ -4,23 +4,16 @@
typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
typedef struct emu_jmpbuf_s {
void* jmpbuf;
int jmpbuf_ok;
x86emu_t* emu;
} emu_jmpbuf_t;
void CleanStackSize(box86context_t* context);
emu_jmpbuf_t* GetJmpBuf();
void init_pthread_helper();
void fini_pthread_helper(box86context_t* context);
void clean_current_emuthread(void);
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet);
#ifndef DYNAREC
#ifndef USE_CUSTOM_MUTEX
//check and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
int checkUnlockMutex(void* m);
#endif
+2 -2
View File
@@ -7,7 +7,7 @@ typedef struct box86context_s box86context_t;
typedef int (*wrappedlib_init_t)(library_t * lib, box86context_t* box86); // 0 = success
typedef void (*wrappedlib_fini_t)(library_t * lib);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, size_t size, int* weak, int version, const char* vername, int local);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, size_t size, int* weak, int version, const char* vername, int local, const char* defver);
void setNeededLibs(library_t* lib, int n, ...);
#define SETALT(A) lib->w.altmy = box_strdup(#A)
@@ -19,4 +19,4 @@ typedef struct wrappedlib_s {
wrappedlib_fini_t fini;
} wrappedlib_t;
#endif //__WRAPPEDLIBS_H__
#endif //__WRAPPEDLIBS_H__
+62 -22
View File
@@ -16,10 +16,24 @@
// workaround for Globals symbols
#define GLOB(A) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <= %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
#define GLOB(A, B) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
} else \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <- %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
}
#define TOGLOB(A, B) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
} else \
if (B && GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL, B)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p -> %p\n", (void*)globoffs, &A); \
memcpy(&A, (void*)globoffs, sizeof(A)); \
}
@@ -29,14 +43,14 @@ EXPORT void* gdk_display = NULL; // in case it's used...
void my_checkGlobalGdkDisplay()
{
uintptr_t globoffs, globend;
GLOB(gdk_display)
GLOB(gdk_display, NULL)
}
void my_setGlobalGThreadsInit()
{
int val = 1;
uintptr_t globoffs, globend;
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL, NULL)) {
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
memcpy((void*)globoffs, &val, sizeof(val));
}
@@ -74,29 +88,55 @@ EXPORT void* ttytype;
void my_checkGlobalTInfo()
{
uintptr_t globoffs, globend;
GLOB(COLS)
GLOB(LINES)
GLOB(TABSIZE)
GLOB(curscr)
GLOB(newscr)
GLOB(stdscr)
GLOB(acs_map)
GLOB(UP)
GLOB(BC)
GLOB(PC)
GLOB(ospeed)
GLOB(ttytype)
GLOB(COLS, NULL)
GLOB(LINES, NULL)
GLOB(TABSIZE, NULL)
GLOB(curscr, NULL)
GLOB(newscr, NULL)
GLOB(stdscr, NULL)
GLOB(acs_map, NULL)
GLOB(UP, NULL)
GLOB(BC, NULL)
GLOB(PC, NULL)
GLOB(ospeed, NULL)
GLOB(ttytype, NULL)
}
void my_updateGlobalTInfo()
{
uintptr_t globoffs, globend;
TOGLOB(COLS, NULL)
TOGLOB(LINES, NULL)
TOGLOB(TABSIZE, NULL)
TOGLOB(curscr, NULL)
TOGLOB(newscr, NULL)
TOGLOB(stdscr, NULL)
TOGLOB(acs_map, NULL)
TOGLOB(UP, NULL)
TOGLOB(BC, NULL)
TOGLOB(PC, NULL)
TOGLOB(ospeed, NULL)
TOGLOB(ttytype, NULL)
}
// **************** getopts ****************
EXPORT char *optarg;
EXPORT int optind, opterr, optopt;
void my_updateGlobalOpt()
{
uintptr_t globoffs, globend;
TOGLOB(optarg, "GLIBC_2.2.5");
TOGLOB(optind, "GLIBC_2.2.5");
TOGLOB(opterr, "GLIBC_2.2.5");
TOGLOB(optopt, "GLIBC_2.2.5");
}
void my_checkGlobalOpt()
{
uintptr_t globoffs, globend;
GLOB(optarg);
GLOB(optind);
GLOB(opterr);
GLOB(optopt);
GLOB(optarg, "GLIBC_2.2.5");
GLOB(optind, "GLIBC_2.2.5");
GLOB(opterr, "GLIBC_2.2.5");
GLOB(optopt, "GLIBC_2.2.5");
}
+355 -190
View File
@@ -12,7 +12,6 @@
#include "x86emu.h"
#include "box86context.h"
#include "elfloader.h"
#include "symbols.h"
#include "bridge.h"
@@ -20,7 +19,6 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
lib_t *NewLibrarian(box86context_t* context, int ownlibs)
{
(void)context;
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
maplib->mapoffsets = kh_init(mapoffsets);
@@ -31,39 +29,7 @@ lib_t *NewLibrarian(box86context_t* context, int ownlibs)
return maplib;
}
static void freeLibraryRecurse(lib_t *maplib, x86emu_t *emu, int idx, char *freed, library_t* owner) {
if (freed[idx]) return; // Already freed
library_t *lib = maplib->libraries[idx];
if(lib==owner) return; // don't free owner of maplib
freed[idx] = 1; // Avoid infinite loops
printf_log(LOG_DEBUG, "Unloading %s\n", lib->name);
for (int i = lib->dependedby.size - 1; i >= 0; --i) {
int j;
for (j = 0; j < maplib->libsz; ++j) {
if (lib->dependedby.libs[i] == maplib->libraries[j]) break;
}
if (j == maplib->libsz) {
// dependant lib already freed
// library as been freed already
continue;
}
if (freed[j] == 1) {
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->dependedby.libs[i]->name);
continue;
}
freeLibraryRecurse(maplib, emu, j, freed, owner);
if (freed[idx] != 1) {
printf_log(LOG_DEBUG, "Note: library already freed (cyclic dependancy break)\n");
return;
}
}
library_t *ptr = maplib->libraries[idx];
if(maplib->ownlibs/* && (!maplib->owner || ptr->maplib==maplib)*/)
Free1Library(&ptr, emu);
freed[idx] = 2;
}
void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
{
// should that be in reverse order?
@@ -72,26 +38,13 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
library_t* owner = (*maplib)->owner;
(*maplib)->owner = NULL; // to avoid recursive free...
if((*maplib)->ownlibs && (*maplib)->libsz) {
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
char *freed = (char*)box_calloc((*maplib)->libsz, sizeof(char));
if (!freed) {
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
for (int i=(*maplib)->libsz-1; i>=0; --i)
if((*maplib)->libraries[i]!=owner) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
Free1Library(&(*maplib)->libraries[i], emu);
}
} else {
for (int i=(*maplib)->libsz-1; i>=0; --i) {
freeLibraryRecurse(*maplib, emu, i, freed, owner);
}
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
(*maplib)->libsz = 0;
box_free(freed);
/*if((*maplib)->ownlibs && (*maplib)->libsz) {
for(int i=0; i<(*maplib)->libsz; ++i) {
printf_dump(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
DecRefCount(&(*maplib)->libraries[i], emu);
}
}
}*/
box_free((*maplib)->libraries);
(*maplib)->libraries = NULL;
@@ -111,7 +64,6 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
box86context_t* GetLibrarianContext(lib_t* maplib)
{
(void)maplib;
return my_context;
}
@@ -153,7 +105,27 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
++maplib->libsz;
}
static void MapLibRemoveLib(lib_t* maplib, library_t* lib);
void MapLibPrependLib(lib_t* maplib, library_t* lib, library_t* ref)
{
if(libraryInMapLib(maplib, lib))
return;
if (maplib->libsz == maplib->libcap) {
maplib->libcap += 8;
maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
}
// find insersion point
int point = ref?maplib->libsz:0;
if(ref)
for(int i=0; i<maplib->libsz; ++i)
if(maplib->libraries[i]==ref) {
point = i;
i = maplib->libsz;
}
if(point<maplib->libsz)
memmove(&maplib->libraries[point+1], &maplib->libraries[point], sizeof(library_t*)*(maplib->libsz-point));
maplib->libraries[point] = lib;
++maplib->libsz;
}
static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
{
@@ -175,7 +147,7 @@ static void MapLibAddMapLib(lib_t* dest, library_t* lib_src, lib_t* src)
FreeLibrarian(&src, NULL);
}
static void MapLibRemoveLib(lib_t* maplib, library_t* lib)
void MapLibRemoveLib(lib_t* maplib, library_t* lib)
{
if(!maplib || !lib)
return;
@@ -206,63 +178,71 @@ static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
}
}
int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box86context_t* box86, x86emu_t* emu)
void promoteLocalLibGlobal(library_t* lib)
{
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
if(!lib || !my_context)
return;
// promote lib from local to global...
// for add the depending local libs...
if(lib->maplib) {
MapLibAddMapLib(my_context->maplib, lib, lib->maplib);
}
if(!libraryInMapLib(my_context->maplib, lib))
MapLibAddLib(my_context->maplib, lib);
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
}
int isLibLocal(library_t* lib)
{
if(!lib || !my_context)
return 0;
return libraryInMapLib(my_context->local_maplib, lib);
}
static int AddNeededLib_add(lib_t** maplib, int local, needed_libs_t* needed, int n, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
{
const char* path = needed->names[n];
printf_dump(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
// first check if lib is already loaded
library_t *lib = getLib(my_context->maplib, path);
if(lib) {
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
IncRefCount(lib, emu); // increment cntref
needed->libs[n] = lib;
printf_dump(LOG_DEBUG, "Already present in maplib => success\n");
return 0;
}
// check also in the local loaded lib
lib = getLib(my_context->local_maplib, path);
if(lib) {
printf_log(LOG_DEBUG, "Already present in local_maplib => success\n");
printf_dump(LOG_DEBUG, "Already present in local_maplib => success\n");
needed->libs[n] = lib;
IncRefCount(lib, emu); // increment cntref
if(local) {
// add lib to maplib...
if(maplib) {
if(lib->maplib) {
MapLibAddMapLib(maplib, lib, lib->maplib);
}
if(!libraryInMapLib(maplib, lib))
MapLibAddLib(maplib, lib);
if(maplib->ownlibs)
MapLibRemoveMapLib(my_context->local_maplib, maplib);
if(*maplib) {
if(!libraryInMapLib(*maplib, lib))
MapLibPrependLib(*maplib, lib, NULL); // todo: Also insert libs needed by lib, after lib? But current lib->maplib is probably not the solution
if((*maplib)->ownlibs)
MapLibRemoveMapLib(my_context->local_maplib, *maplib);
}
} else {
// promote lib from local to global...
// for add the depending local libs...
if(lib->maplib) {
MapLibAddMapLib(my_context->maplib, lib, lib->maplib);
}
if(!libraryInMapLib(my_context->maplib, lib))
MapLibAddLib(my_context->maplib, lib);
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
promoteLocalLibGlobal(lib);
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
return 0;
}
// load a new one
lib = NewLibrary(path, box86);
needed->libs[n] = lib = NewLibrary(path, box86, verneeded);
if(!lib) {
printf_log(LOG_DEBUG, "Faillure to create lib => fail\n");
printf_dump(LOG_DEBUG, "Faillure to create lib => fail\n");
return 1; //Error
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedbylib(&lib->dependedby, deplib);
// add lib now
if(local) {
MapLibAddLib(my_context->local_maplib, lib);
if(maplib) {
MapLibAddLib(maplib, lib);
if(!lib->maplib)
lib->maplib = maplib;
if(*maplib) {
MapLibAddLib(*maplib, lib);
} else {
lib->maplib = NewLibrarian(box86, 0);
MapLibAddLib(lib->maplib, lib);
@@ -271,11 +251,11 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
MapLibAddLib(my_context->maplib, lib);
}
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
if(!*maplib)
*maplib = (local)?lib->maplib:my_context->maplib;
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
if(AddSymbolsLibrary(*maplib, lib, emu)) { // also add needed libs
printf_dump(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
}
@@ -284,89 +264,124 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
// Crashed already
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
printf_dump(LOG_DEBUG, "Failure to add lib linkmap\n");
return 1;
}
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]);
lm->l_addr = (Elf32_Addr)GetElfDelta(lib->e.elf);
lm->l_name = lib->name;
lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]);
lm->l_ld = GetDynamicSection(lib->e.elf);
}
return 0;
}
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, library_t* lib, box86context_t* box86, x86emu_t* emu)
int AddNeededLib_init(lib_t* maplib, int local, int bindnow, library_t* lib, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
{
(void)neededlibs; (void)deplib;
if(!lib) // no lib, error is already detected, no need to return a new one
return 0;
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
int mainelf = GetElfIndex(lib);
elfheader_t* mainelf = GetElf(lib);
if(mainelf==-1) {
if(!mainelf) {
// It's a native libs, nothing else to do
} else {
// it's an emulated lib,
// load dependancies and launch init sequence
if(LoadNeededLibs(box86->elfs[mainelf], maplib, &lib->needed, lib, 0, bindnow, box86, emu)) {
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
if(LoadNeededLibs(mainelf, maplib, local, bindnow, box86, emu)) {
printf_dump(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
const char* libs[] = {"libGL.so.1"};
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 1, box86, emu);
char* names[] = {"libGL.so.1"}; // TODO: it will never be uninit...
library_t* libs[] = { NULL };
needed_libs_t tmp = {0};
tmp.size = tmp.cap = 1;
tmp.names = names;
tmp.libs = libs;
AddNeededLib(maplib, 0, 0, &tmp, verneeded, box86, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
AddNeededLib(maplib, &lib->needed, lib, 0, 0, libs, 2, box86, emu);
char* names[] = {"libSDL-1.2.so.0", "libdl.so.2"}; // TODO: they will never be uninit...
library_t* libs[] = { NULL, NULL };
needed_libs_t tmp = {0};
tmp.size = tmp.cap = 2;
tmp.names = names;
tmp.libs = libs;
AddNeededLib(maplib, 0, 0, &tmp, verneeded, box86, emu);
}
// finalize the lib
if(FinalizeLibrary(lib, local?maplib:NULL, bindnow, emu)) {
printf_log(LOG_DEBUG, "Failure to finalizing lib => fail\n");
printf_dump(LOG_DEBUG, "Failure to finalizing lib => fail\n");
return 1;
}
}
// success
printf_log(LOG_DEBUG, "Created lib and added to maplib => success\n");
printf_dump(LOG_DEBUG, "Created lib and added to maplib => success\n");
return 0;
}
void AddNeededLib_remove(lib_t* maplib, int local, library_t** lib, box86context_t* box86, x86emu_t* emu)
{
if(!lib || !*lib) // no lib, error is already detected, no need to return a new one
return;
if(!maplib)
maplib = (local)?(*lib)->maplib:my_context->maplib;
DecRefCount(lib, emu);
}
EXPORTDYN
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu)
int AddNeededLib(lib_t* maplib, int local, int bindnow, needed_libs_t* needed, elfheader_t* verneeded, box86context_t* box86, x86emu_t* emu)
{
if(!needed) // no needed libs, no problems
return 0;
box86_mapclean = 0;
if(!neededlibs) {
neededlibs = box_calloc(1, sizeof(needed_libs_t));
}
int idx = neededlibs->size;
int ret = 0;
// Add libs and symbol
for(int i=0; i<npath; ++i) {
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box86, emu)) {
printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]);
return 1;
for(int i=0; i<needed->size; ++i) {
if(AddNeededLib_add(&maplib, local, needed, i, verneeded, box86, emu)) {
printf_log(strchr(needed->names[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", needed->names[i]);
ret = 1;
}
}
int idx_end = neededlibs->size;
// error while loadind lib, unload...
if(ret) {
return ret;
}
// add dependant libs and init them
for (int i=idx; i<idx_end; ++i)
if(AddNeededLib_init(maplib, neededlibs, deplib, local, bindnow, neededlibs->libs[i], box86, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
if(!allow_missing_libs) return 1;
for (int i=0; i<needed->size; ++i)
if(AddNeededLib_init(maplib, local, bindnow, needed->libs[i], verneeded, box86, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", needed->names[i]);
if(!allow_missing_libs) ret = 1;
}
return 0;
// error while loadind lib, unload...
return ret;
}
EXPORTDYN
void RemoveNeededLib(lib_t* maplib, int local, needed_libs_t* needed, box86context_t* box86, x86emu_t* emu)
{
if(!needed) // no needed libs, no problems
return;
for(int i=0; i<needed->size; ++i) {
if(box86_log>=LOG_DEBUG && needed->libs[i])
printf_dump(LOG_DEBUG, "Will remove after failed init %s\n", needed->names[i]);
AddNeededLib_remove(maplib, local, &needed->libs[i], box86, emu);
}
}
library_t* GetLibMapLib(lib_t* maplib, const char* name)
{
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
return getLib(maplib, name);
}
library_t* GetLibInternal(const char* name)
{
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
printf_dump(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
library_t* lib = getLib(my_context->maplib, name);
if(!lib) lib = getLib(my_context->local_maplib, name);
return lib;
@@ -376,7 +391,9 @@ EXPORTDYN
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start = 0, end = 0;
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername))
const char *globdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name);
const char *weakdefver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name);
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername, globdefver, weakdefver))
return start;
return 0;
}
@@ -388,7 +405,21 @@ static int isLocal(elfheader_t* self, library_t* l)
return 0;
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername)
static void CheckNeededLibs(needed_libs_t* needed)
{
while(needed->nb_done<needed->size) {
library_t* lib = needed->libs[needed->nb_done++];
if(lib) {
int n = GetNeededLibsN(lib);
char** names = GetNeededLibsNames(lib);
for (int i=0; i<n; ++i) {
add1lib_neededlib(needed, GetNeededLib(lib, i), names[i]);
}
}
}
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, size_t size, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
assert(self); // need self for this one
//search for the self, to start "next"
@@ -400,39 +431,41 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
}
if(go<0)
go = 0; // not found...
if(maplib)
for(int i=go; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0))
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, globdefver))
if(*start)
return 1;
}
if(maplib)
for(int i=go; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0);
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 0, weakdefver);
// loop done, weak symbol found
if(weak && *start)
return 1;
// if self defined, give it another chance with self...
if(self) {
if(my_context->elfs[0]!=self) {
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
if(GetSizedSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, globdefver))
if(*start)
return 1;
defver = GetDefaultVersion(my_context->weakdefver, name);
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, defver))
if(GetSizedSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, size, version, vername, 1, weakdefver))
if(*start)
weak = 1;
}
if(maplib)
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, globdefver))
if(*start)
return 1;
}
if(maplib)
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1);
if(GetElfIndex(maplib->libraries[i])==-1 || (GetElf(maplib->libraries[i])!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, weakdefver);
}
if(weak && *start)
return 1;
@@ -440,39 +473,67 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
// nope, not found
return 0;
}
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
int weak = 0;
size_t size = 0;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
if(*start)
return 1;
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
// search in needed libs from neededlibs first, in order
for(int i=0; i<my_context->neededlibs.size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
if(*start)
// search in needed libs from preloaded first, in order
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
if(*start) {
return 1;
}
if(maplib==my_context->maplib) {
// search non-weak symbol, from older to newer (first GLOBAL object wins, starting with self)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start) {
return 1;
}
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
if(*start) {
return 1;
}
}
// search in global symbols
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
return 1;
if(maplib) {
if((maplib==my_context->maplib) && self && self!=my_context->elfs[0] && self!=(void*)1)
if(GetSymbolStartEnd(GetMapSymbols(self), name, start, end, version, vername, 1, globdefver))
if(*start) {
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
if(*start) {
return 1;
}
}
}
// check with default version...
defver = GetDefaultVersion(my_context->weakdefver, name);
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
if(*start)
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
if(*start) {
ok = 1;
}
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibWeakSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), weakdefver))
if(*start) {
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
if(*start)
ok = 1;
}
@@ -481,15 +542,15 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
}
void** my_GetGTKDisplay();
void** my_GetGthreadsGotInitialized();
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1);
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
if(end2>*end && start2==end2)
*end = end2;
}
@@ -514,6 +575,108 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 0;
}
static int GetGlobalWeakSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
int weak = 0;
size_t size = 0;
// search in needed libs from preloaded first, in order
if(my_context->preload)
for(int i=0; i<my_context->preload->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->preload->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->preload->libs[i]), globdefver))
if(*start)
return 1;
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, globdefver))
if(*start)
return 1;
// This kind-of create a map to search lib only 1 time, and in order of needed...
if(my_context->neededlibs)
CheckNeededLibs(my_context->neededlibs);
// search in needed libs from neededlibs first, in order
if(my_context->neededlibs)
for(int i=0; i<my_context->neededlibs->size; ++i)
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs->libs[i], name, start, end, size, &weak, version, vername, isLocal(self, my_context->neededlibs->libs[i]), globdefver))
if(*start)
return 1;
// search in global symbols
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), globdefver))
if(*start)
return 1;
}
// check with default version...
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, weakdefver))
if(*start)
ok = 1;
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, isLocal(self, maplib->libraries[i]), weakdefver))
if(*start)
ok = 1;
}
// nope, not found
return (ok && *start)?1:0;
}
int GetGlobalWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
if(GetGlobalWeakSymbolStartEnd_internal(maplib, name, start, end, self, version, vername, globdefver, weakdefver)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalWeakSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername, globdefver, weakdefver)) {
if(end2>*end && start2==end2)
*end = end2;
}
box_free(buff);
}
return 1;
}
// some special case symbol, defined inside box86 itself
if(!strcmp(name, "gdk_display")) {
*start = (uintptr_t)my_GetGTKDisplay();
*end = *start+sizeof(void*);
printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
return 1;
}
if(!strcmp(name, "g_threads_got_initialized")) {
*start = (uintptr_t)my_GetGthreadsGotInitialized();
*end = *start+sizeof(int);
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// not found...
return 0;
}
const char* GetMaplibDefaultVersion(lib_t *maplib, lib_t* local_maplib, int isweak, const char* symname)
{
const char* ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(my_context->elfs[0]):GetGlobalDefaultVersion(my_context->elfs[0]), symname);
if(ret)
return ret;
for(int i=0; i<maplib->libsz; ++i) {
elfheader_t *h = GetElf(maplib->libraries[i]);
if(h)
ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname);
if(ret)
return ret;
}
if(local_maplib)
for(int i=0; i<local_maplib->libsz; ++i) {
elfheader_t *h = GetElf(local_maplib->libraries[i]);
if(h)
ret = GetDefaultVersion(isweak?GetWeakDefaultVersion(h):GetGlobalDefaultVersion(h), symname);
if(ret)
return ret;
}
return NULL;
}
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start = 0;
@@ -522,63 +685,65 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
int weak = 0;
elfheader_t* ret = NULL;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
const char* defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 0, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
return my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
elfheader_t* h = GetElf(maplib->libraries[i]);
if(!h) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
if(weak)
ret = my_context->elfs[idx];
ret = h;
else
return my_context->elfs[idx];
return h;
}
}
defver = GetDefaultVersion(my_context->weakdefver, name);
defver = GetMaplibDefaultVersion(my_context->maplib, (my_context->maplib==maplib)?NULL:maplib, 1, name);
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
ret = my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver)) {
elfheader_t* h = GetElf(maplib->libraries[i]);
if(!h) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
if(weak)
ret = my_context->elfs[idx];
ret = h;
else
return my_context->elfs[idx];
return h;
}
}
// return what has been found (maybe nothing)
return ret;
}
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, const char* defver)
{
int weak = 0;
size_t size = 0;
// check global GLOB_DAT kind of symbols
if(GetSymbolStartEnd(GetGlobalData(maplib), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
for(int i=0; i<maplib->libsz; ++i)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
if(*start || *end)
return 1;
// nope, not found
return 0;
}
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername, const char* defver)
{
uintptr_t start, end;
size_t size = 0;
@@ -586,7 +751,7 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
// check with default version...
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, size, &weak, version, vername, 1, defver))
if(start || end)
return 1;
// nope, not found
@@ -594,22 +759,23 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
}
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername, const char* globdefver, const char* weakdefver)
{
// check with default version...
int weak;
size_t size = 0;
const char* defver = globdefver?globdefver:weakdefver;
if(my_context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, NULL))
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
if(self)
return 0;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1))
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || GetElf(maplib->libraries[i])==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, size, &weak, version, vername, 1, defver))
if(*start || *end)
return 1;
if(self)
@@ -623,7 +789,6 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base, library_t** lib)
{
(void)maplib;
// first, search in self...
const char* ret = NULL;
uintptr_t offs = 0;
@@ -645,15 +810,15 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
*lib = NULL; // main elf
else {
for(int i=0; i<my_context->maplib->libsz; ++i) {
int idx = GetElfIndex(my_context->maplib->libraries[i]);
if((idx!=-1) && (my_context->elfs[idx]==h)) {
elfheader_t* head = GetElf(my_context->maplib->libraries[i]);
if((head) && (head==h)) {
*lib = my_context->maplib->libraries[i];
return ret;
}
}
for(int i=0; i<my_context->local_maplib->libsz; ++i) {
int idx = GetElfIndex(my_context->local_maplib->libraries[i]);
if((idx!=-1) && (my_context->elfs[idx]==h)) {
elfheader_t* head = GetElf(my_context->local_maplib->libraries[i]);
if((head) && (head==h)) {
*lib = my_context->local_maplib->libraries[i];
return ret;
}
-2
View File
@@ -21,8 +21,6 @@ typedef struct lib_s {
int ownlibs;
library_t *owner; // in case that maplib is owned by a lib
box86context_t* context;
bridge_t *bridge; // all x86 -> arm bridge
} lib_t;
+453 -373
View File
File diff suppressed because it is too large. Load diff
+29 -23
View File
@@ -13,17 +13,25 @@ typedef struct bridge_s bridge_t;
typedef struct elfheader_s elfheader_t;
typedef struct kh_bridgemap_s kh_bridgemap_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct x86emu_s x86emu_t;
typedef struct x86emu_s x86emu_t;
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
typedef struct symbol1_s {
wrapper_t w;
int resolved;
uintptr_t addr;
} symbol1_t;
typedef struct symbol2_s {
wrapper_t w;
const char* name;
int weak;
wrapper_t w;
const char* name;
int weak;
int resolved;
uintptr_t addr;
} symbol2_t;
KHASH_MAP_DECLARE_STR(symbolmap, wrapper_t)
KHASH_MAP_DECLARE_STR(symbolmap, symbol1_t)
KHASH_MAP_DECLARE_STR(symbol2map, symbol2_t)
KHASH_MAP_DECLARE_STR(datamap, uint32_t)
@@ -37,25 +45,24 @@ typedef struct wlib_s {
void* lib; // dlopen result
void* priv; // actual private
char* altprefix; // if function names are mangled..
int needed;
char** neededlibs;
needed_libs_t* needed;
kh_symbolmap_t *symbolmap;
kh_symbolmap_t *wsymbolmap;
kh_symbolmap_t *mysymbolmap;
kh_symbolmap_t *wmysymbolmap;
kh_symbolmap_t *stsymbolmap;
kh_symbolmap_t *wstsymbolmap;
kh_symbol2map_t *symbol2map;
kh_datamap_t *datamap;
kh_datamap_t *wdatamap;
kh_datamap_t *mydatamap;
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
int refcnt; // refcounting the lib
} wlib_t;
typedef struct elib_s {
int elf_index;
int finalized;
elfheader_t *elf;
int finalized;
} elib_t;
typedef struct library_s {
@@ -63,27 +70,20 @@ typedef struct library_s {
char* path; // original path
int nbdot; // nombre of "." after .so
int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined
int active;
wrappedlib_fini_t fini;
wrappedlib_get_t getglobal; // get global symbol (not weak)
wrappedlib_get_t getweak; // get weak symbol
wrappedlib_get_t getlocal; // get local symbol
wrappedlib_get_t getglobal; // get global (non-weak)
wrappedlib_get_t getweak; // get weak symbol
wrappedlib_get_t getlocal; // get local symbol
union {
wlib_t w;
elib_t e;
}; // private lib data
needed_libs_t needed;
needed_libs_t dependedby;
int refcnt; // refcounting the lib
}; // private lib data
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
kh_bridgemap_t *gbridgemap; // global symbol bridgemap
kh_bridgemap_t *wbridgemap; // weak symbol bridgemap
kh_bridgemap_t *lbridgemap; // local symbol bridgemap
int dlopen; // idx to the dlopen idx (or 0 if not dlopen)
} library_t;
void add_neededlib(needed_libs_t* needed, library_t* lib);
void free_neededlib(needed_libs_t* needed);
void add_dependedbylib(needed_libs_t* dependedby, library_t* lib);
void free_dependedbylib(needed_libs_t* dependedby);
// type for map elements
typedef struct map_onesymbol_s {
@@ -99,11 +99,11 @@ typedef struct map_onesymbol2_s {
} map_onesymbol2_t;
typedef struct map_onedata_s {
const char* name;
uint32_t sz;
uint32_t sz; // TODO: convert to size_t
int weak;
} map_onedata_t;
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int* weak, int version, const char* vername, int local); // Add bridges to functions
int getSymbolInMaps(library_t *lib, const char* name, int noweak, uintptr_t *addr, uintptr_t *size, int *weak, int version, const char* vername, int local); // Add bridges to functions
typedef struct linkmap_s {
// actual struct link_map
@@ -117,7 +117,13 @@ typedef struct linkmap_s {
} linkmap_t;
linkmap_t* getLinkMapLib(library_t* lib);
linkmap_t* getLinkMapElf(elfheader_t* h);
linkmap_t* addLinkMapLib(library_t* lib);
void removeLinkMapLib(library_t* lib);
int FiniLibrary(library_t* lib, x86emu_t* emu);
void Free1Library(library_t **lib, x86emu_t* emu);
void RemoveDlopen(library_t** lib, int idx); // defined in wrappedlibdl.c
#endif //__LIBRARY_PRIVATE_H_
+19 -5
View File
@@ -17,7 +17,7 @@ typedef struct onesymbol_s {
} onesymbol_t;
typedef struct versymbol_s {
int version; // -1 = no-version, 0=local, 1=global, X=versionned
int version; // -1 = no-version, 0=local, 1=global, X=versioned
const char* vername; // NULL or version name if version=X
onesymbol_t sym;
} versymbol_t;
@@ -94,7 +94,7 @@ static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vernam
return &s->syms[i];
return NULL;
}
/* static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
static versymbol_t* FindFirstVersion(versymbols_t* s, size_t size)
{
if(!s || !s->sz)
return NULL;
@@ -102,7 +102,7 @@ static versymbol_t* FindVersion(versymbols_t* s, size_t size, const char* vernam
if(s->syms[i].version>1 && (!size || (size==s->syms[i].sym.sz)))
return &s->syms[i];
return NULL;
} */
}
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, size_t size, int local, const char* defver)
@@ -122,7 +122,7 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
if(!ret) ret = FindNoVersion(s, size);
if(!ret) ret = FindVersionGlobal(s, size);
if(!ret && defver) ret = FindVersion(s, size, defver);
//if(!ret) ret = FindFirstVersion(s);
//if(!ret) ret = FindFirstVersion(s, size);
return ret;
}
if(ver==-2) {
@@ -170,6 +170,19 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
v->syms[idx].sym.sz = sz;
}
void ForceUpdateSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
versymbols_t * v = &kh_val(mapsymbols, k);
if(ret) {v->sz = v->cap = 0; v->syms = NULL;}
// now check if that version already exist, and update record and exit if yes
for(int i=0; i<v->sz; ++i) {
v->syms[i].sym.offs = addr;
v->syms[i].sym.sz = sz;
}
}
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver)
{
if(!mapsymbols)
@@ -289,5 +302,6 @@ const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
khint_t k = kh_get(defaultversion, def, symname);
if(k==kh_end(def))
return NULL;
return kh_value(def, k);
else
return kh_value(def, k);
}
+48
View File
@@ -4,6 +4,7 @@
GO("libpthread.so.0", libpthread)
GO("librt.so.1", librt)
GO("libbsd.so.0", libbsd)
GO("libGL.so.1", libgl)
GO("libGL.so", libgl)
GO("libGLU.so.1", libglu)
@@ -70,6 +71,7 @@ GO("libopenal.so", openal)
GO("openal.so", openal)
GO("libalut.so.0", alut)
GO("libalure.so.1", alure)
GO("libOpenCL.so.1", opencl)
GO("libcurl.so.4", curl)
GO("libcurl-gnutls.so.4", curl)
GO("libcurl.so.3", curl)
@@ -107,6 +109,7 @@ GO("libdbus-glib-1.so.2", dbusglib1)
GO("libgudev-1.0.so.0", gudev1)
GO("libappindicator.so.1", appindicator)
GO("libappindicator3.so.1", appindicator3)
GO("libayatana-appindicator3.so.1", ayatanaappindicator3)
GO("libatk-1.0.so.0", atk)
GO("libatk-bridge-2.0.so.0", atkbridge)
GO("libpangoft2-1.0.so", pangoft2)
@@ -174,10 +177,13 @@ GO("libpcap.so.0", pcap)
GO("libFAudio.so.0", faudio)
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
GO("libfuse.so.2", libfuse)
GO("libatomic.so.1", atomic)
GO("libpcre.so.3", libpcre)
#ifdef ANDROID
GO("libc.so", libc)
GO("libm.so", libm)
GO("libbsd.so", libbsd)
GO("libdl.so", libdl)
GO("libcups.so", libcups)
GO("liblber-2.4.so", lber)
@@ -194,6 +200,48 @@ GO("libX11.so", libx11)
GO("libXext.so", libxext)
GO("libxcb.so", libxcb)
GO("libXau.so", libxau)
GO("libXxf86vm.so", libxxf86vm)
GO("libXinerama.so", xinerama)
GO("libXrandr.so", libxrandr)
GO("libXfixes.so", libxfixes)
GO("libXcursor.so", libxcursor)
GO("libXrender.so", libxrender)
GO("libXpresent.so", libxpresent)
GO("libXft.so", libxft)
GO("libXi.so", libxi)
GO("libXss.so", libxss)
GO("libXpm.so", libxpm)
GO("libXdmcp.so", libxdmcp)
GO("libX11-xcb.so", libx11xcb)
GO("libxcb-xfixes.so", libxcbxfixes)
GO("libxcb-shape.so", libxcbshape)
GO("libxcb-shm.so", libxcbshm)
GO("libxcb-randr.so", libxcbrandr)
GO("libxcb-image.so", libxcbimage)
GO("libxcb-keysyms.so", libxcbkeysyms)
GO("libxcb-xtest.so", libxcbxtest)
GO("libxcb-dri2.so", libxcbdri2)
GO("libxcb-dri3.so", libxcbdri3)
GO("libxcb-present.so", libxcbpresent)
GO("libXtst.so", libxtst)
GO("libXt.so", libxt)
GO("libXcomposite.so", libxcomposite)
GO("libXdamage.so", libxdamage)
GO("libXmu.so", libxmu)
GO("libpulse-simple.so", pulsesimple)
GO("libpulse.so", pulse)
GO("libsndfile.so", libsndfile)
GO("libusb-1.0.so", libusb1)
GO("libgstapp-1.0.so", gstapp)
GO("libgstaudio-1.0.so", gstaudio)
GO("libgstbase-1.0.so", gstbase)
GO("libgstreamer-1.0.so", gstreamer)
GO("libgsttag-1.0.so", gsttag)
GO("libgstvideo-1.0.so", gstvideo)
GO("libvorbisfile.so", vorbisfile)
GO("libvorbis.so", libvorbis)
GO("libogg.so", libogg)
GO("libz.so", libz)
GO("libandroid-shmem.so", androidshmem)
#else
GO("libc.so.6", libc)
+1
View File
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <asm/stat.h>
#include <sys/vfs.h>
#include <signal.h>
#include "x86emu.h"
#include "emu/x86emu_private.h"
+10 -10
View File
@@ -41,20 +41,20 @@ GO(3)
// compare
#ifdef NOALIGN
#define GO(A) \
static uintptr_t my_compare_fct_##A = 0; \
static int my_compare_##A(FTSENT* a, FTSENT* b) \
{ \
return (int)RunFunction(my_context, my_compare_fct_##A, 2, a, b);\
static uintptr_t my_compare_fct_##A = 0; \
static int my_compare_##A(FTSENT* a, FTSENT* b) \
{ \
return (int)RunFunctionFmt(my_compare_fct_##A, "pp", a, b); \
}
#else
#define GO(A) \
static uintptr_t my_compare_fct_##A = 0; \
static int my_compare_##A(FTSENT* a, FTSENT* b) \
{ \
x86_ftsent_t x86_a, x86_b; \
UnalignFTSENT(&x86_a, a); \
UnalignFTSENT(&x86_b, b); \
return (int)RunFunction(my_context, my_compare_fct_##A, 2, x86_a, x86_b);\
static int my_compare_##A(FTSENT* a, FTSENT* b) \
{ \
x86_ftsent_t x86_a, x86_b; \
UnalignFTSENT(&x86_a, a); \
UnalignFTSENT(&x86_b, b); \
return (int)RunFunctionFmt(my_compare_fct_##A, "pp", x86_a, x86_b); \
}
#endif
SUPER()
+9 -9
View File
@@ -41,10 +41,10 @@ GO(4)
// chunkfun
#define GO(A) \
static uintptr_t my_chunkfun_fct_##A = 0; \
static void* my_chunkfun_##A(size_t a) \
{ \
return (void*)RunFunction(my_context, my_chunkfun_fct_##A, 1, a); \
static uintptr_t my_chunkfun_fct_##A = 0; \
static void* my_chunkfun_##A(size_t a) \
{ \
return (void*)RunFunctionFmt(my_chunkfun_fct_##A, "L", a); \
}
SUPER()
#undef GO
@@ -74,10 +74,10 @@ static void* reverse_chunkfunFct(library_t* lib, void* fct)
}
// freefun
#define GO(A) \
static uintptr_t my_freefun_fct_##A = 0; \
static void my_freefun_##A(void* a) \
{ \
RunFunction(my_context, my_freefun_fct_##A, 1, a); \
static uintptr_t my_freefun_fct_##A = 0; \
static void my_freefun_##A(void* a) \
{ \
RunFunctionFmt(my_freefun_fct_##A, "p", a); \
}
SUPER()
#undef GO
@@ -211,7 +211,7 @@ void actual_obstack_alloc_failed_handler()
{
if(ref_obstack_alloc_failed_handler == my_obstack_alloc_failed_handler)
real_obstack_alloc_failed_handler();
RunFunction(my_context, (uintptr_t)my_obstack_alloc_failed_handler, 0);
RunFunctionFmt((uintptr_t)my_obstack_alloc_failed_handler, "");
}
void obstackSetup()
{
+4 -4
View File
@@ -72,20 +72,20 @@ EXPORT int32_t my_native_close(SDL1_RWops_t *context)
}
EXPORT int32_t my_emulated_seek(SDL1_RWops_t *context, int32_t offset, int32_t whence)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->seek, 3, context->hidden.my.orig, offset, whence);
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->seek, "pii", context->hidden.my.orig, offset, whence);
}
EXPORT int32_t my_emulated_read(SDL1_RWops_t *context, void *ptr, int32_t size, int32_t maxnum)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->read, 4, context->hidden.my.orig, ptr, size, maxnum);
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->read, "ppii", context->hidden.my.orig, ptr, size, maxnum);
}
EXPORT int32_t my_emulated_write(SDL1_RWops_t *context, const void *ptr, int32_t size, int32_t num)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->write, 4, context->hidden.my.orig, ptr, size, num);
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->write, "ppii", context->hidden.my.orig, ptr, size, num);
}
EXPORT int32_t my_emulated_close(SDL1_RWops_t *context)
{
return (int32_t)RunFunction(my_context, (uintptr_t)context->hidden.my.orig->close, 1, context->hidden.my.orig);
return (int32_t)RunFunctionFmt((uintptr_t)context->hidden.my.orig->close, "p", context->hidden.my.orig);
}
SDL1_RWops_t* AddNativeRW(x86emu_t* emu, SDL1_RWops_t* ops)
Loaded 100 of 811 files, more files were not shown because too many files have changed in this diff. Show more