Compare commits

...
365 Commits
Author SHA1 Message Date
ptitSeb f5c4deb42b Bumped to v0.0.8 2021-04-13 20:49:30 +02:00
ptitSeb 069193e8b7 Added a few SDL2 wrapped function from v2.0.10 2021-04-13 20:30:17 +02:00
ptitSeb a424e996b3 Added syscall 298 2021-04-13 20:29:59 +02:00
ptitSeb 3c81248335 Merge pull request #9 from ptitSeb/krishenriksen-patch-3
Update x64runf30f.c
2021-04-13 18:53:04 +02:00
Kris Henriksen 1e3f277a71 Update x64runf30f.c
For opcodes:
1688|0x40ee00: Unimplemented Opcode (90) F3 0F 1E FA 31 ED 49 89 D1 5E 48 89 E2 48 83
1688|0x40eeb0: Unimplemented Opcode (00) F3 0F 1E FA 80 3D A5 FA EE 00 00 75 13 55 48
1688|0x9ca7d8: Unimplemented Opcode (00) F3 0F 1E FA 48 83 EC 08 48 83 C4 08 C3 00 00
2021-04-13 23:06:08 +07:00
ptitSeb 3adeabb06d Added some libc wrapped functions 2021-04-13 17:43:10 +02:00
ptitSeb 4593111871 Added 67 0F 2E/2F opcodes 2021-04-13 17:36:56 +02:00
ptitSeb 7440be495e Better trace for poll 2021-04-13 17:25:43 +02:00
ptitSeb fded1a0718 Added some more wrapped functions in libc 2021-04-13 15:19:59 +02:00
ptitSeb ebbb2821d0 Added 64 3B opcode 2021-04-13 15:14:49 +02:00
ptitSeb 643b950eef Add option to ovoid building fixed address 2021-04-13 15:09:03 +02:00
ptitSeb 63a20f537a Merge pull request #7 from ptitSeb/krishenriksen-patch-1
Update CMakeLists.txt
2021-04-13 13:41:21 +02:00
Kris Henriksen ae94148bee Update CMakeLists.txt
Fix definitions for rk3326
2021-04-13 18:23:38 +07:00
ptitSeb 9301eb9ee0 Remove TokiTori2+ patch code, game is 32bits only 2021-04-13 11:47:30 +02:00
ptitSeb 19448e242c Added a few syscall around inotify 2021-04-13 10:47:47 +02:00
ptitSeb f26c2f0812 Added a few more libc wrapped function, and fixed glob64 wrapping 2021-04-12 21:03:50 +02:00
ptitSeb 6573476ea2 [DYNAREC] Fixed adc16 emitter 2021-04-12 21:03:30 +02:00
ptitSeb f73430a3f8 Added one pango function 2021-04-12 19:37:14 +02:00
ptitSeb 3bf90844b1 Added a few more libc wrapped functions 2021-04-12 19:12:50 +02:00
ptitSeb 6546ae8e67 Added utime wrapped functions 2021-04-12 19:01:07 +02:00
ptitSeb d01bdf9186 Added 9E/9F opcodes ([DYNAREC] too) 2021-04-12 18:49:54 +02:00
ptitSeb 88b6cc1907 Added a 1 more libc wrapped function 2021-04-12 18:49:34 +02:00
ptitSeb 8922b63769 Fixed some issues with pthread wrapping 2021-04-12 16:40:08 +02:00
ptitSeb 30d4713b28 [DYNAREC] Added 66 0F 5D/5F opcodes 2021-04-12 16:20:45 +02:00
ptitSeb 498a52439c [DYNAREC] Fixed F2 0F 5D/5F opcodes 2021-04-12 16:13:02 +02:00
ptitSeb 88798b78fc Improved pthread wrapping 2021-04-12 14:29:38 +02:00
ptitSeb 0ce7390ac1 Added 64 F3 0F 11/59 opcodes 2021-04-12 14:29:19 +02:00
ptitSeb 00f5eb5338 More alignment work on thread (some attr are bigger on arm64 than x86_64) 2021-04-12 10:13:35 +02:00
ptitSeb d9967d7ea5 Added A0/A2 opcodes ([DYNAREC] too) 2021-04-11 19:27:10 +02:00
ptitSeb d42031293d Fixed a warning in wrapped libsdl2 2021-04-11 18:41:34 +02:00
ptitSeb 76903904d0 Merge pull request #6 from rajdakin/generalImprovements
General improvements to box64 and fixed some SDL2 functions
2021-04-11 18:31:59 +02:00
rajdakin a42f232b1e Forgot to add SDL1 2021-04-11 18:24:13 +02:00
rajdakin 72a505a3e8 General improvements to box64 and fixed some SDL2 functions 2021-04-11 17:53:23 +02:00
ptitSeb ae221ed5bd [DYNAREC] Added 0F F2 opcode 2021-04-11 17:18:38 +02:00
ptitSeb 76115b30b8 [DYNAREC] Added 66 0F E1/F2 opcode 2021-04-11 17:05:15 +02:00
ptitSeb 7401d46bcd [DYNAREC] Added 0F 74 opcode 2021-04-11 16:50:59 +02:00
ptitSeb ee61d9c95a [DYNAREC] Added 66 0F DA opcode 2021-04-11 16:47:04 +02:00
ptitSeb 6db666c565 [DYNAREC] Added 0F 63 opcode 2021-04-11 16:44:57 +02:00
ptitSeb 050acaa8c6 [DYNAREC] Added 0F E3 opcode 2021-04-11 16:35:59 +02:00
ptitSeb e83232fcf6 Fixed 0F E3 opcode 2021-04-11 16:35:45 +02:00
ptitSeb ece7ea36d9 [DYNAREC] Added 66 0F E2 ocpode 2021-04-11 16:23:45 +02:00
ptitSeb 73d27a625f [DYNAREC] Added F3 0F 5B opcode 2021-04-11 15:53:08 +02:00
ptitSeb a8d4f17add [DYNAREC] Added F3 0F D6 opcode 2021-04-11 15:46:36 +02:00
ptitSeb af6fb49e48 Added F2 0F F0 ocpode ([DYNAREC] too) 2021-04-11 15:38:09 +02:00
ptitSeb c593988bc1 [DYNAREC] Added 0F DE/DF opcodes 2021-04-11 15:24:25 +02:00
ptitSeb 2d590bb1f5 Added 0F DE opcode 2021-04-11 15:24:08 +02:00
ptitSeb aef3677970 Added wrapped libSDL2_net 2021-04-11 15:08:33 +02:00
ptitSeb 7d11254a52 [DYNAREC] Improved (and fixed) Table64 handling 2021-04-11 11:14:18 +02:00
ptitSeb 3b9feeed12 Improvement in internal mutex handling on signal, and [DYNAREC] multitasking changes to the JmpTable 2021-04-11 11:05:36 +02:00
ptitSeb 6d3ca2df80 [DYNAREC] Fixed, again, arm64_lock_storeifref function 2021-04-11 10:46:18 +02:00
ptitSeb 5d69ed5f4a [DYNAREC] Fixed arm64_lock_storeifref function 2021-04-11 10:41:55 +02:00
ptitSeb 81d13a8e0b [DYNAREC] Removed obsolete comments 2021-04-11 10:22:41 +02:00
ptitSeb 544a2ac034 [DYNAREC] Added address on Jump to non-block address warning log 2021-04-11 10:22:01 +02:00
ptitSeb 9a2bf37ac1 Merge branch 'main' of https://github.com/ptitSeb/box64 into main 2021-04-10 16:38:16 +02:00
ptitSeb 550d252386 Merge pull request #5 from rajdakin/addFunc
Added some libc symbols
2021-04-10 16:33:14 +02:00
rajdakin 2b3bdd7e60 Added some libc symbols 2021-04-10 15:39:58 +02:00
ptitSeb 4f38801ba6 Merge branch 'main' of https://github.com/ptitSeb/box64 into main 2021-04-10 14:36:02 +02:00
ptitSeb 31b41f5b94 Merge pull request #4 from rajdakin/fixFF
Fixed 0xFF INC and DEC opcodes
2021-04-10 14:27:45 +02:00
rajdakin 03ce3c6592 Fixed FF INC and DEC opcodes 2021-04-10 14:26:41 +02:00
ptitSeb 2a4649f6ef Better trace for a few GL functions 2021-04-10 12:04:45 +02:00
ptitSeb 96c3615ea5 [DYNAREC] Fixed address used by this warning 2021-04-10 12:04:20 +02:00
ptitSeb adfcfafdc2 Grab thread emu when calling init Library instead of NULL 2021-04-10 09:06:56 +02:00
ptitSeb 0a37f1cc30 Merge pull request #3 from rajdakin/exitFix
box64 exit fix
2021-04-09 18:19:42 +02:00
rajdakin 70018a774b Fixed the libraries free ordering 2021-04-09 17:52:59 +02:00
rajdakin 009bb94f17 Changed missed unwanted "box86" 2021-04-09 17:52:25 +02:00
ptitSeb 0e0f1e2037 Added gethostbyname wrapped function 2021-04-09 17:31:48 +02:00
ptitSeb a0a0bc8270 Added F0 87 opcode ([DYNAREC] too) 2021-04-09 17:21:53 +02:00
ptitSeb 25c532610b Fixed a warning 2021-04-09 17:19:23 +02:00
ptitSeb fcfd90b86f Fix NOALIGN build 2021-04-09 13:39:13 +02:00
ptitSeb 738d22a68a Added one more wcs wrapped function 2021-04-09 11:37:16 +02:00
ptitSeb 8c63b76343 Added unligned case for lock inc dword ptr[xx] 2021-04-09 11:36:56 +02:00
ptitSeb ba7a04851f Added wcstof wrapped function 2021-04-09 11:10:33 +02:00
ptitSeb e3d15db6c5 pthread_attr_t don't have the same size on x86_64 (0x38) and arm64 (0x40)... 2021-04-09 11:08:26 +02:00
ptitSeb ca46df09d8 Small comment on syscall 2021-04-09 11:07:49 +02:00
ptitSeb f053e02868 More libc wrapped functions 2021-04-08 19:30:27 +02:00
ptitSeb 42cbe1b397 Added 64 F2 0F 11 and 64 39 opcodes 2021-04-08 19:28:39 +02:00
ptitSeb 42fe124a0e A few more wrapped libc functions 2021-04-08 19:22:30 +02:00
ptitSeb d809b59daa Added 67 66 0F 6F/7A opcodes 2021-04-08 19:11:42 +02:00
ptitSeb e14d4042d9 [DYNAREC] Fixed 66 81 opcodes 2021-04-08 18:15:56 +02:00
ptitSeb 371b346bf7 [DYNAREC] Fixed the BOX64_NODYNAREC function 2021-04-08 17:53:19 +02:00
ptitSeb b038dd5c9d Added a libvorbisfile wrapped function and fixed another one (structure as argument are in the stack, always) 2021-04-08 17:06:49 +02:00
ptitSeb 2681a6db0d Added a xcb wrapped function 2021-04-08 16:31:15 +02:00
ptitSeb 5ff1ea1435 Added fsync wrapped function 2021-04-08 16:28:10 +02:00
ptitSeb 759f165549 Fixed fcntl wrapper 2021-04-08 16:27:52 +02:00
ptitSeb cb27ac8d93 Fixed memory protection that wasn't updated correctly 2021-04-08 16:26:33 +02:00
ptitSeb 035c77ad91 Added wrapped libcairo, libpango, libpangoft2 and libpangocairo 2021-04-08 15:46:34 +02:00
ptitSeb b45c249ed9 Added a few more wrapped libc functions 2021-04-08 15:35:38 +02:00
ptitSeb b90991f039 Added F0 0F AB/B3 opcodes 2021-04-08 15:32:35 +02:00
ptitSeb 8d49ae5c68 Added some more libc wrapped functions 2021-04-08 15:09:53 +02:00
ptitSeb 49047cf972 Small change on trace flags output 2021-04-08 13:02:38 +02:00
ptitSeb aa5485ae27 Fixed a warning 2021-04-08 13:01:43 +02:00
ptitSeb fc0d9c5f92 Small change on trace output 2021-04-08 13:01:16 +02:00
ptitSeb 8309c5feeb Merge pull request #2 from rajdakin/addregsdiff
Added a new trace option
2021-04-07 17:16:38 +02:00
ptitSeb 4693cac13b [DYNAREC] Needed to same a bit more register before native funciton call (fix setjmp no saving all registers) 2021-04-07 17:09:47 +02:00
rajdakin 79f2b8448a [TRACE] Added a new trace option 2021-04-07 17:09:37 +02:00
ptitSeb 7e09961ee7 Added 2 _np wrapped function to pthreads 2021-04-07 15:34:15 +02:00
ptitSeb 21aded91f0 Added wrapped libcurl/libcurl-gnutls 2021-04-07 15:32:17 +02:00
ptitSeb 6b4bb5e7cb Small changes to a few libGL wrapped function signature 2021-04-07 14:50:25 +02:00
ptitSeb c1eef81fdb Added 0F DA ocode ([DYNAREC] too) 2021-04-07 14:49:56 +02:00
krishenriksen b1e6fa4f2b Added RK3326 definitions. 2021-04-07 17:39:23 +07:00
ptitSeb e672641878 Added wrapped ldiv function 2021-04-06 17:03:02 +02:00
ptitSeb fef0140098 Added wrapped libcrypto and libssl 2021-04-06 16:58:51 +02:00
ptitSeb 4084eade0c Fixed __realpath_chk wrapping 2021-04-06 13:47:55 +02:00
ptitSeb 748552d792 Unlock all mutex on child process when forking 2021-04-06 13:40:48 +02:00
ptitSeb ff50b0c391 Fixed SDL AudioSpec structure definition 2021-04-06 11:02:47 +02:00
ptitSeb 23e7d5c370 Added 67 80/8B opcodes 2021-04-05 19:04:16 +02:00
ptitSeb 676b7523b3 Added a couple of libc wrapped functions 2021-04-05 18:20:47 +02:00
ptitSeb 880616397f Cleanup trace_func if still present at exit 2021-04-05 17:40:56 +02:00
ptitSeb ace8536987 And another change change to __libc_start_main for non-Dynarec build 2021-04-05 17:31:50 +02:00
ptitSeb 3370ae4dcf Added some more GL wrapped functions 2021-04-05 17:26:10 +02:00
ptitSeb 8a6a1312f2 One more change to __libc_start_main to end emulation when done 2021-04-05 17:25:48 +02:00
ptitSeb a9d633ab2d Fixed _start preparation 2021-04-05 16:47:26 +02:00
ptitSeb 765a9d8325 Re-enabled the pre-calc of next block for new thread 2021-04-05 16:46:30 +02:00
ptitSeb 67c6a661e5 Better trace for glXGetProcAddress 2021-04-05 16:45:50 +02:00
ptitSeb b897d55873 Merge pull request #1 from rajdakin/wrapper_add
[WRAPPER] Added a new feature in the wrapper, forced all i32 to i64
2021-04-04 18:42:35 +02:00
rajdakin 7b099f9c64 [WRAPPER] Added a new feature in the wrapper, forced all i32 to i64 2021-04-04 18:36:18 +02:00
ptitSeb c172fbd883 [DYNAREC] Added 66 64 8B opcode 2021-04-04 14:55:58 +02:00
ptitSeb 5fb581a51f Added some more libc wrapped functions 2021-04-04 14:54:43 +02:00
ptitSeb f3a08a51ef Ooops, that typo was breaking some C#/Unity stuff 2021-04-04 14:54:22 +02:00
ptitSeb a7b9590f6f Disabled handling of CC opcode for now (ignoring it is better) 2021-04-04 14:53:37 +02:00
ptitSeb 998a114172 Added some more 67 opcodes (may need to find a better solution for this) 2021-04-04 11:28:21 +02:00
ptitSeb 29f65bb6be More work on mmap and the MAP_32BIT flag 2021-04-04 10:19:47 +02:00
ptitSeb cce9293413 One more libc wrapped function 2021-04-03 22:32:19 +02:00
ptitSeb b91a95ee49 [DYNAREC] A few more printer on litteral LDR 2021-04-03 22:32:00 +02:00
ptitSeb 0eb682a95b [DYNAREC] Some more fixes on some DB opcodes (until ARMv8.5 detection is implemented) 2021-04-03 22:31:37 +02:00
ptitSeb 424312c2d8 More work on stack alignements 2021-04-03 22:31:00 +02:00
ptitSeb 969ee91506 More work around stack alignement and frame pointer 2021-04-03 21:37:25 +02:00
ptitSeb f56ee97676 [DYNAREC] Fixed x87 virtual stack managment 2021-04-03 21:36:53 +02:00
ptitSeb f667ec631d Added some more libc wrapped functions 2021-04-03 19:15:19 +02:00
ptitSeb 7bcf1cc0ae [DYNAREC] Added DF opcodes 2021-04-03 18:50:14 +02:00
ptitSeb dba4ff3cff [DYNAREC] Added DD opcodes 2021-04-03 15:47:55 +02:00
ptitSeb 0ff030a44c [DYNAREC] Fixed many issues with x87 cache handling 2021-04-03 15:47:44 +02:00
ptitSeb 7babbcf62b [DYNAREC] removed a warning 2021-04-03 14:47:59 +02:00
ptitSeb fd303c6e94 [DYNAREC] Added D8 opcodes 2021-04-03 14:40:55 +02:00
ptitSeb a8495b00f2 [DYNAREC] Added DB opcodes 2021-04-03 14:32:04 +02:00
ptitSeb ae70f168a8 [DYNAREC] Added D9 opcodes 2021-04-03 11:43:17 +02:00
ptitSeb b239bec2c5 [DYNAREC] Better 0F 77 EMMS emulation 2021-04-03 10:37:00 +02:00
ptitSeb d0f05fed3b [DYNAREC] Added F3 0F 52 opcode 2021-04-03 10:30:02 +02:00
ptitSeb 717c0e1299 [DYNAREC] Added F3 0F E6 opcode 2021-04-03 10:00:52 +02:00
ptitSeb 8760064ddb [DYNAREC] Added 66 03/C6 opcodes 2021-04-03 09:44:26 +02:00
ptitSeb ab0059eeee Better trace for strcmp 2021-04-03 09:39:35 +02:00
ptitSeb 19a7d2139a Added wrapped pwrite function 2021-04-03 09:15:30 +02:00
ptitSeb 5319117636 Changed the way alignment of mutex is done 2021-04-03 08:59:19 +02:00
ptitSeb c5b32180d2 Small fix for dl_iterate_phdr 2021-04-03 08:58:54 +02:00
ptitSeb 62baaf99b1 Better trace for opendir and strlen 2021-04-03 08:58:31 +02:00
ptitSeb c03dd5951a Added 64 00..35/C6 opcodes 2021-04-02 19:39:50 +02:00
ptitSeb 555f4e132f Added a few more libc wrapped function and fixed munmap wrapping 2021-04-02 19:27:32 +02:00
ptitSeb c3209a2736 [DYNAREC] Fixed 0F 5D/5F/6E/6F opcodes 2021-04-02 18:28:22 +02:00
ptitSeb 0b29d724db [DYNAREC] Added 66 0F E0 opcode 2021-04-02 16:19:38 +02:00
ptitSeb 931a8063b4 [DYNAREC] Added 0F E8/E9 opcodes and fixed 0F E7 opcode 2021-04-02 16:16:31 +02:00
ptitSeb c74406c89e [DYNAREC] Added 66 AB opcodes 2021-04-02 15:54:10 +02:00
ptitSeb c44b8b1936 [DYNAREC] Added 0F D8/D9/DC/DD opcodes 2021-04-02 15:50:20 +02:00
ptitSeb b1671dd98d [DYNAREC] Added 0F DB opcode 2021-04-02 15:46:44 +02:00
ptitSeb 0baf0ff24a [DYNAREC] Added 0F 73 opcode 2021-04-02 15:43:40 +02:00
ptitSeb 2929d7256b [DYNAREC] Added 0F 38 00 opcode 2021-04-02 15:17:24 +02:00
ptitSeb 8d769dd3c2 [DYNAREC] Added 0F 38 0B opcode 2021-04-02 15:14:58 +02:00
ptitSeb e8d6f083a3 Added 66 0F 38 0B opcode ([DYNAREC] too) 2021-04-02 15:11:19 +02:00
ptitSeb 817c3d7058 Added 0F E0 opcode ([DYNAREC] too) 2021-04-02 14:41:19 +02:00
ptitSeb e2a7dd0f17 Added 0F E7 opcode ([DYNAREC] too) 2021-04-02 14:27:49 +02:00
ptitSeb f781537adb Added wrapped swscanf 2021-04-02 14:27:11 +02:00
ptitSeb c2c65f46cb [DYNAREC] Fixed SQXTUN2_8 emiter, and so 66 0F 67 opcode 2021-04-02 14:13:57 +02:00
ptitSeb 0f65adfaab Fixed trace on mremap 2021-04-02 14:13:02 +02:00
ptitSeb efafe96b08 Changed LOG Level of dl_iterate_phdr warning 2021-04-02 13:47:26 +02:00
ptitSeb 858957f6f7 [DYNAREC] Fixed CSETM printer 2021-04-02 13:46:45 +02:00
ptitSeb 128724d147 Implemented a workaround for mmap64 with MAP_32BIT flag 2021-04-02 13:38:23 +02:00
ptitSeb c6c6bfcf2c Minor change to elfloader 2021-04-02 13:36:03 +02:00
ptitSeb 4f451ff653 Better trace for mmap64 2021-04-02 13:35:40 +02:00
ptitSeb 7822f29140 Change Elfloader handling of R_X86_64_GLOB_DAT with R_X86_64_COPY by preapplying the Copy (it fixed Knytt Underground) 2021-04-02 11:04:34 +02:00
ptitSeb 98d434a0a9 Added wrapped rawmemchr function 2021-04-02 11:01:42 +02:00
ptitSeb 61c1f7157c Added wrapped libutil 2021-04-02 09:22:12 +02:00
ptitSeb 5ab4028257 Just to be sure the sign is extended to 64bits 2021-04-01 21:55:30 +02:00
ptitSeb 717769f1cc Better trace for mkdir 2021-04-01 21:54:53 +02:00
ptitSeb 7278bc9cde Added a few more libc wrapped functions 2021-04-01 21:54:31 +02:00
ptitSeb 7bc67cd168 Added libs64 as default LD_LIBRARY_PATH 2021-04-01 19:54:36 +02:00
ptitSeb bc23a90ef7 Try to add 0F AE /7 CLFLUSH opcode 2021-04-01 18:09:14 +02:00
ptitSeb 2070b53967 Added some more libc wrapped functions 2021-04-01 18:02:01 +02:00
ptitSeb 37a8ac3b32 Try to setup some kind of Stack Frame on new thread 2021-04-01 18:01:47 +02:00
ptitSeb 3b2e75055f Added wrapped glob64 and freeglob64 functions 2021-04-01 17:51:46 +02:00
ptitSeb 9f5e12992a Added F0 FF opcodes 2021-04-01 17:44:44 +02:00
ptitSeb eede8e1e8d Added wrapped fdatasync function 2021-04-01 17:17:29 +02:00
ptitSeb b40c4ebcd7 Added 67 89 opcode 2021-04-01 17:03:48 +02:00
ptitSeb 53e449a96f [DYNAREC] Added 0F 51 opcode 2021-04-01 17:02:56 +02:00
ptitSeb d35217d39d [DYNAREC] Small Fix for 67 8D opcode 2021-04-01 16:12:02 +02:00
ptitSeb 883463f2d5 [DYNAREC] Fixed F3 0F 70 opcode 2021-04-01 16:01:53 +02:00
ptitSeb 9abfdb3431 Small change to 67 C1 opcode 2021-04-01 15:37:08 +02:00
ptitSeb e942a8433b [DYNAREC] Added 66 0F E6 opcode 2021-04-01 15:36:51 +02:00
ptitSeb 0163746709 [DYNAREC] Small change to 8D opcode 2021-04-01 15:36:22 +02:00
ptitSeb dfbdd81d41 [DYNAREC] Fixed 67 8D opcde, and remove hack for 67 REX.W, it was wrong 2021-04-01 15:35:34 +02:00
ptitSeb b474a9061b [DYNAREC] Added 66 0F 5C opcode 2021-04-01 14:59:43 +02:00
ptitSeb eaeef7e9e9 Added wrapped fchmodat function 2021-04-01 14:59:21 +02:00
ptitSeb 30091b2af6 [DYNAREC] Added 66 0F 58/59 opcode 2021-04-01 14:39:38 +02:00
ptitSeb 73b51adfb3 Added 67 C1 opcode 2021-04-01 14:39:12 +02:00
ptitSeb 34a82f7bfc [DYNAREC] Handling 67 REX.W as just REX.W 2021-04-01 14:38:13 +02:00
ptitSeb 159bbcf4a4 [DYNAREC] Added 66 0F F5 opcode 2021-04-01 14:08:49 +02:00
ptitSeb 398a8b12c2 Added 0F 31 opcode ([DYNAREC] too) 2021-04-01 13:47:58 +02:00
ptitSeb d45558782f [DYNAREC] Added 66 0F C6 opcode 2021-04-01 13:47:46 +02:00
ptitSeb 1c3f4c078f Added 66 0F 3A 0F opcode ([DYNAREC] too) 2021-04-01 13:23:17 +02:00
ptitSeb 48588a2556 Cosmetic change 2021-04-01 11:42:31 +02:00
ptitSeb 4ae5391637 Wrapped malloc to call calloc instead (not sure it's really needed) 2021-04-01 11:42:09 +02:00
ptitSeb 28e11dec31 Better trace for XCreateWindow 2021-04-01 11:41:36 +02:00
ptitSeb b343ab69a5 Fixed 0F 7E opcode, plus a few other small changes 2021-04-01 09:15:35 +02:00
ptitSeb 697dc5fa3f [DYNAREC] Small optim of 0F 6E opcode 2021-04-01 09:12:51 +02:00
ptitSeb fa12161c47 [DYNAREC] Added 0F 68/69/6A opcodes 2021-03-31 22:01:47 +02:00
ptitSeb 9f0f1efafe [DYNAREC] Added 0F E5 opcode 2021-03-31 21:22:42 +02:00
ptitSeb aa4c56e466 [DYNAREC] Added 0F F8/F9/FA opcode 2021-03-31 21:18:01 +02:00
ptitSeb 09e1464bc8 [DYNAREC] Added F3 0F 70 opcodes and another fix for F2 0F 70 opcode 2021-03-31 21:14:42 +02:00
ptitSeb b689c745a0 [DYNAREC] Added 66 0F D5 and 0F D5 opcodes and fixed F2 0F 70 opcode 2021-03-31 21:08:22 +02:00
ptitSeb 28c2c56271 [DYNAREC] Added 0F FC/FD/FE opcode 2021-03-31 20:41:01 +02:00
ptitSeb 2d666965cf [DYNAREC] Added 0F 70 opcode 2021-03-31 20:19:11 +02:00
ptitSeb 444d5c7580 [DYNAREC] Added 0F C4/C5 opcode 2021-03-31 20:06:05 +02:00
ptitSeb 5d694fe2f2 [DYNAREC] Added 0F F6 opcode 2021-03-31 20:01:36 +02:00
ptitSeb ccd9692875 [DYNAREC] Added 0F EF opcode 2021-03-31 19:57:42 +02:00
ptitSeb 8c553cad5d [DYNAREC] Added 66 0F 63 opcode 2021-03-31 19:19:35 +02:00
ptitSeb a99a68b03a [DYNAREC] Added 66 0F E5 opcode 2021-03-31 19:12:52 +02:00
ptitSeb acb01382df [DYNAREC] Added 66 0F E8/E9/EA opcodes 2021-03-31 19:08:03 +02:00
ptitSeb 23d63686e6 [DYNAREC] Added 66 0F DC/DD/DE opcodes 2021-03-31 19:04:21 +02:00
ptitSeb c0083beec0 [DYNAREC] Added 66 0F D8/D9 opcodes 2021-03-31 18:50:29 +02:00
ptitSeb 1d680c2039 [DYNAREC] Added 67 8D opcode 2021-03-31 18:40:54 +02:00
ptitSeb bb273b55e2 [DYNAREC] Added 0F 77 opcode 2021-03-31 18:33:40 +02:00
ptitSeb d119ae5ed4 [DYNAREC] Add 66 0F E4 opcode 2021-03-31 18:30:17 +02:00
ptitSeb d78dbbe4c7 [DYNAREC] Added 0F 6E/6F opcodes 2021-03-31 17:30:43 +02:00
ptitSeb 663ac80fd0 [DYNAREC] Added 0F 67/71 opcodes 2021-03-31 17:22:23 +02:00
ptitSeb 2d34788607 [DYNAREC] Added 0F EB/EC/ED opcodes 2021-03-31 17:07:12 +02:00
ptitSeb cbf4e37bba [DYNAREC] Added 0F 38 04 opcode 2021-03-31 16:58:29 +02:00
ptitSeb 74b70253b2 [DYNAREC] Added 0F 60/61/62 opcodes 2021-03-31 16:55:08 +02:00
ptitSeb 0343ee119c [DYNAREC] Added 0F 6E/6F opcodes 2021-03-31 16:47:49 +02:00
ptitSeb f9c9868349 [DYNAREC] Added 66 0F EC/ED opcodes 2021-03-31 16:38:41 +02:00
ptitSeb 1395090241 [DYNAREC] Added 66 0F 38 04 opcode 2021-03-31 16:26:34 +02:00
ptitSeb dc938e8a60 [DYNAREC] Added 66 0F 38 00 and fixed 66 0F 67 opcodes 2021-03-31 13:23:56 +02:00
ptitSeb 7dd4f1ab72 [DYNAREC] Added 66 0F 67 opcode 2021-03-31 11:32:45 +02:00
ptitSeb d53c9c1e87 [DYNAREC] Added F2 0F 70 opcode 2021-03-31 11:17:21 +02:00
ptitSeb 424a08607c [DYNAREC] Added 66 0F F6 opcode 2021-03-31 11:05:02 +02:00
ptitSeb 0d2a060e66 [DYNAREC] Added F3 0F 2D opcode 2021-03-31 10:08:09 +02:00
ptitSeb 9748c55dd0 Added 0F 38 00/04/0B/1C/1D/1E opcodes 2021-03-31 10:02:56 +02:00
ptitSeb 130d96b31e [DYNAREC] Fixed 66 0F C4 opcode 2021-03-31 09:57:25 +02:00
ptitSeb e6e420d9a3 Added 66 0F 38 01/02/03/04/05 opcodes 2021-03-30 21:46:13 +02:00
ptitSeb bde4adcdef Added 0F 70/C4/C5/F6 opcodes 2021-03-30 21:40:31 +02:00
ptitSeb 3746ae9cf3 Added 66 0F 38 00 opcode 2021-03-30 21:32:48 +02:00
ptitSeb 0c4eed79da Added 0F 71/72/73 opcodes 2021-03-30 21:27:17 +02:00
ptitSeb 8bbd9abd27 Added wrapped fts_* function (FTS struct seems aligned on 64bits) 2021-03-30 21:15:06 +02:00
ptitSeb dfa15ad9fc Added a few more libc wrapped functions 2021-03-30 21:06:46 +02:00
ptitSeb 00ac1fdcd1 Changed wrapper generator to force 32bits i/u value to 64bits 2021-03-30 21:02:42 +02:00
ptitSeb af7bfc7de7 Added F2 0F 12 opcode ([DYNAREC] too) 2021-03-30 21:02:19 +02:00
ptitSeb e3759a5cd0 Added 'bin64' to the folder were to look for libs 2021-03-30 20:58:25 +02:00
ptitSeb c5f4820b4e Added A1/A3 opcodes ([DYNAREC] too) 2021-03-30 20:55:23 +02:00
ptitSeb a3d9da2fd4 Try to improve a bit signal handling 2021-03-30 19:36:27 +02:00
ptitSeb e592d2eb6d [DYNAREC] Fixed PLD emitter, fixing 0F 18 opcode for good this time 2021-03-30 18:51:17 +02:00
ptitSeb e57aaadb1d Fixed some wrapped function signature, and added a few more 2021-03-30 18:15:07 +02:00
ptitSeb 0d2492bfde Added wrapped swprintf 2021-03-30 17:55:29 +02:00
ptitSeb 1a3483e086 Fixed wrapped SDL_GetThreadID function signature 2021-03-30 17:55:10 +02:00
ptitSeb 171c213b32 Wraped some SDL2 printf functions 2021-03-30 15:26:46 +02:00
ptitSeb c4dcb316ca Added __strtol_internal wrapped function 2021-03-30 15:18:11 +02:00
ptitSeb 725f612eb5 [DYNAREC] disable dynarec when all fini function of loaded libs are done 2021-03-30 15:17:57 +02:00
ptitSeb 3539ed5bfe [DYNAREC] Fixed 66 0F C4/C5 opcodes, and small optim on 66 0F 70 2021-03-30 14:56:54 +02:00
ptitSeb a8bd94e34f [DYNAREC] Added a few more printers 2021-03-30 14:55:58 +02:00
ptitSeb 0d59028eb2 [DYNAREC] Optimized a bit 66 0F 70 opcode 2021-03-30 11:31:04 +02:00
ptitSeb 7ae39b38a0 Added wrapped __isoc99_vsscanf function 2021-03-29 20:35:57 +02:00
ptitSeb b69f9b9536 Added wrapped syslog and __syslog_chk 2021-03-29 20:28:50 +02:00
ptitSeb 6dbc4d44a8 Added wrapped libbz2 and liblzma 2021-03-29 20:19:37 +02:00
ptitSeb 397eff9712 [DYNAREC] Fixed 0F 18 opcodes 2021-03-29 19:20:31 +02:00
ptitSeb 51c23856f3 [DYNAREC] FillBlock is behind a mutex now, and use LR for easier debugging on jump_to_next 2021-03-29 18:42:36 +02:00
ptitSeb 6cb6605a63 Small change in start en end of emulated software 2021-03-29 18:41:38 +02:00
ptitSeb 6ad164d522 [DYNAREC] DynaMap is behind a strict mutex now 2021-03-29 18:39:00 +02:00
ptitSeb 19915ad238 Added syscall 57 2021-03-29 18:37:44 +02:00
ptitSeb 5e8fb55955 Goes with the new wrapped backtrace functions 2021-03-29 18:37:07 +02:00
ptitSeb d535bf35a8 Removed x64emu_t structure dedicated to signal handling, using main thread one now 2021-03-29 18:36:33 +02:00
ptitSeb 17d73a93f1 Some work around backtrace to try get symbol from stack frame (not sure it does work) 2021-03-29 18:35:39 +02:00
ptitSeb ac2f2516a2 [ARM64] Added a new arm64_lock_storeifref helper 2021-03-29 17:28:00 +02:00
ptitSeb 8994f9580c [DYNAREC] Small changes in F0 0F C7 opcode 2021-03-29 17:27:08 +02:00
ptitSeb 6013325637 Don't need to set FS here 2021-03-29 17:26:02 +02:00
ptitSeb ba19837104 Cosmetic change for F0 0F B1 opcode 2021-03-29 17:25:35 +02:00
ptitSeb 509a1bf56e Try to sistematicaly erase upper RAX on cmpxchg opcode 2021-03-29 17:24:32 +02:00
ptitSeb 5b07a475e1 [DYNAREC] Try to mitigate case of cmp/tst apparently 'for nothing' 2021-03-29 17:23:06 +02:00
ptitSeb bb97366338 Added wrapped wcstombs function 2021-03-29 11:24:19 +02:00
ptitSeb a527fdcc28 [DYNAREC] Added 0F C2 opcode 2021-03-29 11:23:36 +02:00
ptitSeb 5c3a4deed8 [DYNAREC] Added 0F 5D/5E/5F opcodes 2021-03-28 21:54:55 +02:00
ptitSeb 70b9bed510 [DYNAREC] Added 0F 18 opcodes 2021-03-28 21:43:01 +02:00
ptitSeb 37795375b6 [DYNAREC] Added F0 29 opcode 2021-03-28 21:25:18 +02:00
ptitSeb 903f9ddb41 [DYNAREC] Added F0 C7 opcode 2021-03-28 21:16:22 +02:00
ptitSeb 4b6ade050f Added wrapped asctime and friends 2021-03-28 19:21:34 +02:00
ptitSeb 02cfa0be7f Simply wrapped pthread_exit, don't force emu->quit to 1 2021-03-28 18:56:08 +02:00
ptitSeb da7a7a4d0e Removed a useless line in setjump wrapped function 2021-03-28 18:55:37 +02:00
ptitSeb 84a1b6976f [DYNAREC] Small optim on Native Call 2021-03-28 18:55:02 +02:00
ptitSeb 4d1641b321 [DYNAREC] Compute arm size of son block 2021-03-28 18:54:25 +02:00
ptitSeb ee561da549 Added more libc and pthreads wrapped functions 2021-03-28 15:54:51 +02:00
ptitSeb ba1493857f [DYNAREC] Improved Dynablock construction, stopping when overlaping block is detected 2021-03-28 15:08:55 +02:00
ptitSeb fb7a0318a0 [DYNAREC] Enhanced the special case of CMP follow by CALL handling (need to find a better solution) 2021-03-28 15:08:20 +02:00
ptitSeb 479ade9cb7 Fixed aio_suspend64 funciton signature 2021-03-28 14:32:41 +02:00
ptitSeb dfe62ceac8 Better Stack handling (backported from box86) 2021-03-28 14:31:11 +02:00
ptitSeb a36c9bfe73 A few more libc wrapped functions 2021-03-26 22:55:08 +01:00
ptitSeb a7119cae76 Added wrapped libudev0 and libudev1 2021-03-26 22:48:22 +01:00
ptitSeb c33368bfb4 Added 0F 18 opcode 2021-03-26 22:43:07 +01:00
ptitSeb 886999bc5b Added more libc wrapped functions 2021-03-26 22:40:12 +01:00
ptitSeb 1a750182d6 [DYNAREC] Added some more 66 0F opcodes, plus a few small bug fixes 2021-03-26 21:40:39 +01:00
ptitSeb 03a69053a6 Fixed a signature of an X11 wrapped function 2021-03-26 21:39:21 +01:00
ptitSeb 5788d4af1e Added more libc wrapped symbols 2021-03-26 20:13:12 +01:00
ptitSeb 517fe28806 Added a small batch of opcodes 2021-03-26 18:35:35 +01:00
ptitSeb b272bdb198 Added malloc_trim wrapped function 2021-03-26 17:57:44 +01:00
ptitSeb 910d22a532 Fixed Xutf8ResetIC signature 2021-03-26 17:55:04 +01:00
ptitSeb 2a85ea9c61 Added 64 66 0F D6 and 64 0F 29 opcodes 2021-03-26 17:48:51 +01:00
ptitSeb 3ee5c792d1 Fixed swprintf wrapping 2021-03-26 17:32:25 +01:00
ptitSeb 8e377ca074 Added DE opcodes 2021-03-26 17:05:57 +01:00
ptitSeb 451cfa521b Added DC opcodes 2021-03-26 15:43:38 +01:00
ptitSeb 6d02f7f897 Added a few more libc wrapped functions 2021-03-26 15:43:25 +01:00
ptitSeb 3e811f869e Added 66 0F 16/17 ocpode ([DYNAREC] too) 2021-03-26 15:42:54 +01:00
ptitSeb 1f17a57528 Set stack alignment to be 16bytes minimum 2021-03-26 15:27:52 +01:00
ptitSeb 8c2ea218a5 Added wrapped libdbus-1 2021-03-26 15:24:40 +01:00
ptitSeb 9f01b2ec0d Added wrapped libcups, plus some changes in wrapped libSDL2 and pthread 2021-03-26 14:42:50 +01:00
ptitSeb 86c5dfd664 Added (faked) crashhandler wrapped lib 2021-03-26 14:04:49 +01:00
ptitSeb c31aa8a78d Avoid to much much warning mesage when searching for a correct lib binary 2021-03-26 14:00:02 +01:00
ptitSeb 648d99c9e6 And one more wrapped libc function 2021-03-26 13:59:31 +01:00
ptitSeb cfe541e3ca Added alternative to __secure_getenv not always present in libc 2021-03-26 13:47:45 +01:00
ptitSeb b6faad0354 Added even more libc wrapped functions 2021-03-26 12:42:05 +01:00
ptitSeb 8aee3f4185 Added syscall 318 2021-03-26 12:41:20 +01:00
ptitSeb fe44725804 Added more libc and libfontconfig wrapped functions 2021-03-26 12:27:00 +01:00
ptitSeb 870e0872c0 Added F0 0F B0 opcode 2021-03-26 12:18:14 +01:00
ptitSeb 2874e30991 [DYNAREC] Fixed, again (for good) 66 0F 70 opcode 2021-03-26 12:13:37 +01:00
ptitSeb d92b46426c Added some more libc wrapped functions 2021-03-26 11:42:45 +01:00
ptitSeb 1c34edb857 Added syscall 13, 22, 157 and 217 2021-03-26 11:42:32 +01:00
ptitSeb aba3bcc81a Added 66 8D and 66 E8 opcode 2021-03-26 11:41:15 +01:00
ptitSeb 085529217e [DYNAREC] Fixed 66 0F 70 opcode 2021-03-26 11:40:25 +01:00
ptitSeb 50d8016e86 [DYNAREC] Added a small optim on 0F 57 opcode 2021-03-26 11:39:19 +01:00
ptitSeb 4a033b8e76 Added syscall 131 2021-03-26 10:01:55 +01:00
ptitSeb 4f5ad4b3ac Added wrapped __swprintf_chk function 2021-03-26 08:56:12 +01:00
ptitSeb 104d51df8c Added wrapped memalign and friends 2021-03-26 08:50:34 +01:00
ptitSeb 5c9ab0a27d Added 0F 6E opcode 2021-03-26 08:38:07 +01:00
ptitSeb 065d91cf9b Added 66 8B opcode (was already in dynarec) 2021-03-26 08:34:34 +01:00
ptitSeb acceb3155a Even more libc wrapped functions 2021-03-25 22:15:16 +01:00
ptitSeb 4130e0847c Minor fixes to MODRM decoder functions 2021-03-25 21:58:07 +01:00
ptitSeb 37a451a38e [DYNAREC] Fixed 8A opcode 2021-03-25 21:57:39 +01:00
ptitSeb dd26d06e1c Added wrapped libgnutls 2021-03-25 21:02:47 +01:00
ptitSeb 235784b46f Added wrapped libfontconfig and libfreetype, plus some elfloader/tls bugfix 2021-03-25 20:56:45 +01:00
ptitSeb 66af0f810c Fixed a bug on Interpretor with 64 prefixed opcodes 2021-03-25 20:55:44 +01:00
ptitSeb 72b60a2ab3 Fixed a potential issue with getAlignedMutex 2021-03-25 19:03:02 +01:00
ptitSeb 40e6f46013 Fixed to ElfLoader and TLS, Syscall, mmap & co functions signature and a few libc wrapped functions 2021-03-25 18:52:26 +01:00
ptitSeb a701ff87ec More libc wrapped symbols 2021-03-25 17:02:51 +01:00
ptitSeb 6e78bc1726 Added wrapped libICE and libSM plus a few more libc wrapped functions 2021-03-25 16:35:54 +01:00
ptitSeb 3b4181c616 [DYNAREC] Added 8A opcode 2021-03-25 16:24:09 +01:00
ptitSeb 2bd3fa6aa7 [DYNAREC] Added 66 0F 6D opcode 2021-03-25 16:12:03 +01:00
ptitSeb 4d0d971212 Small fix to avoid dereferencing a NULL x64emu_t structure 2021-03-25 16:11:32 +01:00
ptitSeb 1e451e3353 [DYNAREC] Added 0F 0B opcode 2021-03-25 15:50:02 +01:00
ptitSeb 207f829066 [DYNAREC] Added 86 opcode 2021-03-25 15:39:19 +01:00
ptitSeb f1fba8eb42 [DYNAREC] Fixed a nasty bug in GETGB macro 2021-03-25 15:39:04 +01:00
ptitSeb 146287331a [DYNAREC] Oops, fixed the mess with 66 REX 0F opcodes introduced earlier 2021-03-25 15:26:59 +01:00
ptitSeb 490dcac380 Small change in getAlignedMutex function (probably more work needed) 2021-03-25 15:20:05 +01:00
ptitSeb e8264eb0db A bit more libc wrapped function 2021-03-25 15:19:18 +01:00
ptitSeb 3c07dd58eb Added F3 0F BC opcode ([DYNAREC] too) 2021-03-25 15:06:48 +01:00
ptitSeb fcdd8fc383 Added some more libc wrapped functions 2021-03-25 14:41:11 +01:00
ptitSeb 0b56f5aebd Added wrapped libuuid 2021-03-25 14:14:31 +01:00
ptitSeb 178537116b Added a few more wrapped functions 2021-03-25 14:13:05 +01:00
ptitSeb 11cfae2a98 [DYNAREC] Added some mecanism to handle weird 66 REX mixing 2021-03-25 13:53:48 +01:00
ptitSeb 348bd64449 Added a bunch of X11 related wrapped libs 2021-03-25 13:26:02 +01:00
ptitSeb b36eca9792 [DYNAREC] Added F2 0F C2 opcode 2021-03-25 12:38:40 +01:00
ptitSeb 683b77c9bd Added some more libc wrapped function (and now SuperHexagon works fine) 2021-03-25 12:32:46 +01:00
ptitSeb 7809f23d4b Added wrapped libvorbis and libvorbisfile 2021-03-25 12:16:18 +01:00
ptitSeb 37a9549298 Added 2 more libc wrapped function 2021-03-25 11:55:01 +01:00
ptitSeb 8fa2368a63 Added wrapped libogg 2021-03-25 11:53:49 +01:00
ptitSeb 72ca99051b Improved shutdown sequence 2021-03-25 11:36:14 +01:00
ptitSeb 905e3ae583 Added a few more libc wrapped functions 2021-03-25 11:35:51 +01:00
ptitSeb 29be84ba47 Fixed longjmp wrapped function signature 2021-03-25 10:36:37 +01:00
ptitSeb 636c350461 Added wrapped mmap64 and friends 2021-03-25 10:34:10 +01:00
ptitSeb 89e305878b Fixed R_X86_64_64 handling is elfloader 2021-03-25 10:26:48 +01:00
ptitSeb 45873cc2b1 Added a bunch of libc wrapped functions 2021-03-25 09:44:36 +01:00
ptitSeb a32955ffec Fixed non-Dynarec build that would crash at start 2021-03-25 08:54:33 +01:00
ptitSeb 5b45f871df Start of a new dev. cycle 2021-03-25 08:53:54 +01:00
218 changed files with 27206 additions and 3748 deletions

No files matched your search

+65 -8
View File
@@ -1,11 +1,13 @@
cmake_minimum_required(VERSION 3.0)
option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch arm64 and armhf" ${RPI4ARM64})
option(RK3326 "Set to ON if targeting an Rockchip RK3326 based device" ${RK3326})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
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 Box64" ${NO_LOADAADR})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(RK3399 OR RPI4ARM64)
if(RK3399 OR RPI4ARM64 OR RK3326)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -47,6 +49,13 @@ if(RPI4ARM64)
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8")
endif()
if(RK3326)
add_definitions(-DRK3326)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a35+crypto")
endif()
if(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto)
@@ -129,11 +138,16 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run67.c"
"${BOX64_ROOT}/src/emu/x64run670f.c"
"${BOX64_ROOT}/src/emu/x64run6766.c"
"${BOX64_ROOT}/src/emu/x64run67660f.c"
"${BOX64_ROOT}/src/emu/x64rund8.c"
"${BOX64_ROOT}/src/emu/x64rund9.c"
"${BOX64_ROOT}/src/emu/x64runda.c"
"${BOX64_ROOT}/src/emu/x64rundb.c"
"${BOX64_ROOT}/src/emu/x64rundc.c"
"${BOX64_ROOT}/src/emu/x64rundd.c"
"${BOX64_ROOT}/src/emu/x64runde.c"
"${BOX64_ROOT}/src/emu/x64rundf.c"
"${BOX64_ROOT}/src/emu/x64runf0.c"
"${BOX64_ROOT}/src/emu/x64runf20f.c"
@@ -163,26 +177,57 @@ set(ELFLOADER_SRC
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
"${BOX64_ROOT}/src/wrapped/wrappedbz2.c"
"${BOX64_ROOT}/src/wrapped/wrappedcairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedcrashhandler.c"
"${BOX64_ROOT}/src/wrapped/wrappedcrypto.c"
"${BOX64_ROOT}/src/wrapped/wrappedcurl.c"
"${BOX64_ROOT}/src/wrapped/wrappeddbus.c"
"${BOX64_ROOT}/src/wrapped/wrappedfontconfig.c"
"${BOX64_ROOT}/src/wrapped/wrappedfreetype.c"
"${BOX64_ROOT}/src/wrapped/wrappedgnutls.c"
"${BOX64_ROOT}/src/wrapped/wrappedldlinux.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibasound.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibc.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibgl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibglu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibice.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpthread.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibresolv.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibrt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibsm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibssl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibuuid.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibvorbis.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibx11xcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxau.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcb.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcomposite.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxcursor.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxdamage.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxdmcp.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxext.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxfixes.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxi.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxmu.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxpm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxrandr.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxrender.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxss.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxtst.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibxxf86vm.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibz.c"
"${BOX64_ROOT}/src/wrapped/wrappedlzma.c"
"${BOX64_ROOT}/src/wrapped/wrappedopenal.c"
"${BOX64_ROOT}/src/wrapped/wrappedpango.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangocairo.c"
"${BOX64_ROOT}/src/wrapped/wrappedpangoft2.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
@@ -193,8 +238,13 @@ set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedsdl2.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl2ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg2.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev0.c"
"${BOX64_ROOT}/src/wrapped/wrappedudev1.c"
"${BOX64_ROOT}/src/wrapped/wrappedutil.c"
"${BOX64_ROOT}/src/wrapped/wrappedvorbisfile.c"
"${BOX64_ROOT}/src/wrapped/wrappedxinerama.c"
)
@@ -256,16 +306,17 @@ if(ARM_DYNAREC)
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_65.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_66.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_67.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d8.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_d9.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_da.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_db.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dc.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_dd.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_de.c"
#"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_df.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f0.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_660f.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_6664.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f20f.c"
"${BOX64_ROOT}/src/dynarec/dynarec_arm64_f30f.c"
)
@@ -321,10 +372,16 @@ if(ARM_DYNAREC)
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
if(NOT NOLOADADDR)
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
else()
set_target_properties(${BOX64} PROPERTIES LINK_FLAGS "-rdynamic")
endif()
else()
target_link_options(${BOX64} PUBLIC -rdynamic)
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
if(NOT NOLOADADDR)
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
+10
View File
@@ -53,6 +53,16 @@ Only on builds with trace enabled.
* 0 : The XMM (i.e. SSE/SSE2) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the XMM registers.
#### BOX64_TRACE_EMM
Only on builds with trace enabled.
* 0 : The EMM (i.e. XMM/x87) register will not be logged with the general and x86 registers. (Default.)
* 1 : Dump the EMM registers.
#### BOX64_TRACE_COLOR
Only on builds with trace enabled.
* 0 : The general registers will always be the default white color. (Default.)
* 1 : The general registers will change color in the dumps when they changed value.
#### BOX64_LOAD_ADDR
Try to load at 0xXXXXXX main binary (if binary is a PIE)
* 0xXXXXXXXX : The load address . (Only active on PIE programs.)
+306 -206
View File
@@ -3,7 +3,8 @@
import os
import sys
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H']
values = ['E', 'e', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', 'N', 'M', 'H', 'P']
assert(all(c not in values[:i] for i, c in enumerate(values)))
def splitchar(s):
try:
ret = [len(s), values.index(s[0])]
@@ -38,8 +39,10 @@ def main(root, defines, files, ver):
global values
# Initialize variables: gbl for all values, redirects for redirections
gbl = {}
redirects = {}
# mytypedefs is a list of all "*FE*" types per filename
gbl = {}
redirects = {}
mytypedefs = {}
# First read the files inside the headers
for filepath in files:
@@ -82,10 +85,21 @@ def main(root, defines, files, ver):
# If the line is a `GO...' line (GO/GOM/GO2/...)...
elif ln.startswith("GO"):
# ... then look at the second parameter of the line
funname = ln.split(",")[0].split("(")[1].strip()
ln = ln.split(",")[1].split(")")[0].strip()
if len(ln) < 3:
raise NotImplementedError("Type {0} too short ({1}:{2})".format(ln, filename, line[:-1]))
if "E" in ln:
if ("E" in ln[:2]) or ("E" in ln[3:]):
raise NotImplementedError(
"emu64_t* not as the first parameter ({0}:{1})".format(filename, line[:-1]))
if len(ln) < 4:
raise NotImplementedError("Type {0} too short ({1}:{2})".format(ln, filename, line[:-1]))
if ln[1] not in ["F"]:
raise NotImplementedError("Bad middle letter {0} ({1}:{2})".format(ln[1], filename, line[:-1]))
if any(c not in values for c in ln[2:]) or (('v' in ln[2:]) and (len(ln) > 3)):
old = ln
# This needs more work
@@ -93,16 +107,27 @@ def main(root, defines, files, ver):
if any(c not in acceptables for c in ln[2:]):
raise NotImplementedError("{0} ({1}:{2})".format(ln[2:], filename, line[:-1]))
# Ok, this is acceptable: there is 0, 1 and/or void
ln = (ln
ln = ln[:2] + (ln[2:]
.replace("v", "") # void -> nothing
.replace("0", "p") # 0 -> pointer
.replace("1", "i")) # 1 -> integer
assert(len(ln) >= 3)
redirects.setdefault(" && ".join(dependants), {})
redirects[" && ".join(dependants)][old] = ln
# Simply append the function name if it's not yet existing
gbl.setdefault(" && ".join(dependants), [])
if ln not in gbl[" && ".join(dependants)]:
gbl[" && ".join(dependants)].append(ln)
if ln[2] == "E":
# filename isn't stored with the '_private.h' part
if len(ln) > 3:
ln = ln[:2] + ln[3:]
else:
ln = ln[:2] + "v"
mytypedefs.setdefault(filename[:-10], {})
mytypedefs[filename[:-10]].setdefault(ln, [])
mytypedefs[filename[:-10]][ln].append(funname)
gbl_vals = {}
for k in gbl:
@@ -182,8 +207,12 @@ def main(root, defines, files, ver):
gbl[k].sort(key=lambda v: splitchar(v))
values = values + ['0', '1']
for k in redirects:
redirects[k].sort(key=lambda v: splitchar(v[0]) + [0] + splitchar(v[1]))
redirects[k].sort(key=lambda v: splitchar(v[0]) + [-1] + splitchar(v[1]))
values = values[:-2]
mytypedefs_vals = dict((fn, sorted(mytypedefs[fn].keys(), key=lambda v: splitchar(v))) for fn in mytypedefs)
for fn in mytypedefs:
for v in mytypedefs_vals[fn]:
mytypedefs[fn][v].sort()
# Check if there was any new functions
functions_list = ""
@@ -203,17 +232,58 @@ def main(root, defines, files, ver):
# Mark as OK for CMake
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
file.write(functions_list)
#return 0
return 0
except IOError:
# The file does not exist yet, first run
pass
# Detect simple wrappings
simple_wraps = {}
# H could be allowed maybe?
allowed_simply = "v"
allowed_regs = "cCwWiuIUlLp"
allowed_fpr = "fd"
# Sanity checks
forbidden_simple = "EeDKVOSNMHP"
assert(len(allowed_simply) + len(allowed_regs) + len(allowed_fpr) + len(forbidden_simple) == len(values))
assert(all(c not in allowed_regs for c in allowed_simply))
assert(all(c not in allowed_simply + allowed_regs for c in allowed_fpr))
assert(all(c not in allowed_simply + allowed_regs + allowed_fpr for c in forbidden_simple))
assert(all(c in allowed_simply + allowed_regs + allowed_fpr + forbidden_simple for c in values))
# Only search on real wrappers
for k in ["()"] + gbl_idxs:
for v in gbl[k]:
regs_count = 0
fpr_count = 0
if v[0] in forbidden_simple:
continue
for c in v[2:]:
if c in allowed_regs:
regs_count = regs_count + 1
elif c in allowed_fpr:
fpr_count = fpr_count + 1
elif c in allowed_simply:
continue
else:
break
else:
# No character in forbidden_simply
if (regs_count <= 6) and (fpr_count <= 4):
# All checks passed!
simple_wraps.setdefault(k, []).append(v)
simple_idxs = list(simple_wraps.keys())
simple_idxs.sort(key=lambda v: [-1] if v == "()" else splitdef(v, defines))
# Now the files rebuilding part
# File headers and guards
files_headers = {
"wrapper.c": """/*****************************************************************
* File automatically generated by rebuild_wrappers.py (v%s)
*****************************************************************/
files_header = {
"wrapper.c": """/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v{version}) *
*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -229,7 +299,7 @@ extern void* my__IO_2_1_stdin_ ;
extern void* my__IO_2_1_stdout_;
static void* io_convert(void* v)
{
{lbr}
if(!v)
return v;
if(v==my__IO_2_1_stderr_)
@@ -239,15 +309,16 @@ static void* io_convert(void* v)
if(v==my__IO_2_1_stdout_)
return stdout;
return v;
}
{rbr}
#define ST0val ST0.d
int of_convert(int);
""",
"wrapper.h": """/*****************************************************************
* File automatically generated by rebuild_wrappers.py (v%s)
*****************************************************************/
"wrapper.h": """/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v{version}) *
*******************************************************************/
#ifndef __WRAPPER_H_
#define __WRAPPER_H_
#include <stdint.h>
@@ -261,7 +332,7 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
// list of defined wrapper
// v = void, i = int32, u = uint32, U/I= (u)int64
// l = signed long, L = unsigned long (long is an int with the size of a pointer)
// p = pointer, P = callback
// p = pointer, P = void* on the stack
// f = float, d = double, D = long double, K = fake long double
// V = vaargs, E = current x86emu struct, e = ref to current x86emu struct
// 0 = constant 0, 1 = constant 1
@@ -275,57 +346,53 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
// M = ... automatically sending 2 args
// H = Huge 128bits value/struct
""",
"fntypes.h": """/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v{version}) *
*******************************************************************/
#ifndef __{filename}TYPES_H_
#define __{filename}TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
"""
}
files_guards = {"wrapper.c": """""",
files_guard = {"wrapper.c": """""",
"wrapper.h": """
#endif //__WRAPPER_H_
int isSimpleWrapper(wrapper_t fun);
#endif // __WRAPPER_H_
""",
"fntypes.h": """
#endif // __{filename}TYPES_H_
"""
}
# Rewrite the wrapper.h file:
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
file.write(files_headers["wrapper.h"] % ver)
for v in gbl["()"]:
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
for k in redirects_idxs:
file.write("\n#if " + k + "\n")
for v in redirects[k]:
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write(files_guards["wrapper.h"])
# Rewrite the wrapper.c file:
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_headers["wrapper.c"] % ver)
def generate_typedefs(arr, file):
# i and u should only be 32 bits
# E e v c w i I C W u U f d D K l L p V O S N M H P
types = ["x64emu_t*", "x64emu_t**", "void", "int8_t", "int16_t", "int64_t", "int64_t", "uint8_t", "uint16_t", "uint64_t", "uint64_t", "float", "double", "long double", "double", "intptr_t", "uintptr_t", "void*", "void*", "int32_t", "void*", "...", "...", "unsigned __int128", "void*"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
# First part: typedefs
for v in gbl["()"]:
# E e v c w i I C W u U f d D K l L p V O S N M H
types = ["x64emu_t*", "x64emu_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*", "...", "...", "unsigned __int128"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
for v in arr:
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.c"), 'w') as file:
file.write(files_header["wrapper.c"].format(lbr="{", rbr="}", version=ver))
# First part: typedefs
generate_typedefs(gbl["()"], file)
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
# E e v c w i I C W u U f d D K l L p V O S N M H
types = ["x64emu_t*", "x64emu_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*", "...", "...", "unsigned __int128"]
if len(values) != len(types):
raise NotImplementedError("len(values) = {lenval} != len(types) = {lentypes}".format(lenval=len(values), lentypes=len(types)))
file.write("typedef " + types[values.index(v[0])] + " (*" + v + "_t)"
+ "(" + ', '.join(types[values.index(t)] for t in v[2:]) + ");\n")
generate_typedefs(gbl[k], file)
file.write("#endif\n")
file.write("\n")
@@ -335,153 +402,162 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
# Helper variables
reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
# vreg: value is in a general register
# E e v c w i I C W u U f d D K l L p V O S N M H
vreg = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2]
# E e v c w i I C W u U f d D K l L p V O S N M H P
vreg = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 0]
# vxmm: value is in a XMM register
# E e v c w i I C W u U f d D K l L p V O S N M H
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# E e v c w i I C W u U f d D K l L p V O S N M H P
vxmm = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# vother: value is elsewere
# E e v c w i I C W u U f d D K l L p V O S N M, H
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
# E e v c w i I C W u U f d D K l L p V O S N M, H P
vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0]
# vstack: value is on the stack (or out of register)
# E e v c w i I C W u U f d D K l L p V O S N M, H
vstack = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2]
# E e v c w i I C W u U f d D K l L p V O S N M, H P
vstack = [0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 1, 2, 2, 1]
arg_s = [
"", # E
"", # e
"", # v
"*(int8_t*)(R_RSP + {p}), ", # c
"*(int16_t*)(R_RSP + {p}), ", # w
"*(int32_t*)(R_RSP + {p}), ", # i
"*(int64_t*)(R_RSP + {p}), ", # I
"*(uint8_t*)(R_RSP + {p}), ", # C
"*(uint16_t*)(R_RSP + {p}), ", # W
"*(uint32_t*)(R_RSP + {p}), ", # u
"*(uint64_t*)(R_RSP + {p}), ", # U
"*(float*)(R_RSP + {p}), ", # f
"*(double*)(R_RSP + {p}), ", # d
"*(long double*)(R_RSP + {p}), ", # D
"FromLD((void*)(R_RSP + {p})), ", # K
"*(intptr_t*)(R_RSP + {p}), ", # l
"*(uintptr_t*)(R_RSP + {p}), ", # L
"*(void**)(R_RSP + {p}), ", # p
"", # V
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
"io_convert(*(void**)(R_RSP + {p})), ", # S
"*(void**)(R_RSP + {p}), ", # N
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
"*(unsigned __int128)(R_RSP + {p}), " # H
"", # E
"", # e
"", # v
"*(int8_t*)(R_RSP + {p}), ", # c
"*(int16_t*)(R_RSP + {p}), ", # w
"*(int64_t*)(R_RSP + {p}), ", # i should be int32_t
"*(int64_t*)(R_RSP + {p}), ", # I
"*(uint8_t*)(R_RSP + {p}), ", # C
"*(uint16_t*)(R_RSP + {p}), ", # W
"*(uint64_t*)(R_RSP + {p}), ", # u should be uint32_t
"*(uint64_t*)(R_RSP + {p}), ", # U
"*(float*)(R_RSP + {p}), ", # f
"*(double*)(R_RSP + {p}), ", # d
"*(long double*)(R_RSP + {p}), ", # D
"FromLD((void*)(R_RSP + {p})), ", # K
"*(intptr_t*)(R_RSP + {p}), ", # l
"*(uintptr_t*)(R_RSP + {p}), ", # L
"*(void**)(R_RSP + {p}), ", # p
"", # V
"of_convert(*(int32_t*)(R_RSP + {p})), ", # O
"io_convert(*(void**)(R_RSP + {p})), ", # S
"*(void**)(R_RSP + {p}), ", # N
"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ", # M
"*(unsigned __int128)(R_RSP + {p}), ", # H
"*(void**)(R_RSP + {p}), ", # P
]
arg_r = [
"", # E
"", # e
"", # v
"(int8_t){p}, ", # c
"(int16_t){p}, ", # w
"(int32_t){p}, ", # i
"(int64_t){p}, ", # I
"(uint8_t){p}, ", # C
"(uint16_t){p}, ", # W
"(uint32_t){p}, ", # u
"(uint64_t){p}, ", # U
"", # f
"", # d
"", # D
"", # K
"(intptr_t){p}, ", # l
"(uintptr_t){p}, ", # L
"(void*){p}, ", # p
"", # V
"of_convert((int32_t){p}), ", # O
"io_convert((void*){p}), ", # S
"(void*){p}, ", # N
"(void*){p}, ", # M
"#error use pp instead, ", #H
"", # E
"", # e
"", # v
"(int8_t){p}, ", # c
"(int16_t){p}, ", # w
"(int64_t){p}, ", # i should int32_t
"(int64_t){p}, ", # I
"(uint8_t){p}, ", # C
"(uint16_t){p}, ", # W
"(uint64_t){p}, ", # u should uint32_t
"(uint64_t){p}, ", # U
"", # f
"", # d
"", # D
"", # K
"(intptr_t){p}, ", # l
"(uintptr_t){p}, ", # L
"(void*){p}, ", # p
"", # V
"of_convert((int32_t){p}), ", # O
"io_convert((void*){p}), ", # S
"(void*){p}, ", # N
"(void*){p}, ", # M
"\n#error Use pp instead\n", # H
"", # P
]
arg_x = [
"", # E
"", # e
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # E
"", # e
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"emu->xmm[{p}].f[0], ", # f
"emu->xmm[{p}].d[0], ", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
]
arg_o = [
"emu, ", # E
"&emu, ", # e
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"(void*)(R_RSP + {p}), ", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"emu, ", # E
"&emu, ", # e
"", # v
"", # c
"", # w
"", # i
"", # I
"", # C
"", # W
"", # u
"", # U
"", # f
"", # d
"", # D
"", # K
"", # l
"", # L
"", # p
"(void*)(R_RSP + {p}), ", # V
"", # O
"", # S
"", # N
"", # M
"", # H
"", # P
]
vals = [
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=fn({0});", # i
"R_RAX=(uint64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint32_t)fn({0});", # u
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"\n#error Invalid return type: emulator\n", # E
"\n#error Invalid return type: &emulator\n", # e
"fn({0});", # v
"R_RAX=fn({0});", # c
"R_RAX=fn({0});", # w
"R_RAX=(int64_t)fn({0});", # i int32_t normaly
"R_RAX=(int64_t)fn({0});", # I
"R_RAX=(unsigned char)fn({0});", # C
"R_RAX=(unsigned short)fn({0});", # W
"R_RAX=(uint64_t)fn({0});", # u uint32_t normaly
"R_RAX=fn({0});", # U
"emu->xmm[0].f[0]=fn({0});", # f
"emu->xmm[0].d[0]=fn({0});", # d
"long double ld=fn({0}); fpu_do_push(emu); ST0val = ld;", # D
"double db=fn({0}); fpu_do_push(emu); ST0val = db;", # K
"R_RAX=(intptr_t)fn({0});", # l
"R_RAX=(uintptr_t)fn({0});", # L
"R_RAX=(uintptr_t)fn({0});", # p
"\n#error Invalid return type: va_list\n", # V
"\n#error Invalid return type: at_flags\n", # O
"\n#error Invalid return type: _io_file*\n", # S
"\n#error Invalid return type: ... with 1 arg\n", # N
"\n#error Invalid return type: ... with 2 args\n", # M
"unsigned __int128 u128 = fn({0}); R_RAX=(u128&0xFFFFFFFFFFFFFFFFL); R_RDX=(u128>>64)&0xFFFFFFFFFFFFFFFFL;", # H
"\n#error Invalid return type: pointer in the stack\n", # P
]
# Asserts
if len(values) != len(arg_s):
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(values), lenargr=len(arg_s)))
raise NotImplementedError("len(values) = {lenval} != len(arg_s) = {lenargs}".format(lenval=len(values), lenargs=len(arg_s)))
if len(values) != len(arg_r):
raise NotImplementedError("len(values) = {lenval} != len(arg_r) = {lenargr}".format(lenval=len(values), lenargr=len(arg_r)))
if len(values) != len(arg_x):
raise NotImplementedError("len(values) = {lenval} != len(arg_x) = {lenargx}".format(lenval=len(values), lenargx=len(arg_x)))
if len(values) != len(arg_o):
raise NotImplementedError("len(values) = {lenval} != len(arg_o) = {lenargo}".format(lenval=len(values), lenargo=len(arg_o)))
if len(values) != len(vals):
raise NotImplementedError("len(values) = {lenval} != len(vals) = {lenvals}".format(lenval=len(values), lenvals=len(vals)))
@@ -510,27 +586,8 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
def function_writer(f, N, W, rettype, args):
f.write("void {0}(x64emu_t *emu, uintptr_t fcn) {2} {1} fn = ({1})fcn; ".format(N, W, "{"))
if any(cc in 'PG' for cc in args):
# Vulkan struct or GValue pointer, need to unwrap functions at the end
delta = 4
for c in args:
if c == 'P':
f.write("void* save{d}=NULL; void *arg{d} = VulkanFromx86(*(void**)(R_RSP + {d}), &save{d}); ".format(d=delta))
if c == 'G':
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_RSP + {d})); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " ")
delta = 4
for c in args:
if c == 'P':
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
if c == 'G':
f.write("unalignGValue(*(void**)(R_RSP + {d}), &arg{d}); ".format(d=delta))
delta = delta + deltas[values.index(c)]
f.write("}\n")
else:
# Generic function
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
# Generic function
f.write(vals[values.index(rettype)].format(function_args(args)[:-2]) + " }\n")
for v in gbl["()"]:
function_writer(file, v, v + "_t", v[0], v[2:])
@@ -548,7 +605,50 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
function_writer(file, v[0], v[1] + "_t", v[0][0], v[0][2:])
file.write("#endif\n")
file.write(files_guards["wrapper.c"])
# Write the isSimpleWrapper function
file.write("\nint isSimpleWrapper(wrapper_t fun) {\n")
for k in simple_idxs:
if k != "()":
file.write("#if " + k + "\n")
for v in simple_wraps[k]:
file.write("\tif (fun == &" + v + ") return 1;\n")
if k != "()":
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:
with open(os.path.join(root, "src", "wrapped", "generated", "wrapper.h"), 'w') as file:
file.write(files_header["wrapper.h"].format(lbr="{", rbr="}", version=ver))
for v in gbl["()"]:
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
for k in gbl_idxs:
file.write("\n#if " + k + "\n")
for v in gbl[k]:
file.write("void " + v + "(x64emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write("\n")
for v in redirects["()"]:
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
for k in redirects_idxs:
file.write("\n#if " + k + "\n")
for v in redirects[k]:
file.write("void " + v[0] + "(x64emu_t *emu, uintptr_t fnc);\n")
file.write("#endif\n")
file.write(files_guard["wrapper.h"].format(lbr="{", rbr="}", version=ver))
# Rewrite the *types.h files:
for fn in mytypedefs:
with open(os.path.join(root, "src", "wrapped", "generated", fn + "types.h"), 'w') as file:
file.write(files_header["fntypes.h"].format(lbr="{", rbr="}", version=ver, filename=fn))
generate_typedefs(mytypedefs_vals[fn], file)
file.write("\n#define SUPER() ADDED_FUNCTIONS()")
for v in mytypedefs_vals[fn]:
for f in mytypedefs[fn][v]:
file.write(" \\\n\tGO({0}, {1}_t)".format(f, v))
file.write("\n")
file.write(files_guard["fntypes.h"].format(lbr="{", rbr="}", version=ver, filename=fn))
# Save the string for the next iteration, writing was successful
with open(os.path.join(root, "src", "wrapped", "generated", "functions_list.txt"), 'w') as file:
@@ -561,6 +661,6 @@ if __name__ == '__main__':
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.2.0.09") != 0:
if main(sys.argv[1], sys.argv[2:limit[0]], sys.argv[limit[0]+1:], "1.3.0.10") != 0:
exit(2)
exit(0)
+101 -17
View File
@@ -68,6 +68,77 @@ void free_tlsdatasize(void* p)
void x64Syscall(x64emu_t *emu);
int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#define GO(A, B) \
i = checkMutex(&A); \
if(i) { \
pthread_mutex_unlock(&A); \
ret|=(1<<B); \
}
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
GO(my_context->mutex_trace, 7)
#ifdef DYNAREC
GO(my_context->mutex_dyndump, 8)
#else
GO(my_context->mutex_lock, 8)
#endif
GO(my_context->mutex_tls, 9)
GO(my_context->mutex_thread, 10)
#undef GO
return ret;
}
void relockMutex(int locks)
{
relockCustommemMutex(locks);
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
GO(my_context->mutex_once, 5)
GO(my_context->mutex_once2, 6)
GO(my_context->mutex_trace, 7)
#ifdef DYNAREC
GO(my_context->mutex_dyndump, 8)
#else
GO(my_context->mutex_lock, 8)
#endif
GO(my_context->mutex_tls, 9)
GO(my_context->mutex_thread, 10)
#undef GO
}
static void init_mutexes(box64context_t* context)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&context->mutex_once, &attr);
pthread_mutex_init(&context->mutex_once2, &attr);
pthread_mutex_init(&context->mutex_trace, &attr);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, &attr);
#else
pthread_mutex_init(&context->mutex_dyndump, &attr);
#endif
pthread_mutex_init(&context->mutex_tls, &attr);
pthread_mutex_init(&context->mutex_thread, &attr);
pthread_mutexattr_destroy(&attr);
}
static void atfork_child_box64context(void)
{
// (re)init mutex if it was lock before the fork
init_mutexes(my_context);
}
EXPORTDYN
box64context_t *NewBox64Context(int argc)
{
@@ -96,16 +167,9 @@ box64context_t *NewBox64Context(int argc)
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
pthread_mutex_init(&context->mutex_once, NULL);
pthread_mutex_init(&context->mutex_once2, NULL);
pthread_mutex_init(&context->mutex_trace, NULL);
#ifndef DYNAREC
pthread_mutex_init(&context->mutex_lock, NULL);
#else
pthread_mutex_init(&context->mutex_dyndump, NULL);
#endif
pthread_mutex_init(&context->mutex_tls, NULL);
pthread_mutex_init(&context->mutex_thread, NULL);
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
pthread_key_create(&context->tlskey, free_tlsdatasize);
@@ -129,16 +193,16 @@ void FreeBox64Context(box64context_t** context)
box64context_t* ctx = *context; // local copy to do the cleanning
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib, NULL);
if(ctx->maplib)
FreeLibrarian(&ctx->maplib, NULL);
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
}
free(ctx->elfs);
if(ctx->maplib)
FreeLibrarian(&ctx->maplib);
if(ctx->local_maplib)
FreeLibrarian(&ctx->local_maplib);
FreeCollection(&ctx->box64_path);
FreeCollection(&ctx->box64_ld_lib);
FreeCollection(&ctx->box64_emulated_libs);
@@ -174,8 +238,6 @@ void FreeBox64Context(box64context_t** context)
FreeDLPrivate(&ctx->dlprivate);
free(ctx->stack);
free(ctx->fullpath);
free(ctx->box64path);
@@ -266,3 +328,25 @@ void free_neededlib(needed_libs_t* needed)
free(needed->libs);
needed->libs = NULL;
}
void add_dependedlib(needed_libs_t* depended, library_t* lib)
{
if(!depended)
return;
if(depended->size == depended->cap) {
depended->cap += 8;
depended->libs = (library_t**)realloc(depended->libs, depended->cap*sizeof(library_t*));
}
depended->libs[depended->size++] = lib;
}
void free_dependedlib(needed_libs_t* depended)
{
if(!depended)
return;
depended->cap = 0;
depended->size = 0;
if(depended->libs)
free(depended->libs);
depended->libs = NULL;
}
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX64_MAJOR 0
#define BOX64_MINOR 0
#define BOX64_REVISION 6
#define BOX64_REVISION 8
#endif //__BOX64_VERSION_H_
+199 -33
View File
@@ -21,6 +21,7 @@
#include <sys/mman.h>
#include "custommem.h"
#include "khash.h"
#include "threads.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm64_lock.h"
@@ -55,7 +56,7 @@ typedef struct blocklist_s {
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
static pthread_mutex_t mutex_blocks = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex_blocks;
static int n_blocks = 0; // number of blocks for custom malloc
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
@@ -427,6 +428,7 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
return 0;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
#ifndef USE_MMAP
pthread_mutex_lock(&mutex_mmap);
void *p = NULL;
if(posix_memalign(&p, box64_pagesize, size)) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
@@ -450,14 +452,11 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)p, &ret);
kh_value(blocks, k) = db;
pthread_mutex_unlock(&mutex_mmap);
return (uintptr_t)p;
}
if(pthread_mutex_trylock(&mutex_mmap)) {
sched_yield(); // give it a chance
if(pthread_mutex_trylock(&mutex_mmap))
return 0; // cannot lock, baillout
}
pthread_mutex_lock(&mutex_mmap);
uintptr_t ret = FindFreeDynarecMap(db, size);
if(!ret)
@@ -470,7 +469,10 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
{
if(!addr || !size)
return;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
pthread_mutex_lock(&mutex_mmap);
#ifndef USE_MMAP
free((void*)addr);
#else
@@ -482,6 +484,7 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
}
pthread_mutex_unlock(&mutex_mmap);
return;
}
pthread_mutex_lock(&mutex_mmap);
@@ -514,12 +517,21 @@ void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
int idx3 = (i>>32)&((1<<DYNAMAP_SHIFT)-1);
int idx2 = (i>>16)&((1<<DYNAMAP_SHIFT)-1);
int idx1 = (i )&((1<<DYNAMAP_SHIFT)-1);
if(!dynmap123[idx3])
dynmap123[idx3] = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
if(!dynmap123[idx3][idx2])
dynmap123[idx3][idx2] = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
if(!dynmap123[idx3][idx2][idx1])
dynmap123[idx3][idx2][idx1] = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
if(!dynmap123[idx3]) {
dynablocklist_t*** p = (dynablocklist_t***)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t**));
if(arm64_lock_storeifnull(&dynmap123[idx3], p)!=p)
free(p);
}
if(!dynmap123[idx3][idx2]) {
dynablocklist_t** p = (dynablocklist_t**)calloc(1<<DYNAMAP_SHIFT, sizeof(dynablocklist_t*));
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2], p)!=p)
free(p);
}
if(!dynmap123[idx3][idx2][idx1]) {
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
if(arm64_lock_storeifnull(&dynmap123[idx3][idx2][idx1], p)!=p)
FreeDynablockList(&p);
}
}
}
@@ -559,23 +571,25 @@ void addJumpTableIfDefault64(void* addr, void* jmp)
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = box64_jmptbldefault1;
box64_jmptbl3[idx3] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
free(tbl);
}
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = box64_jmptbldefault0;
box64_jmptbl3[idx3][idx2] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
free(tbl);
}
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm64_next;
box64_jmptbl3[idx3][idx2][idx1] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
free(tbl);
}
if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)
box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)jmp;
arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1][idx0], jmp, arm64_next);
}
void setJumpTableDefault64(void* addr)
{
@@ -594,6 +608,23 @@ void setJumpTableDefault64(void* addr)
return;
box64_jmptbl3[idx3][idx2][idx1][idx0] = (uintptr_t)arm64_next;
}
int isJumpTableDefault64(void* addr)
{
uintptr_t idx3, idx2, idx1, idx0;
idx3 = (((uintptr_t)addr)>>48)&0xffff;
idx2 = (((uintptr_t)addr)>>32)&0xffff;
idx1 = (((uintptr_t)addr)>>16)&0xffff;
idx0 = (((uintptr_t)addr) )&0xffff;
if(box64_jmptbl3[idx3] == box64_jmptbldefault2)
return 1;
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1)
return 1;
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0)
return 1;
if(box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)
return 1;
return (box64_jmptbl3[idx3][idx2][idx1][idx0]==(uintptr_t)arm64_next)?1:0;
}
uintptr_t getJumpTable64()
{
return (uintptr_t)box64_jmptbl3;
@@ -602,27 +633,30 @@ uintptr_t getJumpTable64()
uintptr_t getJumpTableAddress64(uintptr_t addr)
{
uintptr_t idx3, idx2, idx1, idx0;
idx3 = (((uintptr_t)addr)>>48)&0xffff;
idx2 = (((uintptr_t)addr)>>32)&0xffff;
idx1 = (((uintptr_t)addr)>>16)&0xffff;
idx0 = (((uintptr_t)addr) )&0xffff;
idx3 = ((addr)>>48)&0xffff;
idx2 = ((addr)>>32)&0xffff;
idx1 = ((addr)>>16)&0xffff;
idx0 = ((addr) )&0xffff;
if(box64_jmptbl3[idx3] == box64_jmptbldefault2) {
uintptr_t*** tbl = (uintptr_t***)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t**));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = box64_jmptbldefault1;
box64_jmptbl3[idx3] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3], tbl, box64_jmptbldefault2)!=tbl)
free(tbl);
}
if(box64_jmptbl3[idx3][idx2] == box64_jmptbldefault1) {
uintptr_t** tbl = (uintptr_t**)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t*));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = box64_jmptbldefault0;
box64_jmptbl3[idx3][idx2] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2], tbl, box64_jmptbldefault1)!=tbl)
free(tbl);
}
if(box64_jmptbl3[idx3][idx2][idx1] == box64_jmptbldefault0) {
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm64_next;
box64_jmptbl3[idx3][idx2][idx1] = tbl;
if(arm64_lock_storeifref(&box64_jmptbl3[idx3][idx2][idx1], tbl, box64_jmptbldefault0)!=tbl)
free(tbl);
}
return (uintptr_t)&box64_jmptbl3[idx3][idx2][idx1][idx0];
@@ -650,7 +684,7 @@ void protectDB(uintptr_t addr, uintptr_t size)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
if(!(prot&PROT_DYNAREC))
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
}
pthread_mutex_unlock(&mutex_prot);
}
@@ -674,7 +708,7 @@ void protectDBnolock(uintptr_t addr, uintptr_t size)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
kh_value(memprot, k)[ii] = prot|PROT_DYNAREC;
if(!(prot&PROT_DYNAREC))
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~(PROT_WRITE|PROT_CUSTOM));
}
}
@@ -708,7 +742,7 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
uint8_t prot = kh_value(memprot, k)[ii];
kh_value(memprot, k)[ii] = prot&~PROT_DYNAREC;
if(prot&PROT_DYNAREC) {
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
}
}
@@ -734,8 +768,8 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
const uintptr_t ii = i&(MEMPROT_SIZE-1);
uint32_t dyn = kh_value(memprot, k)[ii]&PROT_DYNAREC;
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
kh_value(memprot, k)[ii] = prot|dyn;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
kh_value(memprot, k)[ii] = prot|dyn|PROT_ALLOC;
}
pthread_mutex_unlock(&mutex_prot);
}
@@ -755,7 +789,27 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
kh_value(memprot, k) = m;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
kh_value(memprot, k)[ii] = prot;
kh_value(memprot, k)[ii] = prot|PROT_ALLOC;
}
pthread_mutex_unlock(&mutex_prot);
}
void freeProtection(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "freeProtection %p:%p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
khint_t k = kh_put(memprot, memprot, key, &ret);
if(ret) {
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
}
const uintptr_t ii = i&(MEMPROT_SIZE-1);
kh_value(memprot, k)[ii] = 0;
}
pthread_mutex_unlock(&mutex_prot);
}
@@ -775,15 +829,126 @@ uint32_t getProtection(uintptr_t addr)
return ret;
}
#define LOWEST (void*)0x20000
int availableBlock(uint8_t* p, size_t n)
{
for (int i=0; i<n; ++i, ++p)
if(*p)
return 0;
return 1;
}
void* find32bitBlock(size_t size)
{
// slow iterative search... Would need something better one day
const uint32_t key = 0; // upper value is 0 by request
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
return LOWEST;
}
uint8_t *prot = kh_val(memprot, k);
pthread_mutex_unlock(&mutex_prot);
void* p = (void*)LOWEST;
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
do {
const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT;
if(availableBlock(prot+idx, pages))
return p;
p += 0x10000;
} while(p!=(void*)0xffff0000);
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
return NULL;
}
void* findBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
if(!hint) hint=LOWEST;
const uint32_t key = (((uintptr_t)hint)>>32)&0xffffffff;
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
return hint;
}
uint8_t *prot = kh_val(memprot, k);
pthread_mutex_unlock(&mutex_prot);
void* p = hint;
void* end = (void*)((uintptr_t)hint+0x100000000LL);
uintptr_t step = (size+0xfff)&~0xfff;
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
do {
const uintptr_t idx = (((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT;
if(availableBlock(prot+idx, pages))
return p;
p += step;
} while(p!=end);
printf_log(LOG_NONE, "Warning: cannot find a 0x%lx block in 32bits address space\n", size);
return NULL;
}
#undef LOWEST
int unlockCustommemMutex()
{
int ret = 0;
int i = 0;
#define GO(A, B) \
i = checkMutex(&A); \
if(i) { \
pthread_mutex_unlock(&A); \
ret|=(1<<B); \
}
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
return ret;
}
void relockCustommemMutex(int locks)
{
#define GO(A, B) \
if(locks&(1<<B)) \
pthread_mutex_lock(&A); \
GO(mutex_blocks, 0)
GO(mutex_prot, 1)
#ifdef DYNAREC
GO(mutex_mmap, 2)
#endif
#undef GO
}
static void init_mutexes(void)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex_blocks, &attr);
pthread_mutex_init(&mutex_prot, &attr);
#ifdef DYNAREC
pthread_mutex_init(&mutex_mmap, &attr);
#endif
pthread_mutexattr_destroy(&attr);
}
static void atfork_child_custommem(void)
{
// (re)init mutex if it was lock before the fork
init_mutexes();
}
void init_custommem_helper(box64context_t* ctx)
{
if(inited) // already initialized
return;
inited = 1;
memprot = kh_init(memprot);
pthread_mutex_init(&mutex_prot, NULL);
init_mutexes();
#ifdef DYNAREC
pthread_mutex_init(&mutex_mmap, NULL);
#ifdef ARM64
if(box64_dynarec)
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i) {
@@ -796,6 +961,7 @@ void init_custommem_helper(box64context_t* ctx)
#error Unsupported architecture!
#endif
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
}
void fini_custommem_helper(box64context_t *ctx)
@@ -870,5 +1036,5 @@ void fini_custommem_helper(box64context_t *ctx)
#endif
free(p_blocks);
pthread_mutex_destroy(&mutex_prot);
//pthread_mutex_destroy(&mutex_blocks);
pthread_mutex_destroy(&mutex_blocks);
}
+469 -23
View File
@@ -137,6 +137,7 @@
#define ADDx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(1, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(0, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(ADDSUB_REG_gen(0, 0, 0, 0b00, Rm, lsl, Rn, Rd))
#define ADDxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b00, Rm, 0, Rn, Rd))
#define ADDSxw_REG(Rd, Rn, Rm) EMIT(ADDSUB_REG_gen(rex.w, 0, 1, 0b00, Rm, 0, Rn, Rd))
#define ADDxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(ADDSUB_REG_gen(rex.w, 0, 0, 0b01, Rm, lsr, Rn, Rd))
@@ -306,6 +307,14 @@
#define LDAXRxw(Rt, Rn) EMIT(MEMAX_gen(2+rex.w, 1, 31, Rn, Rt))
#define STLXRxw(Rs, Rt, Rn) EMIT(MEMAX_gen(2+rex.w, 0, Rs, Rn, Rt))
#define MEMAX_pair(size, L, Rs, Rt2, Rn, Rt) (1<<31 | (size)<<30 | 0b001000<<24 | (L)<<22 | 1<<21 | (Rs)<<16 | 1<<15 | (Rt2)<<10 | (Rn)<<5 | (Rt))
#define LDAXPx(Rt, Rt2, Rn) EMIT(MEMAX_pair(1, 1, 31, Rt2, Rn, Rt))
#define LDAXPw(Rt, Rt2, Rn) EMIT(MEMAX_pair(0, 1, 31, Rt2, Rn, Rt))
#define LDAXPxw(Rt, Rt2, Rn) EMIT(MEMAX_pair(rex.w, 1, 31, Rt2, Rn, Rt))
#define STLXPx(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(1, 0, Rs, Rt2, Rn, Rt))
#define STLXPw(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(0, 0, Rs, Rt2, Rn, Rt))
#define STLXPxw(Rs, Rt, Rt2, Rn) EMIT(MEMAX_pair(rex.w, 0, Rs, Rt2, Rn, Rt))
// LOAD/STORE Exclusive
#define MEMX_gen(size, L, Rs, Rn, Rt) ((size)<<30 | 0b001000<<24 | (L)<<22 | (Rs)<<16 | 0<<15 | 0b11111<<10 | (Rn)<<5 | (Rt))
#define LDXRB(Rt, Rn) EMIT(MEMX_gen(0b00, 1, 31, Rn, Rt))
@@ -319,6 +328,24 @@
#define LDXRxw(Rt, Rn) EMIT(MEMX_gen(2+rex.w, 1, 31, Rn, Rt))
#define STXRxw(Rs, Rt, Rn) EMIT(MEMX_gen(2+rex.w, 0, Rs, Rn, Rt))
// Prefetch
#define PRFM_register(Rm, option, S, Rn, Rt) (0b11<<30 | 0b111<<27 | 0b10<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | 0b10<<10 | (Rn)<<5 | (Rt))
#define PLD_L1_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00000))
#define PLD_L2_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00010))
#define PLD_L3_KEEP(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00100))
#define PLD_L1_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00001))
#define PLD_L2_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00011))
#define PLD_L3_STREAM(Rn, Rm) EMIT(PRFM_register(Rm, 0b011, 0, Rn, 0b00101))
#define PRFM_imm(imm12, Rn, Rt) (0b11<<30 | 0b111<<27 | 0b01<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define PLD_L1_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00000))
#define PLD_L2_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00010))
#define PLD_L3_KEEP_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00100))
#define PLD_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00001))
#define PLD_L2_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00011))
#define PLD_L3_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b00101))
// BR and Branches
#define BR_gen(Z, op, A, M, Rn, Rm) (0b1101011<<25 | (Z)<<24 | (op)<<21 | 0b11111<<16 | (A)<<11 | (M)<<10 | (Rn)<<5 | (Rm))
#define BR(Rn) EMIT(BR_gen(0, 0b00, 0, 0, Rn, 0))
@@ -584,9 +611,31 @@
#define MRS_nzvc(Rt) EMIT(MRS_gen(1, 1, 3, 4, 2, 0, Rt))
// MSR : to System register
#define MSR_nzvc(Rt) EMIT(MRS_gen(0, 1, 3, 4, 2, 0, Rt))
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=2
#define VMRS(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
#define VMSR(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
// mrs x0, fpcr : 1101010100 1 1 1 011 0100 0100 000 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=0
#define MRS_fpcr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 0, Rt))
#define MSR_fpcr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 0, Rt))
// mrs x0, fpsr : 1101010100 1 1 1 011 0100 0100 001 00000 o0=1(op0=3), op1=0b011(3) CRn=0b0100(4) CRm=0b0100(4) op2=1
#define MRS_fpsr(Rt) EMIT(MRS_gen(1, 1, 3, 4, 4, 1, Rt))
#define MSR_fpsr(Rt) EMIT(MRS_gen(0, 1, 3, 4, 4, 1, Rt))
// NEON Saturation Bit
#define FPSR_QC 27
// NEON Input Denormal Cumulative
#define FPSR_IDC 7
// NEON IneXact Cumulative
#define FPSR_IXC 4
// NEON Underflow Cumulative
#define FPSR_UFC 3
// NEON Overflow Cumulative
#define FPSR_OFC 2
// NEON Divide by 0 Cumulative
#define FPSR_DZC 1
// NEON Invalid Operation Cumulative
#define FPSR_IOC 0
// FCSEL
#define FCSEL_scalar(type, Rm, cond, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | (cond)<<12 | 0b11<<10 | (Rn)<<5 | (Rd))
#define FCSELS(Sd, Sn, Sm, cond) EMIT(FCSEL_scalar(0b00, Sm, cond, Sn, Sd))
#define FCSELD(Dd, Dn, Dm, cond) EMIT(FCSEL_scalar(0b01, Dm, cond, Dn, Dd))
// VLDR
#define VMEM_gen(size, opc, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | 0b01<<24 | (opc)<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
@@ -602,6 +651,22 @@
#define VSTR64_U12(Dt, Rn, imm15) EMIT(VMEM_gen(0b11, 0b00, ((uint32_t)(imm15>>3))&0xfff, Rn, Dt))
// imm16 must be 4-aligned
#define VSTR128_U12(Qt, Rn, imm16) EMIT(VMEM_gen(0b00, 0b10, ((uint32_t)((imm16)>>4))&0xfff, Rn, Qt))
// (imm14) must be 1-aligned
#define VSTR16_U12(Ht, Rn, imm14) EMIT(VMEM_gen(0b01, 0b00, ((uint32_t)(imm14>>1))&0xfff, Rn, Ht))
#define VMEMUR_vector(size, opc, imm9, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (Rn)<<5 | (Rt))
// signed offset, no alignement!
#define VLDR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b01, (imm9)&0b111111111, Rn, Vt))
#define VLDR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b11, (imm9)&0b111111111, Rn, Vt))
// signed offset, no alignement!
#define VSTR8_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR16_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b01, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR32_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b10, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR64_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b11, 0b00, (imm9)&0b111111111, Rn, Vt))
#define VSTR128_I9(Vt, Rn, imm9) EMIT(VMEMUR(0b00, 0b10, (imm9)&0b111111111, Rn, Vt))
#define VMEMW_gen(size, opc, imm9, op2, Rn, Rt) ((size)<<30 | 0b111<<27 | 1<<26 | (opc)<<22 | (imm9)<<12 | (op2)<<10 | 0b01<<10 | (Rn)<<5 | (Rt))
#define VLDR64_S9_postindex(Rt, Rn, imm9) EMIT(VMEMW_gen(0b11, 0b01, (imm9)&0x1ff, 0b01, Rn, Rt))
@@ -629,6 +694,12 @@
#define VSTR128_REG(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 0, Rn, Dt))
#define VSTR128_REG_LSL4(Qt, Rn, Rm) EMIT(VMEM_REG_gen(0b00, 0b10, Rm, 0b011, 1, Rn, Dt))
#define VLDR_PC_gen(opc, imm19, Rt) ((opc)<<30 | 0b011<<27 | 1<<26 | (imm19)<<5 | (Rt))
#define VLDR32_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b00, ((imm19)>>2)&0x7FFFF, Vt))
#define VLDR64_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b01, ((imm19)>>2)&0x7FFFF, Vt))
#define VLDR128_literal(Vt, imm19) EMIT(VLDR_PC_gen(0b10, ((imm19)>>2)&0x7FFFF, Vt))
#define LD1R_gen(Q, size, Rn, Rt) ((Q)<<30 | 0b0011010<<23 | 1<<22 | 0<<21 | 0b110<<13 | (size)<<10 | (Rn)<<5 | (Rt))
#define VLDQ1R_8(Vt, Rn) EMIT(LD1R_gen(1, 0b00, Rn, Vt))
#define VLDQ1R_16(Vt, Rn) EMIT(LD1R_gen(1, 0b01, Rn, Vt))
@@ -664,9 +735,24 @@
#define VSHLQ_32(Vd, Vn, shift) EMIT(SHL_vector(1, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
#define VSHLQ_64(Vd, Vn, shift) EMIT(SHL_vector(1, 0b1000 | (((shift)>>3)&7), (shift)&7, Vn, Vd))
#define VSHL_8(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0001, (shift)&7, Vn, Vd))
#define VSHL_16(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0010 | ((shift)>>3)&1, (shift)&7, Vn, Vd))
#define VSHL_16(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0010 | (((shift)>>3)&1), (shift)&7, Vn, Vd))
#define VSHL_32(Vd, Vn, shift) EMIT(SHL_vector(0, 0b0100 | (((shift)>>3)&3), (shift)&7, Vn, Vd))
#define SHL_scalar(U, size, Rm, R, S, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b010<<13 | (R)<<12 | (S)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SSHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(0, 0b11, Vm, 0, 0, Vn, Vd))
#define SHL_scalar_imm(U, immh, immb, Rn, Rd) (0b01<<30 | 0b111110<<23 | (immh)<<19 | (immb)<<16 | 0b01010<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SHL_64(Vd, Vn, shift) EMIT(SHL_scalar_imm(0, 0b1000 | (((shift)>>3)&7), (shift)&7, Vn, Vd))
#define SHL_vector_vector(Q, U, size, Rm, R, S, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b010<<13 | (R)<<12 | (S)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SSHL_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b00, Vm, 0, 0, Vn, Vd))
#define SSHL_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b01, Vm, 0, 0, Vn, Vd))
#define SSHL_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 0, 0b10, Vm, 0, 0, Vn, Vd))
#define SSHLQ_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b00, Vm, 0, 0, Vn, Vd))
#define SSHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b01, Vm, 0, 0, Vn, Vd))
#define SSHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b10, Vm, 0, 0, Vn, Vd))
#define SSHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 0, 0b11, Vm, 0, 0, Vn, Vd))
#define SHR_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b00000<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VSHRQ_8(Vd, Vn, shift) EMIT(SHR_vector(1, 1, 0b0001, (8-(shift))&7, Vn, Vd))
#define VSHRQ_16(Vd, Vn, shift) EMIT(SHR_vector(1, 1, 0b0010 | (((16-(shift))>>3)&1), (16-(shift))&7, Vn, Vd))
@@ -683,7 +769,12 @@
#define VSSHR_16(Vd, Vn, shift) EMIT(SHR_vector(0, 0, 0b0010 | (((16-(shift))>>3)&1), (16-(shift))&7, Vn, Vd))
#define VSSHR_32(Vd, Vn, shift) EMIT(SHR_vector(0, 0, 0b0100 | (((32-(shift))>>3)&3), (32-(shift))&7, Vn, Vd))
#define SHR_scalar_imm(U, immh, immb, o1, o0, Rn, Rd) (0b01<<30 | (U)<<29 | 0b111110<<23 | (immh)<<19 | (immb)<<16 | (o1)<<13 | (o0)<<12 | 1<<10 | (Rn)<<5 | (Rd))
#define SSHR_64(Vd, Vn, shift) EMIT(SHR_scalar_imm(0, 0b1000 | (((64-(shift))>>3)&7), (64-(shift))&7, 0, 0, Vn, Vd))
#define USHR_64(Vd, Vn, shift) EMIT(SHR_scalar_imm(1, 0b1000 | (((64-(shift))>>3)&7), (64-(shift))&7, 0, 0, Vn, Vd))
#define EXT_vector(Q, Rm, imm4, Rn, Rd) ((Q)<<30 | 0b101110<<24 | (Rm)<<16 | (imm4)<<11 | (Rn)<<5 | (Rd))
#define VEXT_8(Rd, Rn, Rm, index) EMIT(EXT_vector(0, Rm, index, Rn, Rd))
#define VEXTQ_8(Rd, Rn, Rm, index) EMIT(EXT_vector(1, Rm, index, Rn, Rd))
// Shift Left and Insert (not touching lower part of dest)
@@ -723,6 +814,22 @@
#define VSUB_16(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
#define VSUB_32(Vd, Vn, Vm) EMIT(ADDSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
#define NEGABS_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define NEG_8(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b00, Vn, Vd))
#define NEG_16(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b01, Vn, Vd))
#define NEG_32(Vd, Vn) EMIT(NEGABS_vector(0, 1, 0b10, Vn, Vd))
#define NEGQ_8(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b00, Vn, Vd))
#define NEGQ_16(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b01, Vn, Vd))
#define NEGQ_32(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b10, Vn, Vd))
#define NEGQ_64(Vd, Vn) EMIT(NEGABS_vector(1, 1, 0b11, Vn, Vd))
#define ABS_8(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b00, Vn, Vd))
#define ABS_16(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b01, Vn, Vd))
#define ABS_32(Vd, Vn) EMIT(NEGABS_vector(0, 0, 0b10, Vn, Vd))
#define ABSQ_8(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b00, Vn, Vd))
#define ABSQ_16(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b01, Vn, Vd))
#define ABSQ_32(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b10, Vn, Vd))
#define ABSQ_64(Vd, Vn) EMIT(NEGABS_vector(1, 0, 0b11, Vn, Vd))
// FMOV
#define FMOV_general(sf, type, mode, opcode, Rn, Rd) ((sf)<<31 | 0b11110<<24 | (type)<<22 | 1<<21 | (mode)<<19 | (opcode)<<16 | (Rn)<<5 | (Rd))
// 32-bit to single-precision
@@ -742,12 +849,21 @@
#define FMOVS(Sd, Sn) EMIT(FMOV_register(0b00, Sn, Sd))
#define FMOVD(Dd, Dn) EMIT(FMOV_register(0b01, Dn, Dd))
#define FMOV_vector_imm(Q, op, abc, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | 0b1111<<12 | 1<<10 | (defgh)<<5 | (Rd))
#define VFMOVS_8(Vd, u8) EMIT(FMOV_vector_imm(0, 0, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
#define VFMOVSQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 0, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
#define VFMOVDQ_8(Vd, u8) EMIT(FMOV_vector_imm(1, 1, ((u8)>>5)&0b111, (u8)&0b11111, Vd))
#define FMOV_scalar_imm(type, imm8, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (imm8)<<13 | 0b100<<10 | (Rd))
#define FMOVS_8(Sd, u8) EMIT(FMOV_scalar_imm(0b00, u8, Sd))
#define FMOVD_8(Dd, u8) EMIT(FMOV_scalar_imm(0b01, u8, Dd))
// VMOV
#define VMOV_element(imm5, imm4, Rn, Rd) (1<<30 | 1<<29 | 0b01110000<<21 | (imm5)<<16 | (imm4)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VMOVeB(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<1) | 1, i2, Vn, Vd))
#define VMOVeH(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<2) | 2, i2<<1, Vn, Vd))
#define VMOVeS(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<3) | 4, i2<<2, Vn, Vd))
#define VMOVeD(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<4) | 8, i2<<3, Vn, Vd))
#define VMOVeB(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<1) | 1, (i2), Vn, Vd))
#define VMOVeH(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<2) | 2, (i2)<<1, Vn, Vd))
#define VMOVeS(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<3) | 4, (i2)<<2, Vn, Vd))
#define VMOVeD(Vd, i1, Vn, i2) EMIT(VMOV_element(((i1)<<4) | 8, (i2)<<3, Vn, Vd))
#define VMOV_from(imm5, Rn, Rd) (1<<30 | 0<<29 | 0b01110000<<21 | (imm5)<<16 | 0b0011<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VMOVQBfrom(Vd, index, Wn) EMIT(VMOV_from(((index)<<1) | 1, Wn, Vd))
@@ -761,6 +877,9 @@
#define VMOVHto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<2) | 2, Vn, Wd))
#define VMOVSto(Wd, Vn, index) EMIT(UMOV_gen(0, ((index)<<3) | 4, Vn, Wd))
#define MVN_vector(Q, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VMVNQ(Rd, Rn) EMIT(MVN_vector(1, Rn, Rd))
// VORR
#define ORR_vector(Q, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | 0b10<<22 | 1<<21 | (Rm)<<16 | 0b00011<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VORRQ(Vd, Vn, Vm) EMIT(ORR_vector(1, Vm, Vn, Vd))
@@ -802,18 +921,27 @@
// ADD Pair
#define ADDP_vector(Q, size, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VADDPQ_8(Vd, Vn, Vm) EMIT(ADDP(1, 0b00, Vm, Vn, Vd))
#define VADDPQ_16(Vd, Vn, Vm) EMIT(ADDP(1, 0b01, Vm, Vn, Vd))
#define VADDPQ_32(Vd, Vn, Vm) EMIT(ADDP(1, 0b10, Vm, Vn, Vd))
#define VADDPQ_64(Vd, Vn, Vm) EMIT(ADDP(1, 0b11, Vm, Vn, Vd))
#define VADDP_8(Vd, Vn, Vm) EMIT(ADDP(0, 0b00, Vm, Vn, Vd))
#define VADDP_16(Vd, Vn, Vm) EMIT(ADDP(0, 0b01, Vm, Vn, Vd))
#define VADDP_32(Vd, Vn, Vm) EMIT(ADDP(0, 0b10, Vm, Vn, Vd))
#define VADDPQ_8(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b00, Vm, Vn, Vd))
#define VADDPQ_16(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b01, Vm, Vn, Vd))
#define VADDPQ_32(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b10, Vm, Vn, Vd))
#define VADDPQ_64(Vd, Vn, Vm) EMIT(ADDP_vector(1, 0b11, Vm, Vn, Vd))
#define VADDP_8(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b00, Vm, Vn, Vd))
#define VADDP_16(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b01, Vm, Vn, Vd))
#define VADDP_32(Vd, Vn, Vm) EMIT(ADDP_vector(0, 0b10, Vm, Vn, Vd))
#define FADDP_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11010<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFADDPQS(Vd, Vn, Vm) EMIT(FADDP_vector(1, 0, Vm, Vn, Vd))
#define VFADDPQD(Vd, Vn, Vm) EMIT(FADDP_vector(1, 1, Vm, Vn, Vd))
// NEG / ABS
#define FNEGABS_scalar(type, opc, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | (opc)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FNEGS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b10, Sn, Sd))
#define FNEGD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b10, Dn, Dd))
#define FABSS(Sd, Sn) EMIT(FNEGABS_scalar(0b00, 0b01, Sn, Sd))
#define FABSD(Dd, Dn) EMIT(FNEGABS_scalar(0b01, 0b01, Dn, Dd))
// MUL
#define FMUL_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11011<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMULS(Sd, Sn, Sm) EMIT(FMUL_vector(0, 0, Sm, Sn, Sd))
@@ -1019,8 +1147,8 @@
#define SCVTFDx(Dd, Xn) EMIT(SCVTF_scalar(1, 0b01, 0b00, 0b010, Xn, Dd))
#define SCVTF_vector_scalar(U, sz, Rn, Rd) (1<<30 | (U)<<29 | 0b11110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SCVTFSS(Vd, Vn) EMIT(SCVT_vector_scalar(0, 0, Vn, Vd))
#define SCVTFDD(Vd, Vn) EMIT(SCVT_vector_scalar(0, 1, Vn, Vd))
#define SCVTFSS(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 0, Vn, Vd))
#define SCVTFDD(Vd, Vn) EMIT(SCVTF_vector_scalar(0, 1, Vn, Vd))
#define SCVTF_vector(Q, U, sz, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SCVTFS(Vd, Vn) EMIT(SCVTF_vector(0, 0, 0, Vn, Vd))
@@ -1028,6 +1156,28 @@
#define SCVTQFS(Vd, Vn) EMIT(SCVTF_vector(1, 0, 0, Vn, Vd))
#define SCVTQFD(Vd, Vn) EMIT(SCVTF_vector(1, 0, 1, Vn, Vd))
// FRINTI Floating-point Round to Integral, using current rounding mode from FPCR (vector).
#define FRINT_vector(Q, U, o2, sz, o1, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o2)<<23 | (sz)<<22 | 0b10000<<17 | 0b1100<<13 | (o1)<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFRINTIS(Vd,Vn) EMIT(FRINT_vector(0, 1, 1, 0, 1, Vn, Vd))
#define VFRINTISQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 0, 1, Vn, Vd))
#define VFRINTIDQ(Vd,Vn) EMIT(FRINT_vector(1, 1, 1, 1, 1, Vn, Vd))
#define FRINTxx_scalar(type, op, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b0100<<17 | (op)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINT32ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b00, Sn, Sd))
#define FRINT32ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b00, Dn, Dd))
#define FRINT32XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b01, Sn, Sd))
#define FRINT32XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b01, Dn, Dd))
#define FRINT64ZS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b10, Sn, Sd))
#define FRINT64ZD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b10, Dn, Dd))
#define FRINT64XS(Sd, Sn) EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
#define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
#define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd))
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
#define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
#define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
#define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
// FMAX / FMIN
#define FMINMAX_vector(Q, U, o1, sz, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o1)<<23 | (sz)<<22 | 0b1<<21 | (Rm)<<16 | 0b11110<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFMINS(Vd, Vn, Vm) EMIT(FMINMAX_vector(0, 0, 1, 0, Vm, Vn, Vd))
@@ -1088,6 +1238,7 @@
#define TBL_gen(Q, Rm, len, op, Rn, Rd) ((Q)<<30 | 0b001110<<24 | (Rm)<<16 | (len)<<13 | (op)<<12 | (Rn)<<5 | (Rd))
//Use Rm[] to pick from Rn element and store in Rd. Out-of-range element gets 0
#define VTBLQ1_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b00, 0, Rn, Rd))
#define VTBL1_8(Rd, Rn, Rm) EMIT(TBL_gen(0, Rm, 0b00, 0, Rn, Rd))
//Use Rm[] to pick from Rn, Rn+1 element and store in Rd. Out-of-range element gets 0
#define VTBLQ2_8(Rd, Rn, Rm) EMIT(TBL_gen(1, Rm, 0b01, 0, Rn, Rd))
//Use Rm[] to pick from Rn, Rn+1, Rn+2 element and store in Rd. Out-of-range element gets 0
@@ -1116,6 +1267,14 @@
#define VTRNQ2_8(Vd, Vn, Vm) EMIT(TRN_gen(1, 0b00, Vm, 1, Vn, Vd))
// QXTN / QXTN2
#define QXTN_scalar(U, size, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 0b10000<<17 | 0b10100<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Signed saturating extract Narrow, from D to S
#define SQXTN_S_D(Sd, Dn) EMIT(QXTN_scalar(0, 0b10, Dn, Sd))
// Signed saturating extract Narrow, from S to H
#define SQXTN_H_S(Hd, Sn) EMIT(QXTN_scalar(0, 0b01, Sn, Hd))
// Signed saturating extract Narrow, from H to B
#define SQXTN_B_H(Bd, Hn) EMIT(QXTN_scalar(0, 0b00, Hn, Bd))
#define QXTN_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b10100<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Signed saturating extract Narrow, takes Rn element and reduce 64->32 with Signed saturation and fit lower part of Rd
#define SQXTN_32(Rd, Rn) EMIT(QXTN_vector(0, 0, 0b10, Rn, Rd))
@@ -1129,22 +1288,39 @@
#define SQXTN_8(Rd, Rn) EMIT(QXTN_vector(0, 0, 0b00, Rn, Rd))
// Signed saturating extract Narrow, takes Rn element and reduce 16->8 with Signed saturation and fit higher part of Rd
#define SQXTN2_8(Rd, Rn) EMIT(QXTN_vector(1, 0, 0b00, Rn, Rd))
// Unsigned saturating Extract Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit lower part of Rd
#define UQXTN_32(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b10, Rn, Rd))
// Unsigned saturating Extract Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit higher part of Rd
#define UQXTN2_32(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b10, Rn, Rd))
// Unsigned saturating extract Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit lower part of Rd
#define UQXTN_16(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b01, Rn, Rd))
// Unsigned saturating extract Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit higher part of Rd
#define UQXTN2_16(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b01, Rn, Rd))
// Unsigned saturating extract Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit lower part of Rd
#define UQXTN_8(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b00, Rn, Rd))
// Unsigned saturating extract Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit higher part of Rd
#define UQXTN2_8(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b00, Rn, Rd))
#define QXTUN_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b10010<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit lower part of Rd
#define SQXTUN_32(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b10, Rn, Rd))
#define SQXTUN_32(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b10, Rn, Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 64->32 with Unsigned saturation and fit higher part of Rd
#define SQXTUN2_32(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b10, Rn, Rd))
#define SQXTUN2_32(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b10, Rn, Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit lower part of Rd
#define SQXTUN_16(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b01, Rn, Rd))
#define SQXTUN_16(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b01, Rn, Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 32->16 with Unsigned saturation and fit higher part of Rd
#define SQXTUN2_16(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b01, Rn, Rd))
#define SQXTUN2_16(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b01, Rn, Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit lower part of Rd
#define SQXTUN_8(Rd, Rn) EMIT(QXTN_vector(0, 1, 0b00, Rn, Rd))
#define SQXTUN_8(Rd, Rn) EMIT(QXTUN_vector(0, 1, 0b00, Rn, Rd))
// Signed saturating extract Unsigned Narrow, takes Rn element and reduce 16->8 with Unsigned saturation and fit higher part of Rd
#define SQXTUN2_8(Rd, Rn) EMIT(QXTN_vector(1, 1, 0b00, Rn, Rd))
#define SQXTUN2_8(Rd, Rn) EMIT(QXTUN_vector(1, 1, 0b00, Rn, Rd))
// Integer CMP
// EQual
#define CMEQ_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VCMEQ_8(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b00, Rm, Rn, Rd))
#define VCMEQ_16(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b01, Rm, Rn, Rd))
#define VCMEQ_32(Rd, Rn, Rm) EMIT(CMEQ_vector(0, 1, 0b10, Rm, Rn, Rd))
#define VCMEQQ_8(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b00, Rm, Rn, Rd))
#define VCMEQQ_16(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b01, Rm, Rn, Rd))
#define VCMEQQ_32(Rd, Rn, Rm) EMIT(CMEQ_vector(1, 1, 0b10, Rm, Rn, Rd))
@@ -1172,6 +1348,22 @@
#define VCHIQQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b10, 0, Rm, Rn, Rd))
#define VCHIQQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b11, 0, Rm, Rn, Rd))
// Vector Float CMP
// EQual
#define FCMP_vector(Q, U, E, sz, Rm, ac, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (E)<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b1110<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define FCMEQQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 0, 0, 1, Rm, 0, Rn, Rd))
#define FCMEQQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 0, 0, 0, Rm, 0, Rn, Rd))
// Greater or Equal
#define FCMGEQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 1, Rm, 0, Rn, Rd))
#define FCMGEQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 0, Rm, 0, Rn, Rd))
#define FCMGEQD_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 1, Rm, 1, Rn, Rd))
#define FCMGEQS_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 0, 0, Rm, 1, Rn, Rd))
// Greater Than
#define FCMGTQD(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 1, Rm, 0, Rn, Rd))
#define FCMGTQS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 0, Rm, 0, Rn, Rd))
#define FCMGTQD_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 1, Rm, 1, Rn, Rd))
#define FCMGTQS_ABS(Rd, Rn, Rm) EMIT(FCMP_vector(1, 1, 1, 0, Rm, 1, Rn, Rd))
// UMULL / SMULL
#define MULL_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b1100<<12 |(Rn)<<5 |(Rd))
#define VUMULL_8(Rd, Rn, Rm) EMIT(MULL_vector(0, 1, 0b00, Rm, Rn, Rd))
@@ -1180,5 +1372,259 @@
#define VUMULL2_8(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b00, Rm, Rn, Rd))
#define VUMULL2_16(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b01, Rm, Rn, Rd))
#define VUMULL2_32(Rd, Rn, Rm) EMIT(MULL_vector(1, 1, 0b10, Rm, Rn, Rd))
#define VSMULL_8(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b00, Rm, Rn, Rd))
#define VSMULL_16(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b01, Rm, Rn, Rd))
#define VSMULL_32(Rd, Rn, Rm) EMIT(MULL_vector(0, 0, 0b10, Rm, Rn, Rd))
#define VSMULL2_8(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b00, Rm, Rn, Rd))
#define VSMULL2_16(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b01, Rm, Rn, Rd))
#define VSMULL2_32(Rd, Rn, Rm) EMIT(MULL_vector(1, 0, 0b10, Rm, Rn, Rd))
// MUL
#define MUL_vector(Q, size, Rm, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10011<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VMUL_8(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b00, Vm, Vn, Vd))
#define VMUL_16(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b01, Vm, Vn, Vd))
#define VMUL_32(Vd, Vn, Vm) EMIT(MUL_vector(0, 0b10, Vm, Vn, Vd))
#define VMULQ_8(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b00, Vm, Vn, Vd))
#define VMULQ_16(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b01, Vm, Vn, Vd))
#define VMULQ_32(Vd, Vn, Vm) EMIT(MUL_vector(1, 0b10, Vm, Vn, Vd))
// (S/Q)ADD
#define QADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00001<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SQADDQ_8(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b00, Vm, Vn, Vd))
#define SQADDQ_16(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SQADDQ_32(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b10, Vm, Vn, Vd))
#define SQADDQ_64(Vd, Vn, Vm) EMIT(QADD_vector(1, 0, 0b11, Vm, Vn, Vd))
#define UQADDQ_8(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b00, Vm, Vn, Vd))
#define UQADDQ_16(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b01, Vm, Vn, Vd))
#define UQADDQ_32(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b10, Vm, Vn, Vd))
#define UQADDQ_64(Vd, Vn, Vm) EMIT(QADD_vector(1, 1, 0b11, Vm, Vn, Vd))
#define SQADD_8(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b00, Vm, Vn, Vd))
#define SQADD_16(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b01, Vm, Vn, Vd))
#define SQADD_32(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b10, Vm, Vn, Vd))
#define SQADD_64(Vd, Vn, Vm) EMIT(QADD_vector(0, 0, 0b11, Vm, Vn, Vd))
#define UQADD_8(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b00, Vm, Vn, Vd))
#define UQADD_16(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b01, Vm, Vn, Vd))
#define UQADD_32(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b10, Vm, Vn, Vd))
#define UQADD_64(Vd, Vn, Vm) EMIT(QADD_vector(0, 1, 0b11, Vm, Vn, Vd))
// Absolute Difference
#define AD_vector(Q, U, size, Rm, ac, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b0111<<12 | (ac)<<11 | 1<<10 | (Rn)<<5 | (Rd))
// Signed Absolute Difference and accumulate
#define SABAQ_8(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b00, Rm, 1, Rn, Rd))
#define SABAQ_16(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b01, Rm, 1, Rn, Rd))
#define SABAQ_32(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b10, Rm, 1, Rn, Rd))
#define SABA_8(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b00, Rm, 1, Rn, Rd))
#define SABA_16(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b01, Rm, 1, Rn, Rd))
#define SABA_32(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b10, Rm, 1, Rn, Rd))
// Signed Absolute Difference
#define SABDQ_8(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b00, Rm, 0, Rn, Rd))
#define SABDQ_16(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b01, Rm, 0, Rn, Rd))
#define SABDQ_32(Rd, Rn, Rm) EMIT(AD_vector(1, 0, 0b10, Rm, 0, Rn, Rd))
#define SABD_8(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b00, Rm, 0, Rn, Rd))
#define SABD_16(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b01, Rm, 0, Rn, Rd))
#define SABD_32(Rd, Rn, Rm) EMIT(AD_vector(0, 0, 0b10, Rm, 0, Rn, Rd))
#define ADL_vector(Q, U, size, Rm, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b01<<14 | (op)<<13 | 1<<12 | (Rn)<<5 | (Rd))
#define SABAL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b00, Rm, 0, Rn, Rd))
#define SABAL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b00, Rm, 0, Rn, Rd))
#define SABAL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b01, Rm, 0, Rn, Rd))
#define SABAL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b01, Rm, 0, Rn, Rd))
#define SABAL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b10, Rm, 0, Rn, Rd))
#define SABAL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b10, Rm, 0, Rn, Rd))
#define UABAL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b00, Rm, 0, Rn, Rd))
#define UABAL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b00, Rm, 0, Rn, Rd))
#define UABAL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b01, Rm, 0, Rn, Rd))
#define UABAL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b01, Rm, 0, Rn, Rd))
#define UABAL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b10, Rm, 0, Rn, Rd))
#define UABAL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b10, Rm, 0, Rn, Rd))
#define SABDL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b00, Rm, 1, Rn, Rd))
#define SABDL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b00, Rm, 1, Rn, Rd))
#define SABDL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b01, Rm, 1, Rn, Rd))
#define SABDL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b01, Rm, 1, Rn, Rd))
#define SABDL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 0, 0b10, Rm, 1, Rn, Rd))
#define SABDL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 0, 0b10, Rm, 1, Rn, Rd))
#define UABDL_8(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b00, Rm, 1, Rn, Rd))
#define UABDL2_8(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b00, Rm, 1, Rn, Rd))
#define UABDL_16(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b01, Rm, 1, Rn, Rd))
#define UABDL2_16(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b01, Rm, 1, Rn, Rd))
#define UABDL_32(Rd, Rn, Rm) EMIT(ADL_vector(0, 1, 0b10, Rm, 1, Rn, Rd))
#define UABDL2_32(Rd, Rn, Rm) EMIT(ADL_vector(1, 1, 0b10, Rm, 1, Rn, Rd))
// Add Pairwise
#define ADDLP_vector(Q, U, size, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (op)<<14 | 0b10<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SADDLPQ_8(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b00, 0, Rn, Rd))
#define SADDLPQ_16(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b01, 0, Rn, Rd))
#define SADDLPQ_32(Rd, Rn) EMIT(ADDLP_vector(1, 0, 0b10, 0, Rn, Rd))
#define SADDLP_8(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b00, 0, Rn, Rd))
#define SADDLP_16(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b01, 0, Rn, Rd))
#define SADDLP_32(Rd, Rn) EMIT(ADDLP_vector(0, 0, 0b10, 0, Rn, Rd))
#define UADDLPQ_8(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b00, 0, Rn, Rd))
#define UADDLPQ_16(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b01, 0, Rn, Rd))
#define UADDLPQ_32(Rd, Rn) EMIT(ADDLP_vector(1, 1, 0b10, 0, Rn, Rd))
#define UADDLP_8(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b00, 0, Rn, Rd))
#define UADDLP_16(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b01, 0, Rn, Rd))
#define UADDLP_32(Rd, Rn) EMIT(ADDLP_vector(0, 1, 0b10, 0, Rn, Rd))
// Add accros vector
#define ADDLV_vector(Q, U, size, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 0b11000<<17 | 0b00011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define SADDLVQ_8(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b00, Rn, Rd))
#define SADDLVQ_16(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b01, Rn, Rd))
#define SADDLVQ_32(Rd, Rn) EMIT(ADDLV_vector(1, 0, 0b10, Rn, Rd))
#define SADDLV_8(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b00, Rn, Rd))
#define SADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b01, Rn, Rd))
#define SADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 0, 0b10, Rn, Rd))
#define UADDLVQ_8(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b00, Rn, Rd))
#define UADDLVQ_16(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b01, Rn, Rd))
#define UADDLVQ_32(Rd, Rn) EMIT(ADDLV_vector(1, 1, 0b10, Rn, Rd))
#define UADDLV_8(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b00, Rn, Rd))
#define UADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b01, Rn, Rd))
#define UADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b10, Rn, Rd))
// MOV Immediate
#define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd))
#define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
#define MOVI_8(Rd, imm8) EMIT(MOVI_vector(0, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd))
// SHLL and eXtend Long
#define SHLL_vector(Q, U, immh, immb, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b10100<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define USHLL2_8(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0001, (imm)&0x7, Vn, Vd))
#define USHLL_8(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0001, (imm)&0x7, Vn, Vd))
#define SSHLL2_8(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0001, (imm)&0x7, Vn, Vd))
#define SSHLL_8(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0001, (imm)&0x7, Vn, Vd))
#define USHLL2_16(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
#define USHLL_16(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
#define SSHLL2_16(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
#define SSHLL_16(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0010|(((imm)>>3)&1), (imm)&0x7, Vn, Vd))
#define USHLL2_32(Vd, Vn, imm) EMIT(SHLL_vector(1, 1, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
#define USHLL_32(Vd, Vn, imm) EMIT(SHLL_vector(0, 1, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
#define SSHLL2_32(Vd, Vn, imm) EMIT(SHLL_vector(1, 0, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
#define SSHLL_32(Vd, Vn, imm) EMIT(SHLL_vector(0, 0, 0b0100|(((imm)>>3)&3), (imm)&0x7, Vn, Vd))
#define UXTL_8(Vd, Vn) USHLL_8(Vd, Vn, 0)
#define UXTL2_8(Vd, Vn) USHLL2_8(Vd, Vn, 0)
#define UXTL_16(Vd, Vn) USHLL_16(Vd, Vn, 0)
#define UXTL2_16(Vd, Vn) USHLL2_16(Vd, Vn, 0)
#define UXTL_32(Vd, Vn) USHLL_32(Vd, Vn, 0)
#define UXTL2_32(Vd, Vn) USHLL2_32(Vd, Vn, 0)
#define SXTL_8(Vd, Vn) SSHLL_8(Vd, Vn, 0)
#define SXTL2_8(Vd, Vn) SSHLL2_8(Vd, Vn, 0)
#define SXTL_16(Vd, Vn) SSHLL_16(Vd, Vn, 0)
#define SXTL2_16(Vd, Vn) SSHLL2_16(Vd, Vn, 0)
#define SXTL_32(Vd, Vn) SSHLL_32(Vd, Vn, 0)
#define SXTL2_32(Vd, Vn) SSHLL2_32(Vd, Vn, 0)
// SHRN
#define QSHRN_vector(Q, U, immh, immb, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b011110<<23 | (immh)<<19 | (immb)<<16 | 0b1001<<12 | (op)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define UQSHRN_8(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
#define UQSHRN2_8(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN_8(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN2_8(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0001, (8-(imm))&0x7, 0, Vn, Vd))
#define UQSHRN_16(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
#define UQSHRN2_16(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN_16(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN2_16(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0010|(((16-(imm))>>3)&1), (16-(imm))&0x7, 0, Vn, Vd))
#define UQSHRN_32(Vd, Vn, imm) EMIT(QSHRN_vector(0, 1, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
#define UQSHRN2_32(Vd, Vn, imm) EMIT(QSHRN_vector(1, 1, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN_32(Vd, Vn, imm) EMIT(QSHRN_vector(0, 0, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
#define SQSHRN2_32(Vd, Vn, imm) EMIT(QSHRN_vector(1, 0, 0b0100|(((32-(imm))>>3)&3), (32-(imm))&0x7, 0, Vn, Vd))
// UQSUB
#define QSUB_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00101<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define UQSUB_8(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b00, Vm, Vn, Vd))
#define UQSUB_16(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b01, Vm, Vn, Vd))
#define UQSUB_32(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b10, Vm, Vn, Vd))
#define UQSUB_64(Vd, Vn, Vm) EMIT(QSUB_vector(0, 1, 0b11, Vm, Vn, Vd))
#define SQSUB_8(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b00, Vm, Vn, Vd))
#define SQSUB_16(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b01, Vm, Vn, Vd))
#define SQSUB_32(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b10, Vm, Vn, Vd))
#define SQSUB_64(Vd, Vn, Vm) EMIT(QSUB_vector(0, 0, 0b11, Vm, Vn, Vd))
#define UQSUBQ_8(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b00, Vm, Vn, Vd))
#define UQSUBQ_16(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b01, Vm, Vn, Vd))
#define UQSUBQ_32(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b10, Vm, Vn, Vd))
#define UQSUBQ_64(Vd, Vn, Vm) EMIT(QSUB_vector(1, 1, 0b11, Vm, Vn, Vd))
#define SQSUBQ_8(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b00, Vm, Vn, Vd))
#define SQSUBQ_16(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SQSUBQ_32(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b10, Vm, Vn, Vd))
#define SQSUBQ_64(Vd, Vn, Vm) EMIT(QSUB_vector(1, 0, 0b11, Vm, Vn, Vd))
// MAX/MIN vector
#define MINMAX_vector(Q, U, size, Rm, op, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b0110<<12 | (op)<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 0, Vn, Vd))
#define SMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 0, Vn, Vd))
#define SMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 0, Vn, Vd))
#define SMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 0, Vn, Vd))
#define UMAX_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 0, Vn, Vd))
#define UMAX_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 0, Vn, Vd))
#define UMAX_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 0, Vn, Vd))
#define UMAX_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 0, Vn, Vd))
#define SMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b00, Vm, 1, Vn, Vd))
#define SMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b01, Vm, 1, Vn, Vd))
#define SMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b10, Vm, 1, Vn, Vd))
#define SMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 0, 0b11, Vm, 1, Vn, Vd))
#define UMIN_8(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b00, Vm, 1, Vn, Vd))
#define UMIN_16(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b01, Vm, 1, Vn, Vd))
#define UMIN_32(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b10, Vm, 1, Vn, Vd))
#define UMIN_64(Vd, Vn, Vm) EMIT(MINMAX_vector(0, 1, 0b11, Vm, 1, Vn, Vd))
#define SMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 0, Vn, Vd))
#define SMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 0, Vn, Vd))
#define SMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 0, Vn, Vd))
#define SMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 0, Vn, Vd))
#define UMAXQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 0, Vn, Vd))
#define UMAXQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 0, Vn, Vd))
#define UMAXQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 0, Vn, Vd))
#define UMAXQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 0, Vn, Vd))
#define SMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b00, Vm, 1, Vn, Vd))
#define SMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b01, Vm, 1, Vn, Vd))
#define SMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b10, Vm, 1, Vn, Vd))
#define SMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 0, 0b11, Vm, 1, Vn, Vd))
#define UMINQ_8(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b00, Vm, 1, Vn, Vd))
#define UMINQ_16(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b01, Vm, 1, Vn, Vd))
#define UMINQ_32(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b10, Vm, 1, Vn, Vd))
#define UMINQ_64(Vd, Vn, Vm) EMIT(MINMAX_vector(1, 1, 0b11, Vm, 1, Vn, Vd))
// HADD vector
#define HADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 1<<10 | (Rn)<<5 | (Rd))
#define SHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b00, Vm, Vn, Vd))
#define SHADD_16(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b01, Vm, Vn, Vd))
#define SHADD_32(Vd, Vn, Vm) EMIT(HADD_vector(0, 0, 0b10, Vm, Vn, Vd))
#define SHADDQ_8(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b00, Vm, Vn, Vd))
#define SHADDQ_16(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SHADDQ_32(Vd, Vn, Vm) EMIT(HADD_vector(1, 0, 0b10, Vm, Vn, Vd))
#define UHADD_8(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b00, Vm, Vn, Vd))
#define UHADD_16(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b01, Vm, Vn, Vd))
#define UHADD_32(Vd, Vn, Vm) EMIT(HADD_vector(0, 1, 0b10, Vm, Vn, Vd))
#define UHADDQ_8(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b00, Vm, Vn, Vd))
#define UHADDQ_16(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b01, Vm, Vn, Vd))
#define UHADDQ_32(Vd, Vn, Vm) EMIT(HADD_vector(1, 1, 0b10, Vm, Vn, Vd))
#define RHADD_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b00010<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SRHADD_8(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b00, Vm, Vn, Vd))
#define SRHADD_16(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b01, Vm, Vn, Vd))
#define SRHADD_32(Vd, Vn, Vm) EMIT(RHADD_vector(0, 0, 0b10, Vm, Vn, Vd))
#define SRHADDQ_8(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b00, Vm, Vn, Vd))
#define SRHADDQ_16(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SRHADDQ_32(Vd, Vn, Vm) EMIT(RHADD_vector(1, 0, 0b10, Vm, Vn, Vd))
#define URHADD_8(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b00, Vm, Vn, Vd))
#define URHADD_16(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b01, Vm, Vn, Vd))
#define URHADD_32(Vd, Vn, Vm) EMIT(RHADD_vector(0, 1, 0b10, Vm, Vn, Vd))
#define URHADDQ_8(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b00, Vm, Vn, Vd))
#define URHADDQ_16(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b01, Vm, Vn, Vd))
#define URHADDQ_32(Vd, Vn, Vm) EMIT(RHADD_vector(1, 1, 0b10, Vm, Vn, Vd))
// QRDMULH Signed saturating (Rounding) Doubling Multiply returning High half
#define QDMULH_vector(Q, U, size, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (size)<<22 | 1<<21 | (Rm)<<16 | 0b10110<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define SQRDMULH_8(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b00, Vm, Vn, Vd))
#define SQRDMULH_16(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b01, Vm, Vn, Vd))
#define SQRDMULH_32(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 1, 0b10, Vm, Vn, Vd))
#define SQRDMULHQ_8(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b00, Vm, Vn, Vd))
#define SQRDMULHQ_16(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b01, Vm, Vn, Vd))
#define SQRDMULHQ_32(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 1, 0b10, Vm, Vn, Vd))
#define SQDMULH_8(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b00, Vm, Vn, Vd))
#define SQDMULH_16(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b01, Vm, Vn, Vd))
#define SQDMULH_32(Vd, Vn, Vm) EMIT(QDMULH_vector(0, 0, 0b10, Vm, Vn, Vd))
#define SQDMULHQ_8(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b00, Vm, Vn, Vd))
#define SQDMULHQ_16(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b01, Vm, Vn, Vd))
#define SQDMULHQ_32(Vd, Vn, Vm) EMIT(QDMULH_vector(1, 0, 0b10, Vm, Vn, Vd))
#endif //__ARM64_EMITTER_H__
+34 -6
View File
@@ -13,8 +13,11 @@
.global arm64_lock_write_d
.global arm64_lock_read_dd
.global arm64_lock_write_dd
.global arm64_lock_read_dq
.global arm64_lock_write_dq
.global arm64_lock_xchg
.global arm64_lock_storeifnull
.global arm64_lock_storeifref
arm64_lock_read_b:
@@ -64,24 +67,49 @@ arm64_lock_write_dd:
stlxr w0, x1, [x2]
ret
arm64_lock_read_dq:
// address is r2, return is r0, r1
ldaxp x4, x3, [x2]
str x4, [x0]
str x3, [x1]
ret
arm64_lock_write_dq:
// address is r2, value is r0, r1, return is r0
// r0 needs to be aligned
stlxp w3, x0, x1, [x2]
mov w0, w3
ret
arm64_lock_xchg:
// address is x0, value is x1, return old value in x0
ldaxr x2, [x0]
stlxr w3, x1, [x0]
cmp w3, #1
beq arm64_lock_xchg
cbnz w3, arm64_lock_xchg
mov x0, x2
ret
arm64_lock_storeifnull:
// address is x0, value is x1, x1 store to x0 only if [x0] is 0. return new [x0] value (so x1 or old value)
ldaxr x2, [x0]
cmp x2, #0
bne arm64_lock_storeifnull_exit
cbnz x2, arm64_lock_storeifnull_exit
mov x2, x1
stlxr w3, x2, [x0]
cmp w3, #1
beq arm64_lock_storeifnull
cbnz w3, arm64_lock_storeifnull
arm64_lock_storeifnull_exit:
mov x0, x2
ret
arm64_lock_storeifref:
// address is x0, value is x1, x1 store to x0 only if [x0] is x3. return new [x0] value (so x1 or old value)
ldaxr x3, [x0]
cmp x2, x3
bne arm64_lock_storeifref_exit
stlxr w4, x1, [x0]
cbnz w4, arm64_lock_storeifref
mov x0, x1
ret
arm64_lock_storeifref_exit:
mov x0, x3
ret
+9 -1
View File
@@ -17,15 +17,23 @@ extern uint32_t arm64_lock_read_d(void* addr);
// STLXR of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_d(void* addr, uint32_t val);
// LDAXRD of ADDR
// LDAXR of ADDR
extern uint64_t arm64_lock_read_dd(void* addr);
// STLXR of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_dd(void* addr, uint64_t val);
// LDAXRD of ADDR
extern void arm64_lock_read_dq(uint64_t * a, uint64_t* b, void* addr);
// STLXRD of ADDR, return 0 if ok, 1 if not
extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
// Atomicaly exchange value at [p] with val, return old p
extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
// Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
extern void* arm64_lock_storeifnull(void*p, void* val);
// Atomicaly store value to [p] only if [p] is ref. Return new [p] value (so val or old)
extern void* arm64_lock_storeifref(void*p, void* val, void* ref);
#endif //__ARM64_LOCK__H__
+1
View File
@@ -19,6 +19,7 @@ arm64_next:
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
str x18, [sp, (8 * 10)]
mov x2, lr // "from" is in lr, so put in x2
// call the function
bl LinkNext
// preserve return value
+274 -6
View File
@@ -180,10 +180,21 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
}
if(isMask(opcode, "0x011000iiiiiiiiiiiiiiiiiiittttt", &a)) {
int size = ((opcode>>30)&1)?3:2;
int offset = signExtend(imm, 9)<<size;
int offset = signExtend(imm, 19)<<2;
snprintf(buff, sizeof(buff), "LDR %s, [#%+d]\t;%p", (size==2)?Wt[Rt]:Xt[Rt], offset, (void*)(addr+offset));
return buff;
}
if(isMask(opcode, "10011000iiiiiiiiiiiiiiiiiiittttt", &a)) {
int offset = signExtend(imm, 19)<<2;
snprintf(buff, sizeof(buff), "LDRSW %s, [#%+d]\t;%p", Xt[Rt], offset, (void*)(addr+offset));
return buff;
}
if(isMask(opcode, "ff011100iiiiiiiiiiiiiiiiiiittttt", &a)) {
int offset = signExtend(imm, 19)<<2;
const char* Y[] = {"S", "D", "Q", "?"};
snprintf(buff, sizeof(buff), "LDR %s%d, [#%+d]\t;%p", Y[sf], Rt, offset, (void*)(addr+offset));
return buff;
}
if(isMask(opcode, "1x111000011mmmmmoooS10nnnnnttttt", &a)) {
int size = (opcode>>30)&3;
const char* extend[] = {"?0", "?1", "UXTW", "LSL", "?4", "?5", "SXTW", "SXTX"};
@@ -275,6 +286,14 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], offset);
return buff;
}
if(isMask(opcode, "011110011xiiiiiiiiiiiinnnnnttttt", &a)) {
int offset = imm<<1;
if(!offset)
snprintf(buff, sizeof(buff), "LDRSH %s, [%s]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "LDRSH %s, [%s, #%d]", a.x?Wt[Rt]:Xt[Rt], XtSp[Rn], offset);
return buff;
}
if(isMask(opcode, "001110011xiiiiiiiiiiiinnnnnttttt", &a)) {
int offset = imm<<1;
if(!offset)
@@ -699,7 +718,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
if(isMask(opcode, "f1011010100mmmmmdddd00nnnnnddddd", &a)) {
if(isMask(opcode, "f1011010100mmmmmcccc00nnnnnddddd", &a)) {
if(Rm!=31 && (cond&0b1110)!=0b1110 && Rn!=31 && Rn==Rm)
snprintf(buff, sizeof(buff), "CINV %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond^1]);
else if(Rm==31 && (cond&0b1110)!=0b1110 && Rn==31)
@@ -840,6 +859,42 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// VADD / VSUB
if(isMask(opcode, "0QU01110ff1mmmmm100001nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[((sf)<<1) | a.Q];
snprintf(buff, sizeof(buff), "V%s V%d.%s, V%d.%s, V%d.%s", a.U?"SUB":"ADD", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// VMUL
if(isMask(opcode, "0Q001110ff1mmmmm100111nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[((sf)<<1) | a.Q];
snprintf(buff, sizeof(buff), "VMUL V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// CMP
if(isMask(opcode, "0Q101110ff1mmmmm100011nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[((sf)<<1) | a.Q];
snprintf(buff, sizeof(buff), "VCMEQ V%d.%s, V%d.%s, V%d.%s", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// Shift
if(isMask(opcode, "0QU011110hhhhrrr000001nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd ="??";
int s = 0;
if(shift==0b0001) {Vd = Y[a.Q]; s=16-((shift)<<3 | immr);}
else if((shift&0b1110)==0b0010) {Vd = Y[2+a.Q]; s=32-((shift)<<3 | immr);}
else if((shift&0b1100)==0b0100) {Vd = Y[4+a.Q]; s=64-((shift)<<3 | immr);}
else if((shift&0b1000)==0b1000) {Vd = Y[6+a.Q]; s=128-((shift)<<3 | immr);}
snprintf(buff, sizeof(buff), "%cSHR V%d.%s, V%d.%s, #%d", a.U?'U':'S', Rd, Vd, Rn, Vd, s);
return buff;
}
// INS
if(isMask(opcode, "01101110000rrrrr0ssss1nnnnnddddd", &a)) {
char s = '?';
@@ -905,7 +960,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFSUB %c%d.%d%c, %c%d.%d%c, %c%d.%c%d", s, Rd, n, d, s, Rn, n, d, s, Rm, s, d);
snprintf(buff, sizeof(buff), "VFSUB %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
return buff;
}
if(isMask(opcode, "00011110ff1mmmmm001110nnnnnddddd", &a)) {
@@ -933,7 +988,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "VFDIV %c%d.%d%c, %c%d.%d%c, %c%d.%c%d", s, Rd, n, d, s, Rn, n, d, s, Rm, s, d);
snprintf(buff, sizeof(buff), "VFDIV %c%d.%d%c, %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d, s, Rm, n, d);
return buff;
}
if(isMask(opcode, "00011110ff1mmmmm000110nnnnnddddd", &a)) {
@@ -965,6 +1020,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "FCMP %c%d, %c%d", s, Rn, s, Rm);
return buff;
}
//FMIN/FMAX
if(isMask(opcode, "00011110ff1mmmmm01oo10nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
snprintf(buff, sizeof(buff), "F%s %c%d, %c%d, %c%d", (option==3)?"MINNM":((option==2)?"MINNMP":((!option)?"MAXNM":"MAXNMP")), s, Rd, s, Rn, s, Rm);
return buff;
}
if(isMask(opcode, "0Q001110of1mmmmm110001nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
int n = (sf==0)?2:1;
n *= a.Q?2:1;
snprintf(buff, sizeof(buff), "F%sNM%s V%d.%d%c, V%d.%d%c, V%d.%d%c", option?"MIN":"MAX", a.Q?"Q":"", Rd, n, s, Rn, n, s, Rm, n, s);
return buff;
}
// FCVT
if(isMask(opcode, "f0011110pp10010U000000nnnnnddddd", &a)) {
@@ -992,6 +1060,13 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "SCVTF %c%d, %s", s, Rd, sf?Xt[Rn]:Wt[Rn]);
return buff;
}
if(isMask(opcode, "0QU011100f100001110110nnnnnddddd", &a)) {
char s = a.Q?'V':'D';
char d = sf?'D':'S';
int n = (a.Q && !sf)?4:2;
snprintf(buff, sizeof(buff), "%cCVTF %c%d.%d%c, %c%d.%d%c", a.U?'U':'S', s, Rd, n, d, s, Rn, n, d);
return buff;
}
if(isMask(opcode, "0001111000100010110000nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "FCVT D%d, S%d", Rd, Rn);
@@ -1002,13 +1077,25 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
if(isMask(opcode, "0Q00111001100001011110nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "FCVTL%s V%d.2D, V%d.%dS", a.Q?"2":"", Rd, Rn, a.Q?4:0);
snprintf(buff, sizeof(buff), "FCVTL%s V%d.2D, V%d.%dS", a.Q?"2":"", Rd, Rn, a.Q?4:2);
return buff;
}
if(isMask(opcode, "0Q10111000100001011010nnnnnddddd", &a)) {
if(isMask(opcode, "0Q10111001100001011010nnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "FCVTXN%s V%d.%dS, V%d.2D", a.Q?"2":"", Rd, a.Q?4:2, Rn);
return buff;
}
if(isMask(opcode, "01U11110of100001101o10nnnnnddddd", &a)) {
char s = (sf==0)?'S':((sf==1)?'D':'?');
const char* roundings[] = {"N", "M", "P", "Z"};
snprintf(buff, sizeof(buff), "FCVT%s%s %c%d, %c%d", roundings[option], a.U?"U":"", s, Rd, s, Rn);
return buff;
}
if(isMask(opcode, "f0011110oo1cc000000000nnnnnddddd", &a)) {
char s = (option==0)?'S':((option==1)?'D':'?');
const char* roundings[] = {"N", "P", "M", "Z"};
snprintf(buff, sizeof(buff), "FCVT%sS %s, %c%d", roundings[a.c], sf?Xt[Rd]:Wt[Rd], s, Rn);
return buff;
}
// FMOV
if(isMask(opcode, "00011110pp100000010000nnnnnddddd", &a)) {
@@ -1031,6 +1118,187 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
return buff;
}
// TBL / TBX
if(isMask(opcode, "0Q001110000mmmmm0ffo00nnnnnddddd", &a)) {
char X = (option)?'X':'L';
const char* Y = (a.Q)?"16B":"8B";
if(sf==0)
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rm, Y);
else if(sf==1)
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rm, Y);
else if(sf==2)
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rn+2, Rm, Y);
else
snprintf(buff, sizeof(buff), "TB%c V%d.%s, {V%d.16B, V%d.16B, V%d.16B, V%d.16B}, V%d.%s", X, Rd, Y, Rn, Rn+1, Rn+2, Rn+3, Rm, Y);
return buff;
}
// ZIP / UZP
if(isMask(opcode, "0Q001110ff0mmmmm0o1110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "ZIP%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
if(isMask(opcode, "0Q001110ff0mmmmm0o0110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "2D"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "UZP%d V%d.%s, V%d.%s, V%d.%s", a.o+1, Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// EXT
if(isMask(opcode, "0Q101110000mmmmm0iiii0nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B"};
const char* Vd = Y[a.Q];
snprintf(buff, sizeof(buff), "EXT V%d.%s, V%d.%s, V%d.%s, #%d", Rd, Vd, Rn, Vd, Rm, Vd, imm);
return buff;
}
// Absolute Difference
// SABA / SABD / UABA / UABD
if(isMask(opcode, "0QU01110ff1mmmmm0111c1nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "%cAB%c V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
if(isMask(opcode, "0QU01110ff1mmmmm01c100nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* Z[] = {"8H", "4S", "2D", "?"};
const char* Va = Z[(sf<<1)];
snprintf(buff, sizeof(buff), "%cAB%cL%s V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', a.Q?"2":"", Rd, Va, Rn, Vd, Rm, Vd);
return buff;
}
// Add pair / accros vector
if(isMask(opcode, "0QU01110ff1000000c1010nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* Z[] = {"4H", "8H", "2S", "4S", "1D", "2D", "??", "???"};
const char* Va = Z[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "%cAD%cLP V%d.%s, V%d.%s", a.U?'U':'S', a.c?'A':'D', Rd, Va, Rn, Vd);
return buff;
}
if(isMask(opcode, "0QU01110ff110000001110nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* Z[] = {"H", "S", "D", "?"};
snprintf(buff, sizeof(buff), "%cADDLV V%d.%s, V%d.%s", a.U?'U':'S', Rd, Z[sf], Rn, Vd);
return buff;
}
// HADD
if(isMask(opcode, "0QU01110ff1mmmmm000001nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "%cHADD V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
if(isMask(opcode, "0QU01110ff1mmmmm000101nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "%cRHADD V%d.%s, V%d.%s, V%d.%s", a.U?'U':'S', Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
//SQ(R)DMULH
if(isMask(opcode, "0QU01110ff1mmmmm101101nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "??", "???"};
const char* Vd = Y[(sf<<1) | a.Q];
snprintf(buff, sizeof(buff), "SQ%sDMULH V%d.%s, V%d.%s, V%d.%s", a.U?"R":"", Rd, Vd, Rn, Vd, Rm, Vd);
return buff;
}
// MOV immediate
if(isMask(opcode, "0Q00111100000iii111001iiiiiddddd", &a)) {
const char* Y[] = {"8B", "16B"};
const char* Vd = Y[a.Q];
snprintf(buff, sizeof(buff), "MOVI V%d.%s, #0x%x", Rd, Vd, imm);
return buff;
}
// LD1/ST1 single structure
if(isMask(opcode, "0Q0011010L000000cc0Sffnnnnnttttt", &a)) {
int scale = a.c;
int idx = 0;
const char* Y[] = {"B", "H", "S", "D"};
switch(scale) {
case 3: scale = sf; /* rep = 1; */ break;
case 0: idx = (a.Q<<3) | (a.S<<2) | sf; break;
case 1: idx = (a.Q<<2) | (a.S<<1) | (sf>>1); break;
case 2: if(!(sf&1))
idx = (a.Q<<1) | a.S;
else {
scale = 3;
idx = a.Q;
}
break;
}
snprintf(buff, sizeof(buff), "%s1 {V%d.%s}[%d], [%s]", a.L?"LD":"ST", Rt, Y[scale], idx, XtSp[Rn]);
return buff;
}
// LDUR/STUR
if(isMask(opcode, "ff111100cL0iiiiiiiii00nnnnnttttt", &a)) {
const char* Y[] = {"B", "H", "S", "D", "Q"};
int sz = sf;
if(sz==0 && a.c)
sz = 4;
int offset = signExtend(imm, 9);
if(!offset)
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%sUR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
return buff;
}
// LDR/STR vector immediate
if(isMask(opcode, "ff111101cLiiiiiiiiiiiinnnnnttttt", &a)) {
const char* Y[] = {"B", "H", "S", "D", "Q"};
int sz = sf;
if(sz==0 && a.c)
sz = 4;
int offset = imm<<sz;
if(!offset)
snprintf(buff, sizeof(buff), "%sR %s%d, [%s]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "%sR %s%d, [%s, %+d]", a.L?"LD":"ST", Y[sz], Rd, XtSp[Rn], imm);
return buff;
}
// (S/U)QXT(U)N
if(isMask(opcode, "0Q101110ff100001001010nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* Z[] = {"8H", "4S", "2D", "?"};
const char* Va = Z[sf];
snprintf(buff, sizeof(buff), "SQXTUN%s V%d.%s, V%d.%s", a.Q?"2":"", Rd, Vd, Rn, Va);
return buff;
}
if(isMask(opcode, "0QU01110ff100001010010nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
const char* Vd = Y[(sf<<1) | a.Q];
const char* Z[] = {"8H", "4S", "2D", "?"};
const char* Va = Z[sf];
snprintf(buff, sizeof(buff), "%cQXTN%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Vd, Rn, Va);
return buff;
}
// (S/U)SSHL(2) / (U/S)XTL(2)
if(isMask(opcode, "0QU011110hhhhiii101001nnnnnddddd", &a)) {
const char* Y[] = {"8B", "16B", "4H", "8H", "2S", "4S", "?", "??"};
const char* Z[] = {"8H", "4S", "2D", "?"};
int sz = 3;
if((a.h&0b1111)==0b0001) sz=0;
else if((a.h&0b1110)==0b0010) sz=1;
else if((a.h&0b1100)==0b0100) sz=2;
int sh=(((a.h)<<3)|(imm)) - (8<<sz);
const char* Vd = Y[(sz<<1)|a.Q];
const char* Va = Z[sz];
if(!sh)
snprintf(buff, sizeof(buff), "%cXTL%s V%d.%s, V%d.%s", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd);
else
snprintf(buff, sizeof(buff), "%cSHLL%s V%d.%s, V%d.%s, #%d", a.U?'U':'S', a.Q?"2":"", Rd, Va, Rn, Vd, sh);
return buff;
}
snprintf(buff, sizeof(buff), "%08X ???", __builtin_bswap32(opcode));
+10 -10
View File
@@ -69,7 +69,7 @@ void FreeDynablock(dynablock_t* db)
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x64_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
arm64_lock_xchg(&db->parent->direct[addr-startdb], 0); // secured write
}
// remove jumptable
setJumpTableDefault64(db->x64_addr);
@@ -247,10 +247,6 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
@@ -323,22 +319,26 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
if(!created)
return block; // existing block...
#if 1
#if 0
if(box64_dynarec_dump)
pthread_mutex_lock(&my_context->mutex_dyndump);
#endif
// fill the block
block->x64_addr = (void*)addr;
if(!FillBlock64(block, filladdr)) {
void* old = (void*)arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], 0);
pthread_mutex_lock(&my_context->mutex_dyndump);
void* ret = FillBlock64(block, filladdr);
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(!ret) {
dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr);
void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block);
if(old!=block && old) {// put it back in place, strange things are happening here!
dynarec_log(LOG_INFO, "Warning, a wild block appeared at %p: %p\n", (void*)addr, old);
arm64_lock_xchg(&dynablocks->direct[addr-dynablocks->text], (uintptr_t)old);
// doing nothing else, the block as not be writen
}
free(block);
block = NULL;
}
#if 1
#if 0
if(box64_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
+4 -3
View File
@@ -37,9 +37,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
{
#ifdef HAVE_TRACE
if(!addr) {
x2-=8; // actual PC is 2 instructions ahead
dynablock_t* db = FindDynablockFromNativeAddress(x2);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2, db, db?(void*)getX64Address(db, (uintptr_t)x2):NULL);
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x64addr=%p)\n", x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
}
#endif
dynablock_t* current = NULL;
@@ -47,6 +46,8 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
if(!block) {
// no block, let link table as is...
dynablock_t* db = FindDynablockFromNativeAddress(x2-4);
printf_log(LOG_NONE, "Warning, jumping to a no-block address %p from %p (db=%p, x64addr=%p)\n", (void*)addr, x2-4, db, db?(void*)getX64Address(db, (uintptr_t)x2-4):NULL);
//tableupdate(arm64_epilog, addr, table);
return arm64_epilog;
}
+35 -16
View File
@@ -315,8 +315,11 @@ int Table64(dynarec_arm_t *dyn, uint64_t val)
idx = i;
// not found, add it
if(idx==-1) {
if(dyn->table64size == dyn->table64cap) {
dyn->table64cap+=4;
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64cap * sizeof(uint64_t));
}
idx = dyn->table64size++;
dyn->table64 = (uint64_t*)realloc(dyn->table64, dyn->table64size * sizeof(uint64_t));
dyn->table64[idx] = val;
}
// calculate offset
@@ -325,18 +328,21 @@ int Table64(dynarec_arm_t *dyn, uint64_t val)
}
void arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
void arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass0(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass1(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass2(dynarec_arm_t* dyn, uintptr_t addr);
uintptr_t arm_pass3(dynarec_arm_t* dyn, uintptr_t addr);
void* FillBlock64(dynablock_t* block, uintptr_t addr) {
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end)
return NULL;
if(addr>=box64_nodynarec_start && addr<box64_nodynarec_end) {
block->done = 1;
return (void*)block;
}
// init the helper
dynarec_arm_t helper = {0};
helper.start = addr;
arm_pass0(&helper, addr);
uintptr_t start = addr;
uintptr_t end = arm_pass0(&helper, addr);
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
block->done = 1;
@@ -344,11 +350,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
helper.cap = helper.size+3; // needs epilog handling
helper.insts = (instruction_arm64_t*)calloc(helper.cap, sizeof(instruction_arm64_t));
// already protect the block and compute hash signature
protectDB(addr, end-addr+1);
uint32_t hash = X31_hash_code((void*)addr, end-addr+1);
// pass 1, addresses, x64 jump addresses, flags
arm_pass1(&helper, addr);
// calculate barriers
uintptr_t start = helper.insts[0].x64.addr;
uintptr_t end = helper.insts[helper.size].x64.addr+helper.insts[helper.size].x64.size;
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x64.jmp) {
uintptr_t j = helper.insts[i].x64.jmp;
@@ -398,10 +405,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
helper.arm_size = 0;
int oldtable64size = helper.table64size;
int oldarmsize = helper.arm_size;
helper.arm_size = 0;
helper.table64size = 0; // reset table64 (but not the cap)
arm_pass3(&helper, addr);
if(sz!=(helper.arm_size + helper.table64size*8)) {
if((oldarmsize!=helper.arm_size) || (oldtable64size<helper.table64size)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size+helper.table64size*8);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x64 opcodes:\n", helper.size);
@@ -413,10 +422,11 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
printf_log(LOG_NONE, "Table64 \t%d -> %d\n", oldtable64size*8, helper.table64size*8);
printf_log(LOG_NONE, " ------------\n");
//TODO: Cancel block and return empty one
}
// add table64 if needed
if(helper.table64size) {
memcpy(p+helper.arm_size, helper.table64, helper.table64size*8);
memcpy((void*)helper.tablestart, helper.table64, helper.table64size*8);
}
// all done...
__clear_cache(p, p+sz); // need to clear the cache before execution...
@@ -440,11 +450,18 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
block->block = p;
block->need_test = 0;
//block->x64_addr = (void*)start;
block->x64_size = end-start;
block->x64_size = end-start+1;
if(box64_dynarec_largest<block->x64_size)
box64_dynarec_largest = block->x64_size;
block->hash = X31_hash_code(block->x64_addr, block->x64_size);
// fill sons if any
// Check if something changed, to abbort if it as
if(block->hash != hash) {
dynarec_log(LOG_INFO, "Warning, a block changed while beeing processed hash(%p:%ld)=%x/%x\n", block->x64_addr, block->x64_size, block->hash, hash);
free(helper.sons_x64);
free(helper.sons_arm);
FreeDynarecMap(block, (uintptr_t)p, sz);
return NULL;
} // fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
@@ -458,10 +475,12 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
son->x64_size = end-helper.sons_x64[i];
if(!son->x64_size) {printf_log(LOG_NONE, "Warning, son with null x64 size! (@%p / ARM=%p)", son->x64_addr, son->block);}
son->father = block;
son->size = sz + son->block - block->block; // update size count, for debugging
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
sons[sons_size] = son;
++sons_size;
}
}
if(sons_size) {
+133 -23
View File
@@ -24,7 +24,7 @@
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop, opcode;
uint8_t gd, ed;
@@ -37,8 +37,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint64_t u64;
uint8_t wback, wb1, wb2;
int fixedaddress;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
opcode = F8;
MAYUSE(eb1);
@@ -47,17 +45,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(tmp);
MAYUSE(j32);
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x00:
INST_NAME("ADD Eb, Gb");
@@ -833,7 +820,37 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETED(0);
emit_test32(dyn, ninst, rex, ed, gd, x3, x5);
break;
case 0x86:
INST_NAME("(LOCK)XCHG Eb, Gb");
// Do the swap
nextop = F8;
if(MODREG) {
GETGB(x4);
if(rex.rex) {
ed = xRAX+(nextop&7)+(rex.b<<3);
eb1 = ed;
eb2 = 0;
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3);
eb2 = ((ed&4)>>2);
}
UBFXw(x1, eb1, eb2*8, 8);
// do the swap 14 -> ed, 1 -> gd
BFIx(gb1, x1, gb2*8, 8);
BFIx(eb1, x4, eb2*8, 8);
} else {
GETGB(x4);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
// do the swap with exclusive locking
LDAXRB(x1, ed);
// do the swap 14 -> strb(ed), 1 -> gd
STLXRB(x3, x4, ed);
CBNZx_MARKLOCK(x3);
BFIx(gb1, x1, gb2*8, 8);
}
break;
case 0x87:
INST_NAME("(LOCK)XCHG Ed, Gd");
nextop = F8;
@@ -903,7 +920,39 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
STRxw_U12(gd, ed, fixedaddress);
}
break;
case 0x8A:
INST_NAME("MOV Gb, Eb");
nextop = F8;
if(rex.rex) {
gb1 = gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
gb2=0;
} else {
gd = (nextop&0x38)>>3;
gb1 = xRAX+(gd&3);
gb2 = ((gd&4)>>2);
}
if(MODREG) {
if(rex.rex) {
wback = xRAX+(nextop&7)+(rex.b<<3);
wb2 = 0;
} else {
wback = (nextop&7);
wb2 = (wback>>2);
wback = xRAX+(wback&3);
}
if(wb2) {
UBFXw(x4, wback, wb2*8, 8);
ed = x4;
} else {
ed = wback;
}
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(x4, wback, fixedaddress);
ed = x4;
}
BFIx(gb1, ed, gb2*8, 8);
break;
case 0x8B:
INST_NAME("MOV Gd, Ed");
nextop=F8;
@@ -926,7 +975,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
MOVxw_REG(gd, ed);
} else if(ed>=xRAX && !rex.w) {
}
else if(!rex.w) {
MOVw_REG(gd, gd); //truncate the higher 32bits as asked
}
}
@@ -966,7 +1016,46 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ORRw_mask(xFlags, xFlags, 0b011111, 0); //mask=0x00000002
SET_DFNONE(x1);
break;
case 0x9E:
INST_NAME("SAHF");
SETFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF, SF_SUBSET);
MOV32w(x2, 0b11010101);
BICw_REG(xFlags, xFlags, x2);
UBFXx(x1, xRAX, 8, 8);
ANDw_REG(x1, x1, x2);
ORRw_REG(xFlags, xFlags, x1);
SET_DFNONE(x1);
break;
case 0x9F:
INST_NAME("LAHF");
READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
BFIx(xRAX, xFlags, 8, 8);
break;
case 0xA0:
INST_NAME("MOV AL,Ob");
u64 = F64;
MOV64x(x1, u64);
LDRB_U12(x2, x1, 0);
BFIx(xRAX, x2, 0, 8);
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
u64 = F64;
MOV64x(x1, u64);
LDRxw_U12(xRAX, x1, 0);
break;
case 0xA2:
INST_NAME("MOV Ob,AL");
u64 = F64;
MOV64x(x1, u64);
STRB_U12(xRAX, x1, 0);
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
u64 = F64;
MOV64x(x1, u64);
STRxw_U12(xRAX, x1, 0);
break;
case 0xA4:
if(rep) {
INST_NAME("REP MOVSB");
@@ -1453,9 +1542,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
TABLE64(x3, addr); // expected return address
CMPSx_REG(xRIP, x3);
B_MARK(cNE);
LDRw_U12(x1, xEmu, offsetof(x64emu_t, quit));
CMPSw_U12(x1, 1);
B_NEXT(cNE);
LDRw_U12(w1, xEmu, offsetof(x64emu_t, quit));
CBZw_NEXT(w1);
MARK;
jump_to_epilog(dyn, 0, xRIP, ninst);
}
@@ -1766,7 +1854,26 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
}
break;
case 0xD8:
addr = dynarec64_D8(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xD9:
addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDB:
addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDD:
addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xDF:
addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0xE8:
INST_NAME("CALL Id");
i32 = F32S;
@@ -2061,7 +2168,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(ninst && dyn->insts && dyn->insts[ninst-1].x64.set_flags, 1) {
PASS2IF(dyn->insts &&
((ninst && dyn->insts[ninst-1].x64.set_flags)
|| ((ninst>1) && dyn->insts[ninst-2].x64.set_flags)), 1)
{
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
+726 -21
View File
@@ -39,25 +39,27 @@
if(MODREG) { \
a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR128_U12(a, ed, fixedaddress); \
}
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
#define GETGM(a) \
gd = ((nextop&0x38)>>3); \
a = mmx_get_reg(dyn, ninst, x1, gd)
#define GETEM(a, D) \
if(MODREG) { \
a = mmx_get_reg(dyn, ninst, x1, (nextop&7)); \
#define GETEM(a, D) \
if(MODREG) { \
a = mmx_get_reg(dyn, ninst, x1, (nextop&7));\
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0); \
a = fpu_get_scratch_double(dyn); \
VLD1_64(a, ed); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
a = fpu_get_scratch(dyn); \
VLDR64_U12(a, ed, fixedaddress); \
}
#define PUTEM(a) \
if(!MODREG) { \
VST1_64(a, ed); \
#define PUTEM(a) \
if(!MODREG) { \
VSTR64_U12(a, ed, fixedaddress); \
}
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
@@ -68,9 +70,10 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
uint8_t gd, ed;
uint8_t wback, wb2;
uint8_t eb1, eb2;
uint64_t tmp64u;
int v0, v1;
int q0, q1;
int d0;
int d0, d1;
int s0;
int fixedaddress;
MAYUSE(s0);
@@ -79,6 +82,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(eb2);
MAYUSE(eb1);
MAYUSE(wb2);
@@ -91,7 +95,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x0B:
INST_NAME("UD2");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
CALL(arm_ud, -1);
break;
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
@@ -188,6 +196,37 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
VST1_64(v0, 1, ed);
}
break;
case 0x18:
nextop = F8;
if((nextop&0xC0)==0xC0) {
INST_NAME("NOP (multibyte)");
} else
switch((nextop>>3)&7) {
case 0:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
PLD_L1_STREAM_U12(ed, fixedaddress);
break;
case 1:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
PLD_L1_KEEP_U12(ed, fixedaddress);
break;
case 2:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
PLD_L2_KEEP_U12(ed, fixedaddress);
break;
case 3:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff, 7, rex, 0, 0);
PLD_L3_KEEP_U12(ed, fixedaddress);
break;
default:
INST_NAME("NOP (multibyte)");
FAKEED;
}
break;
case 0x1F:
INST_NAME("NOP (multibyte)");
@@ -243,6 +282,55 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
FCOMI(x1, x2);
break;
case 0x31:
INST_NAME("RDTSC");
CALL(ReadTSC, xRAX); // will return the u64 in xEAX
LSRx(xRDX, xRAX, 32);
MOVw_REG(xRAX, xRAX); // wipe upper part
break;
case 0x38:
//SSE3
nextop=F8;
switch(nextop) {
case 0x00:
INST_NAME("PSHUFB Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn);
MOVI_8(d0, 0b10001111);
VAND(d0, d0, q1); // mask the index
VTBL1_8(q0, q0, d0);
break;
case 0x04:
INST_NAME("PMADDUBSW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
UXTL_8(v0, q0); // this is unsigned, so 0 extended
SXTL_8(v1, q1); // this is signed
VMULQ_16(v0, v0, v1);
SADDLPQ_16(v1, v0);
SQXTN_16(q0, v1);
break;
case 0x0B:
INST_NAME("PMULHRSW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
SQRDMULH_16(q0, q0, q1);
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
@@ -261,6 +349,14 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GOCOND(0x40, "CMOV", "Gd, Ed");
#undef GO
case 0x51:
INST_NAME("SQRTPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX_empty(v0);
VFSQRTQS(v0, q0);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
nextop = F8;
@@ -285,9 +381,16 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x57:
INST_NAME("XORPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VEORQ(v0, v0, q0);
GETG;
if(MODREG && ((nextop&7)+(rex.b<<3)==gd)) {
// special case for XORPS Gx, Gx
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VEORQ(q0, q0, q0);
} else {
q0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0x58:
INST_NAME("ADDPS Gx, Ex");
@@ -324,6 +427,325 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
GETGX(v0);
VFSUBQS(v0, v0, q0);
break;
case 0x5D:
INST_NAME("MINPS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
VFMINQS(v0, v0, v1);
break;
case 0x5E:
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFDIVQS(v0, v0, q0);
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
VFMAXQS(v0, v0, v1);
break;
case 0x60:
INST_NAME("PUNPCKLBW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
VZIP1_8(d0, d0, d1);
break;
case 0x61:
INST_NAME("PUNPCKLWD Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
VZIP1_16(d0, d0, d1);
break;
case 0x62:
INST_NAME("PUNPCKLDQ Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
VZIP1_32(d0, d0, d1);
break;
case 0x63:
INST_NAME("PACKSSWB Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
q0 = fpu_get_scratch(dyn);
VMOVeD(q0, 0, d0, 0);
VMOVeD(q0, 1, d1, 0);
SQXTN_8(d0, q0);
break;
case 0x67:
INST_NAME("PACKUSWB Gm, Em");
nextop = F8;
GETGM(v0);
q0 = fpu_get_scratch(dyn);
VMOVeD(q0, 0, v0, 0);
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
VMOVeD(q0, 1, v1, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(q0, 1, ed);
}
SQXTUN_8(v0, q0);
break;
case 0x68:
INST_NAME("PUNPCKHBW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 1);
VZIP2_8(q0, q0, q1);
break;
case 0x69:
INST_NAME("PUNPCKHWD Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 1);
VZIP2_16(q0, q0, q1);
break;
case 0x6A:
INST_NAME("PUNPCKHDQ Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 1);
VZIP2_32(q0, q0, q1);
break;
case 0x6E:
INST_NAME("MOVD Gm, Ed");
nextop = F8;
gd = (nextop&0x38)>>3;
v0 = mmx_get_reg_empty(dyn, ninst, x3, gd);
if(MODREG) {
ed = xRAX + (nextop&7) + (rex.b<<3);
if(rex.w) {
FMOVDx(v0, ed);
} else {
FMOVSw(v0, ed);
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
if(rex.w) {
VLDR64_U12(v0, ed, fixedaddress);
} else {
VLDR32_U12(v0, ed, fixedaddress);
}
}
break;
case 0x6F:
INST_NAME("MOVQ Gm, Em");
nextop = F8;
GETG;
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, nextop&7); // no rex.b on MMX
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, v1, 0);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
case 0x70:
INST_NAME("PSHUFW Gm,Em,Ib");
nextop = F8;
gd = (nextop&0x38)>>3;
if(MODREG) {
u8 = F8;
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
if(u8==0x4E) {
if(v0==v1) {
VEXT_8(v0, v0, v0, 4); // Swap Up/Lower 32bits parts
} else {
VMOVeS(v0, 0, v1, 1);
VMOVeS(v0, 1, v1, 0);
}
} else if(u8==0x00) {
// dumplicate lower 16bits to all spot
if(v0!=v1) {
VMOVeH(v0, 0, v1, 0);
}
VMOVeH(v0, 1, v1, 0);
VMOVeS(v0, 1, v1, 0);
} else if(v0!=v1) {
VMOVeH(v0, 0, v1, (u8>>(0*2))&3);
VMOVeH(v0, 1, v1, (u8>>(1*2))&3);
VMOVeH(v0, 2, v1, (u8>>(2*2))&3);
VMOVeH(v0, 3, v1, (u8>>(3*2))&3);
} else {
uint64_t swp[4] = {
(0)|(1<<8),
(2)|(3<<8),
(4)|(5<<8),
(6)|(7<<8)
};
d0 = fpu_get_scratch(dyn);
tmp64u = swp[(u8>>(0*2))&3] | (swp[(u8>>(1*2))&3]<<16);
tmp64u |= (swp[(u8>>(2*2))&3]<<32) | (swp[(u8>>(3*2))&3]<<48);
MOV64x(x2, tmp64u);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(v0, v1, d0);
}
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
if (u8) {
i32 = -1;
for (int i=0; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
ADDx_U12(x2, ed, idx*2);
i32 = idx;
}
VLD1_16(v0, i, x2);
}
} else {
VLD1R_16(v0, ed);
}
}
break;
case 0x71:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLW Em, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8) {
if (u8>15) {
VEOR(q0, q0, q0);
} else if(u8) {
VSHR_16(q0, q0, u8);
}
if(!MODREG) {
VSTR64_U12(q0, ed, fixedaddress);
}
}
break;
case 4:
INST_NAME("PSRAW Ex, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8>15) u8=15;
if(u8) {
VSSHR_16(q0, q0, u8);
}
if(!MODREG) {
VSTR64_U12(q0, ed, fixedaddress);
}
break;
case 6:
INST_NAME("PSLLW Ex, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8) {
if (u8>15) {
VEOR(q0, q0, q0);
} else {
VSHL_16(q0, q0, u8);
}
if(!MODREG) {
VSTR64_U12(q0, ed, fixedaddress);
}
}
break;
default:
*ok = 0;
DEFAULT;
}
break;
case 0x73:
nextop = F8;
switch((nextop>>3)&7) {
case 2:
INST_NAME("PSRLQ Em, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8) {
if (u8>63) {
VEOR(q0, q0, q0);
} else if(u8) {
USHR_64(q0, q0, u8);
}
PUTEM(q0);
}
break;
case 6:
INST_NAME("PSLLQ Em, Ib");
GETEM(q0, 1);
u8 = F8;
if(u8) {
if (u8>63) {
VEOR(q0, q0, q0);
} else {
SHL_64(q0, q0, u8);
}
PUTEM(q0);
}
break;
default:
DEFAULT;
}
break;
case 0x74:
INST_NAME("PCMPEQB Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
VCMEQ_8(d0, d0, d1);
break;
case 0x77:
INST_NAME("EMMS");
// empty MMX, FPU now usable
mmx_purgecache(dyn, ninst, x1);
/*emu->top = 0;
emu->fpu_stack = 0;*/ //TODO: Check if something is needed here?
break;
case 0x7E:
INST_NAME("MOVD Ed, Gm");
nextop = F8;
GETGM(v0);
if((nextop&0xC0)==0xC0) {
ed = xRAX + (nextop&7) + (rex.b<<3);
if(rex.w) {
VMOVQDto(ed, v0, 0);
} else {
VMOVSto(ed, v0, 0);
MOVxw_REG(ed, ed);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, 0, 0);
if(rex.w) {
VSTR64_U12(v0, ed, fixedaddress);
} else {
VSTR32_U12(v0, ed, fixedaddress);
}
}
break;
case 0x7F:
INST_NAME("MOVQ Em, Gm");
nextop = F8;
GETGM(v0);
if(MODREG) {
v1 = mmx_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOV(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
@@ -628,7 +1050,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
ed = xRAX+(nextop&7)+(rex.b<<3);
u8 = F8;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
@@ -649,7 +1071,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
@@ -673,7 +1095,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
@@ -697,7 +1119,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
u8 = F8;
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 1);
u8 = F8;
fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4);
LDRxw_U12(x1, wback, fixedaddress);
@@ -814,6 +1236,66 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC2:
INST_NAME("CMPPS Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
switch(u8&7) {
// the inversion of the params in the comparison is there to handle NaN the same way SSE does
case 0: FCMEQQS(v0, v0, v1); break; // Equal
case 1: FCMGTQS(v0, v1, v0); break; // Less than
case 2: FCMGEQS(v0, v1, v0); break; // Less or equal
case 3: FCMEQQS(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
FCMEQQS(q0, v1, v1);
VANDQ(v0, v0, q0);
}
VMVNQ(v0, v0);
break; // NaN (NaN is not equal to himself)
case 4: FCMEQQS(v0, v0, v1); VMVNQ(v0, v0); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: FCMGTQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or equal or unordered
case 6: FCMGEQS(v0, v1, v0); VMVNQ(v0, v0); break; // Greater or unordered
case 7: FCMEQQS(v0, v0, v0);
if(v0!=v1) {
q0 = fpu_get_scratch(dyn);
FCMEQQS(q0, v1, v1);
VANDQ(v0, v0, q0);
}
break; // not NaN
}
break;
case 0xC4:
INST_NAME("PINSRW Gm,Ed,Ib");
nextop = F8;
GETGM(v0);
if(MODREG) {
u8 = (F8)&3;
ed = xRAX+(nextop&7)+(rex.b<<3);
VMOVQHfrom(v0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
u8 = (F8)&3;
VLD1_16(v0, u8, wback);
}
break;
case 0xC5:
INST_NAME("PEXTRW Gd,Em,Ib");
nextop = F8;
GETGD;
if(MODREG) {
GETEM(v0, 1);
u8 = (F8)&3;
VMOVHto(gd, v0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
u8 = (F8)&3;
LDRH_U12(gd, wback, u8*2);
}
break;
case 0xC6:
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
@@ -854,6 +1336,229 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
REVxw(gd, gd);
break;
case 0xD5:
INST_NAME("PMULLW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
VMUL_16(q0, q0, q1);
break;
case 0xD8:
INST_NAME("PSUBUSB Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
UQSUB_8(q0, q0, q1);
break;
case 0xD9:
INST_NAME("PSUBUSW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
UQSUB_16(q0, q0, q1);
break;
case 0xDA:
INST_NAME("PMINUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
UMIN_8(d0, d0, d1);
break;
case 0xDB:
INST_NAME("PAND Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VAND(v0, v0, v1);
break;
case 0xDC:
INST_NAME("PADDUSB Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
UQADD_8(q0, q0, q1);
break;
case 0xDD:
INST_NAME("PADDUSW Gm,Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
UQADD_16(q0, q0, q1);
break;
case 0xDE:
INST_NAME("PMAXUB Gm, Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
UMAX_8(d0, d0, d1);
break;
case 0xDF:
INST_NAME("PANDN Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VBIC(v0, v1, v0);
break;
case 0xE0:
INST_NAME("PAVGB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
URHADD_8(v0, v0, v1);
break;
case 0xE3:
INST_NAME("PAVGW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
URHADD_16(d0, d0, d1);
break;
case 0xE5:
INST_NAME("PMULHW Gm,Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
q0 = fpu_get_scratch(dyn);
VSMULL_16(q0, v0, v1);
SQSHRN_16(v0, q0, 16);
break;
case 0xE7:
INST_NAME("MOVNTQ Em, Gm"); // Non Temporal par not handled for now
nextop = F8;
gd = (nextop&0x38)>>3;
if((nextop&0xC0)==0xC0) {
DEFAULT;
} else {
v0 = mmx_get_reg(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0xE8:
INST_NAME("PSUBSB Gm,Em");
nextop = F8;
GETGM(v0);
GETEM(q0, 0);
SQSUB_8(v0, v0, q0);
break;
case 0xE9:
INST_NAME("PSUBSW Gm,Em");
nextop = F8;
GETGM(v0);
GETEM(q0, 0);
SQSUB_16(v0, v0, q0);
break;
case 0xEB:
INST_NAME("POR Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VORR(v0, v0, v1);
break;
case 0xEC:
INST_NAME("PADDSB Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
SQADD_8(d0, d0, d1);
break;
case 0xED:
INST_NAME("PADDSW Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
SQADD_16(d0, d0, d1);
break;
case 0xEF:
INST_NAME("PXOR Gm,Em");
nextop = F8;
gd = ((nextop&0x38)>>3);
if(MODREG && ((nextop&7))==gd) {
// special case for PXOR Gx, Gx
q0 = mmx_get_reg_empty(dyn, ninst, x1, gd);
VEOR(q0, q0, q0);
} else {
q0 = mmx_get_reg(dyn, ninst, x1, gd);
GETEM(q1, 0);
VEOR(q0, q0, q1);
}
break;
case 0xF2:
INST_NAME("PSLLD Gm,Em");
nextop = F8;
GETGM(d0);
GETEM(d1, 0);
v0 = fpu_get_scratch(dyn);
VMOVeD(v0, 0, d1, 0);
VMOVeD(v0, 1, d1, 0);
SQXTN_32(v0, v0); // 2*q1 in 32bits now
SSHL_32(d0, d0, v0);
break;
case 0xF6:
INST_NAME("PSADBW Gm, Em");
nextop = F8;
GETGM(q0);
GETEM(q1, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VEOR(d1, d1, d1); // is it necessary?
UABDL_8(d0, q0, q1);
UADDLVQ_16(d1, d0);
VMOVeD(q0, 0, d1, 0);
break;
case 0xF8:
INST_NAME("PSUBB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VSUB_8(v0, v0, v1);
break;
case 0xF9:
INST_NAME("PSUBW Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VSUB_16(v0, v0, v1);
break;
case 0xFA:
INST_NAME("PSUBD Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VSUB_32(v0, v0, v1);
break;
case 0xFC:
INST_NAME("PADDB Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VADD_8(v0, v0, v1);
break;
case 0xFD:
INST_NAME("PADDW Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VADD_16(v0, v0, v1);
break;
case 0xFE:
INST_NAME("PADDD Gm, Em");
nextop = F8;
GETGM(v0);
GETEM(v1, 0);
VADD_32(v0, v0, v1);
break;
default:
DEFAULT;
}
+37 -1
View File
@@ -27,12 +27,15 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
{
uint8_t opcode = F8;
uint8_t nextop;
uint8_t u8;
int32_t j32;
uint8_t gd, ed;
uint8_t gd, ed, eb1, eb2;
uint8_t wback;
int64_t i64;
int fixedaddress;
MAYUSE(j32);
MAYUSE(eb1);
MAYUSE(eb2);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
@@ -47,6 +50,16 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
@@ -162,6 +175,29 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC6:
INST_NAME("MOV FS:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
if(MODREG) { // reg <= u8
u8 = F8;
if(!rex.rex) {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
} else {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0;
}
MOV32w(x3, u8);
BFIx(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
MOV32w(x3, u8);
STRB_REG(x3, ed, x4);
}
break;
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, _FS);
+42 -8
View File
@@ -51,6 +51,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
opcode = F8;
}
if(rex.w && opcode!=0x0f) // rex.w cancels "66", but not for 66 0f type of prefix
return dynarec64_00(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
switch(opcode) {
case 0x01:
INST_NAME("ADD Ew, Gw");
@@ -286,6 +289,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x64:
addr = dynarec64_6664(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x66:
addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
break;
case 0x69:
INST_NAME("IMUL Gw,Ew,Iw");
SETFLAGS(X_ALL, SF_PENDING);
@@ -325,7 +336,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_add16(dyn, ninst, ed, x5, x2, x4);
@@ -334,7 +345,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ew, Iw");} else {INST_NAME("OR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_or16(dyn, ninst, x1, x5, x2, x4);
@@ -344,7 +355,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(opcode==0x81) {INST_NAME("ADC Ew, Iw");} else {INST_NAME("ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_adc16(dyn, ninst, x1, x5, x2, x4);
@@ -354,7 +365,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
if(opcode==0x81) {INST_NAME("SBB Ew, Iw");} else {INST_NAME("SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_sbb16(dyn, ninst, x1, x5, x2, x4);
@@ -363,7 +374,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ew, Iw");} else {INST_NAME("AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_and16(dyn, ninst, x1, x5, x2, x4);
@@ -372,7 +383,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ew, Iw");} else {INST_NAME("SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_sub16(dyn, ninst, x1, x5, x2, x4);
@@ -381,7 +392,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ew, Iw");} else {INST_NAME("XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
MOV32w(x5, i16);
emit_xor16(dyn, ninst, x1, x5, x2, x4);
@@ -390,7 +401,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ew, Iw");} else {INST_NAME("CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x2, i16);
@@ -480,6 +491,29 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
emit_test16(dyn, ninst, x1, x2, x3, x4, x5);
break;
case 0xAB:
if(rep) {
INST_NAME("REP STOSW");
CBZx_NEXT(xRCX);
TBNZ_MARK2(xFlags, F_DF);
MARK; // Part with DF==0
STRH_S9_postindex(xRAX, xRDI, 2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK(xRCX);
B_NEXT_nocond;
MARK2; // Part with DF==1
STRH_S9_postindex(xRAX, xRDI, -2);
SUBx_U12(xRCX, xRCX, 1);
CBNZx_MARK2(xRCX);
// done
} else {
INST_NAME("STOSW");
GETDIR(x3, 2);
STRH_U12(xRAX, xRDI, 0);
ADDx_REG(xRDI, xRDI, x3);
}
break;
case 0xB8:
case 0xB9:
case 0xBA:
+501 -25
View File
@@ -50,24 +50,52 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t eb1, eb2;
uint64_t tmp64u;
int v0, v1;
int q0, q1;
int d0;
int d0, d1;
int fixedaddress;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j32);
#if 0//STEP == 3
#if 0//STEP > 1
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
switch(opcode) {
case 0x10:
INST_NAME("MOVUPD Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x11:
INST_NAME("MOVUPD Ex,Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
v1 = sse_get_reg_empty(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 15, rex, 0, 0);
VSTR128_U12(v0, ed, fixedaddress);
}
break;
case 0x12:
INST_NAME("MOVLPD Gx, Eq");
nextop = F8;
@@ -119,6 +147,30 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VLD1_64(v0, 1, ed);
}
break;
case 0x16:
INST_NAME("MOVHPD Gx, Eq");
nextop = F8;
GETGX(v0);
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VLD1_64(v0, 1, ed);
break;
case 0x17:
INST_NAME("MOVHPD Eq, Gx");
nextop = F8;
GETGX(v0);
if(MODREG) {
// access register instead of memory is bad opcode!
DEFAULT;
return addr;
}
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
VST1_64(v0, 1, ed);
break;
case 0x1F:
INST_NAME("NOP (multibyte)");
@@ -168,6 +220,76 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FCOMI(x1, x2);
break;
case 0x38: // SSSE3 opcodes
nextop = F8;
switch(nextop) {
case 0x00:
INST_NAME("PSHUFB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
d0 = fpu_get_scratch(dyn);
MOVIQ_8(d0, 0b10001111);
VANDQ(d0, d0, q1); // mask the index
VTBLQ1_8(q0, q0, d0);
break;
case 0x04:
INST_NAME("PMADDUBSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
v1 = fpu_get_scratch(dyn);
UXTL_8(v0, q0); // this is unsigned, so 0 extended
SXTL_8(v1, q1); // this is signed
VMULQ_16(v0, v0, v1);
SADDLPQ_16(v1, v0);
UXTL2_8(v0, q0); // this is unsigned
SQXTN_16(q0, v1); // SQXTN reset the vector so need to grab the high part first
SXTL2_8(v1, q1); // this is signed
VMULQ_16(v0, v0, v1);
SADDLPQ_16(v0, v0);
SQXTN2_16(q0, v0);
break;
case 0x0B:
INST_NAME("PMULHRSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
SQRDMULHQ_16(q0, q0, q1);
break;
default:
DEFAULT;
}
break;
case 0x3A: // these are some more SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F:
INST_NAME("PALIGNR Gx, Ex, Ib");
nextop = F8;
GETGX(q0);
GETEX(q1, 1);
u8 = F8;
if(u8>31) {
VEORQ(q0, q0, q0);
} else if(u8>15) {
d0 = fpu_get_scratch(dyn);
VEORQ(d0, d0, d0);
VEXTQ_8(q0, q0, d0, u8-16);
} else {
VEXTQ_8(q0, q1, q0, u8);
}
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
GETFLAGS; \
@@ -214,7 +336,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETGX(v0);
VEORQ(v0, v0, q0);
break;
case 0x58:
INST_NAME("ADDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFADDQD(v0, v0, q0);
break;
case 0x59:
INST_NAME("MULPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFMULQD(v0, v0, q0);
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
nextop = F8;
@@ -247,7 +382,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFCVTNSQS(v0, v1);
#endif
break;
case 0x5C:
INST_NAME("SUBPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFSUBQD(v0, v0, q0);
break;
case 0x5D:
INST_NAME("MINPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFMINQD(v0, v0, q0);
break;
case 0x5F:
INST_NAME("MAXPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0);
VFMAXQD(v0, v0, q0);
break;
case 0x60:
INST_NAME("PUNPCKLBW Gx,Ex");
nextop = F8;
@@ -269,7 +425,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q0, 0);
VZIP1Q_32(v0, v0, q0);
break;
case 0x63:
INST_NAME("PACKSSWB Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
SQXTN_8(q0, q0);
if(q0==q1) {
VMOVeD(q0, 1, q0, 0);
} else {
SQXTN2_8(q0, q1);
}
break;
case 0x64:
INST_NAME("PCMPGTB Gx,Ex");
nextop = F8;
@@ -291,7 +458,18 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(v1, 0);
VCMGTQ_32(v0, v0, v1);
break;
case 0x67:
INST_NAME("PACKUSWB Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
SQXTUN_8(v0, v0);
if(v0==v1) {
VMOVeD(v0, 1, v0, 0);
} else {
SQXTUN2_8(v0, v1);
}
break;
case 0x68:
INST_NAME("PUNPCKHBW Gx,Ex");
nextop = F8;
@@ -337,7 +515,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VLD1_64(v0, 1, ed);
}
break;
case 0x6D:
INST_NAME("PUNPCKHQDQ Gx,Ex");
nextop = F8;
GETGX(v0);
VMOVeD(v0, 0, v0, 1);
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
VMOVeD(v0, 1, v1, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
ADDSx_U12(x1, ed, 8);
VLD1_64(v0, 1, x1);
}
break;
case 0x6E:
INST_NAME("MOVD Gx, Ed");
nextop = F8;
@@ -369,41 +560,47 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
nextop = F8;
GETG;
i32 = -1;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(u8==0x4E) {
if(v0==v1) {
VSWP(v0, v0+1);
VEXTQ_8(v0, v0, v0, 8); // Swap Up/Lower 64bits parts
} else {
VMOVeD(v0, 0, v1, 1);
VMOVeD(v0, 1, v1, 0);
}
} else if(u8==0x00) {
// dumplicate lower 32bits to all spot
if(v0!=v1) {
VMOVeS(v0, 0, v1, 0);
}
VMOVeS(v0, 1, v1, 0);
VMOVeD(v0, 1, v0, 0);
} else if(v0!=v1) {
VMOVeS(v0, 0, v1, (u8>>(0*2))&3);
VMOVeS(v0, 1, v1, (u8>>(1*2))&3);
VMOVeS(v0, 2, v1, (u8>>(2*2))&3);
VMOVeS(v0, 3, v1, (u8>>(3*2))&3);
} else {
uint32_t swp[4] = {
uint64_t swp[4] = {
(0)|(1<<8)|(2<<16)|(3<<24),
(4)|(5<<8)|(6<<16)|(7<<24),
(8)|(9<<8)|(10<<16)|(11<<24),
(12)|(13<<8)|(14<<16)|(15<<24)
};
d0 = fpu_get_scratch(dyn);
if(v0==v1) {
q1 = fpu_get_scratch(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
MOV32w(x2, swp[(u8>>(0*2))&3]);
MOV32w(x3, swp[(u8>>(1*2))&3]);
VMOVQSfrom(d0, 0, x2);
VMOVQSfrom(d0, 1, x3);
MOV32w(x2, swp[(u8>>(2*2))&3]);
MOV32w(x3, swp[(u8>>(3*2))&3]);
VMOVQSfrom(d0, 2, x2);
VMOVQSfrom(d0, 3, x3);
tmp64u = swp[(u8>>(0*2))&3] | (swp[(u8>>(1*2))&3]<<32);
MOV64x(x2, tmp64u);
VMOVQDfrom(d0, 0, x2);
tmp64u = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
MOV64x(x3, tmp64u);
VMOVQDfrom(d0, 1, x3);
VTBLQ1_8(v0, v1, d0);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 1);
u8 = F8;
if (u8) {
@@ -591,6 +788,28 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0x74:
INST_NAME("PCMPEQB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VCMEQQ_8(v0, v0, q0);
break;
case 0x75:
INST_NAME("PCMPEQW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VCMEQQ_16(v0, v0, q0);
break;
case 0x76:
INST_NAME("PCMPEQD Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
VCMEQQ_32(v0, v0, q0);
break;
case 0x7E:
INST_NAME("MOVD Ed,Gx");
nextop = F8;
@@ -792,6 +1011,55 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
BFIx(gd, x1, 0, 16);
break;
case 0xC4:
INST_NAME("PINSRW Gx,Ed,Ib");
nextop = F8;
GETGX(v0);
if(MODREG) {
u8 = (F8)&7;
ed = xRAX+(nextop&7)+(rex.b<<3);
VMOVQHfrom(v0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
u8 = (F8)&7;
VLD1_16(v0, u8, wback);
}
break;
case 0xC5:
INST_NAME("PEXTRW Gd,Ex,Ib");
nextop = F8;
GETGD;
if(MODREG) {
GETEX(v0, 1);
u8 = (F8)&7;
VMOVHto(gd, v0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, 1);
u8 = (F8)&7;
LDRH_U12(gd, wback, u8*2);
}
break;
case 0xC6:
INST_NAME("SHUFPD Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if(v0==v1 && u8==0) {
VMOVeD(v0, 1, v0, 0);
} else {
if(v0==v1)
q0 = fpu_get_scratch(dyn);
else
q0 = v0;
VMOVeD(q0, 0, v0, (u8&1));
VMOVeD(q0, 1, v1, ((u8>>1)&1));
if(v0==v1) {
VMOVQ(v0, q0);
}
}
break;
case 0xD4:
INST_NAME("PADDQ Gx,Ex");
@@ -800,7 +1068,13 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q0, 0);
VADDQ_64(v0, v0, q0);
break;
case 0xD5:
INST_NAME("PMULLW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
VMULQ_16(q0, q0, q1);
break;
case 0xD6:
INST_NAME("MOVQ Ex, Gx");
nextop = F8;
@@ -815,6 +1089,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xD8:
INST_NAME("PSUBUSB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
UQSUBQ_8(q0, q0, q1);
break;
case 0xD9:
INST_NAME("PSUBUSW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
UQSUBQ_16(q0, q0, q1);
break;
case 0xDA:
INST_NAME("PMINUB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1,0);
UMINQ_8(q0, q0, q1);
break;
case 0xDB:
INST_NAME("PAND Gx,Ex");
nextop = F8;
@@ -822,7 +1117,27 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q0, 0);
VANDQ(v0, v0, q0);
break;
case 0xDC:
INST_NAME("PADDUSB Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
UQADDQ_8(q0, q0, q1);
break;
case 0xDD:
INST_NAME("PADDUSW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
UQADDQ_16(q0, q0, q1);
break;
case 0xDE:
INST_NAME("PMAXUB Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
UMAXQ_8(q0, q0, q1);
break;
case 0xDF:
INST_NAME("PANDN Gx,Ex");
nextop = F8;
@@ -831,6 +1146,114 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VBICQ(v0, q0, v0);
break;
case 0xE0:
INST_NAME("PAVGB Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
URHADDQ_8(v0, v0, v1);
break;
case 0xE1:
INST_NAME("PSRAW Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
VMOVeD(v0, 0, q1, 0);
VMOVeD(v0, 1, q1, 0);
SQXTN_32(v0, v0); // 2*q1 in 32bits now
NEG_32(v0, v0); // because we want SHR and not SHL
VMOVeD(v0, 1, v0, 0);
SQXTN_16(v0, v0); // 4*q1 in 32bits now
VMOVeD(v0, 1, v0, 0);
SSHLQ_16(q0, q0, v0);
break;
case 0xE2:
INST_NAME("PSRAD Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
VMOVeD(v0, 0, q1, 0);
VMOVeD(v0, 1, q1, 0);
SQXTN_32(v0, v0); // 2*q1 in 32bits now
NEG_32(v0, v0); // because we want SHR and not SHL
VMOVeD(v0, 1, v0, 0);
SSHLQ_32(q0, q0, v0);
break;
case 0xE4:
INST_NAME("PMULHUW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VUMULL_16(q0, v0, v1);
VUMULL2_16(q1, v0, v1);
UQSHRN_16(v0, q0, 16);
UQSHRN2_16(v0, q1, 16);
break;
case 0xE5:
INST_NAME("PMULHW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VSMULL_16(q0, v0, v1);
VSMULL2_16(q1, v0, v1);
SQSHRN_16(v0, q0, 16);
SQSHRN2_16(v0, q1, 16);
break;
case 0xE6:
INST_NAME("CVTPD2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
#ifdef PRECISE_CVT
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(x1, x1, 13, 2); // extract round requested
LSLx_REG(x1, x1, 3);
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
// Construct a "switch case", with each case 2 instructions, so 8 bytes
BL(+4); // Branch with Link to next, so LR gets next PC address
ADDx_REG(xLR, xLR, x1);
B(xLR); // could use RET, but it's not really one
VFCVTNSQD(v0, v1); // 0: Nearest (even)
B_NEXT_nocond;
VFCVTMSQD(v0, v1); // 1: Toward -inf
B_NEXT_nocond;
VFCVTPSQD(v0, v1); // 2: Toward +inf
B_NEXT_nocond;
VFCVTZSQD(v0, v1); // 3: Toward 0
#else
VFCVTNSQD(v0, v1);
#endif
break;
case 0xE8:
INST_NAME("PSUBSB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SQSUBQ_8(v0, v0, q0);
break;
case 0xE9:
INST_NAME("PSUBSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SQSUBQ_16(v0, v0, q0);
break;
case 0xEA:
INST_NAME("PMINSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SMINQ_16(v0, v0, q0);
break;
case 0xEB:
INST_NAME("POR Gx,Ex");
nextop = F8;
@@ -838,6 +1261,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(q0, 0);
VORRQ(v0, v0, q0);
break;
case 0xEC:
INST_NAME("PADDSB Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SQADDQ_8(v0, v0, q0);
break;
case 0xED:
INST_NAME("PADDSW Gx,Ex");
nextop = F8;
GETGX(v0);
GETEX(q0, 0);
SQADDQ_16(v0, v0, q0);
break;
case 0xEF:
INST_NAME("PXOR Gx,Ex");
@@ -854,6 +1291,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xF2:
INST_NAME("PSLLD Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
VMOVeD(v0, 0, q1, 0);
VMOVeD(v0, 1, q1, 0);
SQXTN_32(v0, v0); // 2*q1 in 32bits now
VMOVeD(v0, 1, v0, 0);
SSHLQ_32(q0, q0, v0);
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
nextop = F8;
@@ -869,6 +1319,32 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VUZP1Q_32(q1, v1, v1);
VUMULL_32(v0, q0, q1);
break;
case 0xF5:
INST_NAME("PMADDWD Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
q0 = fpu_get_scratch(dyn);
q1 = fpu_get_scratch(dyn);
VSMULL_16(q0, v0, v1);
VSMULL2_16(q1, v0, v1);
VADDPQ_32(v0, q0, q1);
break;
case 0xF6:
INST_NAME("PSADBW Gx, Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
d0 = fpu_get_scratch(dyn);
d1 = fpu_get_scratch(dyn);
VEOR(d1, d1, d1); // is it necessary?
UABDL_8(d0, q0, q1);
UADDLVQ_16(d1, d0);
VMOVeD(q0, 0, d1, 0);
UABDL2_8(d0, q0, q1);
UADDLVQ_16(d1, d0);
VMOVeD(q0, 1, d1, 0);
break;
case 0xF8:
INST_NAME("PSUBB Gx,Ex");
+79
View File
@@ -0,0 +1,79 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int fixedaddress;
// REX prefix before the 66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
/*if(rex.w && opcode!=0x0f) { // rex.w cancels "66", but not for 66 0f type of prefix
MESSAGE(LOG_DUMP, "Here!\n");
return dynarec64_64(dyn, addr-2, ip, ninst, rex, rep, ok, need_epilog);
}*/
switch(opcode) {
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_segdata(dyn, addr, ninst, x4, _FS);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
ed = xRAX+(nextop&7)+(rex.b<<3);
if(rex.w) {
MOVx_REG(gd, ed);
} else {
if(ed!=gd) {
BFIx(gd, ed, 0, 16);
}
}
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
if(rex.w) {
LDRx_REG(gd, ed, x4);
} else {
LDRH_REG(x1, ed, x4);
BFIx(gd, x1, 0, 16);
}
}
break;
default:
DEFAULT;
}
return addr;
}
+18
View File
@@ -26,6 +26,9 @@
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int fixedaddress;
int8_t i8;
int32_t i32, j32;
MAYUSE(j32);
@@ -40,6 +43,21 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x8D:
INST_NAME("LEA Gd, Ed");
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
// should a geted32 be created, to use 32bits regs instead of 64bits?
addr = geted32(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=gd) {
MOVw_REG(gd, ed);
}
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8);\
+231
View File
@@ -0,0 +1,231 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
int fixedaddress;
int v1, v2;
int s0;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FADD ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FADDD(v1, v1, v2);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FMUL ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FMULD(v1, v1, v2);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FSUB ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FSUBD(v1, v1, v2);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FSUBR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FSUBD(v1, v2, v1);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FDIV ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FDIVD(v1, v1, v2);
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
INST_NAME("FDIVR ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FDIVD(v1, v2, v1);
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FADD ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FADDD(v1, v1, s0);
break;
case 1:
INST_NAME("FMUL ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FMULD(v1, v1, s0);
break;
case 2:
INST_NAME("FCOM ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
FCOM(x1, x2, x3);
break;
case 3:
INST_NAME("FCOMP ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FCMPD(v1, s0);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FSUB ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FSUBD(v1, v1, s0);
break;
case 5:
INST_NAME("FSUBR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FSUBD(v1, s0, v1);
break;
case 6:
INST_NAME("FDIV ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FDIVD(v1, v1, s0);
break;
case 7:
INST_NAME("FDIVR ST0, float[ED]");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(s0, s0);
FDIVD(v1, s0, v1);
break;
default:
DEFAULT;
}
}
return addr;
}
+339
View File
@@ -0,0 +1,339 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
int fixedaddress;
int v1, v2;
int s0;
int i1, i2, i3;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FLD STx");
v1 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
v2 = x87_do_push(dyn, ninst);
FMOVD(v2, v1);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
i1 = x87_get_cache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_cache(dyn, ninst, x1, x2, 0);
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
break;
case 0xD0:
INST_NAME("FNOP");
break;
case 0xE0:
INST_NAME("FCHS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
FNEGD(v1, v1);
break;
case 0xE1:
INST_NAME("FABS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
FABSD(v1, v1);
break;
case 0xE4:
INST_NAME("FTST");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
FCMPD_0(v1);
FCOM(x1, x2, x3); // same flags...
break;
case 0xE5:
INST_NAME("FXAM");
x87_refresh(dyn, ninst, x1, x2, 0);
CALL(fpu_fxam, -1); // should be possible inline, but is it worth it?
break;
case 0xE8:
INST_NAME("FLD1");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, 1.0);
break;
case 0xE9:
INST_NAME("FLDL2T");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, L2T);
break;
case 0xEA:
INST_NAME("FLDL2E");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, L2E);
break;
case 0xEB:
INST_NAME("FLDPI");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, PI);
break;
case 0xEC:
INST_NAME("FLDLG2");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, LG2);
break;
case 0xED:
INST_NAME("FLDLN2");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, LN2);
break;
case 0xEE:
INST_NAME("FLDZ");
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, 0.0);
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
FSQRTD(v1, v1);
break;
case 0xFC:
INST_NAME("FRNDINT");
// use C helper for now, nothing staightforward is available
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_frndint, -1);
/*
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
u8 = x87_setround(dyn, ninst, x1, x2, x3);
VCVT_S32_F64(x1, v1); // limit to 32bits....
VCVT_F64_S32(v1, x1);
x87_restoreround(dyn, ninst, u8);
*/
break;
case 0xF0:
INST_NAME("F2XM1");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1);
break;
case 0xF1:
INST_NAME("FYL2X");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2x, -1);
x87_do_pop(dyn, ninst);
break;
case 0xF2:
INST_NAME("FTAN");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_ftan, -1);
v1 = x87_do_push(dyn, ninst);
FTABLE64(v1, 1.0);
break;
case 0xF3:
INST_NAME("FPATAN");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fpatan, -1);
x87_do_pop(dyn, ninst);
break;
case 0xF4:
INST_NAME("FXTRACT");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1);
break;
case 0xF5:
INST_NAME("FPREM1");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem1, -1);
break;
case 0xF6:
INST_NAME("FDECSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
SUBw_U12(x2, x2, 1);
ANDw_mask(x2, x2, 0, 2); //mask=7
STRw_U12(x2, xEmu, offsetof(x64emu_t, top));
break;
case 0xF7:
INST_NAME("FINCSTP");
fpu_purgecache(dyn, ninst, x1, x2, x3);
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
ADDw_U12(x2, x2, 1);
ANDw_mask(x2, x2, 0, 2); //mask=7
STRw_U12(x2, xEmu, offsetof(x64emu_t, top));
break;
case 0xF8:
INST_NAME("FPREM");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1);
break;
case 0xF9:
INST_NAME("FYL2XP1");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fyl2xp1, -1);
x87_do_pop(dyn, ninst);
break;
case 0xFB:
INST_NAME("FSINCOS");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fsincos, -1);
break;
case 0xFD:
INST_NAME("FSCALE");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fscale, -1);
break;
case 0xFE:
INST_NAME("FSIN");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fsin, -1);
break;
case 0xFF:
INST_NAME("FCOS");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fcos, -1);
break;
case 0xD1:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE2:
case 0xE3:
case 0xE6:
case 0xE7:
case 0xEF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
FCVT_D_S(v1, s0);
break;
case 2:
INST_NAME("FST float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VSTR32_U12(s0, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP float[ED], ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
s0 = fpu_get_scratch(dyn);
FCVT_S_D(s0, v1);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VSTR32_U12(s0, ed, fixedaddress);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FLDENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_loadenv, -1);
break;
case 5:
INST_NAME("FLDCW Ew");
GETEW(x1, 0);
STRH_U12(x1, xEmu, offsetof(x64emu_t, cw)); // hopefully cw is not too far for an imm8
UBFXw(x1, x1, 10, 2); // extract round
STRw_U12(x1, xEmu, offsetof(x64emu_t, round));
break;
case 6:
INST_NAME("FNSTENV Ed");
fpu_purgecache(dyn, ninst, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
MOV32w(x2, 0);
CALL(fpu_savenv, -1);
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
ed = x1;
wb1 = 1;
LDRH_U12(x1, xEmu, offsetof(x64emu_t, cw));
EWBACK;
break;
default:
DEFAULT;
}
}
return addr;
}
+289
View File
@@ -0,0 +1,289 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback;
uint8_t u8;
int fixedaddress;
int v1, v2;
int s0;
int j32;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FCMOVNB ST0, STx");
READFLAGS(X_CF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
TSTw_mask(xFlags, 0, 0); //mask=1<<F_CF
FCSELD(v1, v2, v1, cEQ); // F_CF==0
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
INST_NAME("FCMOVNE ST0, STx");
READFLAGS(X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
TSTw_mask(xFlags, 0b011010, 0); //mask=1<<F_ZF
FCSELD(v1, v2, v1, cEQ); // F_ZF==0
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FCMOVNBE ST0, STx");
READFLAGS(X_CF|X_ZF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
MOV32w(x1, (1<<F_CF)|(1<<F_ZF));
TSTw_REG(xFlags, x1);
FCSELD(v1, v2, v1, cEQ); // F_CF==0 & F_ZF==0
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FCMOVNU ST0, STx");
READFLAGS(X_PF);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
TSTw_mask(xFlags, 0b011110, 0); //mask=1<<F_PF
FCSELD(v1, v2, v1, cEQ); // F_PF==0
break;
case 0xE1:
INST_NAME("FDISI8087_NOP"); // so.. NOP?
break;
case 0xE2:
INST_NAME("FNCLEX");
LDRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
MOV32w(x1, 0);
BFIw(x2, x1, 0, 8); // IE .. PE, SF, ES
BFIw(x2, x1, 15, 1); // B
STRH_U12(x2, xEmu, offsetof(x64emu_t, sw));
break;
case 0xE3:
INST_NAME("FNINIT");
x87_purgecache(dyn, ninst, x1, x2, x3);
CALL(reset_fpu, -1);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOMI(x1, x2);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FCOMI ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOMI(x1, x2);
break;
case 0xE0:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ed");
v1 = x87_do_push(dyn, ninst);
s0 = fpu_get_scratch(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
SXTL_32(v1, s0);
SCVTFDD(v1, v1);
break;
case 1:
INST_NAME("FISTTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32ZD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTZD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FIST Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ed, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x4); // x1 have the modified RPSCR reg
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
ed = x1;
}
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
FCVTZSwD(ed, s0);
WBACK;
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst);
break;
case 5:
INST_NAME("FLD tbyte");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL(arm_fld, -1);
break;
case 7:
INST_NAME("FSTP tbyte");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {
MOVx_REG(x1, ed);
}
CALL(arm_fstp, -1);
x87_do_pop(dyn, ninst);
break;
default:
DEFAULT;
}
}
return addr;
}
+198
View File
@@ -0,0 +1,198 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
int fixedaddress;
int v1, v2;
int s0;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREE STx");
break; // not handling Tag...
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
INST_NAME("FST ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FMOVD(v2, v1);
break;
case 0xD8:
INST_NAME("FSTP ST0, ST0");
x87_do_pop(dyn, ninst);
break;
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
INST_NAME("FSTP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FMOVD(v2, v1);
x87_do_pop(dyn, ninst);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
INST_NAME("FUCOM ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMP ST0, STx");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOM(x1, x2, x3);
x87_do_pop(dyn, ninst);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD double");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v1, ed, fixedaddress);
break;
case 1:
INST_NAME("FISTTP i64, ST0");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
s0 = fpu_get_scratch(dyn);
FRINT64ZD(s0, v1);
FCVTZSxD(x2, s0);
STRx_U12(x2, ed, fixedaddress);
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FST double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
break;
case 3:
INST_NAME("FSTP double");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VSTR64_U12(v1, ed, fixedaddress);
x87_do_pop(dyn, ninst);
break;
case 4:
INST_NAME("FRSTOR m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_frstor, -1);
break;
case 6:
INST_NAME("FSAVE m108byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(arm_fsave, -1);
break;
case 7:
INST_NAME("FNSTSW m2byte");
fpu_purgecache(dyn, ninst, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x4, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
LDRw_U12(x1, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x3, xEmu, offsetof(x64emu_t, sw));
BFIw(x3, x1, 11, 3); // inject TOP at bit 11 (3 bits)
STRH_U12(x3, ed, fixedaddress); // store whole sw flags
break;
default:
DEFAULT;
}
}
return addr;
}
+289
View File
@@ -0,0 +1,289 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box64context.h"
#include "dynarec.h"
#include "emu/x64emu_private.h"
#include "emu/x64run_private.h"
#include "x64run.h"
#include "x64emu.h"
#include "box64stack.h"
#include "callback.h"
#include "emu/x64run_private.h"
#include "x64trace.h"
#include "dynarec_arm64.h"
#include "dynarec_arm64_private.h"
#include "arm64_printer.h"
#include "emu/x87emu_private.h"
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed, wback, u8;
int fixedaddress;
int v1, v2;
int j32;
int s0;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
INST_NAME("FFREEP STx");
// not handling Tag...
x87_do_pop(dyn, ninst);
break;
case 0xE0:
INST_NAME("FNSTSW AX");
LDRw_U12(x2, xEmu, offsetof(x64emu_t, top));
LDRH_U12(x1, xEmu, offsetof(x64emu_t, sw));
BFIw(x1, x2, 11, 3); // inject top
BFIw(xRAX, x1, 0, 16);
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
INST_NAME("FUCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
INST_NAME("FCOMIP ST0, STx");
SETFLAGS(X_ALL, SF_SET);
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7);
FCMPD(v1, v2);
FCOMI(x1, x2);
x87_do_pop(dyn, ninst);
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7:
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
DEFAULT;
break;
default:
switch((nextop>>3)&7) {
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
LDRSHw_U12(x1, wback, fixedaddress);
SCVTFDw(v1, x1);
break;
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
// this version needs ARM v8.5, //TODO: add detection of this extensio to use it
FRINT32ZD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst);
break;
case 2:
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
case 3:
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<1, 1, rex, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT32XD(s0, v1);
// no saturation instruction on Arm, so using NEON
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
#endif
x87_do_pop(dyn, ninst);
x87_restoreround(dyn, ninst, u8);
break;
case 4:
INST_NAME("FBLD ST0, tbytes");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbld, -1);
break;
case 5:
INST_NAME("FILD ST0, i64");
v1 = x87_do_push(dyn, ninst);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
LDRx_U12(x1, wback, fixedaddress);
SCVTFDx(v1, x1);
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(ed!=x1) {MOVx_REG(x1, ed);}
CALL(fpu_fbst, -1);
x87_do_pop(dyn, ninst);
break;
case 7:
INST_NAME("FISTP i64, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0);
u8 = x87_setround(dyn, ninst, x1, x2, x4);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
ed = x1;
s0 = fpu_get_scratch(dyn);
#if 0
FRINT64XD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
#else
MSR_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MRS_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
MSR_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_NEXT(x5, FPSR_IOC);
MOV64x(x5, 0x8000000000000000LL);
STRx_U12(x5, wback, fixedaddress);
#endif
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
}
}
return addr;
}
+1 -1
View File
@@ -1257,7 +1257,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
MSR_nzvc(s3); // load CC into ARM CF
ADCw_REG(s1, s1, s2);
IFX(X_PEND) {
STRw_REG(s1, xEmu, offsetof(x64emu_t, res));
STRH_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_AF|X_OF) {
ORRw_REG(s3, s4, s2); // s3 = op1 | op2
+15 -15
View File
@@ -26,7 +26,7 @@
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
IFX_PENDOR0 {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, rex.w?d_cmp64:d_cmp32);
@@ -38,7 +38,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
BICxw(s4, s2, s1); // s4 = ~op1 & op2
}
SUBSxw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_PEND) {
IFX_PENDOR0 {
STRxw_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_AF) {
@@ -76,7 +76,7 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// emit CMP32 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4)
{
IFX(X_PEND) {
IFX_PENDOR0 {
MOV64xw(s4, 0);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s4, xEmu, offsetof(x64emu_t, op2));
@@ -113,7 +113,7 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
// emit CMP16 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
IFX_PENDOR0 {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s3, d_cmp16);
@@ -121,7 +121,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
SET_DFNONE(s3);
}
SUBw_REG(s5, s1, s2); // res = s1 - s2
IFX(X_PEND) {
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
@@ -162,7 +162,7 @@ void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch
void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
IFX_PENDOR0 {
MOV32w(s3, 0);
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -192,7 +192,7 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
IFX_PENDOR0 {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
SET_DF(s4, d_cmp8);
@@ -204,7 +204,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
} else {
SUBw_REG(s5, s1, s2); // res = s1 - s2
}
IFX(X_PEND) {
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
@@ -242,7 +242,7 @@ void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, in
// emit CMP8 instruction, from cmp s1 , 0, using s3 and s4 as scratch
void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
IFX_PENDOR0 {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
MOV32w(s4, 0);
STRB_U12(s4, xEmu, offsetof(x64emu_t, op2));
@@ -273,7 +273,7 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
// emit TEST32 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
IFX_PENDOR0 {
SET_DF(s3, rex.w?d_tst64:d_tst32);
} else {
SET_DFNONE(s4);
@@ -283,7 +283,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
BICw(xFlags, xFlags, s3);
}
ANDSxw_REG(s3, s1, s2); // res = s1 & s2
IFX(X_PEND) {
IFX_PENDOR0 {
STRxw_U12(s3, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
@@ -310,7 +310,7 @@ void emit_test32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
// emit TEST16 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
@@ -322,7 +322,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
BFCw(xFlags, F_CF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX(X_PEND) {
IFX_PENDOR0 {
STRH_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
@@ -342,7 +342,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4,
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
{
IFX(X_PEND) {
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
@@ -354,7 +354,7 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
BFCw(xFlags, F_CF, 1);
}
ANDSw_REG(s5, s1, s2); // res = s1 & s2
IFX(X_PEND) {
IFX_PENDOR0 {
STRB_U12(s5, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
+72 -7
View File
@@ -120,8 +120,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
// Aligned version
MARKLOCK;
LDAXRxw(x1, wback);
ed = x1;
CMPSxw_REG(xRAX, ed);
CMPSxw_REG(xRAX, x1);
B_MARK(cNE);
// EAX == Ed
STLXRxw(x4, gd, wback);
@@ -132,18 +131,16 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARK3;
LDRxw_U12(x1, wback, 0);
LDAXRB(x3, wback); // dummy read, to arm the write...
ed = x1;
CMPSxw_REG(xRAX, ed);
CMPSxw_REG(xRAX, x1);
B_MARK(cNE);
// EAX == Ed
STLXRB(x4, gd, wback);
CBNZx_MARK3(x4);
STRxw_U12(gd, wback, 0);
B_MARK_nocond;
MARK;
// Common part (and fallback for EAX != Ed)
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, ed, x3, x4, x5);}
MOVxw_REG(xRAX, ed);
UFLAG_IF {emit_cmp32(dyn, ninst, rex, xRAX, x1, x3, x4, x5);}
MOVxw_REG(xRAX, x1); // upper par of RAX will be erase on 32bits, no mater what
}
break;
@@ -185,11 +182,52 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC7:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2);
B_MARK(cNE); // EAX != Ed[0]
CMPSxw_REG(xRDX, x3);
B_MARK(cNE); // EDX != Ed[1]
STLXPxw(x4, xRBX, xRCX, wback);
CBNZx_MARKLOCK(x4);
MOV32w(x1, 1);
B_MARK3_nocond;
MARK;
MOVxw_REG(xRAX, x2);
MOVxw_REG(xRDX, x3);
MOV32w(x1, 0);
MARK3;
BFIw(xFlags, x1, F_ZF, 1);
break;
default:
DEFAULT;
}
break;
case 0x29:
INST_NAME("LOCK SUB Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGD;
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
MARKLOCK;
LDAXRxw(x1, wback);
emit_sub32(dyn, ninst, rex, x1, gd, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -371,6 +409,33 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0x87:
INST_NAME("LOCK XCHG Ed, Gd");
nextop = F8;
if(MODREG) {
GETGD;
GETED(0);
MOVxw_REG(x1, gd);
MOVxw_REG(gd, ed);
MOVxw_REG(ed, x1);
} else {
GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(ed, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE);
MARKLOCK;
LDAXRxw(x1, ed);
STLXRxw(x3, gd, ed);
CBNZx_MARKLOCK(x3);
B_MARK2_nocond;
MARK;
LDRxw_U12(x1, ed, 0);
STRxw_U12(gd, ed, 0);
MARK2;
MOVxw_REG(gd, x1);
}
break;
default:
DEFAULT;
}
+82 -2
View File
@@ -37,12 +37,17 @@
#define GETGX(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
#define GETGX_empty(a) gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
uint8_t wback;
uint8_t u8;
uint64_t u64;
int v0, v1;
int q0;
int d0, d1;
@@ -89,6 +94,21 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VSTR64_U12(v0, ed, fixedaddress);
}
break;
case 0x12:
INST_NAME("MOVDDUP Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
d0 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVeD(v0, 0, d0, 0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
VMOVeD(v0, 1, v0, 0);
break;
case 0x2A:
INST_NAME("CVTSI2SD Gx, Ed");
@@ -188,7 +208,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x5D:
INST_NAME("MINSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MINSD: if any input is NaN, or Ex[0]<Gx[0], copy Ex[0] -> Gx[0]
@@ -208,7 +228,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
nextop = F8;
gd = (nextop&0x38)>>3;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
GETEX(v1, 0);
// MAXSD: if any input is NaN, or Ex[0]>Gx[0], copy Ex[0] -> Gx[0]
@@ -217,6 +237,26 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVeD(v0, 0, d0, 0); // to not erase uper part
break;
case 0x70:
INST_NAME("PSHUFLW Gx, Ex, Ib");
nextop = F8;
GETEX(v1, 1);
GETGX(v0);
u8 = F8;
// only low part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+0)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+1)<<(i*16+8);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 0, d0, 0);
break;
case 0x7C:
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
@@ -231,6 +271,46 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VFADDPQS(v0, v0, v1);
break;
case 0xC2:
INST_NAME("CMPSD Gx, Ex, Ib");
nextop = F8;
GETGX(v0);
GETEX(v1, 1);
u8 = F8;
if((u8&7)==6){
FCMPD(v1, v0);
} else {
FCMPD(v0, v1);
}
switch(u8&7) {
case 0: CSETMx(x2, cEQ); break; // Equal
case 1: CSETMx(x2, cMI); break; // Less than
case 2: //CSETMx(x2, cLE); break; // Less or equal (or unordered on ARM64, not on x86...)
CSETMx(x2, cPL); CSINVx(x2, xZR, x2, cEQ); break; // so use a 2 step here, but 1st test inverted because 2nd step invert again
case 3: CSETMx(x2, cVS); break; // NaN
case 4: CSETMx(x2, cNE); break; // Not Equal (or unordered on ARM, not on X86...)
case 5: CSETMx(x2, cCS); break; // Greater or equal or unordered
case 6: CSETMx(x2, cLT); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: CSETMx(x2, cVC); break; // not NaN
}
VMOVQDfrom(v0, 0, x2);
break;
case 0xF0:
INST_NAME("LDDQU Gx,Ex");
nextop = F8;
GETG;
if(MODREG) {
v1 = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3));
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<4, 7, rex, 0, 0);
VLDR128_U12(v0, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
+110 -1
View File
@@ -46,10 +46,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
uint8_t nextop, u8;
uint8_t gd, ed;
uint8_t wback;
uint64_t u64;
int v0, v1;
int q0, q1;
int d0, d1;
int fixedaddress;
int j32;
MAYUSE(d0);
MAYUSE(d1);
@@ -57,6 +59,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MAYUSE(q1);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(j32);
switch(opcode) {
@@ -136,7 +139,31 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
GETEX(d0, 0);
FCVTZSxwS(gd, d0);
break;
case 0x2D:
INST_NAME("CVTSS2SI Gd, Ex");
nextop = F8;
GETGD;
GETEX(q0, 0);
#ifdef PRECISE_CVT
LDRH_U12(x1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(x1, x1, 13, 2); // extract round requested
LSLx_REG(x1, x1, 3);
ADDx_U12(x1, x1, 8); // add the actual add+jump opcodes
// Construct a "switch case", with each case 2 instructions, so 8 bytes
BL(+4); // Branch with Link to next, so LR gets next PC address
ADDx_REG(xLR, xLR, x1);
B(xLR); // could use RET, but it's not really one
FCVTNSxwS(gd, q0); // 0: Nearest (even)
B_NEXT_nocond;
FCVTMSxwS(gd, q0); // 1: Toward -inf
B_NEXT_nocond;
FCVTPSxwS(gd, q0); // 2: Toward +inf
B_NEXT_nocond;
FCVTZSxwS(gd, q0); // 3: Toward 0
#else
FCVTNSxwS(gd, q0);
#endif
break;
case 0x51:
INST_NAME("SQRTSS Gx, Ex");
nextop = F8;
@@ -146,6 +173,22 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FSQRTS(d1, d0);
VMOVeS(v0, 0, d1, 0);
break;
case 0x52:
INST_NAME("RSQRTSS Gx, Ex");
nextop = F8;
GETGX(v0);
GETEX(v1, 0);
d0 = fpu_get_scratch(dyn);
// so here: F32: Imm8 = abcd efgh that gives => aBbbbbbc defgh000 00000000 00000000
// and want 1.0f = 0x3f800000
// so 00111111 10000000 00000000 00000000
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
FMOVS_8(d0, 0b01110000);
FSQRTS(v0, v1);
FDIVS(d0, d0, v0);
VMOVeS(v0, 0, d0, 0);
break;
case 0x58:
INST_NAME("ADDSS Gx, Ex");
@@ -174,6 +217,13 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
FCVT_D_S(d0, v1);
VMOVeD(v0, 0, d0, 0);
break;
case 0x5B:
INST_NAME("CVTPS2DQ Gx, Ex");
nextop = F8;
GETEX(d0, 0);
GETGX_empty(v0);
VFCVTZSQS(v0, d0);
break;
case 0x5C:
INST_NAME("SUBSS Gx, Ex");
@@ -227,6 +277,25 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VLDR128_U12(v0, ed, fixedaddress);
}
break;
case 0x70:
INST_NAME("PSHUFHW Gx, Ex, Ib");
nextop = F8;
GETEX(v1, 1);
GETGX(v0);
u8 = F8;
// only high part need to be suffled. VTBL only handle 8bits value, so the 16bits suffles need to be changed in 8bits
u64 = 0;
for (int i=0; i<4; ++i) {
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+8)<<(i*16+0);
u64 |= ((uint64_t)((u8>>(i*2))&3)*2+9)<<(i*16+8);
}
MOV64x(x2, u64);
d0 = fpu_get_scratch(dyn);
VMOVQDfrom(d0, 0, x2);
VTBL1_8(d0, v1, d0);
VMOVeD(v0, 1, d0, 0);
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
@@ -257,6 +326,22 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
break;
case 0xBC:
INST_NAME("TZCNT Gd, Ed");
SETFLAGS(X_CF|X_ZF, SF_SET);
nextop = F8;
GETED(0);
GETGD;
SET_DFNONE(x1);
TSTxw_REG(ed, ed);
BFIw(xFlags, x1, F_CF, 1); // CF = is source 0?
RBITxw(x1, ed); // reverse
CLZxw(gd, x1); // x2 gets leading 0 == TZCNT
TSTxw_REG(gd, gd);
CSETw(x1, cEQ);
BFIw(xFlags, x1, F_ZF, 1); // ZF = is dest 0?
break;
case 0xC2:
INST_NAME("CMPSS Gx, Ex, Ib");
nextop = F8;
@@ -282,6 +367,30 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VMOVQSfrom(v0, 0, x2);
break;
case 0xD6:
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX_empty(v0);
if(MODREG) {
v1 = mmx_get_reg(dyn, ninst, x1, (nextop&7));
VEORQ(v0, v0, v0); // usefull?
VMOV(v0, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
VLDR64_U12(v0, ed, fixedaddress);
}
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
d0 = fpu_get_scratch(dyn);
SXTL_32(v0, v1);
SCVTQFD(v0, v0); // there is only I64 -> Double vector conversion, not from i32
break;
default:
DEFAULT;
}
+154 -35
View File
@@ -140,6 +140,125 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
return addr;
}
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
{
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
if(hint>0) ret = hint;
if(hint>0 && hint<xRAX) scratch = hint;
int absmin = 0;
if(s) absmin=-absmax;
MAYUSE(scratch);
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = F8;
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
if((sib&0x7)==5) {
uint32_t tmp = F32;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
MOV32w(scratch, tmp);
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
*fixaddress = tmp;
}
} else {
MOV32w(ret, tmp);
}
} else {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x7)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x7)+(rex.b<<3);
}
}
} else if((nextop&7)==5) {
uint32_t tmp = F32;
MOV32w(ret, tmp);
GETIP(addr+delta);
ADDw_REG(ret, ret, xRIP);
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
if(ret==hint) {
MOVw_REG(hint, ret); //to clear upper part
}
}
} else {
int64_t i64;
uint8_t sib = 0;
int sib_reg = 0;
if((nextop&7)==4) {
sib = F8;
sib_reg = ((sib>>3)&7)+(rex.x<<3);
}
if(nextop&0x80)
i64 = F32S;
else
i64 = F8S;
if(i64==0 || ((i64>=absmin) && (i64<=absmax) && !(i64&mask))) {
*fixaddress = i64;
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(ret, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
ret = xRAX+(sib&0x07)+(rex.b<<3);
}
} else {
ret = xRAX+(nextop&0x07)+(rex.b<<3);
}
} else {
int64_t sub = (i64<0)?1:0;
if(sub) i64 = -i64;
if(i64<0x1000) {
if((nextop&7)==4) {
if (sib_reg!=4) {
ADDw_REG_LSL(scratch, xRAX+(sib&0x07)+(rex.b<<3), xRAX+sib_reg, (sib>>6));
} else {
scratch = xRAX+(sib&0x07)+(rex.b<<3);
}
} else
scratch = xRAX+(nextop&0x07)+(rex.b<<3);
if(sub) {
SUBw_U12(ret, scratch, i64);
} else {
ADDw_U12(ret, scratch, i64);
}
} else {
MOV32w(scratch, i64);
if((nextop&7)==4) {
if (sib_reg!=4) {
if(sub) {
SUBw_REG(scratch, xRAX+(sib&0x07)+(rex.b<<3), scratch);
} else {
ADDw_REG(scratch, scratch, xRAX+(sib&0x07)+(rex.b<<3));
}
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
PASS3(int tmp = xRAX+(sib&0x07)+(rex.b<<3));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
} else {
PASS3(int tmp = xRAX+(nextop&0x07)+(rex.b<<3));
if(sub) {
SUBw_REG(ret, tmp, scratch);
} else {
ADDw_REG(ret, tmp, scratch);
}
}
}
}
}
*ed = ret;
return addr;
}
/* setup r2 to address pointed by ED, r3 as scratch also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s)
{
@@ -263,7 +382,7 @@ void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
#ifdef HAVE_TRACE
//MOVx(x2, 15); no access to PC reg
#endif
BR(x3);
BLR(x3); // save LR...
}
void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
@@ -281,7 +400,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst)
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
MOVx_REG(x1, xRIP);
BR(x2);
BLR(x2); // save LR
}
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
@@ -305,7 +424,7 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n)
UBFXx(x3, xRIP, 0, JMPTABL_SHIFT);
LDRx_REG_LSL3(x2, x2, x3);
MOVx_REG(x1, xRIP);
BR(x2);
BLR(x2); // save LR
}
void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
@@ -415,22 +534,22 @@ void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
MESSAGE(LOG_DUMP, "\tSynch x87 Stackcount (%d)\n", dyn->x87stack);
int a = dyn->x87stack;
// Add x87stack to emu fpu_stack
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDx_U12(scratch, scratch, a);
ADDw_U12(scratch, scratch, a);
} else {
SUBx_U12(scratch, scratch, -a);
SUBw_U12(scratch, scratch, -a);
}
STRx_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
STRw_U12(scratch, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
LDRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
if(a>0) {
SUBx_U12(scratch, scratch, a);
SUBw_U12(scratch, scratch, a);
} else {
ADDx_U12(scratch, scratch, -a);
ADDw_U12(scratch, scratch, -a);
}
ADDx_U12(scratch, scratch, 7);
STRx_U12(scratch, xEmu, offsetof(x64emu_t, top));
ANDw_mask(scratch, scratch, 0, 2); //mask=7
STRw_U12(scratch, xEmu, offsetof(x64emu_t, top));
// reset x87stack
dyn->x87stack = 0;
MESSAGE(LOG_DUMP, "\t------x87 Stackcount\n");
@@ -483,7 +602,7 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst)
#endif
}
static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
int ret = 0;
@@ -498,15 +617,15 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
// reset x87stack
dyn->x87stack = 0;
// Add x87stack to emu fpu_stack
LDRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
if(a>0) {
ADDx_U12(s2, s2, a);
ADDw_U12(s2, s2, a);
} else {
SUBx_U12(s2, s2, -a);
SUBw_U12(s2, s2, -a);
}
STRx_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
STRw_U12(s2, xEmu, offsetof(x64emu_t, fpu_stack));
// Sub x87stack to top, with and 7
LDRx_U12(s2, xEmu, offsetof(x64emu_t, top));
LDRw_U12(s2, xEmu, offsetof(x64emu_t, top));
// update tags (and top at the same time)
if(a>0) {
// new tag to fulls
@@ -514,7 +633,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
ADDx_U12(s1, xEmu, offsetof(x64emu_t, p_regs));
for (int i=0; i<a; ++i) {
SUBw_U12(s2, s2, 1);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + st)&7
STRw_REG_LSL2(s3, s1, s2);
}
} else {
@@ -524,7 +643,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
for (int i=0; i<-a; ++i) {
STRw_REG_LSL2(s3, s1, s2);
ADDw_U12(s2, s2, 1);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + st)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + st)&7
}
}
STRw_U12(s2, xEmu, offsetof(x64emu_t, top));
@@ -540,7 +659,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1) {
ADDw_U12(s3, s2, dyn->x87cache[i]);
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + st)&7
ANDw_mask(s3, s3, 0, 2); //mask=7 // (emu->top + st)&7
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
fpu_free_reg(dyn, dyn->x87reg[i]);
dyn->x87reg[i] = -1;
@@ -569,8 +688,8 @@ static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]!=-1) {
ADDw_U12(s3, s2, dyn->x87cache[i]);
ANDw_mask(s3, s3, 0b011111, 1); // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s3);
ANDw_mask(s3, s3, 0, 2); // mask=7 // (emu->top + i)&7
VSTR64_REG_LSL3(dyn->x87reg[i], s1, s3);
}
#endif
}
@@ -601,7 +720,7 @@ int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1);
ANDw_mask(s2, s2, 0, 2); //mask=7
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
@@ -640,7 +759,7 @@ void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// Update
if(st) {
ADDw_U12(s2, s2, st);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
@@ -665,9 +784,9 @@ void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
// Update
if(st) {
ADDw_U12(s2, s2, st);
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
}
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
VSTR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t--------x87 Cache for ST%d\n", st);
// and forget that cache
fpu_free_reg(dyn, dyn->x87reg[ret]);
@@ -692,7 +811,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[i], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
// ok
@@ -716,7 +835,7 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
} else {
ADDw_U12(s2, s2, a);
}
ANDw_mask(s2, s2, 0b011111, 1); // (emu->top + i)&7
ANDw_mask(s2, s2, 0, 2); //mask=7 // (emu->top + i)&7
VLDR64_REG_LSL3(dyn->x87reg[ret], s1, s2);
MESSAGE(LOG_DUMP, "\t-------x87 Cache for ST%d\n", st);
#endif
@@ -731,10 +850,10 @@ int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
UBFXx(s2, s1, 10, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
MRS_fpcr(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
MSR_fpcr(s1); // put new fpscr
return s3;
}
@@ -745,17 +864,17 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
UBFXx(s2, s1, 13, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
MRS_fpcr(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
MSR_fpcr(s1); // put new fpscr
return s3;
}
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1)
{
VMSR(s1); // put back fpscr
MSR_fpcr(s1); // put back fpscr
}
// MMX helpers
@@ -792,7 +911,7 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
#endif
}
// purge the MMX cache only(needs 3 scratch registers)
static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int old = -1;
+48 -11
View File
@@ -211,7 +211,7 @@
gb1 = xRAX+(gd&3); \
} \
gd = i; \
UBFXx(gd, gb1, gb2, 8);
UBFXx(gd, gb1, gb2*8, 8);
//GETSGB signe extend GB, will use i for gd
#define GETSGB(i) if(rex.rex) { \
gb1 = xRAX+((nextop&0x38)>>3)+(rex.r<<3); \
@@ -264,6 +264,10 @@
#define B_MARK_nocond \
j32 = GETMARK-(dyn->arm_size); \
B(j32)
// Branch to MARK if reg is 0 (use j32)
#define CBZxw_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
CBZxw(reg, j32)
// Branch to MARK if reg is not 0 (use j32)
#define CBNZx_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
@@ -324,6 +328,10 @@
#define CBZx_NEXT(reg) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZx(reg, j32)
// Test bit N of A and branch to next instruction if not set
#define TBZ_NEXT(A, N) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
TBZ(A, N, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
j32 = GETMARKSEG-(dyn->arm_size); \
@@ -346,6 +354,7 @@
CBNZx(reg, j32)
#define IFX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A)))
#define IFX_PENDOR0 if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(X_PEND) || !dyn->insts[ninst].x64.need_flags))
#define IFXX(A) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A)))
#define IFX2X(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags==(A) || dyn->insts[ninst].x64.need_flags==(B) || dyn->insts[ninst].x64.need_flags==((A)|(B))))
#define IFXN(A, B) if(dyn->insts && (dyn->insts[ninst].x64.need_flags&(A) && !(dyn->insts[ninst].x64.need_flags&(B))))
@@ -353,8 +362,8 @@
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2, s3) \
LDRH_U12(s3, xEmu, offsetof(x64emu_t, sw)); /*offset is 8bits right?*/\
MOV32w(s1, 0b01000111); \
BICw_REG_LSL(s3, s3, s1, 8); \
MOV32w(s1, 0b0100011100000000); \
BICw_REG(s3, s3, s1); \
CSETw(s1, cMI); /* 1 if less than, 0 else */ \
MOV32w(s2, 0b01000101); /* unordered */ \
CSELw(s1, s2, s1, cVS); \
@@ -390,6 +399,7 @@
#define STORE_REG(A) STRx_U12(x##A, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STP_REGS(A, B) STPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STORE_XEMU_REGS(A) \
STORE_REG(RAX); \
STORE_REG(RCX); \
@@ -445,7 +455,13 @@
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); \
if(A) {STRx_U12(A, xEmu, offsetof(x64emu_t, ip));}
// Need to also store current value of some register, as they may be used by functions like setjump
// so RBX, RSP, RBP, R12..R15 (other are scratch or parameters), R10-R11 not usefull, but why not
// RBX, RSP and RBP are already saved in call function
#define STORE_XEMU_CALL(A) \
STP_REGS(R10, R11); \
STP_REGS(R12, R13); \
STP_REGS(R14, R15); \
if(A) {STPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
else {STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}
@@ -503,6 +519,9 @@
#ifndef TABLE64
#define TABLE64(A, V)
#endif
#ifndef FTABLE64
#define FTABLE64(A, V)
#endif
#if STEP < 2
#define GETIP(A)
@@ -518,14 +537,20 @@
} \
} else { \
dyn->last_ip = (A); \
TABLE64(xRIP, dyn->last_ip); \
if(dyn->last_ip<0xffffffff) { \
MOV64x(xRIP, dyn->last_ip); \
} else \
TABLE64(xRIP, dyn->last_ip); \
}
#define GETIP_(A) \
if(dyn->last_ip && ((A)-dyn->last_ip)<0x1000) { \
uint64_t _delta_ip = (A)-dyn->last_ip; \
if(_delta_ip) {ADDx_U12(xRIP, xRIP, _delta_ip);}\
} else { \
TABLE64(xRIP, (A)); \
if((A)<0xffffffff) { \
MOV64x(xRIP, (A)); \
} else \
TABLE64(xRIP, (A)); \
}
#endif
@@ -566,10 +591,12 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define dynarec64_DF STEPNAME(dynarec64_DF)
#define dynarec64_F0 STEPNAME(dynarec64_F0)
#define dynarec64_660F STEPNAME(dynarec64_660F)
#define dynarec64_6664 STEPNAME(dynarec64_6664)
#define dynarec64_F20F STEPNAME(dynarec64_F20F)
#define dynarec64_F30F STEPNAME(dynarec64_F30F)
#define geted STEPNAME(geted_)
#define geted32 STEPNAME(geted32_)
#define geted16 STEPNAME(geted16_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_next STEPNAME(jump_to_next_)
@@ -672,6 +699,8 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
#define fpu_popcache STEPNAME(fpu_popcache)
#define fpu_reset STEPNAME(fpu_reset)
#define fpu_purgecache STEPNAME(fpu_purgecache)
#define mmx_purgecache STEPNAME(mmx_purgecache)
#define x87_purgecache STEPNAME(x87_purgecache)
#ifdef HAVE_TRACE
#define fpu_reflectcache STEPNAME(fpu_reflectcache)
#endif
@@ -679,6 +708,9 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr);
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
/* setup r2 to address pointed by */
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, int absmax, uint32_t mask, int s);
@@ -808,28 +840,33 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_reset(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// purge MMX cache
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1);
// purge x87 cache
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
//uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_D8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_D9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DA(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
//uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_DF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_6664(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog);
+35 -3
View File
@@ -25,22 +25,25 @@
#error No STEP defined
#endif
void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
int ok = 1;
int ninst = 0;
uintptr_t ip = addr;
uintptr_t init_addr = addr;
rex_t rex;
int rep; // 0 none, 1=F2 prefix, 2=F3 prefix
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
dyn->dfnone = 0;
dyn->last_ip = ip; // RIP is always set at start of block!
MAYUSE(init_addr);
fpu_reset(dyn, ninst);
// ok, go now
INIT;
while(ok) {
if(dyn->insts && (ninst>dyn->size)) {dynarec_log(LOG_NONE, "Warning, too many inst treated (%d / %d)\n",ninst, dyn->size);}
ip = addr;
if(dyn->insts && (dyn->insts[ninst].x64.barrier==1)) {
dyn->last_ip = 0;
@@ -65,7 +68,21 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
#endif
addr = dynarec64_00(dyn, addr, ip, ninst, &ok, &need_epilog);
rep = 0;
uint8_t pk = PK(0);
while((pk==0xF2) || (pk==0xF3)) {
rep = pk-0xF1;
++addr;
pk = PK(0);
}
rex.rex = 0;
while(pk>=0x40 && pk<=0x4f) {
rex.rex = pk;
++addr;
pk = PK(0);
}
addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog);
INST_EPILOG;
@@ -94,6 +111,20 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
if(ok && !isJumpTableDefault64((void*)addr))
#else
if(ok && dyn->insts && (ninst==dyn->size))
#endif
{
#if STEP == 3
dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
#endif
BARRIER(2);
fpu_purgecache(dyn, ninst, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
}
}
if(need_epilog) {
fpu_purgecache(dyn, ninst, x1, x2, x3);
@@ -101,4 +132,5 @@ void arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
return addr;
}
+2 -1
View File
@@ -7,4 +7,5 @@
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
#define TABLE64(A, V) if((V)>0xffffffffLL) {Table64(dyn, (V)); EMIT(0);} else {MOV64x(A, V);}
#define TABLE64(A, V) {Table64(dyn, (V)); EMIT(0);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; Table64(dyn, v.q); EMIT(0);}
+2 -1
View File
@@ -32,4 +32,5 @@
++dyn->sons_size; \
}
#define TABLE64(A, V) if((V)>0xffffffffLL) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);} else {MOV64x(A, V);}
#define TABLE64(A, V) {int val64offset = Table64(dyn, (V)); MESSAGE(LOG_DUMP, " Table64: 0x%lx\n", (V)); LDRx_literal(A, val64offset);}
#define FTABLE64(A, V) {mmx87_regs_t v = {.d = V}; int val64offset = Table64(dyn, v.q); MESSAGE(LOG_DUMP, " FTable64: %g\n", v.d); VLDR64_literal(A, val64offset);}
+1
View File
@@ -42,6 +42,7 @@ typedef struct dynarec_arm_s {
int dfnone; // if defered flags is already set to df_none
uint64_t *table64; // table of 64bits value
int table64size;// size of table (will be appended at end of executable code)
int table64cap;
uintptr_t tablestart;
uintptr_t* next; // variable array of "next" jump address
int next_sz;
+1 -1
View File
@@ -351,7 +351,7 @@ void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name)
const char* elfname = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
for (int i = 0; i<cnt; ++i)
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=%ld\n", elfname,
printf_log(LOG_DUMP, " %s:RelA[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname,
i, (void*)rela[i].r_offset, rela[i].r_info, DumpRelType(ELF64_R_TYPE(rela[i].r_info)),
ELF64_R_SYM(rela[i].r_info), IdxSymName(h, ELF64_R_SYM(rela[i].r_info)),
rela[i].r_addend);
+58 -28
View File
@@ -106,7 +106,7 @@ int CalcLoadAddr(elfheader_t* head)
}
head->stacksz = 1024*1024; //1M stack size default?
head->stackalign = 4; // default align for stack
head->stackalign = 16; // default align for stack
for (int i=0; i<head->numPHEntries; ++i) {
if(head->PHEntries[i].p_type == PT_LOAD) {
uintptr_t phend = head->PHEntries[i].p_vaddr - head->vaddr + head->PHEntries[i].p_memsz;
@@ -147,7 +147,7 @@ int AllocElfMemory(box64context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
if(mainbin && head->vaddr==0) {
char* load_addr = getenv("BOX86_LOAD_ADDR");
char* load_addr = getenv("BOX64_LOAD_ADDR");
if(load_addr)
if(sscanf(load_addr, "0x%lx", &offs)!=1)
offs = 0;
@@ -355,7 +355,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
if(!h)
return 0;
Elf64_Rela * rel = (Elf64_Rela *)(h->rela + h->delta);
if(!h->rel)
if(!h->rela)
return 0;
int cnt = h->relasz / h->relaent;
for (int i=0; i<cnt; ++i) {
@@ -364,7 +364,7 @@ int FindR64COPYRel(elfheader_t* h, const char* name, uintptr_t *offs, uint64_t**
const char* symname = SymName(h, sym);
if(!strcmp(symname, name) && t==R_X86_64_COPY) {
*offs = sym->st_value + h->delta;
*p = (uint64_t*)(rel[i].r_offset + h->delta);
*p = (uint64_t*)(rel[i].r_offset + h->delta + rel[i].r_addend);
return 1;
}
}
@@ -552,14 +552,17 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
uintptr_t globoffs, globend;
uint64_t* globp;
uintptr_t tmp = 0;
intptr_t delta;
switch(ELF64_R_TYPE(rela[i].r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_PC32:
// should be "S + A - P" with S=symbol offset, A=addend and P=place of the storage unit, write a word32
// can be ignored
break;
case R_X86_64_RELATIVE:
printf_log(LOG_DUMP, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
*p += head->delta;
printf_log(LOG_DUMP, "Apply %s R_X86_64_RELATIVE @%p (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)(head->delta+ rela[i].r_addend));
*p = head->delta+ rela[i].r_addend;
break;
case R_X86_64_COPY:
if(!strcmp(symname, "stdin") || !strcmp(symname, "stdout") || !strcmp(symname, "stderr")) {
@@ -577,7 +580,8 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
if(offs) {
// add r_addend to p?
printf_log(LOG_DUMP, "Apply R_X86_64_COPY @%p with sym=%s, @%p size=%ld\n", p, symname, (void*)offs, sym->st_size);
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
if(p!=(void*)(offs+rela[i].r_addend))
memmove(p, (void*)(offs+rela[i].r_addend), sym->st_size);
} else {
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply RELA R_X86_64_COPY @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
@@ -587,8 +591,11 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
// set global offs / size for the symbol
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n", (bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0), (void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
*p = globoffs + rela[i].r_addend;
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT with R_X86_64_COPY @%p/%p (%p/%p -> %p/%p) size=%ld on sym=%s \n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname);
memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
*p = globoffs/* + rela[i].r_addend*/; //no addend?
AddWeakSymbol(GetGlobalData(maplib), symname, offs, end-offs+1);
} else {
// Look for same symbol already loaded but not in self (so no need for local_maplib here)
@@ -601,7 +608,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_X86_64_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
printf_log(LOG_DUMP, "Apply %s R_X86_64_GLOB_DAT @%p (%p -> %p) on sym=%s\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname);
*p = offs + rela[i].r_addend;
*p = offs/* + rela[i].r_addend*/; // not addend it seems
}
}
break;
@@ -623,14 +630,16 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
// return -1;
} else {
if(p) {
printf_log(LOG_DUMP, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
printf_log(LOG_DUMP, "Apply %s R_X86_64_JUMP_SLOT @%p with sym=%s (%p -> %p)\n",
(bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(offs+rela[i].r_addend));
*p = offs + rela[i].r_addend;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
printf_log(LOG_DUMP, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend);
printf_log(LOG_DUMP, "Preparing (if needed) %s R_X86_64_JUMP_SLOT @%p (0x%lx->0x%0lx) with sym=%s to be apply later (addend=%ld)\n",
(bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, rela[i].r_addend);
*p += head->delta;
}
break;
@@ -639,8 +648,29 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, elfheader_t* head, int c
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_X86_64_64 @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
// return -1;
} else {
printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s addend=0x%lx (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend+*(uint64_t*)p));
*p += offs+rela[i].r_addend;
printf_log(LOG_DUMP, "Apply %s R_X86_64_64 @%p with sym=%s addend=0x%lx (%p -> %p)\n",
(bind==STB_LOCAL)?"Local":"Global", p, symname, rela[i].r_addend, *(void**)p, (void*)(offs+rela[i].r_addend/*+*(uint64_t*)p*/));
*p /*+*/= offs+rela[i].r_addend;
}
break;
case R_X86_64_TPOFF64:
// Negated offset in static TLS block
{
if(h_tls)
offs = sym->st_value;
else {
if(local_maplib)
h_tls = GetGlobalSymbolElf(local_maplib, symname);
if(!h_tls)
h_tls = GetGlobalSymbolElf(maplib, symname);
}
if(h_tls) {
delta = *(int64_t*)p;
printf_log(LOG_DUMP, "Applying %s %s on %s @%p (%ld -> %ld)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, (int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
*p = (uintptr_t)((int64_t)offs + rela[i].r_addend + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%ld), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int64_t)offs);
}
}
break;
case R_X86_64_DTPMOD64:
@@ -755,7 +785,7 @@ Elf64_Sym* GetFunction(elfheader_t* h, const char* name)
// TODO: create a hash on named to avoid this loop
for (int i=0; i<h->numSymTab; ++i) {
int type = ELF64_ST_TYPE(h->SymTab[i].st_info);
if(/*h->SymTab[i].st_info == 18*/type==STT_FUNC) { // TODO: this "18" is probably defined somewhere
if(type==STT_FUNC) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
if(strcmp(symname, name)==0) {
return h->SymTab+i;
@@ -890,7 +920,7 @@ $PLATFORM – Expands to the processor type of the current machine (see the
uname(1) man page description of the -i option). For more details of this token
expansion, see “System Specific Shared Objects”
*/
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int local, box64context_t *box64, x64emu_t* emu)
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu)
{
DumpDynamicRPath(h);
// update RPATH first
@@ -927,9 +957,9 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
free(origin);
}
if(strchr(rpath, '$')) {
printf_log(LOG_INFO, "BOX86: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
printf_log(LOG_INFO, "BOX64: Warning, RPATH with $ variable not supported yet (%s)\n", rpath);
} else {
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX86_LD_LIBRARY_PATH\n", rpath);
printf_log(LOG_DEBUG, "Prepending path \"%s\" to BOX64_LD_LIBRARY_PATH\n", rpath);
PrependList(&box64->box64_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
@@ -943,8 +973,8 @@ int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, int
for (int i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
char *needed = h->DynStrTab+h->delta+h->Dynamic[i].d_un.d_val;
// TODO: Add LD_LIBRARY_PATH and RPATH Handling
if(AddNeededLib(maplib, neededlibs, local, needed, box64, emu)) {
// TODO: Add LD_LIBRARY_PATH and RPATH handling
if(AddNeededLib(maplib, neededlibs, deplib, local, needed, box64, emu)) {
printf_log(LOG_INFO, "Error loading needed lib: \"%s\"\n", needed);
if(!allow_missing_libs)
return 1; //error...
@@ -1026,7 +1056,7 @@ void RunElfFini(elfheader_t* h, x64emu_t *emu)
h->fini_done = 1;
// first check fini array
Elf64_Addr *addr = (Elf64_Addr*)(h->finiarray + h->delta);
for (int i=0; i<h->finiarray_sz; ++i) {
for (int i=h->finiarray_sz-1; i>=0; --i) {
printf_log(LOG_DEBUG, "Calling Fini[%d] for %s @%p\n", i, ElfName(h), (void*)addr[i]);
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 0);
}
@@ -1094,7 +1124,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
const char* ret = NULL;
uintptr_t s = 0;
uint32_t size = 0;
if(!h)
if(!h || h->fini_done)
return ret;
for (int i=0; i<h->numSymTab && distance!=0; ++i) {
@@ -1132,7 +1162,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
return ret;
}
void* GetDTatOffset(box64context_t* context, int index, int offset)
void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset)
{
return (void*)((char*)GetTLSPointer(context, context->elfs[index])+offset);
}
@@ -1187,7 +1217,7 @@ typedef struct my_dl_phdr_info_s {
void* dlpi_addr;
const char* dlpi_name;
Elf64_Phdr* dlpi_phdr;
int dlpi_phnum;
Elf64_Half dlpi_phnum;
} my_dl_phdr_info_t;
static int dl_iterate_phdr_callback(x64emu_t *emu, void* F, my_dl_phdr_info_t *info, size_t size, void* data)
@@ -1232,7 +1262,7 @@ static void* find_dl_iterate_phdr_Fct(void* fct)
#undef SUPER
EXPORT int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data) {
printf_log(LOG_INFO, "Warning: call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
printf_log(LOG_DEBUG, "Call to partially implemented dl_iterate_phdr(%p, %p)\n", F, data);
box64context_t *context = GetEmuContext(emu);
const char* empty = "";
int ret = 0;
@@ -1261,17 +1291,17 @@ void ResetSpecialCaseMainElf(elfheader_t* h)
if(strcmp(symname, "_IO_2_1_stderr_")==0 && ((void*)sym->st_value+h->delta)) {
memcpy((void*)sym->st_value+h->delta, stderr, sym->st_size);
my__IO_2_1_stderr_ = (void*)sym->st_value+h->delta;
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stderr_ to %p\n", my__IO_2_1_stderr_);
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stderr_ to %p\n", my__IO_2_1_stderr_);
} else
if(strcmp(symname, "_IO_2_1_stdin_")==0 && ((void*)sym->st_value+h->delta)) {
memcpy((void*)sym->st_value+h->delta, stdin, sym->st_size);
my__IO_2_1_stdin_ = (void*)sym->st_value+h->delta;
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stdin_ to %p\n", my__IO_2_1_stdin_);
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stdin_ to %p\n", my__IO_2_1_stdin_);
} else
if(strcmp(symname, "_IO_2_1_stdout_")==0 && ((void*)sym->st_value+h->delta)) {
memcpy((void*)sym->st_value+h->delta, stdout, sym->st_size);
my__IO_2_1_stdout_ = (void*)sym->st_value+h->delta;
printf_log(LOG_DEBUG, "BOX86: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
printf_log(LOG_DEBUG, "BOX64: Set @_IO_2_1_stdout_ to %p\n", my__IO_2_1_stdout_);
}
}
}
+6 -1
View File
@@ -71,8 +71,13 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
return NULL;
}
if(header.e_ident[EI_CLASS]!=ELFCLASS64) {
if(strstr(name, ".so")) {
// less naging on libs...
printf_log(LOG_DEBUG, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
return NULL;
}
if(header.e_ident[EI_CLASS]==ELFCLASS32) {
printf_log(LOG_INFO, "This is a 32bits ELF! box64 can only run 64bits ELF!\n");
printf_log(LOG_INFO, "This is a 32bits ELF! box64 can only run 64bits ELF (%s)!\n", name);
} else {
printf_log(LOG_INFO, "Not a 64bits ELF (%d)\n", header.e_ident[EI_CLASS]);
}
+4
View File
@@ -18,12 +18,16 @@
#define GETED_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGD opgd=GetGd(emu, rex, nextop)
#define GETEB(D) oped=GetEb(emu, rex, nextop, D)
#define GETEB32(D) oped=GetEb32O(emu, rex, nextop, D, 0)
#define GETEB_OFFS(D, O) oped=GetEbO(emu, rex, nextop, D, O)
#define GETGB opgd=GetGb(emu, rex, nextop)
#define GETEW(D) oped=GetEw(emu, rex, nextop, D)
#define GETEW32(D) oped=GetEw32O(emu, rex, nextop, D, 0)
#define GETEW_OFFS(D, O) oped=GetEdO(emu, rex, nextop, D, O)
#define GETGW opgd=GetGw(emu, rex, nextop)
#define GETEX(D) opex=GetEx(emu, rex, nextop, D)
#define GETEX32(D) opex=GetEx32O(emu, rex, nextop, D, 0)
#define GETEX_OFFS(D, O) opex=GetExO(emu, rex, nextop, D, O)
#define GETGX opgx=GetGx(emu, rex, nextop)
#define GETEM(D) opem=GetEm(emu, rex, nextop, D)
#define GETGM opgm=GetGm(emu, rex, nextop)
+50 -17
View File
@@ -5,6 +5,7 @@
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/mman.h>
#include "debug.h"
#include "box64stack.h"
@@ -16,6 +17,9 @@
#include "x64run_private.h"
#include "callback.h"
#include "bridge.h"
#ifdef HAVE_TRACE
#include "x64trace.h"
#endif
#ifdef DYNAREC
#include "custommem.h"
#endif
@@ -107,6 +111,7 @@ void SetupX64Emu(x64emu_t *emu)
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
}
#ifdef HAVE_TRACE
void SetTraceEmu(uintptr_t start, uintptr_t end)
{
if(my_context->zydis) {
@@ -121,6 +126,7 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
trace_start = start;
trace_end = end;
}
#endif
void AddCleanup(x64emu_t *emu, void *p)
{
@@ -173,7 +179,8 @@ void CallAllCleanup(x64emu_t *emu)
static void internalFreeX64(x64emu_t* emu)
{
free(emu->stack2free);
if(emu && emu->stack2free)
munmap(emu->stack2free, emu->size_stack);
}
EXPORTDYN
@@ -311,6 +318,10 @@ uint64_t GetRSP(x64emu_t *emu)
{
return R_RSP;
}
uint64_t GetRBP(x64emu_t *emu)
{
return R_RBP;
}
void SetFS(x64emu_t *emu, uint16_t v)
{
emu->segs[_FS] = v;
@@ -329,12 +340,13 @@ void ResetFlags(x64emu_t *emu)
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
{
static char buff[1000];
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
char* regname[] = {"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI",
" R8", " R9", "R10", "R11", "R12", "R13", "R14", "R15"};
char tmp[160];
buff[0] = '\0';
#ifdef HAVE_TRACE
if(trace_emm) {
// do emm reg is needed
// do emm reg if needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "mm%d:%016lx", i, emu->mmx87[i].q);
strcat(buff, tmp);
@@ -342,13 +354,14 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
}
}
if(trace_xmm) {
// do xmm reg is needed
// do xmm reg if needed
for(int i=0; i<8; ++i) {
sprintf(tmp, "%d:%016lx%016lx", i, emu->xmm[i].q[1], emu->xmm[i].q[0]);
strcat(buff, tmp);
if ((i&3)==3) strcat(buff, "\n"); else strcat(buff, " ");
}
}
#endif
// start with FPU regs...
if(emu->fpu_stack) {
for (int i=0; i<emu->fpu_stack; i++) {
@@ -362,19 +375,28 @@ const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip)
strcat(buff, "\n");
}
for (int i=_AX; i<=_R15; ++i) {
#ifdef HAVE_TRACE
if (trace_regsdiff && (emu->regs[i].q[0] != emu->oldregs[i].q[0])) {
sprintf(tmp, "\e[1;35m%s=%016lx\e[m ", regname[i], emu->regs[i].q[0]);
emu->oldregs[i].q[0] = emu->regs[i].q[0];
} else {
sprintf(tmp, "%s=%016lx ", regname[i], emu->regs[i].q[0]);
}
#else
sprintf(tmp, "%s=%016lx ", regname[i], emu->regs[i].q[0]);
#endif
strcat(buff, tmp);
if (i%5==4) {
if(i==4) {
if(emu->df) {
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "?"
sprintf(tmp, "flags=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
sprintf(tmp, "flags=%s%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(D), FLAG_CHAR(S), FLAG_CHAR(Z), FLAG_CHAR(A), FLAG_CHAR(P), FLAG_CHAR(C));
strcat(buff, tmp);
#undef FLAG_CHAR
} else {
#define FLAG_CHAR(f) (ACCESS_FLAG(F_##f##F)) ? #f : "-"
sprintf(tmp, "FLAGS=%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(C), FLAG_CHAR(P), FLAG_CHAR(A), FLAG_CHAR(Z), FLAG_CHAR(S));
sprintf(tmp, "FLAGS=%s%s%s%s%s%s%s\n", FLAG_CHAR(O), FLAG_CHAR(D), FLAG_CHAR(S), FLAG_CHAR(Z), FLAG_CHAR(A), FLAG_CHAR(P), FLAG_CHAR(C));
strcat(buff, tmp);
#undef FLAG_CHAR
}
@@ -393,8 +415,19 @@ void StopEmu(x64emu_t* emu, const char* reason)
emu->quit = 1;
printf_log(LOG_NONE, "%s", reason);
// dump stuff...
printf_log(LOG_NONE, "CPU Regs=%s\n", DumpCPURegs(emu, R_RIP));
// TODO: stack, memory/instruction around EIP, etc..
printf_log(LOG_NONE, "==== CPU Registers ====\n%s\n", DumpCPURegs(emu, R_RIP));
printf_log(LOG_NONE, "======== Stack ========\nStack is from %lX to %lX\n", R_RBP, R_RSP);
if (R_RBP == R_RSP) {
printf_log(LOG_NONE, "RBP = RSP: leaf function detected; next 128 bytes should be either data or random.\n");
} else {
// TODO: display stack if operation should be allowed (to avoid crashes)
/* for (uint64_t *sp = R_RBP; sp >= R_RSP; --sp) {
} */
}
printf_log(LOG_NONE, "Old IP: %tX\n", emu->old_ip);
#ifdef HAVE_TRACE
printf_log(LOG_NONE, "%s\n", DecodeX64Trace(my_context->dec, emu->old_ip));
#endif
}
void UnimpOpcode(x64emu_t* emu)
@@ -442,16 +475,16 @@ uint64_t ReadTSC(x64emu_t* emu)
{
//TODO: implement hardware counter read?
// Read the TimeStamp Counter as 64bits.
// this is supposed to be the number of instrunctions executed since last reset
// fall back to gettime...
// this is supposed to be the number of instructions executed since last reset
// fall back to gettime...
#ifndef NOGETCLOCK
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
#endif
}
@@ -460,4 +493,4 @@ void ResetSegmentsCache(x64emu_t *emu)
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
}
+2 -1
View File
@@ -52,6 +52,7 @@ typedef struct x64emu_s {
multiuint_t res;
uint32_t *x64emu_parity_tab; // helper
#ifdef HAVE_TRACE
reg64_t oldregs[16];
uintptr_t prev2_ip;
#endif
// segments
@@ -91,4 +92,4 @@ typedef struct x64emu_s {
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
#endif //__X86EMU_PRIVATE_H_
#endif //__X86EMU_PRIVATE_H_
+47 -1
View File
@@ -10,6 +10,7 @@
#include <sys/types.h>
#include <pthread.h>
#include <signal.h>
#include <poll.h>
#include "debug.h"
#include "box64stack.h"
@@ -100,12 +101,57 @@ void x64Int3(x64emu_t* emu)
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI), (int)(R_EDX));
perr = 1;
} else if(strstr(s, "mkdir")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (int)(R_ESI));
perr = 1;
} else if(strstr(s, "opendir")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
perr = 2;
} else if(strstr(s, "strlen")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
} else if(strstr(s, "strcmp")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", (char*)R_RSI);
} else if(!strcmp(s, "poll")) {
struct pollfd* pfd = (struct pollfd*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(%p[%d/%d/%d, ...], %d, %d)", tid, *(void**)(R_RSP), s, pfd, pfd->fd, pfd->events, pfd->revents, R_ESI, R_EDX);
} else if(strstr(s, "my___printf_chk")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, R_EDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
} else if(!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress")) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
} else if(!strcmp(s, "glGetStringi")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
post = 2;
} else if(!strcmp(s, "glFramebufferTexture2D")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, 0x%x, 0x%x, %u, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d);
} else if(!strcmp(s, "glTexSubImage2D")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
} else if(!strcmp(s, "glCompressedTexSubImage2D")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, %d, %d, %d, 0x%x, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, R_R9d, *(uint32_t*)(R_RSP+8), *(uint32_t*)(R_RSP+16), *(void**)(R_RSP+24));
} else if(!strcmp(s, "glVertexAttribPointer")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%u, %d, 0x%x, %d, %d, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, R_ECX, R_R8d, (void*)R_R9);
} else if(!strcmp(s, "glDrawElements")) {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, 0x%x, %p)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_EDX, (void*)R_RCX);
} else if(!strcmp(s, "glUniform4fv")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %d, %p[%g/%g/%g/%g...])", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, (void*)R_RDX, ((float*)(R_RDX))[0], ((float*)(R_RDX))[1], ((float*)(R_RDX))[2], ((float*)(R_RDX))[3]);
} else if(!strcmp(s, "mmap64") || !strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %lu, 0x%x, 0x%x, %d, %ld)", tid, *(void**)(R_RSP), s,
(void*)R_RDI, R_RSI, (int)(R_RDX), (int)R_RCX, (int)R_R8, R_R9);
} else if(!strcmp(s, "sscanf")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, (tmp)?tmp:"(nil)", (void*)(R_RDX));
} else if(!strcmp(s, "XCreateWindow")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %p, %d, %d, %u, %u, %u, %d, %u, %p, 0x%lx, %p)", tid, *(void**)(R_RSP), s,
(void*)R_RDI, (void*)R_RSI, (int)R_EDX, (int)R_ECX, R_R8d, R_R9d,
(uint32_t)*(uint64_t*)(R_RSP+8), (int)*(uint64_t*)(R_RSP+16),
(uint32_t)*(uint64_t*)(R_RSP+24), (void*)*(uint64_t*)(R_RSP+32),
(unsigned long)*(uint64_t*)(R_RSP+40), (void*)*(uint64_t*)(R_RSP+48));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s(0x%lX, 0x%lX, 0x%lX, ...)", tid, *(void**)(R_RSP), s, R_RDI, R_RSI, R_RDX);
}
@@ -143,7 +189,7 @@ void x64Int3(x64emu_t* emu)
}
return;
}
if(my_context->signals[SIGTRAP])
if(0 && my_context->signals[SIGTRAP])
raise(SIGTRAP);
else
printf_log(LOG_INFO, "%04d|Warning, ignoring unsupported Int 3 call @%p\n", GetTID(), (void*)R_RIP);
+1 -1
View File
@@ -96,7 +96,7 @@
*
****************************************************************************/
// This has been heavily modified to fit box86 purpose...
// This has been heavily modified to fit box64 purpose...
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-4
View File
@@ -353,8 +353,6 @@ static inline uint16_t shr16(x64emu_t *emu, uint16_t d, uint8_t s)
static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
{
RESET_FLAGS(emu); // TODO: Defered this one?
emu->df = d_shr32;
emu->op1.u32 = d;
@@ -367,8 +365,6 @@ static inline uint32_t shr32(x64emu_t *emu, uint32_t d, uint8_t s)
static inline uint64_t shr64(x64emu_t *emu, uint64_t d, uint8_t s)
{
RESET_FLAGS(emu); // TODO: Defered this one?
emu->df = d_shr64;
emu->op1.u64 = d;
+62 -12
View File
@@ -48,7 +48,7 @@ int Run(x64emu_t *emu, int step)
return 0;
//ref opcode: http://ref.x64asm.net/geek32.html#xA1
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, emu->context->stack);
printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, (void*)R_RSP);
x64emurun:
@@ -256,7 +256,7 @@ x64emurun:
goto fini;
break;
case 0x67: /* reduce EASize prefix */
if(Run67(emu, rex)) {
if(Run67(emu, rex, rep)) {
unimp = 1;
goto fini;
}
@@ -325,7 +325,7 @@ x64emurun:
tmp32s = F8S;
}
if(rex.w) {
tmp64u = (uint64_t)tmp32s;
tmp64u = (uint64_t)(int64_t)tmp32s;
switch((nextop>>3)&7) {
case 0: ED->q[0] = add64(emu, ED->q[0], tmp64u); break;
case 1: ED->q[0] = or64(emu, ED->q[0], tmp64u); break;
@@ -538,7 +538,37 @@ x64emurun:
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
break;
case 0x9E: /* SAHF */
tmp8u = emu->regs[_AX].byte[1];
CONDITIONAL_SET_FLAG(tmp8u&0x01, F_CF);
CONDITIONAL_SET_FLAG(tmp8u&0x04, F_PF);
CONDITIONAL_SET_FLAG(tmp8u&0x10, F_AF);
CONDITIONAL_SET_FLAG(tmp8u&0x40, F_ZF);
CONDITIONAL_SET_FLAG(tmp8u&0x80, F_SF);
RESET_FLAGS(emu);
break;
case 0x9F: /* LAHF */
CHECK_FLAGS(emu);
R_AH = (uint8_t)emu->eflags.x64;
break;
case 0xA0: /* MOV AL,Ob */
R_AL = *(uint8_t*)F64;
break;
case 0xA1: /* MOV EAX,Od */
if(rex.w)
R_RAX = *(uint64_t*)F64;
else
R_EAX = *(uint32_t*)F64;
break;
case 0xA2: /* MOV Ob,AL */
*(uint8_t*)F64 = R_AL;
break;
case 0xA3: /* MOV Od,EAX */
if(rex.w)
*(uint64_t*)F64 = R_RAX;
else
*(uint32_t*)F64 = R_EAX;
break;
case 0xA4: /* MOVSB */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
@@ -889,7 +919,6 @@ x64emurun:
else
emu->regs[(opcode&7)+(rex.b<<3)].q[0] = F32;
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GETEB(1);
@@ -1085,7 +1114,14 @@ x64emurun:
if(emu->quit)
goto fini;
break;
case 0xDC: /* x87 opcodes */
if(RunDC(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0xDD: /* x87 opcodes */
if(RunDD(emu, rex)) {
unimp = 1;
@@ -1094,7 +1130,14 @@ x64emurun:
if(emu->quit)
goto fini;
break;
case 0xDE: /* x87 opcodes */
if(RunDE(emu, rex)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0xDF: /* x87 opcodes */
if(RunDF(emu, rex)) {
unimp = 1;
@@ -1231,7 +1274,6 @@ x64emurun:
}
}
break;
case 0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
@@ -1274,14 +1316,22 @@ x64emurun:
case 0: /* INC Ed */
if(rex.w)
ED->q[0] = inc64(emu, ED->q[0]);
else
ED->q[0] = inc32(emu, ED->dword[0]);
else {
if(MODREG)
ED->q[0] = inc32(emu, ED->dword[0]);
else
ED->dword[0] = inc32(emu, ED->dword[0]);
}
break;
case 1: /* DEC Ed */
if(rex.w)
ED->q[0] = dec64(emu, ED->q[0]);
else
ED->q[0] = dec32(emu, ED->dword[0]);
else {
if(MODREG)
ED->q[0] = dec32(emu, ED->dword[0]);
else
ED->dword[0] = dec32(emu, ED->dword[0]);
}
break;
case 2: /* CALL NEAR Ed */
tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
+255 -26
View File
@@ -22,6 +22,7 @@
#include "bridge.h"
#include "signals.h"
#ifdef DYNAREC
#include "custommem.h"
#include "../dynarec/arm64_lock.h"
#endif
@@ -38,7 +39,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
uint64_t tmp64u, tmp64u2;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem, *opgm;
mmx87_regs_t *opem, *opgm, eam1;
opcode = F8;
@@ -104,6 +105,22 @@ int Run0F(x64emu_t *emu, rex_t rex)
GETGX;
EX->q[0] = GX->q[1];
break;
case 0x18: /* PREFETCHh Ed */
nextop = F8;
GETED(0);
if(MODREG) {
} else
switch((nextop>>3)&7) {
case 0: //PREFETCHnta
case 1: //PREFETCH1
case 2: //PREFETCH2
case 3: //PREFETCH3
__builtin_prefetch((void*)ED, 0, 0); // ignoring wich level of cache
break;
default: //NOP
break;
}
break;
case 0x1F: /* NOP (multi-byte) */
nextop = F8;
@@ -188,6 +205,75 @@ int Run0F(x64emu_t *emu, rex_t rex)
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0x31: /* RDTSC */
tmp64u = ReadTSC(emu);
R_RDX = tmp64u>>32;
R_RAX = tmp64u&0xFFFFFFFF;
break;
case 0x38: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: /* PSHUFB */
nextop = F8;
GETEM(0);
GETGM;
eam1 = *GM;
for (int i=0; i<8; ++i) {
if(EM->ub[i]&128)
GM->ub[i] = 0;
else
GM->ub[i] = eam1.ub[EM->ub[i]&7];
}
break;
case 0x04: /* PMADDUBSW Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<4; ++i) {
tmp32s = (int32_t)(GM->ub[i*2+0])*EM->sb[i*2+0] + (int32_t)(GM->ub[i*2+1])*EM->sb[i*2+1];
GM->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x0B: /* PMULHRSW Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<4; ++i) {
tmp32s = ((((int32_t)(GM->sw[i])*(int32_t)(EM->sw[i]))>>14) + 1)>>1;
GM->uw[i] = tmp32s&0xffff;
}
break;
case 0x1C: /* PABSB Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<8; ++i) {
GM->sb[i] = abs(EM->sb[i]);
}
break;
case 0x1D: /* PABSW Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<4; ++i) {
GM->sw[i] = abs(EM->sw[i]);
}
break;
case 0x1E: /* PABSD Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<2; ++i) {
GM->sd[i] = abs(EM->sd[i]);
}
break;
default:
return 1;
}
break;
GOCOND(0x40
, nextop = F8;
@@ -443,13 +529,103 @@ int Run0F(x64emu_t *emu, rex_t rex)
GM->sw[2+i] = (EM->sd[i]<-32768)?-32768:((EM->sd[i]>32767)?32767:EM->sd[i]);
break;
case 0x6E: /* MOVD Gm, Ed */
nextop = F8;
GETED(0);
GETGM;
if(rex.w)
GM->q = ED->q[0];
else
GM->q = ED->dword[0]; // zero extended
break;
case 0x6F: /* MOVQ Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
GM->q = EM->q;
break;
case 0x70: /* PSHUFW Gm, Em, Ib */
nextop = F8;
GETEM(1);
GETGM;
tmp8u = F8;
if(EM==GM) {eam1 = *GM; EM = &eam1;} // copy is needed
for(int i=0; i<4; ++i)
GM->uw[i] = EM->uw[(tmp8u>>(i*2))&3];
break;
case 0x71: /* GRP */
nextop = F8;
GETEM(1);
tmp8u = F8;
switch((nextop>>3)&7) {
case 2: /* PSRLW Em, Ib */
if(tmp8u>15)
{EM->q = 0;}
else
for (int i=0; i<4; ++i) EM->uw[i] >>= tmp8u;
break;
case 4: /* PSRAW Em, Ib */
if(tmp8u>15) tmp8u = 15;
for (int i=0; i<4; ++i) EM->sw[i] >>= tmp8u;
break;
case 6: /* PSLLW Em, Ib */
if(tmp8u>15)
{EM->q = 0;}
else
for (int i=0; i<4; ++i) EM->uw[i] <<= tmp8u;
break;
default:
return 1;
}
break;
case 0x72: /* GRP */
nextop = F8;
GETEM(1);
switch((nextop>>3)&7) {
case 2: /* PSRLD Em, Ib */
tmp8u = F8;
if(tmp8u>31)
{EM->q = 0;}
else
for (int i=0; i<2; ++i) EM->ud[i] >>= tmp8u;
break;
case 4: /* PSRAD Em, Ib */
tmp8u = F8;
for (int i=0; i<2; ++i) EM->sd[i] >>= tmp8u;
break;
case 6: /* PSLLD Em, Ib */
tmp8u = F8;
if(tmp8u>31)
{EM->q = 0;}
else
for (int i=0; i<2; ++i) EM->ud[i] <<= tmp8u;
break;
default:
return 1;
}
break;
case 0x73: /* GRP */
nextop = F8;
GETEM(1);
switch((nextop>>3)&7) {
case 2: /* PSRLQ Em, Ib */
tmp8u = F8;
if(tmp8u>63)
{EM->q = 0;}
else
{EM->q >>= tmp8u;}
break;
case 6: /* PSLLQ Em, Ib */
tmp8u = F8;
if(tmp8u>63)
{EM->q = 0;}
else
{EM->q <<= tmp8u;}
break;
default:
return 1;
}
break;
case 0x74: /* PCMPEQB Gm,Em */
nextop = F8;
GETEM(0);
@@ -486,8 +662,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
GETGM;
if(rex.w)
ED->q[0] = GM->q;
else
ED->q[0] = GM->ud[0];
else {
if(MODREG)
ED->q[0] = GM->ud[0];
else
ED->dword[0] = GM->ud[0];
}
break;
case 0x7F: /* MOVQ Em, Gm */
nextop = F8;
@@ -622,6 +802,11 @@ int Run0F(x64emu_t *emu, rex_t rex)
case 3: /* STMXCSR Md */
ED->dword[0] = emu->mxcsr;
break;
case 7: /* CLFLUSH Ed */
#ifdef DYNAREC
cleanDBFromAddressRange((uintptr_t)ED, 8, 0);
#endif
break;
default:
return 1;
}
@@ -659,13 +844,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
} else {
cmp32(emu, R_EAX, ED->dword[0]);
R_RAX = ED->dword[0]; // to erase upper part of RAX
if(ACCESS_FLAG(F_ZF)) {
if(MODREG)
ED->q[0] = GD->dword[0];
else
ED->dword[0] = GD->dword[0];
} else {
R_RAX = ED->dword[0];
}
}
break;
@@ -960,6 +1144,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
}
break;
case 0xC4: /* PINSRW Gm,Ew,Ib */
nextop = F8;
GETED(0);
GETGM;
tmp8u = F8;
GM->uw[tmp8u&3] = ED->word[0]; // only low 16bits
break;
case 0xC5: /* PEXTRW Gw,Em,Ib */
nextop = F8;
GETEM(0);
GETGD;
tmp8u = F8;
GD->q[0] = EM->uw[tmp8u&3]; // 16bits extract, 0 extended
break;
case 0xC6: /* SHUFPS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
@@ -1078,7 +1276,13 @@ int Run0F(x64emu_t *emu, rex_t rex)
GM->uw[i] = (tmp32s < 0) ? 0 : tmp32s;
}
break;
case 0xDA: /* PMINUB Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<8; ++i)
GM->ub[i] = (GM->ub[i]<EM->ub[i])?GM->ub[i]:EM->ub[i];
break;
case 0xDB: /* PAND Gm,Em */
nextop = F8;
GETEM(0);
@@ -1103,14 +1307,26 @@ int Run0F(x64emu_t *emu, rex_t rex)
GM->uw[i] = (tmp32u>65535) ? 65535 : tmp32u;
}
break;
case 0xDE: /* PMAXUB Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for (int i=0; i<8; ++i)
GM->ub[i] = (GM->ub[i]>EM->ub[i])?GM->ub[i]:EM->ub[i];
break;
case 0xDF: /* PANDN Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
GM->q = (~GM->q) & EM->q;
break;
case 0xE0: /* PAVGB Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<8; ++i)
GM->ub[i] = ((uint32_t)GM->ub[i]+EM->ub[i]+1)>>1;
break;
case 0xE1: /* PSRAW Gm, Em */
nextop = F8;
GETEM(0);
@@ -1135,22 +1351,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
GM->sd[i] >>= tmp8u;
}
break;
case 0xE3: /* PSRAQ Gm, Em */
case 0xE3: /* PAVGW Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
if(EM->q>63)
tmp8u = 64;
else
tmp8u = EM->ub[0];
GM->sq >>= tmp8u;
for(int i=0; i<4; ++i)
GM->uw[i] = ((uint32_t)GM->uw[i]+EM->uw[i]+1)>>1;
break;
case 0xE4: /* PMULHUW Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<4; ++i) {
tmp32u = (int32_t)GM->uw[i] * EM->uw[i];
tmp32u = (uint32_t)GM->uw[i] * (uint32_t)EM->uw[i];
GM->uw[i] = (tmp32u>>16)&0xffff;
}
break;
@@ -1159,17 +1372,24 @@ int Run0F(x64emu_t *emu, rex_t rex)
GETEM(0);
GETGM;
for(int i=0; i<4; ++i) {
tmp32s = (int32_t)GM->sw[i] * EM->sw[i];
GM->uw[i] = (tmp32s>>16)&0xffff;
tmp32s = (int32_t)GM->sw[i] * (int32_t)EM->sw[i];
GM->sw[i] = (tmp32s>>16)&0xffff;
}
break;
case 0xE7: /* MOVNTQ Em,Gm */
nextop = F8;
if((nextop&0xC0)==0xC0)
return 1;
GETEM(0);
GETGM;
EM->q = GM->q;
break;
case 0xE8: /* PSUBSB Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GM->sb[i] - EM->sb[i];
tmp32s = (int32_t)GM->sb[i] - (int32_t)EM->sb[i];
GM->sb[i] = (tmp32s>127)?127:((tmp32s<-128)?-128:tmp32s);
}
break;
@@ -1257,27 +1477,36 @@ int Run0F(x64emu_t *emu, rex_t rex)
GM->sd[i] = tmp32s + tmp32s2;
}
break;
case 0xF6: /* PSADBW Gm, Em */
nextop = F8;
GETEM(0);
GETGM;
tmp32u = 0;
for (int i=0; i<8; ++i)
tmp32u += (GM->ub[i]>EM->ub[i])?(GM->ub[i] - EM->ub[i]):(EM->ub[i] - GM->ub[i]);
GM->q = tmp32u;
break;
case 0xF8: /* PSUBB Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<8; ++i)
GM->sb[i] -= EM->sb[i];
GM->ub[i] -= EM->ub[i];
break;
case 0xF9: /* PSUBW Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<4; ++i)
GM->sw[i] -= EM->sw[i];
GM->uw[i] -= EM->uw[i];
break;
case 0xFA: /* PSUBD Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<2; ++i)
GM->sd[i] -= EM->sd[i];
GM->ud[i] -= EM->ud[i];
break;
case 0xFC: /* PADDB Gm, Em */
@@ -1285,21 +1514,21 @@ int Run0F(x64emu_t *emu, rex_t rex)
GETEM(0);
GETGM;
for(int i=0; i<8; ++i)
GM->sb[i] += EM->sb[i];
GM->ub[i] += EM->ub[i];
break;
case 0xFD: /* PADDW Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<4; ++i)
GM->sw[i] += EM->sw[i];
GM->uw[i] += EM->uw[i];
break;
case 0xFE: /* PADDD Gm,Em */
nextop = F8;
GETEM(0);
GETGM;
for(int i=0; i<2; ++i)
GM->sd[i] += EM->sd[i];
GM->ud[i] += EM->ud[i];
break;
default:
+171 -3
View File
@@ -33,6 +33,8 @@ int Run64(x64emu_t *emu, rex_t rex)
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx;
int rep;
uintptr_t tlsdata = GetFSBaseEmu(emu);
opcode = F8;
@@ -42,19 +44,180 @@ int Run64(x64emu_t *emu, rex_t rex)
rex.rex = opcode;
opcode = F8;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GETEB_OFFS(0, tlsdata); \
GETGB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
break; \
case B+1: \
nextop = F8; \
GETED_OFFS(0, tlsdata); \
GETGD; \
if(rex.w) \
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
else { \
if(MODREG) \
ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
else \
ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
} \
break; \
case B+2: \
nextop = F8; \
GETEB_OFFS(0, tlsdata); \
GETGB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GETED_OFFS(0, tlsdata); \
GETGD; \
if(rex.w) \
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
else \
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
if(rex.w) \
R_RAX = OP##64(emu, R_RAX, F32S64); \
else \
R_RAX = OP##32(emu, R_EAX, F32); \
break;
case 0x33: /* XOR Gd,Ed */
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x0F:
opcode = F8;
switch(opcode) {
case 0x11:
switch(rep) {
case 1: /* MOVSD Ex, Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->q[0] = GX->q[0];
break;
case 2: /* MOVSS FS:Ex, Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->ud[0] = GX->ud[0];
break;
default:
return 1;
}
break;
case 0x29: /* MOVAPS Ex,Gx */
switch(rep) {
case 0:
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
default:
return 1;
}
break;
case 0x59:
switch(rep) {
case 2: /* MULSS Gx, Ex */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
GX->f[0] *= EX->f[0];
break;
default:
return 1;
}
break;
default:
return 1;
}
break;
case 0x38:
nextop = F8;
GETEB_OFFS(0, tlsdata);
GETGB;
cmp8(emu, EB->byte[0], GB);
break;
case 0x39:
nextop = F8;
GETED_OFFS(0, tlsdata);
GETGD;
if(rex.w)
GD->q[0] = xor64(emu, GD->q[0], ED->q[0]);
cmp64(emu, ED->q[0], GD->q[0]);
else
GD->q[0] = xor32(emu, GD->dword[0], ED->dword[0]);
cmp32(emu, ED->dword[0], GD->dword[0]);
break;
case 0x3B:
nextop = F8;
GETED_OFFS(0, tlsdata);
GETGD;
if(rex.w)
cmp64(emu, GD->q[0], ED->q[0]);
else
cmp32(emu, GD->dword[0], ED->dword[0]);
break;
case 0x66:
opcode = F8;
while(opcode>=0x40 && opcode<=0x4F) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x0F:
opcode = F8;
switch(opcode) {
case 0xD6: /* MOVQ Ex,Gx */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
EX->q[0] = GX->q[0];
if(MODREG)
EX->q[1] = 0;
break;
default:
return 1;
}
break;
default:
return 1;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
@@ -134,6 +297,11 @@ int Run64(x64emu_t *emu, rex_t rex)
GD->q[0] = ED->dword[0];
break;
case 0xC6: /* MOV Eb,Ib */
nextop = F8;
GETEB_OFFS(1, tlsdata);
EB->byte[0] = F8;
break;
case 0xC7: /* MOV Ed,Id */
nextop = F8;
GETED_OFFS(4, tlsdata);
+31 -1
View File
@@ -33,6 +33,7 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
uint8_t tmp8u, tmp8u2;
int16_t tmp16s;
uint16_t tmp16u, tmp16u2;
int32_t tmp32s;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3;
reg64_t *oped, *opgd;
@@ -209,7 +210,30 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
nextop = F8;
GETEW(0);
GETGW;
EW->word[0] = GW->word[0];
if(rex.w)
EW->q[0] = GW->q[0];
else
EW->word[0] = GW->word[0];
break;
case 0x8B: /* MOV Gw,Ew */
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
GW->q[0] = EW->q[0];
else
GW->word[0] = EW->word[0];
break;
case 0x8D: /* LEA Gw,M */
nextop = F8;
GETED(0);
GETGD;
if(rex.w)
GD->q[0] = (uint64_t)ED;
else
GD->word[0] = (uint16_t)(uintptr_t)ED;
break;
case 0x90: /* NOP */
@@ -527,6 +551,12 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
case 0xDD: /* x87 opcdes */
return Run66DD(emu, rex);
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
Push(emu, R_RIP);
R_RIP += tmp32s;
break;
case 0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
tmp8u = (nextop>>3)&7;
+164 -1
View File
@@ -78,6 +78,18 @@ int Run660F(x64emu_t *emu, rex_t rex)
GX->q[0] = GX->q[1];
GX->q[1] = EX->q[1];
break;
case 0x16: /* MOVHPD Gx, Ed */
nextop = F8;
GETED(0);
GETGX;
GX->q[1] = ED->q[0];
break;
case 0x17: /* MOVHPD Ed, Gx */
nextop = F8;
GETED(0);
GETGX;
ED->q[0] = GX->q[1];
break;
case 0x1F: /* NOP (multi-byte) */
nextop = F8;
@@ -155,6 +167,126 @@ int Run660F(x64emu_t *emu, rex_t rex)
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0x38: // SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x00: /* PSHUFB */
nextop = F8;
GETEX(0);
GETGX;
eax1 = *GX;
for (int i=0; i<16; ++i) {
if(EX->ub[i]&128)
GX->ub[i] = 0;
else
GX->ub[i] = eax1.ub[EX->ub[i]&15];
}
break;
case 0x01: /* PHADDW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sw[i] = GX->sw[i*2+0]+GX->sw[i*2+1];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i)
GX->sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
}
break;
case 0x02: /* PHADDD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->sd[0] += GX->sd[1];
GX->sd[1] = GX->sd[2] + GX->sd[3];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
GX->sd[2] = EX->sd[0] + EX->sd[1];
GX->sd[3] = EX->sd[2] + EX->sd[3];
}
break;
case 0x03: /* PHADDSW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
tmp32s = GX->sw[i*2+0]+GX->sw[i*2+1];
GX->sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
GX->sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x04: /* PMADDUBSW Gx,Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i) {
tmp32s = (int32_t)(GX->ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX->ub[i*2+1])*EX->sb[i*2+1];
GX->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x05: /* PHSUBW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sw[i] = GX->sw[i*2+0] - GX->sw[i*2+1];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i)
GX->sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
}
break;
case 0x0B: /* PMULHRSW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i) {
tmp32s = ((((int32_t)(GX->sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
GX->uw[i] = tmp32s&0xffff;
}
break;
default:
return 1;
}
break;
case 0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u>31)
{GX->q[0] = GX->q[1] = 0;}
else
{
for (int i=0; i<16; ++i, ++tmp8u)
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX->ub[tmp8u-16]):EX->ub[tmp8u];
GX->q[0] = eax1.q[0];
GX->q[1] = eax1.q[1];
}
break;
default:
return 1;
}
break;
GOCOND(0x40
, nextop = F8;
CHECK_FLAGS(emu);
@@ -848,6 +980,20 @@ int Run660F(x64emu_t *emu, rex_t rex)
}
break;
case 0xC4: /* PINSRW Gx,Ew,Ib */
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
GX->uw[tmp8u&7] = ED->word[0]; // only low 16bits
break;
case 0xC5: /* PEXTRW Gw,Ex,Ib */
nextop = F8;
GETEX(1);
GETGD;
tmp8u = F8;
GD->dword[0] = EX->uw[tmp8u&7]; // 16bits extract, 0 extended
break;
case 0xC6: /* SHUFPD Gx, Ex, Ib */
nextop = F8;
GETEX(1);
@@ -1020,7 +1166,24 @@ int Run660F(x64emu_t *emu, rex_t rex)
for (int i=0; i<8; ++i)
GX->uw[i] = ((uint32_t)GX->uw[i] + EX->uw[i] + 1)>>1;
break;
case 0xE4: /* PMULHUW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32u = (uint32_t)GX->uw[i] * EX->uw[i];
GX->uw[i] = (tmp32u>>16)&0xffff;
}
break;
case 0xE5: /* PMULHW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->sw[i] * EX->sw[i];
GX->uw[i] = (tmp32s>>16)&0xffff;
}
break;
case 0xE6: /* CVTTPD2DQ Gx, Ex */
nextop = F8;
GETEX(0);
+234 -2
View File
@@ -22,23 +22,143 @@
#include "modrm.h"
int Run67(x64emu_t *emu, rex_t rex)
int Run67(x64emu_t *emu, rex_t rex, int rep)
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u;
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
opcode = F8;
// REX prefix before the F0 are ignored
while(opcode==0x67)
opcode = F8;
// REX prefix before the 67 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
#define GO(B, OP) \
case B+0: \
nextop = F8; \
GETEB32(0); \
GETGB; \
EB->byte[0] = OP##8(emu, EB->byte[0], GB); \
break; \
case B+1: \
nextop = F8; \
GETED32(0); \
GETGD; \
if(rex.w) \
ED->q[0] = OP##64(emu, ED->q[0], GD->q[0]); \
else { \
if(MODREG) \
ED->q[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
else \
ED->dword[0] = OP##32(emu, ED->dword[0], GD->dword[0]); \
} \
break; \
case B+2: \
nextop = F8; \
GETEB32(0); \
GETGB; \
GB = OP##8(emu, GB, EB->byte[0]); \
break; \
case B+3: \
nextop = F8; \
GETED32(0); \
GETGD; \
if(rex.w) \
GD->q[0] = OP##64(emu, GD->q[0], ED->q[0]); \
else \
GD->q[0] = OP##32(emu, GD->dword[0], ED->dword[0]); \
break; \
case B+4: \
R_AL = OP##8(emu, R_AL, F8); \
break; \
case B+5: \
if(rex.w) \
R_RAX = OP##64(emu, R_RAX, F32S64); \
else \
R_RAX = OP##32(emu, R_EAX, F32); \
break;
GO(0x00, add) /* ADD 0x00 -> 0x05 */
GO(0x08, or) /* OR 0x08 -> 0x0D */
case 0x0F:
return Run670F(emu, rex, rep);
GO(0x10, adc) /* ADC 0x10 -> 0x15 */
GO(0x18, sbb) /* SBB 0x18 -> 0x1D */
GO(0x20, and) /* AND 0x20 -> 0x25 */
GO(0x28, sub) /* SUB 0x28 -> 0x2D */
GO(0x30, xor) /* XOR 0x30 -> 0x35 */
#undef GO
case 0x66:
return Run6766(emu, rex, rep);
case 0x80: /* GRP Eb,Ib */
nextop = F8;
GETEB32(1);
tmp8u = F8;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x88: /* MOV Eb,Gb */
nextop = F8;
GETEB32(0);
GETGB;
EB->byte[0] = GB;
break;
case 0x89: /* MOV Ed,Gd */
nextop = F8;
GETED32(0);
GETGD;
if(rex.w) {
ED->q[0] = GD->q[0];
} else {
//if ED is a reg, than the opcode works like movzx
if(MODREG)
ED->q[0] = GD->dword[0];
else
ED->dword[0] = GD->dword[0];
}
break;
case 0x8A: /* MOV Gb,Eb */
nextop = F8;
GETEB32(0);
GETGB;
GB = EB->byte[0];
break;
case 0x8B: /* MOV Gd,Ed */
nextop = F8;
GETED32(0);
GETGD;
if(rex.w)
GD->q[0] = ED->q[0];
else
GD->q[0] = ED->dword[0];
break;
case 0x8D: /* LEA Gd,M */
nextop = F8;
@@ -50,6 +170,47 @@ int Run67(x64emu_t *emu, rex_t rex)
GD->q[0] = (uint32_t)(uintptr_t)ED;
break;
case 0xC1: /* GRP2 Ed,Ib */
nextop = F8;
GETED32(1);
tmp8u = F8/* & 0x1f*/; // masking done in each functions
if(rex.w) {
switch((nextop>>3)&7) {
case 0: ED->q[0] = rol64(emu, ED->q[0], tmp8u); break;
case 1: ED->q[0] = ror64(emu, ED->q[0], tmp8u); break;
case 2: ED->q[0] = rcl64(emu, ED->q[0], tmp8u); break;
case 3: ED->q[0] = rcr64(emu, ED->q[0], tmp8u); break;
case 4:
case 6: ED->q[0] = shl64(emu, ED->q[0], tmp8u); break;
case 5: ED->q[0] = shr64(emu, ED->q[0], tmp8u); break;
case 7: ED->q[0] = sar64(emu, ED->q[0], tmp8u); break;
}
} else {
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->q[0] = rol32(emu, ED->dword[0], tmp8u); break;
case 1: ED->q[0] = ror32(emu, ED->dword[0], tmp8u); break;
case 2: ED->q[0] = rcl32(emu, ED->dword[0], tmp8u); break;
case 3: ED->q[0] = rcr32(emu, ED->dword[0], tmp8u); break;
case 4:
case 6: ED->q[0] = shl32(emu, ED->dword[0], tmp8u); break;
case 5: ED->q[0] = shr32(emu, ED->dword[0], tmp8u); break;
case 7: ED->q[0] = sar32(emu, ED->dword[0], tmp8u); break;
}
else
switch((nextop>>3)&7) {
case 0: ED->dword[0] = rol32(emu, ED->dword[0], tmp8u); break;
case 1: ED->dword[0] = ror32(emu, ED->dword[0], tmp8u); break;
case 2: ED->dword[0] = rcl32(emu, ED->dword[0], tmp8u); break;
case 3: ED->dword[0] = rcr32(emu, ED->dword[0], tmp8u); break;
case 4:
case 6: ED->dword[0] = shl32(emu, ED->dword[0], tmp8u); break;
case 5: ED->dword[0] = shr32(emu, ED->dword[0], tmp8u); break;
case 7: ED->dword[0] = sar32(emu, ED->dword[0], tmp8u); break;
}
}
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
@@ -76,6 +237,77 @@ int Run67(x64emu_t *emu, rex_t rex)
R_RIP += tmp8s;
break;
case 0xF7: /* GRP3 Ed(,Id) */
nextop = F8;
tmp8u = (nextop>>3)&7;
GETED32((tmp8u<2)?4:0);
if(rex.w) {
switch(tmp8u) {
case 0:
case 1: /* TEST Ed,Id */
tmp64u = F32S64;
test64(emu, ED->q[0], tmp64u);
break;
case 2: /* NOT Ed */
ED->q[0] = not64(emu, ED->q[0]);
break;
case 3: /* NEG Ed */
ED->q[0] = neg64(emu, ED->q[0]);
break;
case 4: /* MUL RAX,Ed */
mul64_rax(emu, ED->q[0]);
break;
case 5: /* IMUL RAX,Ed */
imul64_rax(emu, ED->q[0]);
break;
case 6: /* DIV Ed */
div64(emu, ED->q[0]);
break;
case 7: /* IDIV Ed */
idiv64(emu, ED->q[0]);
break;
}
} else {
switch(tmp8u) {
case 0:
case 1: /* TEST Ed,Id */
tmp32u = F32;
test32(emu, ED->dword[0], tmp32u);
break;
case 2: /* NOT Ed */
if(MODREG)
ED->q[0] = not32(emu, ED->dword[0]);
else
ED->dword[0] = not32(emu, ED->dword[0]);
break;
case 3: /* NEG Ed */
if(MODREG)
ED->q[0] = neg32(emu, ED->dword[0]);
else
ED->dword[0] = neg32(emu, ED->dword[0]);
break;
case 4: /* MUL EAX,Ed */
mul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 5: /* IMUL EAX,Ed */
imul32_eax(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
break;
case 6: /* DIV Ed */
div32(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
emu->regs[_DX].dword[1] = 0;
break;
case 7: /* IDIV Ed */
idiv32(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
emu->regs[_DX].dword[1] = 0;
break;
}
}
break;
default:
return 1;
}
+68
View File
@@ -0,0 +1,68 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
int Run670F(x64emu_t *emu, rex_t rex, int rep)
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int8_t tmp8s;
int32_t tmp32s, tmp32s2;
uint32_t tmp32u, tmp32u2;
uint64_t tmp64u, tmp64u2;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem, *opgm, eam1;
opcode = F8;
switch(opcode) {
case 0x2E: /* UCOMISS Gx, Ex */
// same for now
case 0x2F: /* COMISS Gx, Ex */
RESET_FLAGS(emu);
nextop = F8;
GETEX32(0);
GETGX;
if(isnan(GX->f[0]) || isnan(EX->f[0])) {
SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF);
} else if(isgreater(GX->f[0], EX->f[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
} else if(isless(GX->f[0], EX->f[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); SET_FLAG(F_CF);
} else {
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
}
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
default:
return 1;
}
return 0;
}
+66
View File
@@ -0,0 +1,66 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#ifdef DYNAREC
#include "../dynarec/arm64_lock.h"
#endif
#include "modrm.h"
int Run6766(x64emu_t *emu, rex_t rex, int rep)
{
uint8_t opcode;
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u, tmp8u2;
int16_t tmp16s;
uint16_t tmp16u, tmp16u2;
int32_t tmp32s;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3;
reg64_t *oped, *opgd;
opcode = F8;
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
opcode = F8;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
// REX prefix before the F0 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x0F: /* more opcdes */
return Run67660F(emu, rex);
default:
return 1;
}
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int Run67660F(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int8_t tmp8s;
int16_t tmp16s;
uint16_t tmp16u;
int32_t tmp32s;
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1, *opex2;
mmx87_regs_t *opem, *opgm;
opcode = F8;
switch(opcode) {
case 0x6F: /* MOVDQA Gx,Ex */
nextop = F8;
GETEX32(0);
GETGX;
GX->q[0] = EX->q[0];
GX->q[1] = EX->q[1];
break;
case 0x76: /* PCMPEQD Gx,Ex */
nextop = F8;
GETEX32(0);
GETGX;
for (int i=0; i<4; ++i)
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
break;
default:
return 1;
}
return 0;
}
+44 -11
View File
@@ -30,8 +30,6 @@
int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
//TODO: register rtld_fini
//TODO: register fini
// let's cheat and set all args...
if(init) {
PushExit(emu);
@@ -44,14 +42,20 @@ int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, c
}
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
Push64(emu, GetRBP(emu)); // set frame pointer
SetRBP(emu, GetRSP(emu)); // save RSP
SetRSP(emu, GetRSP(emu)&~0xFLL); // Align RSP
PushExit(emu);
SetRDX(emu, (uint64_t)my_context->envv);
SetRSI(emu, (uint64_t)my_context->argv);
SetRDI(emu, (uint64_t)my_context->argc);
R_RIP=(uint64_t)main;
#ifdef DYNAREC
DynaRun(emu);
#endif
SetRSP(emu, GetRBP(emu)); // restore RSP
SetRBP(emu, Pop64(emu)); // restore RBP
emu->quit = 1; // finished!
return 0;
}
@@ -921,7 +925,7 @@ void UpdateFlags(x64emu_t *emu)
case d_rcr32:
case d_rcr64:
case d_unknown:
printf_log(LOG_NONE, "Box86: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
printf_log(LOG_NONE, "Box64: %p trying to evaluate Unknown defered Flags\n", (void*)R_RIP);
break;
}
RESET_FLAGS(emu);
@@ -1003,10 +1007,10 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
} else {
printf_log(LOG_NONE, "%s", DecodeX64Trace(my_context->dec, ip));
uint8_t peek = PK(0);
if(peek==0xC3 || peek==0xC2) {
if(peek==0xC3 || peek==0xC2 || (peek==0xF3 && PK(1)==0xC3)) {
printf_log(LOG_NONE, " => %p", *(void**)(R_RSP));
printFunctionAddr(*(uintptr_t*)(R_RSP), "=> ");
} else if(peek==0x55) {
} else if(peek==0x55 || peek==0x53) {
printf_log(LOG_NONE, " => STACK_TOP: %p", *(void**)(R_RSP));
printFunctionAddr(ip, "here: ");
} else if(peek==0xE8) { // Call
@@ -1065,7 +1069,7 @@ reg64_t* GetECommonO(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintptr
base += Fetch32s(emu);
return (reg64_t*)(base+R_RIP+delta);
}
return (reg64_t*)(emu->regs[m+(rex.b<<3)].q[0]);
return (reg64_t*)(base + emu->regs[m+(rex.b<<3)].q[0]);
} else {
if((m&7)==4) {
uint8_t sib = Fetch8(emu);
@@ -1091,7 +1095,7 @@ reg64_t* GetECommon32O(x64emu_t* emu, rex_t rex, uint8_t m, uint8_t delta, uintp
base += Fetch32s(emu);
return (reg64_t*)(base+R_RIP+delta);
}
return (reg64_t*)(uintptr_t)(emu->regs[m+(rex.b<<3)].dword[0]);
return (reg64_t*)(uintptr_t)(base + emu->regs[m+(rex.b<<3)].dword[0]);
} else {
if((m&7)==4) {
uint8_t sib = Fetch8(emu);
@@ -1157,6 +1161,19 @@ reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t
} else return GetECommon32O(emu, rex, m, delta, offset);
}
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Eb
if(m>=0xC0) {
if(rex.rex) {
return &emu->regs[(m&0x07)+(rex.b<<3)];
} else {
int lowhigh = (m&4)>>2;
return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //?
}
} else return GetECommon32O(emu, rex, m, delta, offset);
}
#define GetEw GetEd
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v)
@@ -1229,6 +1246,22 @@ sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta)
} else return (sse_regs_t*)GetECommon(emu, rex, m, delta);
}
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->xmm[(m&0x07)+(rex.b<<3)];
} else return (sse_regs_t*)GetECommonO(emu, rex, m, delta, offset);
}
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset)
{
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->xmm[(m&0x07)+(rex.b<<3)];
} else return (sse_regs_t*)GetECommon32O(emu, rex, m, delta, offset);
}
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
{
@@ -1238,9 +1271,9 @@ reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v)
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v)
{
uint8_t m = (v&0x38)>>3;
if(rex.rex) {
if(rex.rex)
return &emu->regs[(m&7)+(rex.r<<3)];
} else
else
return (reg64_t*)&emu->regs[m&3].byte[m>>2];
}
+10 -1
View File
@@ -81,11 +81,15 @@ reg64_t* GetEbO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t of
reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
reg64_t* GetEdO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEd32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetEb32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
#define GetEw GetEd
#define GetEw32O GetEd32O
reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v);
reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset);
mmx87_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta);
sse_regs_t* GetExO(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
sse_regs_t* GetEx32O(x64emu_t *emu, rex_t rex, uint8_t v, uint8_t delta, uintptr_t offset);
reg64_t* GetGd(x64emu_t *emu, rex_t rex, uint8_t v);
#define GetGw GetGd
reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v);
@@ -104,12 +108,17 @@ int Run660F(x64emu_t *emu, rex_t rex);
int Run6664(x64emu_t *emu, rex_t rex);
int Run66D9(x64emu_t *emu, rex_t rex);
int Run66DD(x64emu_t *emu, rex_t rex);
int Run67(x64emu_t *emu, rex_t rex);
int Run67(x64emu_t *emu, rex_t rex, int rep);
int Run670F(x64emu_t *emu, rex_t rex, int rep);
int Run6766(x64emu_t *emu, rex_t rex, int rep);
int Run67660F(x64emu_t *emu, rex_t rex);
int RunD8(x64emu_t *emu, rex_t rex);
int RunD9(x64emu_t *emu, rex_t rex);
int RunDA(x64emu_t *emu, rex_t rex);
int RunDB(x64emu_t *emu, rex_t rex);
int RunDC(x64emu_t *emu, rex_t rex);
int RunDD(x64emu_t *emu, rex_t rex);
int RunDE(x64emu_t *emu, rex_t rex);
int RunDF(x64emu_t *emu, rex_t rex);
int RunF0(x64emu_t *emu, rex_t rex);
int RunF20F(x64emu_t *emu, rex_t rex);
+146
View File
@@ -0,0 +1,146 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int RunDC(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch(nextop) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7: /* FADD */
ST(nextop&7).d += ST0.d;
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF: /* FMUL */
ST(nextop&7).d *= ST0.d;
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7: /* FCOM */
fpu_fcom(emu, ST(nextop&7).d);
break;
case 0xD8:
case 0xD9:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF: /* FCOMP */
fpu_fcom(emu, ST(nextop&7).d);
fpu_do_pop(emu);
break;
case 0xE0:
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7: /* FSUBR */
ST(nextop&7).d = ST0.d -ST(nextop&7).d;
break;
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF: /* FSUB */
ST(nextop&7).d -= ST0.d;
break;
case 0xF0:
case 0xF1:
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7: /* FDIVR */
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
break;
case 0xF8:
case 0xF9:
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF: /* FDIV */
ST(nextop&7).d /= ST0.d;
break;
default:
GETED(0);
switch((nextop>>3)&7) {
case 0: /* FADD ST0, double */
ST0.d += *(double*)ED;
break;
case 1: /* FMUL ST0, double */
ST0.d *= *(double*)ED;
break;
case 2: /* FCOM ST0, double */
fpu_fcom(emu, *(double*)ED);
break;
case 3: /* FCOMP ST0, double */
fpu_fcom(emu, *(double*)ED);
fpu_do_pop(emu);
break;
case 4: /* FSUB ST0, double */
ST0.d -= *(double*)ED;
break;
case 5: /* FSUBR ST0, double */
ST0.d = *(double*)ED - ST0.d;
break;
case 6: /* FDIV ST0, double */
ST0.d /= *(double*)ED;
break;
case 7: /* FDIVR ST0, double */
ST0.d = *(double*)ED / ST0.d;
break;
default:
return 1;
}
}
return 0;
}
+160
View File
@@ -0,0 +1,160 @@
#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
int RunDE(x64emu_t *emu, rex_t rex)
{
uint8_t nextop;
reg64_t *oped;
nextop = F8;
switch(nextop) {
case 0xC0: /* FADDP STx, ST0 */
case 0xC1: /* FADDP ST1, ST0 */
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
case 0xC6:
case 0xC7:
ST(nextop&7).d += ST0.d;
fpu_do_pop(emu);
break;
case 0xC8: /* FMULP STx, ST0 */
case 0xC9: /* FMULP ST1, ST0 */
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
ST(nextop&7).d *= ST0.d;
fpu_do_pop(emu);
break;
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD7: /* FCOMP */
fpu_fcom(emu, ST(nextop&7).d);
fpu_do_pop(emu);
break;
case 0xD9: /* FCOMPP */
fpu_fcom(emu, ST1.d);
fpu_do_pop(emu);
fpu_do_pop(emu);
break;
/*ST(1).d = ST0.d - ST(1).d;
fpu_do_pop(emu);
break;*/
case 0xE0: /* FSUBRP STx, ST0 */
case 0xE1: /* FSUBRP ST1, ST0 */
case 0xE2:
case 0xE3:
case 0xE4:
case 0xE5:
case 0xE6:
case 0xE7:
ST(nextop&7).d = ST0.d - ST(nextop&7).d;
fpu_do_pop(emu);
break;
case 0xE8: /* FSUBP STx, ST0 */
case 0xE9: /* FSUBP ST1, ST0 */
case 0xEA:
case 0xEB:
case 0xEC:
case 0xED:
case 0xEE:
case 0xEF:
ST(nextop&7).d -= ST0.d;
fpu_do_pop(emu);
break;
case 0xF0: /* FDIVRP STx, ST0 */
case 0xF1: /* FDIVRP ST1, ST0 */
case 0xF2:
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF6:
case 0xF7:
ST(nextop&7).d = ST0.d / ST(nextop&7).d;
fpu_do_pop(emu);
break;
case 0xF8: /* FDIVP STx, ST0 */
case 0xF9: /* FDIVP ST1, ST0 */
case 0xFA:
case 0xFB:
case 0xFC:
case 0xFD:
case 0xFE:
case 0xFF:
ST(nextop&7).d /= ST0.d;
fpu_do_pop(emu);
break;
case 0xD8:
case 0xDA:
case 0xDB:
case 0xDC:
case 0xDD:
case 0xDE:
case 0xDF:
return 1;
default:
switch((nextop>>3)&7) {
case 0: /* FIADD ST0, Ew int */
GETEW(0);
ST0.d += EW->sword[0];
break;
case 1: /* FIMUL ST0, Ew int */
GETEW(0);
ST0.d *= EW->sword[0];
break;
case 4: /* FISUB ST0, Ew int */
GETEW(0);
ST0.d -= EW->sword[0];
break;
case 5: /* FISUBR ST0, Ew int */
GETEW(0);
ST0.d = (double)EW->sword[0] - ST0.d;
break;
case 6: /* FIDIV ST0, Ew int */
GETEW(0);
ST0.d /= EW->sword[0];
break;
case 7: /* FIDIVR ST0, Ew int */
GETEW(0);
ST0.d = (double)EW->sword[0] / ST0.d;
break;
default:
return 1;
}
}
return 0;
}
+356 -5
View File
@@ -168,6 +168,113 @@ int RunF0(x64emu_t *emu, rex_t rex)
opcode = F8;
switch (opcode) {
case 0xAB: /* BTS Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
#ifdef DYNAREC
if(rex.w) {
tmp8u&=63;
if(MODREG) {
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
ED->q[0] |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else
do {
tmp64u = arm64_lock_read_dd(ED);
if(tmp64u & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
tmp32s = 0;
} else {
tmp64u |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
tmp32s = arm64_lock_write_d(ED, tmp64u);
}
} while(tmp32s);
} else {
tmp8u&=31;
if(MODREG) {
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
ED->dword[0] |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
ED->dword[1] = 0;
} else
do {
tmp32u = arm64_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32s = 0;
} else {
tmp32u |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
tmp32s = arm64_lock_write_d(ED, tmp32u);
}
} while(tmp32s);
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
ED->q[0] |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
ED->dword[0] |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
if(MODREG)
ED->dword[1] = 0;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB0: /* CMPXCHG Eb,Gb */
CHECK_FLAGS(emu);
nextop = F8;
GETGB;
GETEB(0);
#ifdef DYNAREC
do {
tmp8u = arm64_lock_read_b(EB);
cmp8(emu, R_AL, tmp8u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_b(EB, GB);
} else {
R_AL = tmp8u;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
cmp8(emu, R_AL, EB->byte[0]);
if(ACCESS_FLAG(F_ZF)) {
EB->byte[0] = GB;
} else {
R_AL = EB->byte[0];
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xB1: /* CMPXCHG Ed,Gd */
nextop = F8;
GETED(0);
@@ -216,6 +323,63 @@ int RunF0(x64emu_t *emu, rex_t rex)
#endif
break;
case 0xB3: /* BTR Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
}
tmp8u&=rex.w?63:31;
#ifdef DYNAREC
if(rex.w)
do {
tmp64u = arm64_lock_read_dd(ED);
if(tmp64u & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
tmp64u ^= (1LL<<tmp8u);
tmp32s = arm64_lock_write_dd(ED, tmp64u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
else
do {
tmp32u = arm64_lock_read_d(ED);
if(tmp32u & (1<<tmp8u)) {
SET_FLAG(F_CF);
tmp32u ^= (1<<tmp8u);
tmp32s = arm64_lock_write_d(ED, tmp32u);
} else {
CLEAR_FLAG(F_CF);
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
if(ED->q[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
if(MODREG)
ED->dword[1] = 0;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xC1: /* XADD Gd,Ed */
nextop = F8;
GETED(0);
@@ -228,10 +392,19 @@ int RunF0(x64emu_t *emu, rex_t rex)
} while(arm64_lock_write_dd(ED, tmp64u2));
GD->q[0] = tmp64u;
} else {
do {
tmp32u = arm64_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
} while(arm64_lock_write_d(ED, tmp32u2));
if(((uintptr_t)ED)&3) {
do {
tmp32u = ED->dword[0] & ~0xff;
tmp32u |= arm64_lock_read_b(ED);
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
} while(arm64_lock_write_b(ED, tmp32u2&0xff));
ED->dword[0] = tmp32u2;
} else {
do {
tmp32u = arm64_lock_read_d(ED);
tmp32u2 = add32(emu, tmp32u, GD->dword[0]);
} while(arm64_lock_write_d(ED, tmp32u2));
}
GD->q[0] = tmp32u;
if(MODREG)
ED->dword[1] = 0;
@@ -254,6 +427,69 @@ int RunF0(x64emu_t *emu, rex_t rex)
#endif
break;
case 0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
#ifdef DYNAREC
if(rex.w)
do {
arm64_lock_read_dq(&tmp64u, &tmp64u2, ED);
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
SET_FLAG(F_ZF);
tmp32s = arm64_lock_write_dq(R_RBX, R_RCX, ED);
} else {
CLEAR_FLAG(F_ZF);
R_RAX = tmp64u;
R_RDX = tmp64u2;
tmp32s = 0;
}
} while(tmp32s);
else
do {
tmp64u = arm64_lock_read_dd(ED);
if((R_EAX == (tmp64u&0xffffffff)) && (R_EDX == ((tmp64u>>32)&0xffffffff))) {
SET_FLAG(F_ZF);
tmp32s = arm64_lock_write_dd(ED, R_EBX|(((uint64_t)R_ECX)<<32));
} else {
CLEAR_FLAG(F_ZF);
R_RAX = tmp64u&0xffffffff;
R_RDX = (tmp64u>>32)&0xffffffff;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp64u = ED->q[0];
tmp64u2= ED->q[1];
if(R_RAX == tmp64u && R_RDX == tmp64u2) {
SET_FLAG(F_ZF);
ED->q[0] = R_RBX;
ED->q[1] = R_RCX;
} else {
CLEAR_FLAG(F_ZF);
R_RAX = tmp64u;
R_RDX = tmp64u2;
}
} else {
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
}
@@ -344,7 +580,122 @@ int RunF0(x64emu_t *emu, rex_t rex)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0x87: /* XCHG Ed,Gd */
nextop = F8;
#ifdef DYNAREC
GETED(0);
GETGD;
if(MODREG) {
if(rex.w) {
tmp64u = GD->q[0];
GD->q[0] = ED->q[0];
ED->q[0] = tmp64u;
} else {
tmp32u = GD->dword[0];
GD->q[0] = ED->dword[0];
ED->q[0] = tmp32u;
}
} else {
if(rex.w) {
GD->q[0] = arm64_lock_xchg(ED, GD->q[0]);
} else {
do {
tmp32u = arm64_lock_read_d(ED);
} while(arm64_lock_write_d(ED, GD->dword[0]));
GD->q[0] = tmp32u;
}
}
#else
GETED(0);
GETGD;
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
tmp64u = GD->q[0];
GD->q[0] = ED->q[0];
ED->q[0] = tmp64u;
} else {
tmp32u = GD->dword[0];
GD->q[0] = ED->dword[0];
if(MODREG)
ED->q[0] = tmp32u;
else
ED->dword[0] = tmp32u;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xFF: /* GRP 5 Ed */
nextop = F8;
GETED(0);
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#ifdef DYNAREC
if(rex.w)
do {
tmp64u = arm64_lock_read_dd(ED);
} while(arm64_lock_write_dd(ED, inc64(emu, tmp64u)));
else {
if((uintptr_t)ED&3) {
//meh.
do {
tmp32u = ED->dword[0];
tmp32u &=~0xff;
tmp32u |= arm64_lock_read_b(ED);
tmp32u = inc32(emu, tmp32u);
} while(arm64_lock_write_b(ED, tmp32u&0xff));
ED->dword[0] = tmp32u;
} else {
do {
tmp32u = arm64_lock_read_d(ED);
} while(arm64_lock_write_d(ED, inc32(emu, tmp32u)));
}
if(MODREG) ED->dword[1] = 0;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
ED->q[0] = inc64(emu, ED->q[0]);
} else {
if(MODREG)
ED->q[0] = inc32(emu, ED->dword[0]);
else
ED->dword[0] = inc32(emu, ED->dword[0]);
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#ifdef DYNAREC
if(rex.w)
do {
tmp64u = arm64_lock_read_dd(ED);
} while(arm64_lock_write_dd(ED, dec64(emu, tmp64u)));
else {
do {
tmp32u = arm64_lock_read_d(ED);
} while(arm64_lock_write_d(ED, dec32(emu, tmp32u)));
if(MODREG) ED->dword[1] = 0;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
ED->q[0] = dec64(emu, ED->q[0]);
} else {
if(MODREG)
ED->q[0] = dec32(emu, ED->dword[0]);
else
ED->dword[0] = dec32(emu, ED->dword[0]);
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xFF 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
break;
}
break;
default:
return 1;
}
+14 -1
View File
@@ -53,6 +53,12 @@ int RunF20F(x64emu_t *emu, rex_t rex)
GETGX;
EX->q[0] = GX->q[0];
break;
case 0x12: /* MOVDDUP Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
GX->q[1] = GX->q[0] = EX->q[0];
break;
case 0x2A: /* CVTSI2SD Gx, Ed */
nextop = F8;
@@ -254,7 +260,14 @@ int RunF20F(x64emu_t *emu, rex_t rex)
GX->q[1] = 0;
break;
default:
case 0xF0: /* LDDQU Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
memcpy(GX, EX, 16);
break;
default:
return 1;
}
return 0;
+44 -1
View File
@@ -28,6 +28,8 @@ int RunF30F(x64emu_t *emu, rex_t rex)
uint8_t nextop;
int8_t tmp8s;
uint8_t tmp8u;
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1;
mmx87_regs_t *opem;
@@ -236,6 +238,42 @@ int RunF30F(x64emu_t *emu, rex_t rex)
memcpy(EX, GX, 16); // unaligned...
break;
case 0xBC: /* TZCNT Ed,Gd */
CHECK_FLAGS(emu);
nextop = F8;
GETED(0);
GETGD;
if(rex.w) {
tmp64u = ED->q[0];
if(tmp64u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;
GD->q[0] = tmp8u;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CLEAR_FLAG(F_CF);
} else {
CLEAR_FLAG(F_ZF);
SET_FLAG(F_CF);
GD->q[0] = 64;
}
} else {
tmp32u = ED->dword[0];
if(tmp32u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp32u&(1<<tmp8u))) ++tmp8u;
GD->dword[0] = tmp8u;
CONDITIONAL_SET_FLAG(tmp8u==0, F_ZF);
CLEAR_FLAG(F_CF);
} else {
CLEAR_FLAG(F_ZF);
SET_FLAG(F_CF);
GD->dword[0] = 32;
}
}
break;
case 0xC2: /* CMPSS Gx, Ex, Ib */
nextop = F8;
GETEX(1);
@@ -271,8 +309,13 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GX->d[0] = EX->sd[0];
break;
case 0x1E: /* NOP (multi-byte), endbr64 */
nextop = F8;
GETED(0);
break;
default:
return 1;
}
return 0;
}
}
+87 -12
View File
@@ -34,18 +34,19 @@
#include "x64tls.h"
typedef struct x64_sigaction_s x64_sigaction_t;
typedef struct x64_stack_s x64_stack_t;
//int32_t my_getrandom(x64emu_t* emu, void* buf, uint32_t buflen, uint32_t flags);
int of_convert(int flag);
int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode);
//int my_sigaction(x64emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact);
int my_sigaction(x64emu_t* emu, int signum, const x64_sigaction_t *act, x64_sigaction_t *oldact);
int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss);
//int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[]);
//void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int offset);
//void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
//int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
//int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
int my_munmap(x64emu_t* emu, void* addr, unsigned long length);
int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
@@ -62,13 +63,34 @@ typedef struct scwrap_s {
} scwrap_t;
scwrap_t syscallwrap[] = {
//{ 0, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
//{ 1, __NR_write, 3 }, // same
//{ 2, __NR_open, 3 }, // flags need transformation
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
//{ 0, __NR_read, 3 }, // wrapped so SA_RESTART can be handled by libc
//{ 1, __NR_write, 3 }, // same
//{ 2, __NR_open, 3 }, // flags need transformation
//{ 3, __NR_close, 1 }, // wrapped so SA_RESTART can be handled by libc
//{ 9, __NR_mmap, 6}, // wrapped to track mmap
//{ 10, __NR_mprotect, 3}, // same
//{ 11, __NR_munmap, 2}, // same
{ 5, __NR_fstat, 2},
{ 186, __NR_gettid, 0 },
//{ 13, __NR_rt_sigaction, 4} // wrapped to use my_ version
#ifdef __NR_pipe
{ 22, __NR_pipe, 1},
#endif
#ifdef __NR_fork
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
#endif
//{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack
{ 157, __NR_prctl, 5 }, // needs wrapping?
{ 186, __NR_gettid, 0 }, //0xBA
{ 202, __NR_futex, 6},
{ 217, __NR_getdents64, 3},
#ifdef __NR_inotify_init
{ 253, __NR_inotify_init, 0}, //0xFD
#endif
{ 254, __NR_inotify_add_watch, 3},
{ 255, __NR_inotify_rm_watch, 2},
{ 294, __NR_inotify_init1, 1},
{ 298, __NR_perf_event_open, 5},
{ 318, __NR_getrandom, 3},
};
struct mmap_arg_struct {
@@ -152,6 +174,36 @@ void EXPORT x64Syscall(x64emu_t *emu)
case 3: // sys_close
R_EAX = (uint32_t)close((int)R_EDI);
break;
case 9: // sys_mmap
R_RAX = (uintptr_t)my_mmap64(emu, (void*)R_RDI, R_RSI, (int)R_EDX, (int)R_R10d, (int)R_R8d, R_R9);
break;
case 10: // sys_mprotect
R_EAX = (uint32_t)my_mprotect(emu, (void*)R_RDI, R_RSI, (int)R_EDX);
break;
case 11: // sys_munmap
R_EAX = (uint32_t)my_munmap(emu, (void*)R_RDI, R_RSI);
break;
case 13: // sys_rt_sigaction
R_EAX = (uint32_t)my_sigaction(emu, (int)R_EDI, (const x64_sigaction_t *)R_RSI, (x64_sigaction_t *)R_RDX/*, (size_t)R_R10*/);
break;
#ifndef __NR_pipe
case 22:
R_EAX = (uint32_t)pipe((void*)R_RDI);
break;
#endif
#ifndef __NR_fork
case 57:
R_RAX = fork();
break;
#endif
case 131: // sys_sigaltstack
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
break;
#ifndef __NR_inotify_init
case 253:
R_EAX = (int)syscall(__NR_inotify_init1, 0);
break;
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported Syscall 0x%02Xh (%d)\n", s, s);
emu->quit = 1;
@@ -164,10 +216,11 @@ void EXPORT x64Syscall(x64emu_t *emu)
#define stack(n) (R_RSP+8+n)
#define i32(n) *(int32_t*)stack(n)
#define u32(n) *(uint32_t*)stack(n)
#define i64(n) *(int64_t*)stack(n)
#define u64(n) *(uint64_t*)stack(n)
#define p(n) *(void**)stack(n)
uint32_t EXPORT my_syscall(x64emu_t *emu)
uintptr_t EXPORT my_syscall(x64emu_t *emu)
{
uint32_t s = R_EDI;;
printf_log(LOG_DUMP, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_RIP, s, s, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
@@ -200,6 +253,28 @@ uint32_t EXPORT my_syscall(x64emu_t *emu)
return my_open(emu, (char*)R_RSI, of_convert(R_EDX), R_ECX);
case 3: // sys_close
return (uint32_t)close(R_ESI);
case 9: // sys_mmap
return (uintptr_t)my_mmap64(emu, (void*)R_RSI, R_RDX, (int)R_RCX, (int)R_R8d, (int)R_R9, i64(0));
case 10: // sys_mprotect
return (uint32_t)my_mprotect(emu, (void*)R_RSI, R_RDX, (int)R_ECX);
case 11: // sys_munmap
return (uint32_t)my_munmap(emu, (void*)R_RSI, R_RDX);
case 13: // sys_rt_sigaction
return (uint32_t)my_sigaction(emu, (int)R_ESI, (const x64_sigaction_t *)R_RDX, (x64_sigaction_t *)R_RCX/*, (size_t)R_R8*/);
#ifndef __NR_pipe
case 22:
return (uint32_t)pipe((void*)R_RSI);
#endif
#ifndef __NR_fork
case 57:
return fork();
#endif
case 131: // sys_sigaltstack
return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
#ifndef __NR_inotify_init
case 253:
return (int)syscall(__NR_inotify_init1, 0);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
emu->quit = 1;
+10 -7
View File
@@ -31,7 +31,6 @@ typedef struct kh_dynablocks_s kh_dynablocks_t;
#define JMPTABL_SHIFT 16
typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
#define MAX_SIGNAL 64
@@ -50,6 +49,8 @@ typedef struct needed_libs_s {
void add_neededlib(needed_libs_t* needed, library_t* lib);
void free_neededlib(needed_libs_t* needed);
void add_dependedlib(needed_libs_t* depended, library_t* lib);
void free_dependedlib(needed_libs_t* depended);
typedef struct base_segment_s {
uintptr_t base;
@@ -70,7 +71,7 @@ typedef struct box64context_s {
uint32_t sel_serial; // will be increment each time selectors changes
zydis_t *zydis; // dlopen the zydis dissasembler
void* box64lib; // dlopen on box86 itself
void* box64lib; // dlopen on box64 itself
int argc;
char** argv;
@@ -79,7 +80,7 @@ typedef struct box64context_s {
char** envv;
char* fullpath;
char* box64path; // path of current box86 executable
char* box64path; // path of current box64 executable
uint32_t stacksz;
int stackalign;
@@ -106,9 +107,6 @@ typedef struct box64context_s {
procaddess_t glxprocaddress;
kh_symbolmap_t *alwrappers; // the map of wrapper for alGetProcAddress
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
vkprocaddess_t vkprocaddress;
pthread_mutex_t mutex_once;
pthread_mutex_t mutex_once2;
@@ -198,4 +196,9 @@ int AddTLSPartition(box64context_t* context, int tlssize);
void thread_set_emu(x64emu_t* emu);
x64emu_t* thread_get_emu();
#endif //__BOX64CONTEXT_H_
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
int unlockMutex();
// relock the muxtex that were unlocked
void relockMutex(int locks);
#endif //__BOX64CONTEXT_H_
+12 -1
View File
@@ -29,13 +29,18 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
dynablocklist_t* getDB(uintptr_t idx);
void addJumpTableIfDefault64(void* addr, void* jmp);
void setJumpTableDefault64(void* addr);
int isJumpTableDefault64(void* addr);
uintptr_t getJumpTable64();
uintptr_t getJumpTableAddress64(uintptr_t addr);
#endif
#define PROT_DYNAREC 0x80
#define PROT_DYNAREC 0x80
#define PROT_ALLOC 0x40
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void freeProtection(uintptr_t addr, uintptr_t size);
uint32_t getProtection(uintptr_t addr);
#ifdef DYNAREC
void protectDB(uintptr_t addr, uintptr_t size);
@@ -44,7 +49,13 @@ void unprotectDB(uintptr_t addr, uintptr_t size);
void lockDB();
void unlockDB();
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
// unlock mutex that are locked by current thread (for signal handling). Return a mask of unlock mutex
int unlockCustommemMutex();
// relock the muxtex that were unlocked
void relockCustommemMutex(int locks);
void init_custommem_helper(box64context_t* ctx);
void fini_custommem_helper(box64context_t* ctx);
+8 -5
View File
@@ -14,16 +14,19 @@ extern int box64_dynarec_forced;
extern int box64_dynarec_largest;
extern uintptr_t box64_nodynarec_start, box64_nodynarec_end;
#endif
extern int dlsym_error; // log dlsym error
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int dlsym_error; // log dlsym error
#ifdef HAVE_TRACE
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int trace_regsdiff; // colorize standard registers on changes
extern uintptr_t trace_start, trace_end;
extern char* trace_func;
#endif
extern int allow_missing_libs;
extern int box64_steam;
extern int box64_nopulse; // disabling the use of wrapped pulseaudio
extern int box64_nogtk; // disabling the use of wrapped gtk
extern int box64_novulkan; // disabling the use of wrapped vulkan
extern uintptr_t trace_start, trace_end;
extern char* trace_func;
extern uintptr_t fmod_smc_start, fmod_smc_end; // to handle libfmod (from Unreal) SMC (self modifying code)
extern uint32_t default_gs;
extern int jit_gdb; // launch gdb when a segfault is trapped
+3 -3
View File
@@ -30,7 +30,7 @@ void CalcStack(elfheader_t* h, uint32_t* stacksz, int* 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, int local, box64context_t *box86, x64emu_t* emu);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, library_t *deplib, int local, box64context_t *box64, x64emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RunElfInit(elfheader_t* h, x64emu_t *emu);
@@ -45,7 +45,7 @@ const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uin
int32_t GetTLSBase(elfheader_t* h);
uint32_t GetTLSSize(elfheader_t* h);
void* GetTLSPointer(box64context_t* context, elfheader_t* h);
void* GetDTatOffset(box64context_t* context, int index, int offset);
void* GetDTatOffset(box64context_t* context, unsigned long int index, unsigned long int offset);
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box64context_t *context, uintptr_t addr);
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
@@ -56,4 +56,4 @@ void CreateMemorymapFile(box64context_t* context, int fd);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
#endif //__ELF_LOADER_H_
#endif //__ELF_LOADER_H_
+1 -1
View File
@@ -16,7 +16,7 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
// 1: if file is an x86 elf, 0: if not (or not found)
int FileIsX64ELF(const char* filename);
#if defined(RPI) || defined(RK3399)
#if defined(RPI) || defined(RK3399) || defined(RK3326)
void sanitize_mojosetup_gtk_background();
#endif
+3 -3
View File
@@ -15,7 +15,7 @@ typedef struct kh_mapoffsets_s kh_mapoffsets_t;
typedef char* cstr_t;
lib_t *NewLibrarian(box64context_t* context, int ownlibs);
void FreeLibrarian(lib_t **maplib);
void FreeLibrarian(lib_t **maplib, x64emu_t* emu);
dlprivate_t *NewDLPrivate();
void FreeDLPrivate(dlprivate_t **lib);
@@ -24,7 +24,7 @@ kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box86, x64emu_t* emu); // 0=success, 1=error
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t *deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu); // 0=success, 1=error
library_t* GetLibMapLib(lib_t* maplib, const char* name);
library_t* GetLibInternal(const char* name);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name);
@@ -48,4 +48,4 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
const char* GetNameOffset(lib_t *maplib, void* offs);
#endif //__LIBRARIAN_H_
#endif //__LIBRARIAN_H_
+3 -3
View File
@@ -9,12 +9,12 @@ typedef struct box64context_s box64context_t;
typedef struct x64emu_s x64emu_t;
typedef struct needed_libs_s needed_libs_t;
library_t *NewLibrary(const char* path, box64context_t* box86);
library_t *NewLibrary(const char* path, box64context_t* box64);
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x64emu_t* emu);
int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu);
int ReloadLibrary(library_t* lib, x64emu_t* emu);
void InactiveLibrary(library_t* lib);
void Free1Library(library_t **lib);
void Free1Library(library_t **lib, x64emu_t* emu);
char* GetNameLib(library_t *lib);
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
@@ -33,4 +33,4 @@ lib_t* GetMaplib(library_t* lib);
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. native)
void* GetHandle(library_t* lib); // NULL if not native
#endif //__LIBRARY_H_
#endif //__LIBRARY_H_
+19
View File
@@ -89,6 +89,25 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos);
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos);
struct x64_stat64 { /* x86_64 arm64 */
uint64_t st_dev; /* 0 */ /* 0 */
uint64_t st_ino; /* 8 */ /* 8 */
uint64_t st_nlink; /* 16 */ /* 20 */
uint32_t st_mode; /* 24 */ /* 16 */
uint32_t st_uid; /* 28 */ /* 24 */
uint32_t st_gid; /* 32 */ /* 28 */
int __pad0; /* 36 */ /* --- */
uint64_t st_rdev; /* 40 */ /* 32 */
int64_t st_size; /* 48 */ /* 48 */
int64_t st_blksize; /* 56 */ /* 56 */
uint64_t st_blocks; /* 64 */ /* 64 */
struct timespec st_atim; /* 72 */ /* 72 */
struct timespec st_mtim; /* 88 */ /* 88 */
struct timespec st_ctim; /* 104 */ /* 104 */
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
} __attribute__((packed)); /* 144 */ /* 128 */
void UnalignStat64(const void* source, void* dest);
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef __PATHCOLL_H_
#define __PATHCOLL_H_
// utility to handle path collection (like BOX86_PATH or BOX86_LD_LIBRARY_PATH)
// utility to handle path collection (like BOX64_PATH or BOX64_LD_LIBRARY_PATH)
// paths can be resized with realloc, so don't take address as invariant
typedef struct path_collection_s
+3
View File
@@ -285,6 +285,9 @@ typedef union {
#define R_ESI emu->regs[_SI].dword[0]
#define R_ESP emu->regs[_SP].dword[0]
#define R_EBP emu->regs[_BP].dword[0]
#define R_R8d emu->regs[_R8].dword[0]
#define R_R9d emu->regs[_R9].dword[0]
#define R_R10d emu->regs[_R10].dword[0]
#define R_AX emu->regs[_AX].word[0]
#define R_BX emu->regs[_BX].word[0]
#define R_CX emu->regs[_CX].word[0]
+4 -4
View File
@@ -1,7 +1,7 @@
#ifndef __SDL2RWOPS_H__
#define __SDL2RWOPS_H__
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL1 SDL_RWops
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL2 SDL_RWops
typedef struct x64emu_s x64emu_t;
typedef SDL2_RWops_t* (*sdl2_allocrw)();
@@ -20,12 +20,12 @@ typedef struct SDL2RWSave_s {
// each function will be added to dictionary, and each native functions will be wrapped so they run in emulated world
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops);
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put Native RW function, wrapping emulated (callback style) ones if needed
void RWNativeEnd2(SDL2_RWops_t* ops); // put back emulated function back in place
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put native RW functions, wrapping the emulated (callback style) ones if needed
void RWNativeEnd2(SDL2_RWops_t* ops); // put emulated function back in place
int64_t RWNativeSeek2(SDL2_RWops_t *ops, int64_t offset, int32_t whence);
uint32_t RWNativeRead2(SDL2_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum);
int32_t RWNativeWrite2(SDL2_RWops_t *ops, const void *ptr, int32_t size, int32_t num);
int32_t RWNativeClose2(SDL2_RWops_t* ops);
#endif
#endif
+3
View File
@@ -20,4 +20,7 @@ void fini_pthread_helper(box64context_t* context);
// prepare an "emuthread structure" in pet and return address of function pointer for a "thread creation routine"
void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet);
//check if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
int checkMutex(void* m);
#endif //_THREADS_H_
+1
View File
@@ -37,6 +37,7 @@ void SetRIP(x64emu_t *emu, uint64_t v);
void SetFS(x64emu_t *emu, uint16_t v);
uint16_t GetFS(x64emu_t *emu);
uint64_t GetRSP(x64emu_t *emu);
uint64_t GetRBP(x64emu_t *emu);
void ResetFlags(x64emu_t *emu);
void ResetSegmentsCache(x64emu_t *emu);
const char* DumpCPURegs(x64emu_t* emu, uintptr_t ip);
+88 -42
View File
@@ -34,17 +34,58 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
return maplib;
}
void FreeLibrarian(lib_t **maplib)
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed) {
if (freed[idx]) return; // Already freed
freed[idx] = 1; // Avoid infinite loops
library_t *lib = maplib->libraries[idx];
printf_log(LOG_DEBUG, "Free %s\n", lib->name);
for (int i = lib->depended.size - 1; i >= 0; --i) {
int j;
for (j = 0; j < maplib->libsz; ++j) {
if (lib->depended.libs[i] == maplib->libraries[j]) break;
}
if (j == maplib->libsz) {
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
continue;
}
if (freed[j] == 1) {
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->depended.libs[i]->name);
continue;
}
freeLibraryRecurse(maplib, emu, j, freed);
if (freed[idx] != 1) {
printf_log(LOG_DEBUG, "Library cleared (cyclic dependancy break)\n");
return;
}
}
library_t *oldptr = maplib->libraries[idx];
Free1Library(&maplib->libraries[idx], emu);
maplib->libraries[idx] = oldptr; // Temporarily save the old address
freed[idx] = 2;
}
void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
{
// should that be in reverse order?
if(!maplib || !*maplib)
return;
if((*maplib)->ownlibs) {
if((*maplib)->ownlibs && (*maplib)->libsz) {
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
for (int i=0; i<(*maplib)->libsz; ++i) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
Free1Library(&(*maplib)->libraries[i].lib);
char *freed = (char*)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) {
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);
}
for (int i=0; i<(*maplib)->libsz; ++i) {
(*maplib)->libraries[i] = NULL;
}
free(freed);
}
}
free((*maplib)->libraries);
@@ -103,9 +144,9 @@ kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
library_t* getLib(lib_t* maplib, const char* path)
{
for(int i=0; i<maplib->libsz; ++i) {
onelib_t *onelib = &maplib->libraries[i];
if(IsSameLib(onelib->lib, path)) {
return onelib->lib;
library_t *lib = maplib->libraries[i];
if(IsSameLib(lib, path)) {
return lib;
}
}
return NULL;
@@ -116,7 +157,7 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib)
if(!maplib)
return 0;
for(int i=0; i<maplib->libsz; ++i)
if(maplib->libraries[i].lib==lib)
if(maplib->libraries[i]==lib)
return 1;
return 0;
}
@@ -125,10 +166,9 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
{
if (maplib->libsz == maplib->libcap) {
maplib->libcap += 8;
maplib->libraries = (onelib_t*)realloc(maplib->libraries, maplib->libcap*sizeof(onelib_t));
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
}
maplib->libraries[maplib->libsz].lib = lib;
maplib->libraries[maplib->libsz].name = GetNameLib(lib);
maplib->libraries[maplib->libsz] = lib;
++maplib->libsz;
}
@@ -137,7 +177,7 @@ void MapLibAddMapLib(lib_t* dest, lib_t* src)
if(!src)
return;
for(int i=0; i<src->libsz; ++i) {
library_t* lib = src->libraries[i].lib;
library_t* lib = src->libraries[i];
if(!lib) continue;
if(lib->maplib && src!=lib->maplib) { //TODO: find why is src!=lib->maplib needed
MapLibAddMapLib(dest, lib->maplib);
@@ -154,24 +194,23 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib)
if(!maplib || !lib)
return;
int idx = 0;
while(idx<maplib->libsz && maplib->libraries[idx].lib!=lib) ++idx;
while(idx<maplib->libsz && maplib->libraries[idx]!=lib) ++idx;
if(idx==maplib->libsz) //not found
return;
--maplib->libsz;
if(idx!=(maplib->libsz))
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(onelib_t)*(maplib->libsz-idx));
maplib->libraries[maplib->libsz].lib = NULL;
maplib->libraries[maplib->libsz].name = NULL;
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx));
}
EXPORTDYN
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box64, x64emu_t* emu)
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
{
printf_log(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_dependedlib(&lib->depended, deplib);
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
return 0;
}
@@ -201,6 +240,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
MapLibRemoveLib(my_context->local_maplib, lib);
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
return 0;
}
// load a new one
@@ -211,6 +251,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
// add lib now
if(local) {
@@ -237,17 +278,17 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
} else {
// it's an emulated lib,
// lets load dependancies before adding symbols and launch init sequence
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, 0, box64, emu)) {
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
printf_log(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")) {
AddNeededLib(maplib, &lib->needed, 0, "libGL.so.1", box64, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, "libGL.so.1", box64, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
AddNeededLib(maplib, &lib->needed, 0, "libSDL-1.2.so.0", box64, emu);
AddNeededLib(maplib, &lib->needed, 0, "libdl.so.2", box64, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, "libSDL-1.2.so.0", box64, emu);
AddNeededLib(maplib, &lib->needed, lib, 0, "libdl.so.2", box64, emu);
}
// add symbols
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
@@ -302,8 +343,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]!=self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start)
return 1;
}
@@ -318,8 +359,8 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start)
return 1;
}
@@ -341,14 +382,14 @@ static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uin
return 1;
// search in global symbols
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start)
return 1;
}
// library from newer to older, weak only now
for(int i=maplib->libsz-1; i>=0; --i) {
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) // only weak symbol haven't been found yet
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end)) // only weak symbol haven't been found yet
if(*start)
return 1;
}
@@ -402,10 +443,10 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
return maplib->context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) {
int idx = GetElfIndex(maplib->libraries[i].lib);
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
return maplib->context->elfs[idx];
@@ -421,7 +462,7 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
if(*start || *end)
return 1;
for(int i=0; i<maplib->libsz; ++i)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start || *end)
return 1;
// nope, not found
@@ -433,8 +474,8 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
uintptr_t start=0;
uintptr_t end=0;
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i].lib)==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end))
if(start || end)
return 1;
// nope, not found
@@ -452,8 +493,8 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
return 0;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start)
return 1;
if(self)
@@ -471,8 +512,8 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start || *end)
return 1;
}
@@ -488,8 +529,8 @@ int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end))
if(*start || *end)
return 1;
}
@@ -567,7 +608,12 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
*base = GetBaseAddress(h);
return ret;
}
// TODO: then search in the other libs...
// TODO: find if cyclic references exists (should also fix MapLibAddMapLib)
/* for (int i = 0; i < maplib->libsz; ++i) {
// if (maplib == maplib->libraries[i]->maplib) continue;
const char *nameInLib = FindSymbolName(maplib->libraries[i]->maplib, p, start, sz, libname, base);
if (nameInLib) return nameInLib;
} */
return NULL;
}
+1 -6
View File
@@ -14,11 +14,6 @@ typedef struct onesymbol_s {
// need to track origin?
} onesymbol_t;
typedef struct {
char *name;
library_t *lib;
} onelib_t;
typedef char* cstr_t;
KHASH_MAP_DECLARE_STR(mapsymbols, onesymbol_t)
@@ -31,7 +26,7 @@ typedef struct lib_s {
khash_t(mapsymbols) *localsymbols;
khash_t(mapoffsets) *mapoffsets;
khash_t(mapsymbols) *globaldata;
onelib_t *libraries;
library_t **libraries;
int libsz;
int libcap;
int ownlibs;
+17 -9
View File
@@ -151,7 +151,7 @@ static void initNativeLib(library_t *lib, box64context_t* context) {
lib->type = 0;
// Call librarian to load all dependant elf
for(int i=0; i<lib->priv.w.needed; ++i) {
if(AddNeededLib(context->maplib, &lib->needed, 0, lib->priv.w.neededlibs[i], context, NULL)) { // probably all native, not emulated, so that's fine
if(AddNeededLib(context->maplib, &lib->needed, lib, 0, lib->priv.w.neededlibs[i], context, thread_get_emu())) {
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", lib->priv.w.neededlibs[i]);
return;
}
@@ -246,13 +246,13 @@ library_t *NewLibrary(const char* path, box64context_t* context)
printf_log(LOG_DEBUG, "Simplified name is \"%s\"\n", lib->name);
if(box64_nopulse) {
if(strstr(lib->name, "libpulse.so")==lib->name || strstr(lib->name, "libpulse-simple.so")==lib->name) {
Free1Library(&lib);
Free1Library(&lib, NULL);
return NULL;
}
}
if(box64_novulkan) {
if(strstr(lib->name, "libvulkan.so")==lib->name) {
Free1Library(&lib);
Free1Library(&lib, NULL);
return NULL;
}
}
@@ -270,7 +270,7 @@ library_t *NewLibrary(const char* path, box64context_t* context)
// nothing loaded, so error...
if(lib->type==-1)
{
Free1Library(&lib);
Free1Library(&lib, NULL);
return NULL;
}
@@ -303,6 +303,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
return 1;
}
RelocateElfPlt(my_context->maplib, local_maplib, elf_header);
#ifdef HAVE_TRACE
if(trace_func) {
if (GetGlobalSymbolStartEnd(my_context->maplib, trace_func, &trace_start, &trace_end)) {
SetTraceEmu(trace_start, trace_end);
@@ -316,6 +317,7 @@ int FinalizeLibrary(library_t* lib, lib_t* local_maplib, x64emu_t* emu)
trace_func = NULL;
}
}
#endif
RunElfInit(elf_header, emu);
}
if(box64_dynarec && strcmp(lib->name, "libfmod.so")==0) {
@@ -375,10 +377,18 @@ void InactiveLibrary(library_t* lib)
lib->active = 0;
}
void Free1Library(library_t **lib)
void Free1Library(library_t **lib, x64emu_t* emu)
{
if(!(*lib)) return;
if((*lib)->type==1 && emu) {
elfheader_t *elf_header = (*lib)->context->elfs[(*lib)->priv.n.elf_index];
RunElfFini(elf_header, emu);
}
if((*lib)->maplib)
FreeLibrarian(&(*lib)->maplib, emu);
if((*lib)->type!=-1 && (*lib)->fini) {
(*lib)->fini(*lib);
}
@@ -410,9 +420,7 @@ void Free1Library(library_t **lib)
if((*lib)->symbol2map)
kh_destroy(symbol2map, (*lib)->symbol2map);
free_neededlib(&(*lib)->needed);
if((*lib)->maplib)
FreeLibrarian(&(*lib)->maplib);
free_neededlib(&(*lib)->depended);
free(*lib);
*lib = NULL;
@@ -697,4 +705,4 @@ lib_t* GetMaplib(library_t* lib)
if(!lib)
return NULL;
return lib->maplib;
}
}
+4 -3
View File
@@ -35,7 +35,7 @@ typedef struct wlib_s {
void* lib; // dlopen result
void* priv; // actual private
void* p2; // second private
void* box64lib; // ref to the dlopen on box86 itself from context
void* box64lib; // ref to the dlopen on box64 itself from context
char* altprefix; // if function names are mangled..
int needed;
char** neededlibs;
@@ -73,8 +73,9 @@ typedef struct library_s {
kh_datamap_t *datamap;
kh_datamap_t *wdatamap;
kh_datamap_t *mydatamap;
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
needed_libs_t needed;
needed_libs_t depended; // used to free library
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
} library_t;
@@ -98,4 +99,4 @@ typedef struct map_onedata_s {
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size); // Add bridges to functions
#endif //__LIBRARY_PRIVATE_H_
#endif //__LIBRARY_PRIVATE_H_
+38 -36
View File
@@ -18,6 +18,7 @@ GO("libSDL2.so", sdl2)
GO("libsdl2-2.0.so.0", sdl2)
GO("libSDL2_mixer-2.0.so.0", sdl2mixer)
GO("libSDL2_image-2.0.so.0", sdl2image)
GO("libSDL2_net-2.0.so.0", sdl2net)
GO("libSDL2_ttf-2.0.so.0", sdl2ttf)
GO("libSDL-1.2.so.0", sdl1)
GO("libSDL_mixer-1.2.so.0", sdl1mixer)
@@ -25,24 +26,24 @@ GO("libSDL_image-1.2.so.0", sdl1image)
GO("libSDL_ttf-2.0.so.0", sdl1ttf)
GO("libsmpeg-0.4.so.0", smpeg)
GO("libsmpeg2-2.0.so.0", smpeg2)
//GO("libvorbisfile.so.3", vorbisfile)
//GO("libvorbis.so.0", libvorbis)
//GO("libogg.so.0", libogg)
GO("libvorbisfile.so.3", vorbisfile)
GO("libvorbis.so.0", libvorbis)
GO("libogg.so.0", libogg)
//GO("libpng12.so.0", png12)
//GO("libpng16.so.16", png16)
GO("libXxf86vm.so.1", libxxf86vm)
GO("libXinerama.so.1", xinerama)
GO("libXrandr.so.2", libxrandr)
GO("libXext.so.6", libxext)
//GO("libXfixes.so.3", libxfixes)
//GO("libXcursor.so.1", libxcursor)
GO("libXfixes.so.3", libxfixes)
GO("libXcursor.so.1", libxcursor)
GO("libXrender.so.1", libxrender)
GO("libXi.so.6", libxi)
//GO("libXss.so.1", libxss)
//GO("libXpm.so.4", libxpm)
GO("libXss.so.1", libxss)
GO("libXpm.so.4", libxpm)
GO("libXau.so.6", libxau)
GO("libXdmcp.so.6", libxdmcp)
//GO("libX11-xcb.so.1", libx11xcb)
GO("libX11-xcb.so.1", libx11xcb)
GO("libxcb.so.1", libxcb)
//GO("libxcb-xfixes.so.0", libxcbxfixes)
//GO("libxcb-shape.so.0", libxcbshape)
@@ -54,11 +55,11 @@ GO("libxcb.so.1", libxcb)
//GO("libxcb-dri2.so.0", libxcbdri2)
//GO("libxcb-dri3.so.0", libxcbdri3)
//GO("libxcb-present.so.0", libxcbpresent)
//GO("libXtst.so.6", libxtst)
//GO("libXt.so.6", libxt)
//GO("libXcomposite.so.1", libxcomposite)
//GO("libXdamage.so.1", libxdamage)
//GO("libXmu.so.6", libxmu)
GO("libXtst.so.6", libxtst)
GO("libXt.so.6", libxt)
GO("libXcomposite.so.1", libxcomposite)
GO("libXdamage.so.1", libxdamage)
GO("libXmu.so.6", libxmu)
GO("libz.so.1", libz)
GO("libopenal.so.1", openal)
GO("libopenal.so.0", openal)
@@ -69,19 +70,19 @@ GO("libalure.so.1", alure)
//GO("libjpeg.so.8", libjpeg)
//GO("libjpeg.so.62", libjpeg62)
//GO("libturbojpeg.so.0", turbojpeg)
//GO("libcurl.so.4", curl)
//GO("libcurl-gnutls.so.4", curl)
//GO("libudev.so.0", udev0)
//GO("libudev.so.1", udev1)
//GO("libdbus-1.so.3", dbus)
GO("libcurl.so.4", curl)
GO("libcurl-gnutls.so.4", curl)
GO("libudev.so.0", udev0)
GO("libudev.so.1", udev1)
GO("libdbus-1.so.3", dbus)
//GO("libiconv.so.2", iconv)
//GO("libdrm.so.2", libdrm)
//GO("libcrypto.so.1", crypto)
//GO("libssl.so.1", libssl)
GO("libcrypto.so.1", crypto)
GO("libssl.so.1", libssl)
//GO("libcrypt.so.1", libcrypt)
//GO("libutil.so.1", util)
//GO("libuuid.so.1", libuuid)
//GO("libresolv.so.2", libresolv)
GO("libutil.so.1", util)
GO("libuuid.so.1", libuuid)
GO("libresolv.so.2", libresolv)
GO("libpulse-simple.so.0", pulsesimple)
GO("libpulse.so.0", pulse)
//GO("libsndfile.so.1", libsndfile)
@@ -103,19 +104,20 @@ GO("libpulse.so.0", pulse)
//GO("libgudev-1.0.so.0", gudev1)
//GO("libappindicator.so.1", appindicator)
//GO("libatk-1.0.so.0", atk)
//GO("libpangoft2-1.0.so", pangoft2)
//GO("libpangoft2-1.0.so.0", pangoft2)
//GO("libpangocairo-1.0.so.0", pangocairo)
//GO("libcairo.so.2", cairo)
//GO("libpango-1.0.so.0", pango)
GO("libpangoft2-1.0.so", pangoft2)
GO("libpangoft2-1.0.so.0", pangoft2)
GO("libpangocairo-1.0.so.0", pangocairo)
GO("libcairo.so.2", cairo)
GO("libpango-1.0.so.0", pango)
//GO("libnm.so.0", libnm)
//GO("libnm-glib.so.4", libnm)
//GO("libnm-util.so.2", libnm)
//GO("libfontconfig.so.1", fontconfig)
//GO("libfreetype.so.6", freetype)
//GO("libbz2.so.1", bz2)
//GO("libSM.so.6", libsm)
//GO("libICE.so.6", libice)
GO("libfontconfig.so.1", fontconfig)
GO("libfreetype.so.6", freetype)
GO("libbz2.so.1", bz2)
GO("liblzma.so.5", lzma)
GO("libSM.so.6", libsm)
GO("libICE.so.6", libice)
//GO("libusb-1.0.so.0", libusb1)
//GO("libncursesw.so.5", libncursesw)
//GO("libformw.so.5", libformw)
@@ -125,8 +127,8 @@ GO("libpulse.so.0", pulse)
//GO("libtinfo.so.6", libtinfo6)
//GO("libtcmalloc_minimal.so.4", tcmallocminimal)
//GO("libmpg123.so.0", mpg123)
//GO("libgnutls.so.30", gnutls)
//GO("libcups.so.2", libcups)
GO("libgnutls.so.30", gnutls)
GO("libcups.so.2", libcups)
//GO("d3dadapter9.so.1", d3dadapter9)
//GO("libvulkan.so.1", vulkan)
//GO("libvulkan.so", vulkan)
@@ -143,4 +145,4 @@ GO("libpulse.so.0", pulse)
GO("ld-linux-x86-64.so.2", ldlinux)
//GO("crashhandler.so", crashhandler)
GO("crashhandler.so", crashhandler)
+224 -131
View File
@@ -100,7 +100,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
++p;
break;
case 14: //%LG long double
if((((uintptr_t)(st+1))&0xf)!=0)
if((((uintptr_t)st)&0xf)!=0)
st++;
#ifdef HAVE_LD80BITS
if((((uintptr_t)mystack)&0xf)!=0)
@@ -136,7 +136,7 @@ void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystac
++p;
break;
default:
// whattt?
// whaaaat?
state = 0;
}
}
@@ -230,11 +230,232 @@ void myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* m
++p;
break;
default:
// whattt?
// whaaaat?
state = 0;
}
}
}
void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos)
{
// loop...
const wchar_t* p = (const wchar_t*)fmt;
int state = 0;
#ifndef HAVE_LD80BITS
double d;
long double ld;
#endif
int x = 0;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
if(xmm) {
*mystack = emu->xmm[x++].q[0];
--xmm;
mystack++;
} else {
*mystack = *st;
st++; mystack++;
}
state = 0;
++p;
break;
case 14: //%LG long double
if((((uintptr_t)st)&0xf)!=0)
st++;
#ifdef HAVE_LD80BITS
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
memcpy(mystack, st, 16);
st+=2; mystack+=2;
#else
// there is 128bits long double on ARM64, but they need 128bit alignment
if((((uintptr_t)mystack)&0xf)!=0)
mystack++;
LD2D((void*)st, &d);
ld = d ;
memcpy(mystack, &ld, 16);
st+=2; mystack+=2;
#endif
state = 0;
++p;
break;
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 30:
if(pos<6)
*mystack = emu->regs[regs_abi[pos++]].q[0];
else {
*mystack = *st;
++st;
}
++mystack;
state = 0;
++p;
break;
default:
// whaaaattt?
state = 0;
}
}
}
void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos)
{
if(!fmt)
return;
// loop...
const wchar_t* p = (const wchar_t*)fmt;
int state = 0;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack....
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 14: //%LG long double
case 20: // fallback
case 21:
case 22:
case 23: // 64bits int
case 24: // normal int / pointer
case 30:
if(pos<6)
*mystack = emu->regs[regs_abi[pos++]].q[0];
else {
*mystack = *st;
++st;
}
++mystack;
state = 0;
++p;
break;
default:
// whaaaat?
state = 0;
}
}
}
#if 0
void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
{
@@ -418,140 +639,12 @@ void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack)
} while (*p && (inblocks || state));
}
void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack)
{
// loop...
const wchar_t* p = (const wchar_t*)fmt;
int state = 0;
double d;
while(*p)
{
switch(state) {
case 0:
switch(*p) {
case '%': state = 1; ++p; break;
default:
++p;
}
break;
case 1: // normal
case 2: // l
case 3: // ll
case 4: // L
switch(*p) {
case '%': state = 0; ++p; break; //%% = back to 0
case 'l': ++state; if (state>3) state=3; ++p; break;
case 'L': state = 4; ++p; break;
case 'a':
case 'A':
case 'e':
case 'E':
case 'g':
case 'G':
case 'F':
case 'f': state += 10; break; // float
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': state += 20; break; // int
case 'h': ++p; break; // ignored...
case '\'':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
case '+':
case '-': ++p; break; // formating, ignored
case 'm': state = 0; ++p; break; // no argument
case 'n':
case 'p':
case 'S':
case 's': state = 30; break; // pointers
case '$': ++p; break; // should issue a warning, it's not handled...
case '*': *(mystack++) = *(st++); ++p; break; //fetch an int in the stack
case ' ': state=0; ++p; break;
default:
state=20; // other stuff, put an int...
}
break;
case 11: //double
case 12: //%lg, still double
case 13: //%llg, still double
case 23: // 64bits int
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
*(uint64_t*)mystack = *(uint64_t*)st;
st+=2; mystack+=2;
state = 0;
++p;
break;
case 14: //%LG long double
#ifdef HAVE_LD80BITS
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
memcpy(mystack, st, 10);
st+=3; mystack+=3;
#else
// there is no long double on ARM, so tranform that in a regular double
LD2D((void*)st, &d);
if((((uint32_t)mystack)&0x7)!=0)
mystack++;
*(uint64_t*)mystack = *(uint64_t*)&d;
st+=3; mystack+=2;
#endif
state = 0;
++p;
break;
case 20: // fallback
case 21:
case 22:
case 24: // normal int / pointer
case 30:
*mystack = *st;
++mystack;
++st;
state = 0;
++p;
break;
default:
// whattt?
state = 0;
}
}
}
#endif
#undef st_atime
#undef st_mtime
#undef st_ctime
struct x64_stat64 { /* x86_64 arm64 */
uint64_t st_dev; /* 0 */ /* 0 */
uint64_t st_ino; /* 8 */ /* 8 */
uint64_t st_nlink; /* 16 */ /* 20 */
uint32_t st_mode; /* 24 */ /* 16 */
uint32_t st_uid; /* 28 */ /* 24 */
uint32_t st_gid; /* 32 */ /* 28 */
int __pad0; /* 36 */ /* --- */
uint64_t st_rdev; /* 40 */ /* 32 */
int64_t st_size; /* 48 */ /* 48 */
int64_t st_blksize; /* 56 */ /* 56 */
uint64_t st_blocks; /* 64 */ /* 64 */
struct timespec st_atim; /* 72 */ /* 72 */
struct timespec st_mtim; /* 88 */ /* 88 */
struct timespec st_ctim; /* 104 */ /* 104 */
uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */
} __attribute__((packed)); /* 144 */ /* 128 */
void UnalignStat64(const void* source, void* dest)
{
struct x64_stat64 *x64st = (struct x64_stat64*)dest;
+128 -67
View File
@@ -119,7 +119,7 @@ struct x64_fpstate
typedef struct x64_fpstate *x64_fpregset_t;
typedef struct
typedef struct x64_stack_s
{
void *ss_sp;
int ss_flags;
@@ -257,12 +257,6 @@ static void sigstack_destroy(void* p)
free(ss);
}
static void free_signal_emu(void* p)
{
if(p)
FreeX64Emu((x64emu_t**)&p);
}
static pthread_key_t sigstack_key;
static pthread_once_t sigstack_key_once = PTHREAD_ONCE_INIT;
@@ -270,38 +264,22 @@ static void sigstack_key_alloc() {
pthread_key_create(&sigstack_key, sigstack_destroy);
}
static pthread_key_t sigemu_key;
static pthread_once_t sigemu_key_once = PTHREAD_ONCE_INIT;
static void sigemu_key_alloc() {
pthread_key_create(&sigemu_key, free_signal_emu);
}
static x64emu_t* get_signal_emu()
{
x64emu_t *emu = (x64emu_t*)pthread_getspecific(sigemu_key);
if(!emu) {
const int stsize = 8*1024; // small stack for signal handler
void* stack = calloc(1, stsize);
emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stsize, 1);
emu->type = EMUTYPE_SIGNAL;
pthread_setspecific(sigemu_key, emu);
}
return emu;
}
uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
{
if(fnc==0 || fnc==1) {
printf_log(LOG_NONE, "BOX86: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
printf_log(LOG_NONE, "BOX64: Warning, calling Signal function handler %s\n", fnc?"SIG_DFL":"SIG_IGN");
return 0;
}
#ifdef HAVE_TRACE
uintptr_t old_start = trace_start, old_end = trace_end;
// trace_start = 0; trace_end = 1; // disabling trace, globably for now...
#if 0
trace_start = 0; trace_end = 1; // disabling trace, globably for now...
#endif
#endif
x64emu_t *emu = get_signal_emu();
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, ESP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
x64emu_t *emu = thread_get_emu();
printf_log(LOG_DEBUG, "%04d|signal function handler %p called, RSP=%p\n", GetTID(), (void*)fnc, (void*)R_RSP);
/*SetFS(emu, default_fs);*/
for (int i=0; i<6; ++i)
@@ -334,7 +312,9 @@ uint64_t RunFunctionHandler(int* exit, uintptr_t fnc, int nargs, ...)
uint64_t ret = R_RAX;
#ifdef HAVE_TRACE
trace_start = old_start; trace_end = old_end;
#endif
return ret;
}
@@ -345,13 +325,12 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
errno = EFAULT;
return -1;
}
x64emu_t *sigemu = get_signal_emu();
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
if(!ss) {
if(!new_ss) {
oss->ss_flags = SS_DISABLE;
oss->ss_sp = sigemu->init_stack;
oss->ss_size = sigemu->size_stack;
oss->ss_sp = emu->init_stack;
oss->ss_size = emu->size_stack;
} else {
oss->ss_flags = new_ss->ss_flags;
oss->ss_sp = new_ss->ss_sp;
@@ -370,15 +349,14 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
free(new_ss);
pthread_setspecific(sigstack_key, NULL);
sigemu->regs[_SP].dword[0] = ((uintptr_t)sigemu->init_stack + sigemu->size_stack) & ~7;
return 0;
}
if(oss) {
if(!new_ss) {
oss->ss_flags = SS_DISABLE;
oss->ss_sp = sigemu->init_stack;
oss->ss_size = sigemu->size_stack;
oss->ss_sp = emu->init_stack;
oss->ss_size = emu->size_stack;
} else {
oss->ss_flags = new_ss->ss_flags;
oss->ss_sp = new_ss->ss_sp;
@@ -392,8 +370,6 @@ EXPORT int my_sigaltstack(x64emu_t* emu, const x64_stack_t* ss, x64_stack_t* oss
pthread_setspecific(sigstack_key, new_ss);
sigemu->regs[_SP].dword[0] = ((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f;
return 0;
}
@@ -402,11 +378,31 @@ void my_sighandler(int32_t sig)
{
pthread_mutex_unlock(&my_context->mutex_trace); // just in case
printf_log(LOG_DEBUG, "Sighanlder for signal #%d called (jump to %p)\n", sig, (void*)my_context->signals[sig]);
// save values
x64emu_t *emu = thread_get_emu();
uintptr_t restorer = my_context->restorer[sig];
uintptr_t old_regs[16] = {0};
uintptr_t old_ip = emu->ip.q[0];
uint64_t old_flags = emu->eflags.x64;
for(int i=0; i<16; ++i)
old_regs[i] = emu->regs[i].q[0];
x64_stack_t *new_ss = (x64_stack_t*)pthread_getspecific(sigstack_key);
if(new_ss) {
// no alternate stack, so signal RSP needs to match thread RSP!
R_RSP = (uintptr_t)(new_ss->ss_sp+new_ss->ss_size-32);
}
int exits = 0;
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 1, sig);
// restore regs
emu->ip.q[0] = old_ip;
emu->eflags.x64 = old_flags;
for(int i=0; i<16; ++i)
emu->regs[i].q[0] = old_regs[i];
if(exits)
exit(ret);
// what about the restored regs?
if(restorer)
RunFunctionHandler(&exits, restorer, 0);
}
@@ -438,8 +434,8 @@ uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr)
void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int* old_code, void* cur_db)
{
// need to create some x64_ucontext????
pthread_mutex_unlock(&my_context->mutex_trace); // just in case
int Locks = unlockMutex();
printf_log(LOG_DEBUG, "Sigactionhanlder for signal #%d called (jump to %p/%s)\n", sig, (void*)my_context->signals[sig], GetNativeName((void*)my_context->signals[sig]));
uintptr_t restorer = my_context->restorer[sig];
@@ -455,12 +451,11 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
}
#endif
// stack tracking
x64emu_t *sigemu = get_signal_emu();
x64_stack_t *new_ss = my_context->onstack[sig]?(x64_stack_t*)pthread_getspecific(sigstack_key):NULL;
int used_stack = 0;
if(new_ss) {
if(new_ss->ss_flags == SS_ONSTACK) { // already using it!
frame = (uintptr_t*)sigemu->regs[_SP].q[0];
frame = (uintptr_t*)emu->regs[_SP].q[0];
} else {
frame = (uintptr_t*)(((uintptr_t)new_ss->ss_sp + new_ss->ss_size - 16) & ~0x0f);
used_stack = 1;
@@ -523,11 +518,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
//((unsigned int *)(&sigcontext.xstate.fpstate.padding))[8*4+12] = 0x46505853; // not yet, when XSAVE / XRSTR will be ready
// get signal mask
if(!new_ss) {
sigcontext->uc_stack.ss_sp = sigemu->init_stack;
sigcontext->uc_stack.ss_size = sigemu->size_stack;
sigcontext->uc_stack.ss_flags = SS_DISABLE;
} else {
if(new_ss) {
sigcontext->uc_stack.ss_sp = new_ss->ss_sp;
sigcontext->uc_stack.ss_size = new_ss->ss_size;
sigcontext->uc_stack.ss_flags = new_ss->ss_flags;
@@ -570,7 +561,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
} else {
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
//X64_ERR seems to be INT:8 CODE:8. So for write access segfault it's 0x0002 For a read it's 0x0004 (and 8 for exec). For an int 2d it could be 0x2D01 for example
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box86 anyway
sigcontext->uc_mcontext.gregs[X64_ERR] = 0x0004; // read error? there is no execute control in box64 anyway
}
if(info->si_code == SEGV_ACCERR && old_code)
*old_code = -1;
@@ -580,20 +571,40 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
sigcontext->uc_mcontext.gregs[X64_TRAPNO] = 6;
// call the signal handler
x64_ucontext_t sigcontext_copy = *sigcontext;
// save old value from emu
#define GO(A) uint64_t old_##A = R_##A
GO(RAX);
GO(RDI);
GO(RSI);
GO(RDX);
GO(RCX);
GO(R8);
GO(R9);
GO(RBP);
#undef GO
// set stack pointer
sigemu->regs[_SP].dword[0] = (uintptr_t)frame;
// set segments
memcpy(sigemu->segs, emu->segs, sizeof(sigemu->segs));
R_RSP = (uintptr_t)frame;
// set frame pointer
R_RBP = sigcontext->uc_mcontext.gregs[X64_RBP];
int exits = 0;
int ret = RunFunctionHandler(&exits, my_context->signals[sig], 3, sig, info, sigcontext);
// restore old value from emu
#define GO(A) R_##A = old_##A
GO(RAX);
GO(RDI);
GO(RSI);
GO(RDX);
GO(RCX);
GO(R8);
GO(R9);
GO(RBP);
#undef GO
if(memcmp(sigcontext, &sigcontext_copy, sizeof(x64_ucontext_t))) {
emu_jmpbuf_t* ejb = GetJmpBuf();
if(ejb->jmpbuf_ok) {
#define GO(R) if(sigcontext->uc_mcontext.gregs[X64_R##R]!=sigcontext_copy.uc_mcontext.gregs[X64_R##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
#define GO(R) ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
GO(AX);
GO(CX);
GO(DX);
@@ -603,7 +614,7 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
GO(SP);
GO(BX);
#undef GO
#define GO(R) if(sigcontext->uc_mcontext.gregs[X64_##R]!=sigcontext_copy.uc_mcontext.gregs[X64_##R]) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[X64_##R]
#define GO(R) ejb->emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
GO(R8);
GO(R9);
GO(R10);
@@ -613,10 +624,10 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
GO(R14);
GO(R15);
#undef GO
if(sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP]) ejb->emu->ip.dword[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
ejb->emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
sigcontext->uc_mcontext.gregs[X64_RIP] = R_RIP;
// flags
if(sigcontext->uc_mcontext.gregs[X64_EFL]!=sigcontext_copy.uc_mcontext.gregs[X64_EFL]) ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
ejb->emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
// get segments
uint16_t seg;
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
@@ -632,17 +643,54 @@ void my_sigactionhandler_oldcode(int32_t sig, siginfo_t* info, void * ucntx, int
*old_code = -1; // re-init the value to allow another segfault at the same place
if(used_stack) // release stack
new_ss->ss_flags = 0;
relockMutex(Locks);
longjmp(ejb->jmpbuf, 1);
}
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":"");
}
// restore regs...
#define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_R##R]
GO(AX);
GO(CX);
GO(DX);
GO(DI);
GO(SI);
GO(BP);
GO(SP);
GO(BX);
#undef GO
#define GO(R) emu->regs[_##R].q[0]=sigcontext->uc_mcontext.gregs[X64_##R]
GO(R8);
GO(R9);
GO(R10);
GO(R11);
GO(R12);
GO(R13);
GO(R14);
GO(R15);
#undef GO
emu->ip.q[0]=sigcontext->uc_mcontext.gregs[X64_RIP];
emu->eflags.x64=sigcontext->uc_mcontext.gregs[X64_EFL];
uint16_t seg;
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 0)&0xffff;
#define GO(S) emu->segs[_##S]=seg; emu->segs_serial[_##S] = 0;
GO(CS);
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 16)&0xffff;
GO(GS);
seg = (sigcontext->uc_mcontext.gregs[X64_CSGSFS] >> 32)&0xffff;
GO(FS);
#undef GO
printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer);
if(exits)
if(exits) {
relockMutex(Locks);
exit(ret);
}
if(restorer)
RunFunctionHandler(&exits, restorer, 0);
RunFunctionHandler(&exits, 0, restorer, 0);
if(used_stack) // release stack
new_ss->ss_flags = 0;
relockMutex(Locks);
}
void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
@@ -662,8 +710,9 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
void * pc = NULL; // unknow arch...
#warning Unhandled architecture
#endif
#ifdef DYNAREC
int Locks = unlockMutex();
uint32_t prot = getProtection((uintptr_t)addr);
#ifdef DYNAREC
dynablock_t* db = NULL;
int db_searched = 0;
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
@@ -698,12 +747,17 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
ejb->emu->ip.q[0] = getX64Address(db, (uintptr_t)pc);
ejb->emu->eflags.x64 = p->uc_mcontext.regs[26];
dynarec_log(LOG_DEBUG, "Auto-SMC detected, getting out of current Dynablock!\n");
relockMutex(Locks);
longjmp(ejb->jmpbuf, 2);
}
dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr);
}
// done
if(prot&PROT_WRITE) return; // if there is no write permission, don't return and continue to program signal handling
if(prot&PROT_WRITE) {
// if there is no write permission, don't return and continue to program signal handling
relockMutex(Locks);
return;
}
} else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&(PROT_READ|PROT_WRITE))) {
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
@@ -713,6 +767,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
if(addr && pc && db) {
// probably a glitch due to intensive multitask...
dynarec_log(/*LOG_DEBUG*/LOG_INFO, "SIGSEGV with Access error on %p for %p , db=%p, retrying\n", pc, addr, db);
relockMutex(Locks);
return; // try again
}
}
@@ -727,6 +782,10 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
printf_log(log_minimum, "%04d|Double %s (code=%d, pc=%p, addr=%p)!\n", GetTID(), signame, old_code, old_pc, old_addr);
exit(-1);
} else {
if(sig==SIGSEGV && info->si_code==2 && ((prot&~PROT_CUSTOM)==5 || (prot&~PROT_CUSTOM)==7)) {
relockMutex(Locks);
return; // that's probably just a multi-task glitch, like seen in terraria
}
#ifdef DYNAREC
if(!db_searched)
db = FindDynablockFromNativeAddress(pc);
@@ -779,8 +838,10 @@ exit(-1);
uint32_t hash = 0;
if(db)
hash = X31_hash_code(db->x64_addr, db->x64_size);
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp, addr, info->si_code,
printf_log(log_minimum, "%04d|%s @%p (%s) (x64pc=%p/%s:\"%s\", rsp=%p, stack=%p:%p own=%p fp=%p), for accessing %p (code=%d/prot=%x), db=%p(%p:%p/%p:%p/%s:%s, hash:%x/%x)",
GetTID(), signame, pc, name, (void*)x64pc, elfname?elfname:"???", x64name?x64name:"???", rsp,
emu->init_stack, emu->init_stack+emu->size_stack, emu->stack2free, (void*)R_RBP,
addr, info->si_code,
prot, db, db?db->block:0, db?(db->block+db->size):0,
db?db->x64_addr:0, db?(db->x64_addr+db->x64_size):0,
getAddrFunctionName((uintptr_t)(db?db->x64_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
@@ -794,6 +855,7 @@ exit(-1);
else
printf_log(log_minimum, "\n");
}
relockMutex(Locks);
if(my_context->signals[sig] && my_context->signals[sig]!=1) {
if(my_context->is_sigaction[sig])
my_sigactionhandler_oldcode(sig, info, ucntx, &old_code, db);
@@ -1168,7 +1230,6 @@ void init_signal_helper(box64context_t* context)
sigaction(SIGILL, &action, NULL);
pthread_once(&sigstack_key_once, sigstack_key_alloc);
pthread_once(&sigemu_key_once, sigemu_key_alloc);
}
void fini_signal_helper()
+407 -120
View File
@@ -7,6 +7,7 @@
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/mman.h>
#include "debug.h"
#include "box64context.h"
@@ -199,7 +200,7 @@ x64emu_t* thread_get_emu()
stacksize = stack_size;
pthread_attr_destroy(&attr);
}
void* stack = calloc(1, stacksize);
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
x64emu_t *emu = NewX64Emu(my_context, 0, (uintptr_t)stack, stacksize, 1);
SetupX64Emu(emu);
thread_set_emu(emu);
@@ -227,6 +228,9 @@ static void* pthread_routine(void* p)
et->emu->type = EMUTYPE_MAIN;
// setup callstack and run...
x64emu_t* emu = et->emu;
Push64(emu, 0); // PUSH BP
R_RBP = R_RSP; // MOV BP, SP
R_RSP -= 56; // Gard zone
PushExit(emu);
R_RIP = et->fnc;
R_RDI = (uintptr_t)et->arg;
@@ -236,16 +240,61 @@ static void* pthread_routine(void* p)
return ret;
}
#ifdef NOALIGN
pthread_attr_t* getAlignedAttr(pthread_attr_t* m) {
return m;
}
void freeAlignedAttr(void* attr) {
}
#else
typedef struct aligned_attr_s {
uint64_t sign;
pthread_attr_t *at;
} aligned_attr_t;
#define SIGN_ATTR *(uint64_t*)"BOX64ATT"
pthread_attr_t* getAlignedAttrWithInit(pthread_attr_t* attr, int init)
{
if(!attr)
return attr;
aligned_attr_t* at = (aligned_attr_t*)attr;
if(init && at->sign==SIGN_ATTR)
return at->at;
pthread_attr_t* ret = (pthread_attr_t*)calloc(1, sizeof(pthread_attr_t));
at->sign = SIGN_ATTR;
at->at = ret;
if(init)
pthread_attr_init(ret); // init?
return ret;
}
pthread_attr_t* getAlignedAttr(pthread_attr_t* attr)
{
return getAlignedAttrWithInit(attr, 1);
}
void freeAlignedAttr(void* attr)
{
if(!attr)
return;
aligned_attr_t* at = (aligned_attr_t*)attr;
if(at->sign==SIGN_ATTR) {
free(at->at);
at->sign = 0LL;
}
}
#endif
EXPORT int my_pthread_attr_destroy(x64emu_t* emu, void* attr)
{
if(emu->context->stacksizes)
FreeStackSize(emu->context->stacksizes, (uintptr_t)attr);
return pthread_attr_destroy(attr);
int ret = pthread_attr_destroy(getAlignedAttr(attr));
freeAlignedAttr(attr);
return ret;
}
EXPORT int my_pthread_attr_getstack(x64emu_t* emu, void* attr, void** stackaddr, size_t* stacksize)
{
int ret = pthread_attr_getstack(attr, stackaddr, stacksize);
int ret = pthread_attr_getstack(getAlignedAttr(attr), stackaddr, stacksize);
if (ret==0)
GetStackSize(emu, (uintptr_t)attr, stackaddr, stacksize);
return ret;
@@ -259,7 +308,7 @@ EXPORT int my_pthread_attr_setstack(x64emu_t* emu, void* attr, void* stackaddr,
AddStackSize(emu->context->stacksizes, (uintptr_t)attr, stackaddr, stacksize);
//Don't call actual setstack...
//return pthread_attr_setstack(attr, stackaddr, stacksize);
return pthread_attr_setstacksize(attr, stacksize);
return pthread_attr_setstacksize(getAlignedAttr(attr), stacksize);
}
EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacksize)
@@ -267,9 +316,87 @@ EXPORT int my_pthread_attr_setstacksize(x64emu_t* emu, void* attr, size_t stacks
//aarch64 have an PTHREAD_STACK_MIN of 131072 instead of 16384 on x86_64!
if(stacksize<PTHREAD_STACK_MIN)
stacksize = PTHREAD_STACK_MIN;
return pthread_attr_setstacksize(attr, stacksize);
return pthread_attr_setstacksize(getAlignedAttr(attr), stacksize);
}
#ifndef NOALIGN
EXPORT int my_pthread_attr_getdetachstate(x64emu_t* emu, pthread_attr_t* attr, int *state)
{
return pthread_attr_getdetachstate(getAlignedAttr(attr), state);
}
EXPORT int my_pthread_attr_getguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
{
return pthread_attr_getguardsize(getAlignedAttr(attr), size);
}
EXPORT int my_pthread_attr_getinheritsched(x64emu_t* emu, pthread_attr_t* attr, int* sched)
{
return pthread_attr_getinheritsched(getAlignedAttr(attr), sched);
}
EXPORT int my_pthread_attr_getschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
{
return pthread_attr_getschedparam(getAlignedAttr(attr), param);
}
EXPORT int my_pthread_attr_getschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int* policy)
{
return pthread_attr_getschedpolicy(getAlignedAttr(attr), policy);
}
EXPORT int my_pthread_attr_getscope(x64emu_t* emu, pthread_attr_t* attr, int* scope)
{
return pthread_attr_getscope(getAlignedAttr(attr), scope);
}
EXPORT int my_pthread_attr_getstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
{
size_t size;
return pthread_attr_getstack(getAlignedAttr(attr), addr, &size);
//return pthread_attr_getstackaddr(getAlignedAttr(attr), addr);
}
EXPORT int my_pthread_attr_getstacksize(x64emu_t* emu, pthread_attr_t* attr, size_t* size)
{
void* addr;
return pthread_attr_getstack(getAlignedAttr(attr), &addr, size);
//return pthread_attr_getstacksize(getAlignedAttr(attr), size);
}
EXPORT int my_pthread_attr_init(x64emu_t* emu, pthread_attr_t* attr)
{
return pthread_attr_init(getAlignedAttrWithInit(attr, 0));
}
EXPORT int my_pthread_attr_setaffinity_np(x64emu_t* emu, pthread_attr_t* attr, size_t cpusize, void* cpuset)
{
return pthread_attr_setaffinity_np(getAlignedAttr(attr), cpusize, cpuset);
}
EXPORT int my_pthread_attr_setdetachstate(x64emu_t* emu, pthread_attr_t* attr, int state)
{
return pthread_attr_setdetachstate(getAlignedAttr(attr), state);
}
EXPORT int my_pthread_attr_setguardsize(x64emu_t* emu, pthread_attr_t* attr, size_t size)
{
return pthread_attr_setguardsize(getAlignedAttr(attr), size);
}
EXPORT int my_pthread_attr_setinheritsched(x64emu_t* emu, pthread_attr_t* attr, int sched)
{
return pthread_attr_setinheritsched(getAlignedAttr(attr), sched);
}
EXPORT int my_pthread_attr_setschedparam(x64emu_t* emu, pthread_attr_t* attr, void* param)
{
return pthread_attr_setschedparam(getAlignedAttr(attr), param);
}
EXPORT int my_pthread_attr_setschedpolicy(x64emu_t* emu, pthread_attr_t* attr, int policy)
{
return pthread_attr_setschedpolicy(getAlignedAttr(attr), policy);
}
EXPORT int my_pthread_attr_setscope(x64emu_t* emu, pthread_attr_t* attr, int scope)
{
return pthread_attr_setscope(getAlignedAttr(attr), scope);
}
EXPORT int my_pthread_attr_setstackaddr(x64emu_t* emu, pthread_attr_t* attr, void* addr)
{
size_t size = 2*1024*1024;
my_pthread_attr_getstacksize(emu, attr, &size);
return pthread_attr_setstack(getAlignedAttr(attr), addr, size);
//return pthread_attr_setstackaddr(getAlignedAttr(attr), addr);
}
#endif
EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_routine, void* arg)
{
int stacksize = 2*1024*1024; //default stack size is 2Mo
@@ -280,7 +407,7 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
if(attr) {
size_t stsize;
if(pthread_attr_getstacksize(attr, &stsize)==0)
if(pthread_attr_getstacksize(getAlignedAttr(attr), &stsize)==0)
stacksize = stsize;
}
if(GetStackSize(emu, (uintptr_t)attr, &attr_stack, &attr_stacksize))
@@ -289,14 +416,14 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
stacksize = attr_stacksize;
own = 0;
} else {
stack = malloc(stacksize);
stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
own = 1;
}
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
x64emu_t *emuthread = NewX64Emu(my_context, (uintptr_t)start_routine, (uintptr_t)stack, stacksize, own);
SetupX64Emu(emuthread);
SetFS(emuthread, GetFS(emu));
//SetFS(emuthread, GetFS(emu));
et->emu = emuthread;
et->fnc = (uintptr_t)start_routine;
et->arg = arg;
@@ -308,14 +435,14 @@ EXPORT int my_pthread_create(x64emu_t *emu, void* t, void* attr, void* start_rou
}
#endif
// create thread
return pthread_create((pthread_t*)t, (const pthread_attr_t *)attr,
return pthread_create((pthread_t*)t, getAlignedAttr(attr),
pthread_routine, et);
}
void* my_prepare_thread(x64emu_t *emu, void* f, void* arg, int ssize, void** pet)
{
int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo
void* stack = malloc(stacksize);
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
x64emu_t *emuthread = NewX64Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
SetupX64Emu(emuthread);
@@ -342,13 +469,13 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
{
// get a stack local copy of the args, as may be live in some register depending the architecture (like ARM)
if(cancel_deep<0) {
printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
printf_log(LOG_NONE/*LOG_INFO*/, "BOX64: Warning, inconsistant value in __pthread_register_cancel (%d)\n", cancel_deep);
cancel_deep = 0;
}
if(cancel_deep!=CANCEL_MAX-1)
++cancel_deep;
else
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX86: Warning, calling __pthread_register_cancel(...) too many time\n");}
{printf_log(LOG_NONE/*LOG_INFO*/, "BOX64: Warning, calling __pthread_register_cancel(...) too many time\n");}
cancel_emu[cancel_deep] = (x64emu_t*)E;
@@ -359,7 +486,7 @@ EXPORT void my___pthread_register_cancel(void* E, void* B)
int i = cancel_deep--;
x64emu_t* emu = cancel_emu[i];
my_longjmp(emu, cancel_buff[i]->__cancel_jmp_buf, 1);
DynaRun(emu); // resume execution
DynaRun(emu); // resume execution // TODO: Use ejb instead?
return;
}
@@ -494,101 +621,19 @@ EXPORT int my_pthread_key_create(x64emu_t* emu, void* key, void* dtor)
}
EXPORT int my___pthread_key_create(x64emu_t* emu, void* key, void* dtor) __attribute__((alias("my_pthread_key_create")));
// phtread_cond_init with null attr seems to only write 1 (NULL) dword on x86, while it's 48 bytes on ARM.
// Not sure why as sizeof(pthread_cond_init) is 48 on both platform... But Neverwinter Night init seems to rely on that
// What about cond that are statically initialized?
// Note, this is is a versionned function (the pthread_cond_*), and this seems to correspond to an old behaviour
KHASH_MAP_INIT_INT(mapcond, pthread_cond_t*);
// should all access to that map be behind a mutex?
kh_mapcond_t *mapcond = NULL;
static pthread_cond_t* add_cond(void* cond)
{
pthread_mutex_lock(&my_context->mutex_thread);
khint_t k;
int ret;
pthread_cond_t *c;
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &ret);
if(!ret)
c = kh_value(mapcond, k); // already there... reinit an existing one?
else
c = kh_value(mapcond, k) = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
*(void**)cond = cond;
pthread_mutex_unlock(&my_context->mutex_thread);
return c;
}
static pthread_cond_t* get_cond(void* cond)
{
pthread_cond_t* ret;
int r;
pthread_mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
if(k==kh_end(mapcond)) {
khint_t k = kh_get(mapcond, mapcond, (uintptr_t)cond);
if(k==kh_end(mapcond)) {
printf_log(LOG_DEBUG, "BOX86: Note: phtread_cond not found, create a new empty one\n");
ret = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &r);
kh_value(mapcond, k) = ret;
*(void**)cond = cond;
pthread_cond_init(ret, NULL);
} else
ret = kh_value(mapcond, k);
} else
ret = kh_value(mapcond, k);
pthread_mutex_unlock(&my_context->mutex_thread);
return ret;
}
static void del_cond(void* cond)
{
if(!mapcond)
return;
pthread_mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
if(k!=kh_end(mapcond)) {
free(kh_value(mapcond, k));
kh_del(mapcond, mapcond, k);
}
pthread_mutex_unlock(&my_context->mutex_thread);
}
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m);
EXPORT int my_pthread_cond_broadcast(x64emu_t* emu, void* cond)
EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, pthread_cond_t* cond, void* mutex, void* abstime)
{
pthread_cond_t * c = get_cond(cond);
return pthread_cond_broadcast(c);
return pthread_cond_timedwait(cond, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
}
EXPORT int my_pthread_cond_destroy(x64emu_t* emu, void* cond)
EXPORT int my_pthread_cond_wait(x64emu_t* emu, pthread_cond_t* cond, void* mutex)
{
pthread_cond_t * c = get_cond(cond);
int ret = pthread_cond_destroy(c);
if(c!=cond) del_cond(cond);
return ret;
}
EXPORT int my_pthread_cond_init(x64emu_t* emu, void* cond, void* attr)
{
pthread_cond_t *c = add_cond(cond);
return pthread_cond_init(c, (const pthread_condattr_t*)attr);
}
EXPORT int my_pthread_cond_signal(x64emu_t* emu, void* cond)
{
pthread_cond_t * c = get_cond(cond);
return pthread_cond_signal(c);
}
EXPORT int my_pthread_cond_timedwait(x64emu_t* emu, void* cond, void* mutex, void* abstime)
{
pthread_cond_t * c = get_cond(cond);
return pthread_cond_timedwait(c, getAlignedMutex((pthread_mutex_t*)mutex), (const struct timespec*)abstime);
}
EXPORT int my_pthread_cond_wait(x64emu_t* emu, void* cond, void* mutex)
{
pthread_cond_t * c = get_cond(cond);
return pthread_cond_wait(c, getAlignedMutex((pthread_mutex_t*)mutex));
return pthread_cond_wait(cond, getAlignedMutex((pthread_mutex_t*)mutex));
}
//EXPORT int my_pthread_attr_setscope(x64emu_t* emu, void* attr, int scope)
//EXPORT int my_pthread_attr_setscope(x64emu_t* emu, void* at*tr, int scope)
//{
// if(scope!=PTHREAD_SCOPE_SYSTEM) printf_log(LOG_INFO, "Warning, scope of call to pthread_attr_setscope(...) changed from %d to PTHREAD_SCOPE_SYSTEM\n", scope);
// return pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
@@ -655,35 +700,69 @@ EXPORT int my_pthread_kill(x64emu_t* emu, void* thread, int sig)
return pthread_kill((pthread_t)thread, sig);
}
EXPORT void my_pthread_exit(x64emu_t* emu, void* retval)
{
emu->quit = 1; // to be safe
pthread_exit(retval);
}
//EXPORT void my_pthread_exit(x64emu_t* emu, void* retval)
//{
// pthread_exit(retval);
//}
#ifdef NOALIGN
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m) {
return m;
}
#else
//#define TRACK_MUTEX
// mutex alignment
#ifdef TRACK_MUTEX
KHASH_MAP_INIT_INT(mutex, pthread_mutex_t*)
static kh_mutex_t* unaligned_mutex = NULL;
#endif
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
typedef struct aligned_mutex_s {
uint64_t dummy;
pthread_mutex_t *m;
uint64_t sign;
} aligned_mutex_t;
#define SIGNMTX *(uint64_t*)"BOX64MTX"
pthread_mutex_t* getAlignedMutexWithInit(pthread_mutex_t* m, int init)
{
if(!m)
return NULL;
aligned_mutex_t* am = (aligned_mutex_t*)m;
if(init && (am->sign==SIGNMTX))
return am->m;
#ifdef TRACK_MUTEX
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
if(k!=kh_end(unaligned_mutex))
return kh_value(unaligned_mutex, k);
int r;
k = kh_put(mutex, unaligned_mutex, (uintptr_t)m, &r);
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
memcpy(ret, m, sizeof(pthread_mutex_t));
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
#else
pthread_mutex_t* ret = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
#endif
if(init) {
int kind = ((int*)m)[4]; // extract kind from original mutex
((int*)ret)[3+__PTHREAD_MUTEX_HAVE_PREV] = kind; // inject in new one (i.e. "init" it)
}
am->sign = SIGNMTX;
am->m = ret;
return ret;
}
pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
{
return getAlignedMutexWithInit(m, 1);
}
EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
{
aligned_mutex_t* am = (aligned_mutex_t*)m;
#ifdef TRACK_MUTEX
if(am->sign==SIGNMTX) {
am->sign = 0;
am->m = NULL;
}
khint_t k = kh_get(mutex, unaligned_mutex, (uintptr_t)m);
if(k!=kh_end(unaligned_mutex)) {
pthread_mutex_t *n = kh_value(unaligned_mutex, k);
@@ -693,14 +772,101 @@ EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
return ret;
}
return pthread_mutex_destroy(m);
#else
if(am->sign!=SIGNMTX) {
return 1; //???
}
int ret = pthread_mutex_destroy(am->m);
free(am->m);
return ret;
#endif
}
typedef union my_mutexattr_s {
int x86;
pthread_mutexattr_t nat;
} my_mutexattr_t;
// mutexattr
EXPORT int my_pthread_mutexattr_destroy(x64emu_t* emu, my_mutexattr_t *attr)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_destroy(&mattr.nat);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my___pthread_mutexattr_destroy(x64emu_t* emu, my_mutexattr_t *attr) __attribute__((alias("my_pthread_mutexattr_destroy")));
EXPORT int my_pthread_mutexattr_getkind_np(x64emu_t* emu, my_mutexattr_t *attr, void* p)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
//int ret = pthread_mutexattr_getkind_np(&mattr.nat, p);
int ret = pthread_mutexattr_gettype(&mattr.nat, p);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my_pthread_mutexattr_gettype(x64emu_t* emu, my_mutexattr_t *attr, void* p)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_gettype(&mattr.nat, p);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my_pthread_mutexattr_init(x64emu_t* emu, my_mutexattr_t *attr)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_init(&mattr.nat);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my___pthread_mutexattr_init(x64emu_t* emu, my_mutexattr_t *attr) __attribute__((alias("my_pthread_mutexattr_init")));
EXPORT int my_pthread_mutexattr_setkind_np(x64emu_t* emu, my_mutexattr_t *attr, int k)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
//int ret = pthread_mutexattr_setkind_np(&mattr.nat, k);
int ret = pthread_mutexattr_settype(&mattr.nat, k);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my_pthread_mutexattr_setprotocol(x64emu_t* emu, my_mutexattr_t *attr, int p)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_setprotocol(&mattr.nat, p);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my_pthread_mutexattr_setpshared(x64emu_t* emu, my_mutexattr_t *attr, int p)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_setpshared(&mattr.nat, p);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my_pthread_mutexattr_settype(x64emu_t* emu, my_mutexattr_t *attr, int t)
{
my_mutexattr_t mattr = {0};
mattr.x86 = attr->x86;
int ret = pthread_mutexattr_settype(&mattr.nat, t);
attr->x86 = mattr.x86;
return ret;
}
EXPORT int my___pthread_mutexattr_settype(x64emu_t* emu, my_mutexattr_t *attr, int t) __attribute__((alias("my_pthread_mutexattr_settype")));
// mutex
int my___pthread_mutex_destroy(pthread_mutex_t *m) __attribute__((alias("my_pthread_mutex_destroy")));
EXPORT int my_pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *att)
EXPORT int my_pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att)
{
return pthread_mutex_init(getAlignedMutex(m), att);
my_mutexattr_t mattr = {0};
if(att)
mattr.x86 = att->x86;
return pthread_mutex_init(getAlignedMutexWithInit(m, 0), att?(&mattr.nat):NULL);
}
EXPORT int my___pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *att) __attribute__((alias("my_pthread_mutex_init")));
EXPORT int my___pthread_mutex_init(pthread_mutex_t *m, my_mutexattr_t *att) __attribute__((alias("my_pthread_mutex_init")));
EXPORT int my_pthread_mutex_lock(pthread_mutex_t *m)
{
@@ -725,6 +891,118 @@ EXPORT int my_pthread_mutex_unlock(pthread_mutex_t *m)
return pthread_mutex_unlock(getAlignedMutex(m));
}
typedef union my_condattr_s {
int x86;
pthread_condattr_t nat;
} my_condattr_t;
// condattr
EXPORT int my_pthread_condattr_destroy(x64emu_t* emu, my_condattr_t* c)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_destroy(&cond.nat);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_condattr_getclock(x64emu_t* emu, my_condattr_t* c, void* cl)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_getclock(&cond.nat, cl);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_condattr_getpshared(x64emu_t* emu, my_condattr_t* c, void* p)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_getpshared(&cond.nat, p);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_condattr_init(x64emu_t* emu, my_condattr_t* c)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_init(&cond.nat);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_condattr_setclock(x64emu_t* emu, my_condattr_t* c, int cl)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_setclock(&cond.nat, cl);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_condattr_setpshared(x64emu_t* emu, my_condattr_t* c, int p)
{
my_condattr_t cond = {0};
cond.x86 = c->x86;
int ret = pthread_condattr_setpshared(&cond.nat, p);
c->x86 = cond.x86;
return ret;
}
EXPORT int my_pthread_cond_init(x64emu_t* emu, pthread_cond_t *pc, my_condattr_t* c)
{
my_condattr_t cond = {0};
if(c)
cond.x86 = c->x86;
int ret = pthread_cond_init(pc, c?(&cond.nat):NULL);
if(c)
c->x86 = cond.x86;
return ret;
}
typedef union my_barrierattr_s {
int x86;
pthread_barrierattr_t nat;
} my_barrierattr_t;
// barrierattr
EXPORT int my_pthread_barrierattr_destroy(x64emu_t* emu, my_barrierattr_t* b)
{
my_barrierattr_t battr = {0};
battr.x86 = b->x86;
int ret = pthread_barrierattr_destroy(&battr.nat);
b->x86 = battr.x86;
return ret;
}
EXPORT int my_pthread_barrierattr_getpshared(x64emu_t* emu, my_barrierattr_t* b, void* p)
{
my_barrierattr_t battr = {0};
battr.x86 = b->x86;
int ret = pthread_barrierattr_getpshared(&battr.nat, p);
b->x86 = battr.x86;
return ret;
}
EXPORT int my_pthread_barrierattr_init(x64emu_t* emu, my_barrierattr_t* b)
{
my_barrierattr_t battr = {0};
battr.x86 = b->x86;
int ret = pthread_barrierattr_init(&battr.nat);
b->x86 = battr.x86;
return ret;
}
EXPORT int my_pthread_barrierattr_setpshared(x64emu_t* emu, my_barrierattr_t* b, int p)
{
my_barrierattr_t battr = {0};
battr.x86 = b->x86;
int ret = pthread_barrierattr_setpshared(&battr.nat, p);
b->x86 = battr.x86;
return ret;
}
EXPORT int my_pthread_barrier_init(x64emu_t* emu, pthread_barrier_t* bar, my_barrierattr_t* b, uint32_t count)
{
my_barrierattr_t battr = {0};
if(b)
battr.x86 = b->x86;
int ret = pthread_barrier_init(bar, b?(&battr.nat):NULL, count);
if(b)
b->x86 = battr.x86;
return ret;
}
#endif
static void emujmpbuf_destroy(void* p)
@@ -752,10 +1030,11 @@ emu_jmpbuf_t* GetJmpBuf()
void init_pthread_helper()
{
InitCancelThread();
mapcond = kh_init(mapcond);
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
#ifndef NOALIGN
#ifdef TRACK_MUTEX
unaligned_mutex = kh_init(mutex);
#endif
#endif
}
@@ -763,20 +1042,15 @@ void fini_pthread_helper(box64context_t* context)
{
FreeCancelThread(context);
CleanStackSize(context);
pthread_cond_t *cond;
kh_foreach_value(mapcond, cond,
pthread_cond_destroy(cond);
free(cond);
);
kh_destroy(mapcond, mapcond);
mapcond = NULL;
#ifndef NOALIGN
#ifdef TRACK_MUTEX
pthread_mutex_t *m;
kh_foreach_value(unaligned_mutex, m,
pthread_mutex_destroy(m);
free(m);
);
kh_destroy(mutex, unaligned_mutex);
#endif
#endif
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
if(ejb) {
@@ -789,3 +1063,16 @@ void fini_pthread_helper(box64context_t* context)
pthread_setspecific(thread_key, NULL);
}
}
int checkMutex(void* m)
{
pthread_mutex_t* mutex = (pthread_mutex_t*)m;
int ret = pthread_mutex_trylock(mutex);
if(ret==0) {
pthread_mutex_unlock(mutex);
return 0;
}
if(ret==EDEADLK)
return 1;
return 0;
}
+79 -21
View File
@@ -40,10 +40,13 @@ uintptr_t box64_nodynarec_end = 0;
int box64_dynarec = 0;
#endif
int dlsym_error = 0;
#ifdef HAVE_TRACE
int trace_xmm = 0;
int trace_emm = 0;
#ifdef HAVE_TRACE
int trace_regsdiff = 0;
uint64_t start_cnt = 0;
uintptr_t trace_start = 0, trace_end = 0;
char* trace_func = NULL;
#ifdef DYNAREC
int box64_dynarec_trace = 0;
#endif
@@ -58,8 +61,6 @@ int box64_nopulse = 0;
int box64_nogtk = 0;
int box64_novulkan = 0;
char* libGL = NULL;
uintptr_t trace_start = 0, trace_end = 0;
char* trace_func = NULL;
uintptr_t fmod_smc_start = 0;
uintptr_t fmod_smc_end = 0;
uint32_t default_gs = 0;
@@ -207,6 +208,13 @@ void LoadLogEnv()
trace_emm = p[0]-'0';
}
}
p = getenv("BOX64_TRACE_COLOR");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[1]<='0'+1)
trace_regsdiff = p[0]-'0';
}
}
p = getenv("BOX64_TRACE_START");
if(p) {
char* p2;
@@ -432,6 +440,7 @@ void PrintHelp() {
printf(" use BOX64_TRACE_INIT instead of BOX_TRACE to start trace before init of Libs and main program\n\t (function name will probably not work then)\n");
printf(" BOX64_TRACE_EMM with 1 to enable dump of MMX registers along with regular registers\n");
printf(" BOX64_TRACE_XMM with 1 to enable dump of SSE registers along with regular registers\n");
printf(" BOX64_TRACE_COLOR with 1 to enable detection of changed general register values\n");
printf(" BOX64_TRACE_START with N to enable trace after N instructions\n");
#ifdef DYNAREC
printf(" BOX64_DYNAREC_TRACE with 0/1 to disable or enable Trace on generated code too\n");
@@ -456,7 +465,7 @@ EXPORTDYN
void LoadEnvVars(box64context_t *context)
{
// check BOX64_LD_LIBRARY_PATH and load it
LoadEnvPath(&context->box64_ld_lib, ".:lib:lib64:x86_64", "BOX64_LD_LIBRARY_PATH");
LoadEnvPath(&context->box64_ld_lib, ".:lib:lib64:x86_64:bin64:libs64", "BOX64_LD_LIBRARY_PATH");
if(FileExist("/lib/x86_64-linux-gnu", 0))
AddPath("/lib/x86_64-linux-gnu", &context->box64_ld_lib, 1);
if(FileExist("/usr/lib/x86_64-linux-gnu", 0))
@@ -589,6 +598,56 @@ void endBox64()
if(!my_context)
return;
x64emu_t* emu = thread_get_emu();
// atexit first
printf_log(LOG_DEBUG, "Calling atexit registered functions (exiting box64)\n");
CallAllCleanup(emu);
// then call all the fini
printf_log(LOG_DEBUG, "Calling fini for all loaded elfs and unload native libs\n");
RunElfFini(my_context->elfs[0], emu);
#ifdef DYNAREC
// disable dynarec now
box64_dynarec = 0;
#endif
FreeLibrarian(&my_context->local_maplib, emu); // unload all libs
FreeLibrarian(&my_context->maplib, emu); // unload all libs
// waiting for all thread except this one to finish
int this_thread = GetTID();
int pid = getpid();
int running = 1;
int attempt = 0;
printf_log(LOG_DEBUG, "Waiting for all threads to finish before unloading box64context\n");
while(running) {
DIR *proc_dir;
char dirname[100];
snprintf(dirname, sizeof dirname, "/proc/self/task");
proc_dir = opendir(dirname);
running = 0;
if (proc_dir)
{
struct dirent *entry;
while ((entry = readdir(proc_dir)) != NULL && !running)
{
if(entry->d_name[0] == '.')
continue;
int tid = atoi(entry->d_name);
// tid != pthread_t, so no pthread functions are available here
if(tid!=this_thread) {
if(attempt>4000) {
printf_log(LOG_INFO, "Stop waiting for remaining thread %04d\n", tid);
// enough wait, kill all thread!
syscall(__NR_tgkill, pid, tid, SIGABRT);
} else {
running = 1;
++attempt;
sched_yield();
}
}
}
closedir(proc_dir);
}
}
// all done, free context
FreeBox64Context(&my_context);
if(libGL) {
@@ -746,23 +805,16 @@ int main(int argc, const char **argv, const char **env) {
AddPath("libudev.so.0", &my_context->box64_emulated_libs, 0);
box64_steam = 1;
}
// special case for steam-runtime-check-requirements to fake 64bits suport
/*// special case for steam-runtime-check-requirements to fake 64bits suport
if(strstr(prgname, "steam-runtime-check-requirements")==prgname) {
printf_log(LOG_INFO, "steam-runtime-check-requirements detected, faking All is good!\n");
exit(0); // exiting, not testing anything
}
}*/
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
free(my_context->argv[0]);
my_context->argv[0] = strdup("./UnrealLinux.bin");
}
#ifdef RPI
// special case for TokiTori 2+, that check if texture max size is > = 8192
if(strstr(prgname, "TokiTori2.bin.x86")==prgname) {
printf_log(LOG_INFO, "TokiTori 2+ detected, runtime patch to fix GPU non-power-of-two faillure\n");
box64_tokitori2 = 1;
}
#endif
// special case for zoom
if(strstr(prgname, "zoom")==prgname) {
printf_log(LOG_INFO, "Zoom detected, trying to use system libturbojpeg if possible\n");
@@ -907,6 +959,7 @@ int main(int argc, const char **argv, const char **env) {
SetRSI(emu, my_context->argc);
SetRDX(emu, (uint64_t)my_context->argv);
SetRCX(emu, (uint64_t)my_context->envv);
SetRBP(emu, 0); // Frame pointer so to "No more frame pointer"
// child fork to handle traces
pthread_atfork(NULL, NULL, my_child_fork);
@@ -932,7 +985,7 @@ int main(int argc, const char **argv, const char **env) {
// pre-load lib if needed
if(ld_preload.size) {
for (int i=0; i<ld_preload.size; ++i) {
if(AddNeededLib(NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
if(AddNeededLib(NULL, NULL, NULL, 0, ld_preload.paths[i], my_context, emu)) {
if(!strstr(ld_preload.paths[i], "vgpreload_"))
printf_log(LOG_INFO, "Warning, cannot pre-load lib: \"%s\"\n", ld_preload.paths[i]);
}
@@ -940,7 +993,7 @@ int main(int argc, const char **argv, const char **env) {
}
FreeCollection(&ld_preload);
// Call librarian to load all dependant elf
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, 0, my_context, emu)) {
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, my_context, emu)) {
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
FreeBox64Context(&my_context);
return -1;
@@ -962,7 +1015,7 @@ int main(int argc, const char **argv, const char **env) {
setupTrace(my_context);
// get entrypoint
my_context->ep = GetEntryPoint(my_context->maplib, elf_header);
#if defined(RPI) || defined(RK3399)
#if defined(RPI) || defined(RK3399) || defined(RK3326)
// before launching emulation, let's check if this is a mojosetup from GOG
if (((strstr(prog, "bin/linux/x86/mojosetup") && getenv("MOJOSETUP_BASE")) || strstr(prog, ".mojosetup/mojosetup"))
&& getenv("GTK2_RC_FILES")) {
@@ -974,17 +1027,22 @@ int main(int argc, const char **argv, const char **env) {
// emulate!
printf_log(LOG_DEBUG, "Start x64emu on Main\n");
SetRSI(emu, my_context->argc);
SetRDX(emu, (uint64_t)my_context->argv);
SetRCX(emu, (uint64_t)my_context->envv);
// Stack is ready, with stacked: NULL env NULL argv argc
SetRIP(emu, my_context->ep);
PushExit(emu);
*(uint64_t*)GetRSP(emu) = my_context->argc;
ResetFlags(emu);
PushExit(emu); // push to pop it just after
SetRDX(emu, Pop64(emu)); // RDX is exit function
Run(emu, 0);
// Get EAX
int ret = GetEAX(emu);
printf_log(LOG_DEBUG, "Emulation finished, EAX=%d\n", ret);
#ifdef HAVE_TRACE
if(trace_func) {
free(trace_func);
trace_func = NULL;
}
#endif
return ret;
}
+52 -23
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include "box64stack.h"
#include "box64context.h"
@@ -15,15 +16,17 @@ EXPORTDYN
int CalcStackSize(box64context_t *context)
{
printf_log(LOG_DEBUG, "Calc stack size, based on %d elf(s)\n", context->elfsize);
context->stacksz = 8*1024*1024; context->stackalign=4;
context->stacksz = 8*1024*1024; context->stackalign=16;
for (int i=0; i<context->elfsize; ++i)
CalcStack(context->elfs[i], &context->stacksz, &context->stackalign);
if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) {
// if (posix_memalign((void**)&context->stack, context->stackalign, context->stacksz)) {
context->stack = mmap(NULL, context->stacksz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
if (context->stack==(void*)-1) {
printf_log(LOG_NONE, "Cannot allocate aligned memory (0x%x/0x%x) for stack\n", context->stacksz, context->stackalign);
return 1;
}
memset(context->stack, 0, context->stacksz);
//memset(context->stack, 0, context->stacksz);
printf_log(LOG_DEBUG, "Stack is @%p size=0x%x align=0x%x\n", context->stack, context->stacksz, context->stackalign);
return 0;
@@ -118,29 +121,55 @@ void SetupInitialStack(x64emu_t *emu)
R_RSP=tmp;
// push the AuxVector themselves
Push(emu, 0); Push(emu, 0); //AT_NULL(0)=0
Push(emu, p_x86_64); Push(emu, 15); //AT_PLATFORM(15)=p_x86_64*
Push(emu, 0); Push(emu, 66); //AT_HWCAP2(26)=0
/* Actual sample:
3 0x400040
4 0x38
5 0xb
6 0x1000
7 0x7f7addca6000
8 (nil)
9 0x401040
11 0x3e8
12 0x3e8
13 0x3e8
14 0x3e8
16 0xbfebfbff
15 0x7ffd5074c4c9
17 0x64
23 (nil)
25 0x7ffd5074c4b9
26 (nil)
31 0x7ffd5074efea
33 0x7ffd507e6000
*/
Push(emu, 0); Push(emu, 0); //AT_NULL(0)=0
//Push(emu, ); Push(emu, 3); //AT_PHDR(3)=address of the PH of the executable
//Push(emu, ); Push(emu, 4); //AT_PHENT(4)=size of PH entry
//Push(emu, ); Push(emu, 5); //AT_PHNUM(5)=number of elf headers
Push(emu, box64_pagesize); Push(emu, 6); //AT_PAGESZ(6)
//Push(emu, real_getauxval(7)); Push(emu, 7); //AT_BASE(7)=ld-2.27.so start (in memory)
Push(emu, 0); Push(emu, 8); //AT_FLAGS(8)=0
Push(emu, R_RIP); Push(emu, 9); //AT_ENTRY(9)=entrypoint
Push(emu, real_getauxval(11)); Push(emu, 11); //AT_UID(11)
Push(emu, real_getauxval(12)); Push(emu, 12); //AT_EUID(12)
Push(emu, real_getauxval(13)); Push(emu, 13); //AT_GID(13)
Push(emu, real_getauxval(14)); Push(emu, 14); //AT_EGID(14)
Push(emu, p_x86_64); Push(emu, 15); //AT_PLATFORM(15)=&"x86_64"
// Push HWCAP:
// FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4
// MSR: 1<<5 : PAE: 1<<6 : MCE: 1<<7 ; CX8: 1<<8 : APIC:1<<9
// SEP: 1<<11: MTRR:1<<12: PGE: 1<<13: MCA: 1<<14; CMOV:1<<15; FCMOV: 1<<16
// MMX: 1<<23:OSFXR:1<<24: XMM: 1<<25:XMM2: 1<<26;AMD3D:1<<31
// FPU: 1<<0 ; VME: 1<<1 ; DE : 1<<2 ; PSE: 1<<3 ; TSC: 1<<4 ; MSR: 1<<5 ; PAE: 1<<6 ; MCE: 1<<7
// CX8: 1<<8 ; APIC:1<<9 ; SEP: 1<<11; MTRR:1<<12; PGE: 1<<13; MCA: 1<<14; CMOV:1<<15
// FCMOV:1<<16; ; MMX: 1<<23
// OSFXR:1<<24; XMM: 1<<25;XMM2: 1<<26; AMD3D:1<<31
Push(emu, (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<8) | (1<<15) | (1<<16) | (1<<23) | (1<<25) | (1<<26));
Push(emu, 16); //AT_HWCAP(16)=...
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
Push(emu, real_getauxval(23)); Push(emu, 23); //AT_SECURE(23)=0
Push(emu, real_getauxval(14)); Push(emu, 14); //AT_EGID(14)
Push(emu, real_getauxval(13)); Push(emu, 13); //AT_GID(13)
Push(emu, real_getauxval(12)); Push(emu, 12); //AT_EUID(12)
Push(emu, real_getauxval(11)); Push(emu, 11); //AT_UID(11)
Push(emu, box64_pagesize); Push(emu, 6); //AT_PAGESZ(6)
Push(emu, R_RIP); Push(emu, 9); //AT_ENTRY(9)=entrypoint
Push(emu, 0/*emu->context->vsyscall*/); Push(emu, 32); //AT_SYSINFO(32)=vsyscall
Push(emu, 16); //AT_HWCAP(16)=...
//Push(emu, sysconf(_SC_CLK_TCK)); Push(emu, 17); //AT_CLKTCK(17)=times() frequency
Push(emu, real_getauxval(23)); Push(emu, 23); //AT_SECURE(23)
Push(emu, p_random); Push(emu, 25); //AT_RANDOM(25)=p_random
Push(emu, 0); Push(emu, 26); //AT_HWCAP2(26)=0
Push(emu, p_arg0); Push(emu, 31); //AT_EXECFN(31)=p_arg0
//Push(emu, ); Push(emu, 33); //AT_SYSINFO_EHDR(33)=address of vDSO
if(!emu->context->auxval_start) // store auxval start if needed
emu->context->auxval_start = (uintptr_t*)R_RSP;
// TODO: continue
// push nil / envs / nil / args / argc
Push(emu, 0);
@@ -150,4 +179,4 @@ void SetupInitialStack(x64emu_t *emu)
for (int i=emu->context->argc-1; i>=0; --i)
Push(emu, p_argv[i]);
Push(emu, emu->context->argc);
}
}
+4 -3
View File
@@ -91,14 +91,15 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
b = b->next;
bridge->last = b;
}
sz = b->sz;
#ifdef DYNAREC
sz = b->sz;
pthread_mutex_unlock(&bridge->mutex);
if(box64_dynarec) {
prot=(getProtection((uintptr_t)b->b)&PROT_DYNAREC)?1:0;
if(prot)
unprotectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
else // only add DB if there is no protection
addDBFromAddressRange((uintptr_t)&b->b[b->sz].CC, sizeof(onebridge_t));
}
} while(sz!=b->sz); // this while loop if someone took the slot when the bridge mutex was unlocked doing memory protection managment
pthread_mutex_lock(&bridge->mutex);
@@ -116,7 +117,7 @@ uintptr_t AddBridge(bridge_t* bridge, wrapper_t w, void* fnc, int N, const char*
kh_value(bridge->bridgemap, k) = (uintptr_t)&b->b[sz].CC;
pthread_mutex_unlock(&bridge->mutex);
#ifdef DYNAREC
if(box64_dynarec && prot)
if(box64_dynarec)
protectDB((uintptr_t)b->b, NBRICK*sizeof(onebridge_t));
#endif
#ifdef HAVE_TRACE
+1 -1
View File
@@ -77,7 +77,7 @@ int FileIsX64ELF(const char* filename)
return 0;
}
#if defined(RPI) || defined(RK3399)
#if defined(RPI) || defined(RK3399) || defined(RK3326)
void sanitize_mojosetup_gtk_background()
{
// get GTK2_RC_FILES folder
+6 -6
View File
@@ -36,8 +36,8 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
R_ECX = 0x6C65746E;
break;
case 0x1:
R_EAX = 0x00000601; // familly and all
R_EBX = 0; // Brand indexe, CLFlush, Max APIC ID, Local APIC ID
R_EAX = 0x00000601; // family and all
R_EBX = 0; // Brand index, CLFlush, Max APIC ID, Local APIC ID
R_EDX = 1 // fpu
| 1<<4 // rdtsc
| 1<<8 // cmpxchg8
@@ -108,10 +108,10 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
R_EDX = 0;
break;
case 0x7: // extended bits...
/*if(R_ECX==0) R_EAX = 0;
else*/ R_EAX = R_ECX = R_EBX = R_EDX = 0;
if(R_ECX==1) R_EAX = 0; // Bit 5 is avx512_bf16
else R_EAX = R_ECX = R_EBX = R_EDX = 0; // TODO
break;
case 0xB: // Extended Topology Enumaretion Leaf
case 0xB: // Extended Topology Enumeration Leaf
//TODO!
R_EAX = 0;
break;
@@ -138,7 +138,7 @@ void my_cpuid(x64emu_t* emu, uint32_t tmp32u)
R_EAX = 0; // reserved
R_EBX = 0; // reserved
R_ECX = (1<<5) | (1<<8); // LZCNT | PREFETCHW
R_EDX = 0;
R_EDX = 1; // x87 FPU
break;
case 0x80000002: // Brand part 1 (P4 signature)
R_EAX = 0x20202020;
+260 -9
View File
@@ -4,6 +4,7 @@
#() vFu
#() vFf
#() vFd
#() vFl
#() vFp
#() vFS
#() cFv
@@ -12,7 +13,6 @@
#() cFf
#() cFp
#() wFp
#() iFE
#() iFv
#() iFi
#() iFu
@@ -20,6 +20,7 @@
#() iFd
#() iFL
#() iFp
#() iFO
#() iFS
#() IFf
#() IFd
@@ -37,22 +38,30 @@
#() fFi
#() fFf
#() fFp
#() dFv
#() dFi
#() dFu
#() dFd
#() dFp
#() lFE
#() lFv
#() lFi
#() lFl
#() lFp
#() LFE
#() LFv
#() LFL
#() LFp
#() pFE
#() pFv
#() pFi
#() pFW
#() pFu
#() pFd
#() pFl
#() pFL
#() pFp
#() pFV
#() HFi
#() HFp
#() vFEp
@@ -62,6 +71,7 @@
#() vFid
#() vFip
#() vFWW
#() vFWp
#() vFui
#() vFuu
#() vFuf
@@ -71,9 +81,12 @@
#() vFff
#() vFfp
#() vFdd
#() vFLp
#() vFpi
#() vFpu
#() vFpf
#() vFpd
#() vFpl
#() vFpL
#() vFpp
#() vFpS
@@ -81,13 +94,15 @@
#() cFpp
#() iFEp
#() iFii
#() iFiI
#() iFiu
#() iFiU
#() iFil
#() iFip
#() iFIi
#() iFui
#() iFuu
#() iFup
#() iFUU
#() iFli
#() iFLL
#() iFLp
@@ -96,6 +111,7 @@
#() iFpI
#() iFpC
#() iFpu
#() iFpU
#() iFpf
#() iFpd
#() iFpl
@@ -104,6 +120,7 @@
#() iFpO
#() iFSi
#() IFEp
#() IFpi
#() IFpu
#() CFui
#() CFpi
@@ -117,8 +134,10 @@
#() uFpi
#() uFpu
#() uFpU
#() uFpL
#() uFpp
#() UFEp
#() UFii
#() UFUp
#() UFpp
#() fFif
@@ -130,16 +149,23 @@
#() dFdi
#() dFdd
#() dFdp
#() dFLL
#() dFpi
#() dFpp
#() lFll
#() lFpi
#() lFpp
#() LFpi
#() LFpL
#() LFpp
#() pFEp
#() pFii
#() pFiu
#() pFip
#() pFui
#() pFuu
#() pFup
#() pFdd
#() pFlp
#() pFLL
#() pFpi
@@ -150,6 +176,7 @@
#() pFpp
#() pFpV
#() pFSi
#() HFll
#() HFpi
#() vFEpi
#() vFEpu
@@ -178,7 +205,9 @@
#() vFuup
#() vFuff
#() vFudd
#() vFull
#() vFupi
#() vFupu
#() vFfff
#() vFfpp
#() vFddd
@@ -193,13 +222,19 @@
#() vFpuI
#() vFpuu
#() vFpup
#() vFpdd
#() vFpll
#() vFpLi
#() vFpLL
#() vFppi
#() vFppu
#() vFppL
#() vFppp
#() iFEiw
#() iFEip
#() iFEWW
#() iFEup
#() iFEUU
#() iFEpi
#() iFEpL
#() iFEpp
@@ -211,14 +246,18 @@
#() iFiip
#() iFiiO
#() iFiuu
#() iFiLi
#() iFiLN
#() iFipu
#() iFipL
#() iFipp
#() iFuuu
#() iFuup
#() iFuff
#() iFuLL
#() iFfff
#() iFLip
#() iFLLp
#() iFLpp
#() iFpii
#() iFpiu
@@ -230,18 +269,26 @@
#() iFpuU
#() iFpuL
#() iFpup
#() iFpUi
#() iFpUU
#() iFpfu
#() iFpff
#() iFpdd
#() iFpli
#() iFpll
#() iFplp
#() iFpLi
#() iFpLL
#() iFpLp
#() iFppi
#() iFppI
#() iFppC
#() iFppW
#() iFppu
#() iFppd
#() iFppl
#() iFppL
#() iFppp
#() iFppV
#() iFSpL
#() IFiIi
#() IFpIi
@@ -257,45 +304,61 @@
#() uFuup
#() uFupu
#() uFupp
#() uFpiu
#() uFpip
#() uFpLp
#() uFppi
#() uFppu
#() uFppp
#() UFppi
#() fFuii
#() fFfff
#() fFffp
#() fFppL
#() dFddd
#() dFddp
#() dFppi
#() dFppp
#() lFipi
#() lFipL
#() lFlll
#() lFlpi
#() lFppi
#() lFppL
#() lFSpl
#() LFipL
#() LFLLi
#() LFLLI
#() LFLpu
#() LFLpL
#() LFpii
#() LFpup
#() LFpLi
#() LFpLp
#() LFppi
#() LFppL
#() LFSpL
#() pFEip
#() pFEpi
#() pFEpp
#() pFiii
#() pFiip
#() pFipi
#() pFipL
#() pFipp
#() pFIpi
#() pFWWW
#() pFuii
#() pFupi
#() pFupL
#() pFUpi
#() pFddd
#() pFpii
#() pFpiu
#() pFpil
#() pFpiL
#() pFpip
#() pFpCC
#() pFpCu
#() pFpui
#() pFpuu
#() pFpuL
@@ -308,11 +371,13 @@
#() pFppi
#() pFppu
#() pFppf
#() pFppl
#() pFppL
#() pFppp
#() pFpOM
#() pFSpl
#() vFEipV
#() vFEpii
#() vFEpip
#() vFEpup
#() vFEppp
@@ -326,6 +391,7 @@
#() vFiddd
#() vFipii
#() vFipup
#() vFippi
#() vFippp
#() vFuiii
#() vFuiip
@@ -356,14 +422,22 @@
#() vFdddd
#() vFpiii
#() vFpiip
#() vFpiuL
#() vFpiup
#() vFpipp
#() vFpuuu
#() vFpudd
#() vFpupp
#() vFpdii
#() vFpddd
#() vFpLLL
#() vFppii
#() vFppid
#() vFppip
#() vFppui
#() vFppuu
#() vFppup
#() vFppdd
#() vFpppi
#() vFpppu
#() vFpppp
@@ -373,7 +447,9 @@
#() iFEipp
#() iFEipV
#() iFEupp
#() iFEpii
#() iFEpip
#() iFEpLi
#() iFEppi
#() iFEppL
#() iFEppp
@@ -381,75 +457,113 @@
#() iFEpOu
#() iFiiii
#() iFiiiu
#() iFiiip
#() iFiiiN
#() iFiipp
#() iFiuii
#() iFilli
#() iFipii
#() iFipui
#() iFipLp
#() iFippi
#() iFippu
#() iFippL
#() iFippp
#() iFuipp
#() iFuuff
#() iFuppi
#() iFuppp
#() iFpiii
#() iFpiiu
#() iFpiid
#() iFpiiL
#() iFpiip
#() iFpiuL
#() iFpiup
#() iFpipi
#() iFpipC
#() iFpipp
#() iFpCCC
#() iFpWWu
#() iFpuiL
#() iFpuip
#() iFpuui
#() iFpuuu
#() iFpuup
#() iFpuLL
#() iFpuLp
#() iFpupu
#() iFpupV
#() iFplip
#() iFpLpi
#() iFpLpL
#() iFpLpp
#() iFppii
#() iFppiu
#() iFppiL
#() iFppip
#() iFppCC
#() iFppuw
#() iFppui
#() iFppuu
#() iFppup
#() iFppll
#() iFpplp
#() iFppLi
#() iFppLL
#() iFppLp
#() iFpppi
#() iFpppu
#() iFpppL
#() iFpppp
#() IFEpIi
#() IFppip
#() IFSIii
#() uFEpup
#() uFifff
#() uFuuuu
#() uFpipu
#() uFpipp
#() uFpCCC
#() uFpuip
#() uFpuuu
#() uFppiu
#() uFpppi
#() UFpipp
#() dFppiL
#() lFEpip
#() lFEppL
#() lFiipL
#() lFipiI
#() lFipLi
#() lFipLI
#() lFipLl
#() lFpili
#() lFpilp
#() lFppii
#() LFpuuu
#() LFpLLp
#() LFpLpp
#() LFppii
#() LFppip
#() LFppLL
#() LFppLp
#() LFpppp
#() pFEipp
#() pFEupp
#() pFEpii
#() pFEpip
#() pFEppi
#() pFEppL
#() pFEppp
#() pFiiiu
#() pFiiup
#() pFippL
#() pFuiii
#() pFulli
#() pFdddd
#() pFpiii
#() pFpiip
#() pFpiuu
#() pFpiLL
#() pFpipi
#() pFpipp
@@ -462,6 +576,7 @@
#() pFpuup
#() pFpupi
#() pFplpp
#() pFpLip
#() pFppii
#() pFppiL
#() pFppip
@@ -474,6 +589,7 @@
#() pFpppL
#() pFpppp
#() pFSppi
#() vFEiipV
#() vFEpuup
#() vFEpLLp
#() vFEpppp
@@ -494,6 +610,7 @@
#() vFuiiiu
#() vFuiiip
#() vFuiiup
#() vFuiifi
#() vFuiIII
#() vFuiuii
#() vFuiuiu
@@ -530,51 +647,81 @@
#() vFfffff
#() vFddddp
#() vFpiiii
#() vFpiipp
#() vFpipii
#() vFpuipp
#() vFpuddd
#() vFpddii
#() vFpdddd
#() vFpliil
#() vFppiii
#() vFppiip
#() vFppiup
#() vFppipp
#() vFppWui
#() vFpppii
#() vFppppi
#() vFppppp
#() iFEippp
#() iFEpiii
#() iFEpipi
#() iFEpipp
#() iFEpipV
#() iFEpLpp
#() iFEpLpV
#() iFEppii
#() iFEppip
#() iFEppiV
#() iFEpplp
#() iFEpppp
#() iFEpppV
#() iFiiipu
#() iFiiipp
#() iFiiupp
#() iFiLLLL
#() iFipiii
#() iFipuip
#() iFippLp
#() iFipppi
#() iFipppp
#() iFuppLp
#() iFpiiii
#() iFpiiiu
#() iFpiiiL
#() iFpiiip
#() iFpiiuu
#() iFpiipi
#() iFpiipp
#() iFpipii
#() iFpipiL
#() iFpippi
#() iFpippp
#() iFpCCCC
#() iFpuuip
#() iFpuuui
#() iFpuuup
#() iFpuuLL
#() iFpuupp
#() iFplluu
#() iFpLlpp
#() iFppiip
#() iFppiup
#() iFppiLi
#() iFppipi
#() iFppipp
#() iFppupi
#() iFppupp
#() iFppllp
#() iFppLpi
#() iFppLpL
#() iFppLpp
#() iFpppii
#() iFpppiL
#() iFpppip
#() iFpppLi
#() iFpppLp
#() iFppppi
#() iFppppL
#() iFppppp
#() IFppIII
#() uFEppuu
@@ -583,10 +730,15 @@
#() uFpCCCC
#() uFpuuuu
#() uFppiip
#() uFppipp
#() uFpplip
#() uFppppp
#() lFipLLi
#() LFLpppp
#() LFpLLLp
#() LFpLppL
#() LFpLppp
#() LFppLLp
#() LFppppp
#() pFEpiii
#() pFEpipL
@@ -595,18 +747,24 @@
#() pFEppii
#() pFEppip
#() pFEpppp
#() pFipipL
#() pFuiiiu
#() pFuiipp
#() pFpiiii
#() pFpiiuu
#() pFpiipi
#() pFpiipp
#() pFpiuuu
#() pFpippp
#() pFpCuup
#() pFpCpup
#() pFpCppp
#() pFpuiii
#() pFpuiip
#() pFpuWWW
#() pFpuuWW
#() pFpuuup
#() pFpdddd
#() pFppiii
#() pFppipi
#() pFppipp
#() pFppuuu
@@ -618,6 +776,7 @@
#() pFppppi
#() pFppppp
#() vFEiiipp
#() vFEpuipp
#() vFEpLLpp
#() vFiiiiii
#() vFiiiuil
@@ -661,51 +820,92 @@
#() vFuppppp
#() vFffffff
#() vFdddddd
#() vFpiiiii
#() vFpiiuuu
#() vFpiippp
#() vFpipipV
#() vFpipppi
#() vFpudddd
#() vFpdddii
#() vFpddddd
#() vFppiiii
#() vFppiiip
#() vFppiipi
#() vFppilpp
#() vFppippi
#() vFppupii
#() vFpplppi
#() vFpplppp
#() vFppLppi
#() vFppLppp
#() vFpppiii
#() vFppppii
#() vFpppppi
#() vFpppppp
#() cFppLppi
#() iFEiippi
#() iFElpppp
#() iFEpiipp
#() iFEpilpV
#() iFEpippi
#() iFEpuppp
#() iFEppiLi
#() iFEppppp
#() iFiiiiii
#() iFiiiiip
#() iFiuiipi
#() iFuppipp
#() iFipupup
#() iFipuppp
#() iFuppppp
#() iFLppipp
#() iFpiiiii
#() iFpiiipp
#() iFpiippp
#() iFpiuuup
#() iFpiuupp
#() iFpippip
#() iFpipppp
#() iFpupuui
#() iFppiiuu
#() iFppiipi
#() iFppipii
#() iFppipiL
#() iFppIppp
#() iFppuiii
#() iFppuiiL
#() iFppuIII
#() iFppuupp
#() iFppupip
#() iFpplppi
#() iFppLupp
#() iFpppiuu
#() iFpppipi
#() iFpppipp
#() iFpppuii
#() iFpppupu
#() iFppppii
#() iFppppip
#() iFppppup
#() iFpppppi
#() iFpppppL
#() iFpppppp
#() uFpippup
#() uFpppppp
#() UFpippup
#() lFipLipu
#() lFipLipp
#() LFpipipi
#() LFSpLiip
#() pFEpippp
#() pFEpuipp
#() pFEpuupp
#() pFEpuppp
#() pFEpLLiN
#() pFEppLLp
#() pFEpppLp
#() pFEppppp
#() pFiCiiCi
#() pFdddddd
#() pFpiiiiu
#() pFpippip
#() pFpCuuCC
@@ -713,6 +913,7 @@
#() pFpCuuup
#() pFpuuuuu
#() pFppiiii
#() pFpppppu
#() pFpppppp
#() pFSpiiii
#() vFiiiiiip
@@ -750,10 +951,20 @@
#() vFuuddiip
#() vFuffffff
#() vFudddddd
#() vFpiiiipp
#() vFpiiliip
#() vFpipipii
#() vFpddiidd
#() vFpdddddd
#() vFppiiipi
#() vFppilppi
#() vFppipiip
#() vFppipipp
#() vFppipppp
#() vFppLpppi
#() vFppLpppp
#() vFpppiiii
#() vFpppuuuu
#() vFppppipi
#() iFEpLiLpV
#() iFEppLpIi
@@ -761,22 +972,37 @@
#() iFEpppppp
#() iFiiiiiip
#() iFpiiuuiu
#() iFpiuiipp
#() iFpiupiii
#() iFpippppp
#() iFpuuiuui
#() iFpuupppp
#() iFpupuuui
#() iFpupLpLi
#() iFpuppppp
#() iFpLipipi
#() iFppiiiip
#() iFppiiuui
#() iFppiipii
#() iFppiipiL
#() iFppipiip
#() iFppipipi
#() iFppippip
#() iFppipppi
#() iFppipppp
#() iFppuipiL
#() iFpppiiii
#() iFpppiiuu
#() iFpppiiup
#() iFpppiipi
#() iFpppiuwu
#() iFpppuiii
#() iFppppiii
#() iFppppdpi
#() iFpppppip
#() iFppppppp
#() uFuippppp
#() pFEpLiiiI
#() pFEppppip
#() pFifffppp
#() pFuupupup
@@ -785,6 +1011,7 @@
#() pFpCuuwwp
#() pFpCuuuuu
#() pFppuuppp
#() pFpppuupp
#() pFppppuuu
#() pFpppppuu
#() pFppppppp
@@ -811,8 +1038,14 @@
#() vFpippiiuu
#() vFpippiipi
#() vFppiiipii
#() vFppipipii
#() vFppippppi
#() vFpplppppi
#() vFpplppppp
#() vFppppiipi
#() iFEpippppp
#() iFEpuuLppp
#() iFEppppipp
#() iFiiiiiiip
#() iFiiupiupi
#() iFuiifpppp
@@ -831,6 +1064,8 @@
#() pFpCuwwWWu
#() pFpCuuuCup
#() pFpppuuLLu
#() pFpppppupp
#() vFiiiiiiiii
#() vFuiiiiiiii
#() vFuiiiiiuip
#() vFuiiiiiuup
@@ -846,23 +1081,29 @@
#() vFuffffffff
#() vFffuuuufff
#() vFddddddddd
#() vFpipiuiipp
#() vFpipppiipi
#() vFppiiipiii
#() vFpplpppppi
#() vFpppppippp
#() iFEpiiiiipi
#() iFEppplPPPP
#() iFiiiiiiiip
#() iFiiiipiiip
#() iFipiipippi
#() iFdddpppppp
#() iFpipLpiiip
#() iFppiuiippL
#() iFpppiiuuii
#() iFpppiipiiu
#() iFppppppppu
#() iFppppppppp
#() pFEppiiuuLi
#() pFEppuippuu
#() pFpiiiiuuuu
#() pFpCuWCCuuu
#() pFpuuwwWWww
#() pFppiiiiiip
#() pFppiiuuuLL
#() pFppipppppp
#() vFiiiiiiiiiu
@@ -880,6 +1121,7 @@
#() vFuffiiffiip
#() vFuddiiddiip
#() vFffffffffff
#() vFpppppppppp
#() iFiiiiiiiiip
#() iFpuupiuiipp
#() iFppuuiiiiii
@@ -905,6 +1147,7 @@
#() iFiiiiiiiiiip
#() iFpipllippppp
#() iFppppiiuuiiL
#() pFEppiiLpppip
#() pFEppuiipuuii
#() vFuuiiiiiiiuip
#() vFuuiiiiiiiuup
@@ -912,6 +1155,7 @@
#() vFffffffffffff
#() vFpipppiiiipii
#() vFpippppiiiipi
#() vFppiiuuuiupup
#() iFEppppiiiiuui
#() iFpipppppppppp
#() iFpppllipppppp
@@ -920,6 +1164,7 @@
#() pFpCuuWWwwCCup
#() pFpuuuWWWWWWWW
#() pFppiiuuuiupLp
#() pFpppppppppppp
#() vFuiiiiiiiiiuup
#() vFuuuuuuuuuuuuu
#() vFuffffffffffff
@@ -932,20 +1177,26 @@
#() vFuddiiddiiddiip
#() vFuuiiiiuuiiiiiii
#() vFfffffffffffffff
#() pFppppppppppppppp
#() iFpppppppppppppppp
#() pFpppppppppppppppp
#() vFppuiiiiipuiiiiiiii
#() pFiiiippppppppppppppp
#() pFipppppppppppppppppppppp
#!defined(NOALIGN) iFEpLp
#!defined(NOALIGN) iFEppu
#defined(HAVE_LD80BITS) DFD
#defined(HAVE_LD80BITS) DFDD
#defined(HAVE_LD80BITS) DFDp
#!defined(HAVE_LD80BITS) KFK
#!defined(HAVE_LD80BITS) KFKK
#!defined(HAVE_LD80BITS) KFKp
#() iFEv -> iFE
#() vFEv -> vFE
#() lFEv -> lFE
#() LFEv -> LFE
#() pFEv -> pFE
#() pFppv -> pFpp
#() iFEvpp -> iFEpp
#() pFEppv -> pFEpp
#() iFEpvpp -> iFEppp
#() iFEpvvppp -> iFEpppp
#() iFEpLvvpp -> iFEpLpp
+27
View File
@@ -0,0 +1,27 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedbz2TYPES_H_
#define __wrappedbz2TYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef int64_t (*iFp_t)(void*);
typedef int64_t (*iFpi_t)(void*, int64_t);
typedef int64_t (*iFpii_t)(void*, int64_t, int64_t);
typedef int64_t (*iFpiii_t)(void*, int64_t, int64_t, int64_t);
#define SUPER() ADDED_FUNCTIONS() \
GO(BZ2_bzCompressEnd, iFp_t) \
GO(BZ2_bzDecompress, iFp_t) \
GO(BZ2_bzDecompressEnd, iFp_t) \
GO(BZ2_bzCompress, iFpi_t) \
GO(BZ2_bzDecompressInit, iFpii_t) \
GO(BZ2_bzCompressInit, iFpiii_t)
#endif // __wrappedbz2TYPES_H_
@@ -0,0 +1,37 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedcryptoTYPES_H_
#define __wrappedcryptoTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFp_t)(void*);
typedef void* (*pFp_t)(void*);
typedef void (*vFpp_t)(void*, void*);
typedef void* (*pFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFpiipp_t)(void*, int64_t, int64_t, void*, void*);
typedef int64_t (*iFppppipp_t)(void*, void*, void*, void*, int64_t, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(CRYPTO_set_id_callback, vFp_t) \
GO(CRYPTO_set_locking_callback, vFp_t) \
GO(sk_new, pFp_t) \
GO(sk_pop_free, vFpp_t) \
GO(PEM_read_bio_DSAPrivateKey, pFpppp_t) \
GO(PEM_read_bio_DSA_PUBKEY, pFpppp_t) \
GO(PEM_read_bio_ECPrivateKey, pFpppp_t) \
GO(PEM_read_bio_EC_PUBKEY, pFpppp_t) \
GO(PEM_read_bio_RSAPrivateKey, pFpppp_t) \
GO(PEM_read_bio_RSA_PUBKEY, pFpppp_t) \
GO(ENGINE_ctrl, iFpiipp_t) \
GO(PEM_write_bio_DSAPrivateKey, iFppppipp_t) \
GO(PEM_write_bio_ECPrivateKey, iFppppipp_t) \
GO(PEM_write_bio_RSAPrivateKey, iFppppipp_t)
#endif // __wrappedcryptoTYPES_H_
+19
View File
@@ -0,0 +1,19 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedcurlTYPES_H_
#define __wrappedcurlTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef uint64_t (*uFpup_t)(void*, uint64_t, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(curl_easy_setopt, uFpup_t)
#endif // __wrappedcurlTYPES_H_
+39
View File
@@ -0,0 +1,39 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappeddbusTYPES_H_
#define __wrappeddbusTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
typedef int64_t (*iFppip_t)(void*, void*, int64_t, void*);
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
typedef int64_t (*iFppppp_t)(void*, void*, void*, void*, void*);
typedef int64_t (*iFpppppp_t)(void*, void*, void*, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(dbus_connection_remove_filter, vFppp_t) \
GO(dbus_timeout_set_data, vFppp_t) \
GO(dbus_watch_set_data, vFppp_t) \
GO(dbus_connection_set_dispatch_status_function, vFpppp_t) \
GO(dbus_connection_set_wakeup_main_function, vFpppp_t) \
GO(dbus_connection_set_data, iFpipp_t) \
GO(dbus_message_set_data, iFpipp_t) \
GO(dbus_pending_call_set_data, iFpipp_t) \
GO(dbus_message_get_args_valist, iFppip_t) \
GO(dbus_connection_add_filter, iFpppp_t) \
GO(dbus_pending_call_set_notify, iFpppp_t) \
GO(dbus_connection_try_register_fallback, iFppppp_t) \
GO(dbus_connection_try_register_object_path, iFppppp_t) \
GO(dbus_connection_set_timeout_functions, iFpppppp_t) \
GO(dbus_connection_set_watch_functions, iFpppppp_t)
#endif // __wrappeddbusTYPES_H_
@@ -0,0 +1,19 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedfontconfigTYPES_H_
#define __wrappedfontconfigTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef int64_t (*iFppiLi_t)(void*, void*, int64_t, uintptr_t, int64_t);
#define SUPER() ADDED_FUNCTIONS() \
GO(FcPatternAddWeak, iFppiLi_t)
#endif // __wrappedfontconfigTYPES_H_
@@ -0,0 +1,21 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedfreetypeTYPES_H_
#define __wrappedfreetypeTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef int64_t (*iFpplp_t)(void*, void*, intptr_t, void*);
typedef int64_t (*iFpuuLppp_t)(void*, uint64_t, uint64_t, uintptr_t, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(FT_Open_Face, iFpplp_t) \
GO(FTC_Manager_New, iFpuuLppp_t)
#endif // __wrappedfreetypeTYPES_H_
@@ -0,0 +1,22 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedgnutlsTYPES_H_
#define __wrappedgnutlsTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFp_t)(void*);
typedef void (*vFpp_t)(void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(gnutls_global_set_log_function, vFp_t) \
GO(gnutls_transport_set_pull_function, vFpp_t) \
GO(gnutls_transport_set_push_function, vFpp_t)
#endif // __wrappedgnutlsTYPES_H_
@@ -0,0 +1,19 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedldlinuxTYPES_H_
#define __wrappedldlinuxTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void* (*pFp_t)(void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(__tls_get_addr, pFp_t)
#endif // __wrappedldlinuxTYPES_H_
@@ -0,0 +1,28 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedlibasoundTYPES_H_
#define __wrappedlibasoundTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef int64_t (*iFp_t)(void*);
typedef void* (*pFppp_t)(void*, void*, void*);
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
typedef void* (*pFpipL_t)(void*, int64_t, void*, uintptr_t);
#define SUPER() ADDED_FUNCTIONS() \
GO(snd_dlclose, iFp_t) \
GO(snd_lib_error_set_handler, iFp_t) \
GO(snd_dlsym, pFppp_t) \
GO(snd_async_add_handler, iFpipp_t) \
GO(snd_async_add_pcm_handler, iFpppp_t) \
GO(snd_dlopen, pFpipL_t)
#endif // __wrappedlibasoundTYPES_H_
+169
View File
@@ -0,0 +1,169 @@
/*******************************************************************
* File automatically generated by rebuild_wrappers.py (v1.3.0.10) *
*******************************************************************/
#ifndef __wrappedlibcTYPES_H_
#define __wrappedlibcTYPES_H_
#ifndef LIBNAME
#error You should only #include this file inside a wrapped*.c file
#endif
#ifndef ADDED_FUNCTIONS
#define ADDED_FUNCTIONS()
#endif
typedef void (*vFv_t)(void);
typedef void (*vFp_t)(void*);
typedef int64_t (*iFp_t)(void*);
typedef intptr_t (*lFv_t)(void);
typedef uintptr_t (*LFv_t)(void);
typedef void (*vFpi_t)(void*, int64_t);
typedef void (*vFpu_t)(void*, uint64_t);
typedef int64_t (*iFpi_t)(void*, int64_t);
typedef int64_t (*iFpL_t)(void*, uintptr_t);
typedef int64_t (*iFpp_t)(void*, void*);
typedef int64_t (*iFpV_t)(void*, void*);
typedef int64_t (*iFSp_t)(void*, void*);
typedef void* (*pFip_t)(int64_t, void*);
typedef void* (*pFpi_t)(void*, int64_t);
typedef void* (*pFpp_t)(void*, void*);
typedef void (*vFipV_t)(int64_t, void*, void*);
typedef void (*vFpii_t)(void*, int64_t, int64_t);
typedef void (*vFpup_t)(void*, uint64_t, void*);
typedef int64_t (*iFiip_t)(int64_t, int64_t, void*);
typedef int64_t (*iFiiN_t)(int64_t, int64_t, ...);
typedef int64_t (*iFipp_t)(int64_t, void*, void*);
typedef int64_t (*iFipV_t)(int64_t, void*, void*);
typedef int64_t (*iFpLi_t)(void*, uintptr_t, int64_t);
typedef int64_t (*iFppi_t)(void*, void*, int64_t);
typedef int64_t (*iFppp_t)(void*, void*, void*);
typedef int64_t (*iFppV_t)(void*, void*, void*);
typedef int64_t (*iFpOu_t)(void*, int32_t, uint64_t);
typedef intptr_t (*lFppL_t)(void*, void*, uintptr_t);
typedef void* (*pFpip_t)(void*, int64_t, void*);
typedef void (*vFiipV_t)(int64_t, int64_t, void*, void*);
typedef void (*vFpLLp_t)(void*, uintptr_t, uintptr_t, void*);
typedef int64_t (*iFpipp_t)(void*, int64_t, void*, void*);
typedef int64_t (*iFpipV_t)(void*, int64_t, void*, void*);
typedef int64_t (*iFpLpp_t)(void*, uintptr_t, void*, void*);
typedef int64_t (*iFpLpV_t)(void*, uintptr_t, void*, void*);
typedef int64_t (*iFppii_t)(void*, void*, int64_t, int64_t);
typedef int64_t (*iFppiV_t)(void*, void*, int64_t, void*);
typedef int64_t (*iFpppp_t)(void*, void*, void*, void*);
typedef void (*vFpLLpp_t)(void*, uintptr_t, uintptr_t, void*, void*);
typedef int64_t (*iFiippi_t)(int64_t, int64_t, void*, void*, int64_t);
typedef int64_t (*iFpilpV_t)(void*, int64_t, intptr_t, void*, void*);
typedef int64_t (*iFpuppp_t)(void*, uint64_t, void*, void*, void*);
typedef void* (*pFpLLiN_t)(void*, uintptr_t, uintptr_t, int64_t, ...);
typedef void* (*pFppLLp_t)(void*, void*, uintptr_t, uintptr_t, void*);
typedef void* (*pFpppLp_t)(void*, void*, void*, uintptr_t, void*);
typedef int64_t (*iFpLiLpV_t)(void*, uintptr_t, int64_t, uintptr_t, void*, void*);
typedef void* (*pFpLiiiI_t)(void*, uintptr_t, int64_t, int64_t, int64_t, int64_t);
typedef int64_t (*iFpippppp_t)(void*, int64_t, void*, void*, void*, void*, void*);
#define SUPER() ADDED_FUNCTIONS() \
GO(__stack_chk_fail, vFv_t) \
GO(_ITM_deregisterTMCloneTable, vFp_t) \
GO(__cxa_finalize, vFp_t) \
GO(__sigsetjmp, iFp_t) \
GO(_setjmp, iFp_t) \
GO(getcontext, iFp_t) \
GO(setjmp, iFp_t) \
GO(fork, lFv_t) \
GO(syscall, LFv_t) \
GO(__longjmp_chk, vFpi_t) \
GO(_longjmp, vFpi_t) \
GO(longjmp, vFpi_t) \
GO(_ITM_registerTMCloneTable, vFpu_t) \
GO(backtrace, iFpi_t) \
GO(munmap, iFpL_t) \
GO(__vprintf_chk, iFpp_t) \
GO(dl_iterate_phdr, iFpp_t) \
GO(execvp, iFpp_t) \
GO(sigaltstack, iFpp_t) \
GO(swapcontext, iFpp_t) \
GO(vprintf, iFpp_t) \
GO(execlp, iFpV_t) \
GO(printf, iFpV_t) \
GO(_IO_file_stat, iFSp_t) \
GO(__sysv_signal, pFip_t) \
GO(signal, pFip_t) \
GO(sigset, pFip_t) \
GO(sysv_signal, pFip_t) \
GO(backtrace_symbols, pFpi_t) \
GO(__realpath_chk, pFpp_t) \
GO(fopen, pFpp_t) \
GO(fopen64, pFpp_t) \
GO(realpath, pFpp_t) \
GO(syslog, vFipV_t) \
GO(backtrace_symbols_fd, vFpii_t) \
GO(_ITM_addUserCommitAction, vFpup_t) \
GO(__fxstat, iFiip_t) \
GO(__fxstat64, iFiip_t) \
GO(__fcntl, iFiiN_t) \
GO(fcntl, iFiiN_t) \
GO(fcntl64, iFiiN_t) \
GO(__lxstat, iFipp_t) \
GO(__lxstat64, iFipp_t) \
GO(__sigaction, iFipp_t) \
GO(__xstat, iFipp_t) \
GO(__xstat64, iFipp_t) \
GO(sigaction, iFipp_t) \
GO(__printf_chk, iFipV_t) \
GO(mprotect, iFpLi_t) \
GO(ftw, iFppi_t) \
GO(ftw64, iFppi_t) \
GO(__cxa_atexit, iFppp_t) \
GO(__isoc99_vsscanf, iFppp_t) \
GO(__vfprintf_chk, iFppp_t) \
GO(__vsscanf, iFppp_t) \
GO(vasprintf, iFppp_t) \
GO(vfprintf, iFppp_t) \
GO(vsscanf, iFppp_t) \
GO(__isoc99_fscanf, iFppV_t) \
GO(__isoc99_sscanf, iFppV_t) \
GO(fprintf, iFppV_t) \
GO(fscanf, iFppV_t) \
GO(sprintf, iFppV_t) \
GO(sscanf, iFppV_t) \
GO(swscanf, iFppV_t) \
GO(__open, iFpOu_t) \
GO(open, iFpOu_t) \
GO(open64, iFpOu_t) \
GO(readlink, lFppL_t) \
GO(fts_open, pFpip_t) \
GO(__syslog_chk, vFiipV_t) \
GO(qsort, vFpLLp_t) \
GO(__vasprintf_chk, iFpipp_t) \
GO(glob, iFpipp_t) \
GO(glob64, iFpipp_t) \
GO(__fprintf_chk, iFpipV_t) \
GO(__vsnprintf, iFpLpp_t) \
GO(__vsnprintf_chk, iFpLpp_t) \
GO(vsnprintf, iFpLpp_t) \
GO(__snprintf, iFpLpV_t) \
GO(snprintf, iFpLpV_t) \
GO(swprintf, iFpLpV_t) \
GO(nftw64, iFppii_t) \
GO(makecontext, iFppiV_t) \
GO(__register_atfork, iFpppp_t) \
GO(__vsprintf_chk, iFpppp_t) \
GO(scandir, iFpppp_t) \
GO(scandir64, iFpppp_t) \
GO(vsprintf, iFpppp_t) \
GO(qsort_r, vFpLLpp_t) \
GO(__fxstatat, iFiippi_t) \
GO(__fxstatat64, iFiippi_t) \
GO(__sprintf_chk, iFpilpV_t) \
GO(__vswprintf_chk, iFpuppp_t) \
GO(vswprintf, iFpuppp_t) \
GO(mremap, pFpLLiN_t) \
GO(bsearch, pFppLLp_t) \
GO(lfind, pFpppLp_t) \
GO(lsearch, pFpppLp_t) \
GO(__snprintf_chk, iFpLiLpV_t) \
GO(__swprintf_chk, iFpLiLpV_t) \
GO(mmap, pFpLiiiI_t) \
GO(mmap64, pFpLiiiI_t) \
GO(__libc_start_main, iFpippppp_t)
#endif // __wrappedlibcTYPES_H_
Loaded 100 of 218 files, more files were not shown because too many files have changed in this diff. Show more