Compare commits

...
610 Commits
Author SHA1 Message Date
ptitSeb 9243ea4ca1 Bumped to v0.1.2 2021-07-03 14:42:17 +02:00
ptitSeb 2e871fc68a Added another name for wine64 2021-07-03 11:10:24 +02:00
ptitSeb 30eb08f8af More README updates 2021-07-03 11:05:49 +02:00
ptitSeb 7f51495877 Improved README 2021-07-03 10:49:59 +02:00
ptitSeb 112bc0d83f More libc wrapped functions 2021-07-03 10:32:48 +02:00
ptitSeb 501a4a8956 Made elf LOADADDR default again 2021-07-03 10:32:34 +02:00
ptitSeb bb4c06f107 More the LOADADDR of the box64 elf a 32bits value 2021-07-03 09:46:48 +02:00
ptitSeb 65fae1077f One more wrapped libc function 2021-07-03 09:46:28 +02:00
ptitSeb e3a36591aa Added even more libc wrapped functions (needed by Wine) 2021-07-02 22:23:31 +02:00
ptitSeb a597f6701f Added a couple of libc wrapped functions 2021-07-02 17:33:23 +02:00
ptitSeb 3b19a7fe1d Added 64 D1/D3 opcodes ([DYNAREC] too) 2021-07-02 17:30:52 +02:00
ptitSeb ccf9775658 Added some more libc wrapped functions 2021-07-02 16:40:41 +02:00
ptitSeb 762a499648 Fixed a typo 2021-07-02 16:34:24 +02:00
ptitSeb aa56188e7e Set default to NOLOADADDR, as many system doesn't like it 2021-07-02 16:05:41 +02:00
ptitSeb 1d92e65fcc Updated docs 2021-07-02 15:47:45 +02:00
ptitSeb a6f132f6da Added 64 0F AF opcode ([DYNAREC] Too) 2021-07-02 15:41:10 +02:00
ptitSeb cb75b670b6 Fixed nextFree memory search function (fixing regression with RaceTheSun and probably a few other) 2021-07-02 15:03:43 +02:00
ptitSeb 7bb9dd18da [DYNAREC] Improved the fast native call path 2021-07-02 14:37:09 +02:00
ptitSeb 140254f311 [DYNAREC] Fixed DIV opcode, and added test17 about div/idiv 2021-07-02 10:17:28 +02:00
ptitSeb 56401f6675 Improved low memory pre-allocation and added 47bits pre-allocation for Wine64 2021-07-01 17:09:03 +02:00
ptitSeb 99ba7707f6 [DYNAREC] Added CF opcode and optimized native call 2021-06-28 13:19:56 +02:00
ptitSeb ea1ef4e602 [DYNAREC] Added 66 98 CBW opcode 2021-06-28 10:53:46 +02:00
ptitSeb 78b6113d8b Start of a new dev. cycle 2021-06-27 12:28:12 +02:00
ptitSeb 59ab48b99e Bumped to v0.1.0 2021-06-27 10:20:11 +02:00
ptitSeb a7a58b920f Added 8C opcode 2021-06-25 13:49:29 +02:00
ptitSeb 1c26df2a90 Added getauxval wrapped function 2021-06-25 11:15:42 +02:00
ptitSeb c60e4839eb More improvments to elfloader 2021-06-23 11:11:29 +02:00
ptitSeb b626fc5095 Fixed a signature of a funciton from libXi 2021-06-23 11:11:00 +02:00
ptitSeb bcd504eb05 Various change to try improve stability on JIT'd program (like mono for Terraria, with moderate success) 2021-06-21 10:49:42 +02:00
ptitSeb 7057b7f929 More logs on 'strange' SIGSEGV... 2021-06-21 10:48:54 +02:00
ptitSeb 6af070e25f [DYNAREC] Added 67 0F 2E/2F opcodes 2021-06-21 10:47:40 +02:00
ptitSeb af1a7bd6f4 Fixed 67 F2/F3 0F 2E/2F not handled for now 2021-06-21 10:46:55 +02:00
ptitSeb dfd3d0ec93 [DYNAREC] Try to free dynablocks when no longer used 2021-06-19 11:15:53 +02:00
ptitSeb 1791c0937a Improved mutex handling 2021-06-19 11:15:20 +02:00
ptitSeb c2dd6a0c6a Small fixes to the my_backtrace (it doesn't seems to be working anyway) 2021-06-18 18:34:49 +02:00
ptitSeb f300e76c9b [DYNAREC] Optimized some flags handling for a few of the complex emiter (+10% speed in 7z bench) 2021-06-18 13:17:37 +02:00
ptitSeb 8f6f880b6a [DYNAREC] Small optim on shl/shr 16bits, and marked all opcode that need optimization in dynarec dumps 2021-06-18 12:09:05 +02:00
ptitSeb 3dcef655c3 [DYNAREC] Optimized DIV/IDIV 32/64bits opcodes 2021-06-18 11:22:57 +02:00
ptitSeb 4c476de74b Optimized memory protection tracking 2021-06-17 17:31:47 +02:00
ptitSeb c9e277aee5 Added a few more libc wrapped functions 2021-06-16 17:26:01 +02:00
ptitSeb 689d6906ef Fixed a warning 2021-06-16 17:25:35 +02:00
ptitSeb 1712afdae9 Improved emulated library loader, to not stop at first binary found even if not at the correct architecture 2021-06-16 15:19:13 +02:00
ptitSeb 8428fafd3a Added some hack to try detect SDL_sound custom build for SDL2 and use emulated one first (fixing some sound in To The Moon) 2021-06-16 15:03:08 +02:00
ptitSeb 3074846477 Fixed SDL_HasIntersection signature (fixing To The Moon blank screen) 2021-06-16 15:02:21 +02:00
ptitSeb 6c1825ba65 Small fix for sdl2rwops emulated close 2021-06-16 15:01:49 +02:00
ptitSeb bef0a5f793 Better trace for lseek functions 2021-06-16 15:01:12 +02:00
ptitSeb 8e694eac57 Some more wrapped functions to libc, and both libudev 2021-06-15 17:15:01 +02:00
ptitSeb 8622f9fdc3 Improved dlsym a bit 2021-06-15 17:14:37 +02:00
ptitSeb 6e6a8f47af Added some speicifc workaround for libcef (staticaly linked with tcmalloc) 2021-06-15 17:14:09 +02:00
ptitSeb 7a57c70d81 Improved cpu capability flags, and silenced a warning in of_unconvert 2021-06-15 17:13:26 +02:00
ptitSeb b2a1af1029 Fixed a crash with some glibc wrapped /not-yet wrapped libs 2021-06-15 17:12:35 +02:00
ptitSeb c44961c063 Improved Log for emit_signal 2021-06-15 17:11:28 +02:00
ptitSeb aceb234c2e Improved steam detection and added steam-runtime-check-requirements workaround 2021-06-15 17:10:54 +02:00
ptitSeb dd6b60818c Added syscall 20 2021-06-15 17:10:18 +02:00
ptitSeb 1978b16581 Improved and fixed Trace for some functions 2021-06-15 17:10:02 +02:00
ptitSeb 0d079b8c0b [DYNAREC] Improved UD2 handling 2021-06-15 17:09:30 +02:00
ptitSeb 913029f4c5 Small work around pthread_once 2021-06-15 17:08:52 +02:00
ptitSeb c667c71a99 Added libtcmallocminimal workaround 2021-06-15 17:08:14 +02:00
ptitSeb 3cd8b9a44e [DYNAREC] Added 66 0F F7 opcode 2021-06-14 18:26:34 +02:00
ptitSeb 126119b1fb [DYNAREC] Added shrd32c emiter and 0F AC opcode 2021-06-14 17:31:01 +02:00
ptitSeb 701bf913e8 [DYNAREC] Added message Need Optim on SH(L/R)D Ed, Gd, CL opcode 2021-06-14 17:10:50 +02:00
ptitSeb 00b5944271 [DYNAREC] Added shld32c emiter and 0F A4 opcode 2021-06-14 17:07:19 +02:00
ptitSeb 196076f952 [DYNAREC] Added 0F 2B opcode 2021-06-14 16:06:11 +02:00
ptitSeb e350224157 Added wrapped execl function 2021-06-14 16:05:45 +02:00
ptitSeb 730e129a80 Change the way locked mutex are detected (taken from box86) 2021-06-14 14:53:20 +02:00
ptitSeb 883fc1681d Added 66 0F 3A 0B opcode ([DYNAREC] too) 2021-06-14 12:19:21 +02:00
ptitSeb 6b2b672c5e Don't launch gdb if Trace is redirected to a file (avoid empty trace when mono stuff crashes) 2021-06-14 12:18:41 +02:00
ptitSeb 1d31bf699f Added 66 0F 38 20..25 SSE4 opcodes ([DYNAREC] too) 2021-06-14 11:09:10 +02:00
ptitSeb c62728f44f [DYNAREC] Fix special case of PSHUFD on memory with Ib=0 (fixed the Blankscreen issue with Unity3D games) 2021-06-13 14:21:47 +02:00
ptitSeb 90efb1ff31 [DYNAREC] Small optim for PSHUFW opcode 2021-06-13 14:20:52 +02:00
ptitSeb 7625cc7ceb [DYNAREC] Small optim on PSUHFD opcode 2021-06-13 12:32:12 +02:00
ptitSeb a074115bf5 Fixed issue with LOCK REX.W XADD opcode 2021-06-13 12:31:20 +02:00
ptitSeb c3aa068179 [DYNAREC] Fixed a few opcodes: BTR/BTC/BTS 16bits, CVTTPD2DQ and PSHUF(L/H)W 2021-06-12 23:46:06 +02:00
ptitSeb e07be95646 [DYNAREC] Fixed CC flag for SAR 2021-06-12 22:31:56 +02:00
ptitSeb 0777a568d7 [DYNAREC] Fixed FIS(TT)(P) opcodes 2021-06-12 21:50:31 +02:00
ptitSeb f6ce622841 [DYNAREC] Improved flag handling 2021-06-12 20:41:34 +02:00
ptitSeb 508545aa87 Added suport for arch_prctl syscall, and GL segment handling ([DYNAREC] too) 2021-06-07 20:06:02 +02:00
ptitSeb 52d86177c5 Added wrapped execv family functions 2021-06-07 18:36:25 +02:00
ptitSeb 979d1cfba9 [DYNAREC] Fixed a warning 2021-06-07 18:35:54 +02:00
ptitSeb 31a01aceab Small adjustment to tls record 2021-06-07 18:07:02 +02:00
ptitSeb 3b39d1270d [DYNAREC] Added 66 F0 81/83 opcodes 2021-06-07 10:08:46 +02:00
ptitSeb d5b286c050 Added 66 F0 81 opcodes 2021-06-07 10:08:06 +02:00
ptitSeb 1f23848e25 [DYNAREC] Small optimisation on handling of relative addressing 2021-06-06 20:34:02 +02:00
ptitSeb db1c033c7c Cosmetic change 2021-06-06 20:33:29 +02:00
ptitSeb 489afcfb41 Added a test for ucomiss opcode 2021-06-06 20:32:55 +02:00
ptitSeb 5519ddad0b [DYNAREC] Fixed end handling in dynablock construction 2021-06-06 17:25:20 +02:00
ptitSeb e788589944 [DYNAREC] Small fix to a printer 2021-06-06 17:24:39 +02:00
ptitSeb 7a894540b9 [DYNAREC] Fixed potential issue with longjmp native function call 2021-06-06 13:26:58 +02:00
ptitSeb 30f0f3a5a1 Small fixes to interpretor 2021-06-06 11:27:49 +02:00
ptitSeb debc7284b3 Fixed regression on pthread_mutex_t 2021-06-06 09:55:14 +02:00
ptitSeb 60f5dfabd8 Added wrapeed times function to libc 2021-06-06 09:26:41 +02:00
ptitSeb dd2f209096 Improvment to a few libc wrapped functions 2021-06-06 08:31:46 +02:00
ptitSeb 3b181576c8 Added a wrapped pthread function, and improved mutex handling 2021-06-06 08:30:57 +02:00
ptitSeb 409334ea56 Some small improvments in signal handling 2021-06-06 08:29:32 +02:00
ptitSeb 71218a6f70 Added some more syscalls 2021-06-06 08:28:30 +02:00
ptitSeb a5be3727e9 Better handling of on-purpose SIGSEGV 2021-06-05 17:51:28 +02:00
ptitSeb 836b646e24 Better trace for ftok and getcwd functions 2021-06-05 17:49:51 +02:00
ptitSeb 15e4830dff Added a few more libc wrapped functions 2021-06-05 15:10:53 +02:00
ptitSeb ac1156d165 Added syscall 228 2021-06-05 15:10:39 +02:00
ptitSeb 370ec24987 Added setpgid wrapped function 2021-06-05 15:07:00 +02:00
ptitSeb 3bdcae10c8 Added a few more wrapped function and improved getopt handling 2021-06-05 15:03:37 +02:00
ptitSeb 681df1604d Fixed python wrapper builder 2021-06-05 14:27:31 +02:00
ptitSeb 05abd88ea5 [DYNAREC] Various small fixes to flags handling 2021-06-05 10:23:38 +02:00
ptitSeb 42670c0130 Fixed BT/BTC/BTR/BTS opcodes ([DYNAREC] too) 2021-06-05 10:23:38 +02:00
ptitSeb f4c15979db Merge pull request #13 from rajdakin/useGenerated
Fixed some wrapped functions, upgraded the python script
2021-06-04 23:22:51 +02:00
rajdakin 8d97f13677 Fixed some wrapped functions, upgraded the python script 2021-06-04 23:01:56 +02:00
ptitSeb 75c4c3d6b9 Fixed SDL_JoystickGetGUIDString function signature 2021-06-04 16:55:40 +02:00
ptitSeb a71e81c842 [DYNAREC] Fixed DD C0..C7 FFREE opcode 2021-06-04 16:55:30 +02:00
ptitSeb add55f3cec Added an option to use stderr for logs 2021-06-04 16:54:50 +02:00
ptitSeb c6f6a9ef72 Improved unloading of libs 2021-06-04 11:05:40 +02:00
ptitSeb 1c1e39ef64 [DYNAREC] Improved SMC handling 2021-06-04 10:56:16 +02:00
ptitSeb f5655d85a3 Rephrased a comment 2021-06-03 21:33:04 +02:00
ptitSeb c31262d339 Merge pull request #12 from rajdakin/pyfix
Fixed the Python script and added more typing
2021-06-03 21:24:35 +02:00
rajdakin 570798358c Fixed the Python script/added more typing 2021-06-03 21:15:29 +02:00
ptitSeb 05c9644ea6 Some fine-tunning on wrapped lubncurses and friends 2021-06-03 16:14:43 +02:00
ptitSeb 051bd2b10b Improved elfloader with COPY and GLOBAL reloc with version 2021-06-03 16:14:23 +02:00
ptitSeb b1b9d10656 Added a wrokaround for libtinfo global variables 2021-06-03 15:31:22 +02:00
ptitSeb 506f78eb32 Some work around libncurses and friends 2021-06-03 15:21:33 +02:00
ptitSeb 1336ddfad7 Fixed special case with FSCALE ocpode ([DYNAREC] too) 2021-06-03 15:21:33 +02:00
ptitSeb f3617f720b Fixed a warning 2021-06-03 15:21:33 +02:00
ptitSeb 844a1f43ed Merge pull request #11 from rajdakin/main
Enhancement of the Python script
2021-06-02 21:25:23 +02:00
rajdakin 8e42412490 Added types to the Python script, fixed some issues 2021-06-02 21:04:43 +02:00
rajdakin 2737180a20 Added some comments to the Python script, changed little things 2021-06-02 21:04:43 +02:00
ptitSeb 57e9e55705 Added one more syscall 2021-06-02 15:35:24 +02:00
ptitSeb 3f3f8b41e9 [DYNAREC] Fix x87opcode with rounding 2021-06-02 15:30:43 +02:00
ptitSeb d3ea390983 Added wrapped libncurses, libncurses6, libncursesw, libformw, libtinfo and libtinfo6 2021-06-02 14:52:10 +02:00
ptitSeb 2f1cc844fd Added 66 A1/A3 opcodes ([DYNAREC] too) 2021-06-02 14:51:06 +02:00
ptitSeb 543af50ff8 Added some more syscalls 2021-06-02 14:41:22 +02:00
ptitSeb f6444c8d45 Added fallback to no version in PltResolver for ver=0 symbol not found 2021-06-02 12:42:32 +02:00
ptitSeb df96dd0060 Added wrapped libxml2 (from box86) 2021-06-01 17:13:34 +02:00
ptitSeb 956e2aace3 Added F5 opcode ([DYNAREC] too) 2021-06-01 17:13:15 +02:00
ptitSeb 1951d525d1 Various small mprovments to interpretor 2021-06-01 16:42:34 +02:00
ptitSeb 3d4d678bdc Some small wrapped libGL improvements 2021-06-01 13:56:14 +02:00
ptitSeb b78d92d288 Added some more wrapped libGL functions (help apitrace) 2021-06-01 10:58:07 +02:00
ptitSeb e5dc4d7e78 Better trace for glXGetProcAddressARB 2021-06-01 10:37:58 +02:00
ptitSeb cd247ef6c1 Improved custom named libGL handling 2021-06-01 10:32:46 +02:00
ptitSeb 104cf8a58b Some adjustements to elfloader needed libs loading 2021-05-31 18:04:25 +02:00
ptitSeb 976f175aa9 Fixed munmap with 0 length 2021-05-31 17:06:12 +02:00
ptitSeb 81a06c47a1 Define CLFLUSH size in CPUID (helps Java programs) 2021-05-31 13:16:12 +02:00
ptitSeb 46b8c6bc83 Added alternate name for libSDL2_image, libSDL2_ttf and libexpat 2021-05-30 20:28:31 +02:00
ptitSeb 5f83a3f98a [DYNAREC] Added 66 0F E7 opcode 2021-05-30 20:18:44 +02:00
ptitSeb 2f6129bfd5 [DYNAREC] Added CC opcode 2021-05-30 18:56:00 +02:00
ptitSeb 26698b6449 Added some support for R_X86_64_TLSDESC relocation 2021-05-30 14:12:54 +02:00
ptitSeb 61839151c0 Fixed BOX64_DYNAREC_DUMP=2 env. var. 2021-05-30 14:00:22 +02:00
ptitSeb b38c9ea253 Added wcsncasecmp wrapped function 2021-05-30 11:57:50 +02:00
ptitSeb 25754a47e0 SDL2 GL GetProcAddress also print detail with BOX64_DLSYM_ERROR now 2021-05-30 11:51:43 +02:00
ptitSeb 278888c912 Improve handling of freetype FTC_Manager 2021-05-30 10:35:06 +02:00
ptitSeb 7faa4704e6 Handling F0 66 prefix same as 66 F0 2021-05-30 09:05:48 +02:00
ptitSeb ba48b6c793 Added a couple more wrapped function to libc 2021-05-29 18:29:43 +02:00
ptitSeb f8a969d43e Reworked elfloader, handle versionned symbols now 2021-05-29 18:05:37 +02:00
ptitSeb 55720342ad Splited Elf Dump from LOG handling 2021-05-28 11:55:57 +02:00
ptitSeb 085239ef4a Added 0F 0D /1 opcode ([DYNAREC] too) 2021-05-28 11:00:44 +02:00
ptitSeb df61d561f6 Added some more wrapped file oriented function to libc 2021-05-28 08:08:59 +02:00
ptitSeb 3cd8b5f48b Added wrapped wcstoul to libc 2021-05-24 11:41:50 +02:00
ptitSeb 2e21e46e86 Added more wrapped functions to libcrypto and floorl to libm 2021-05-24 09:54:31 +02:00
ptitSeb cb73a9a6bc Added a few more wrapped functions to libc and libcrypto 2021-05-23 21:59:33 +02:00
ptitSeb 5199df9b61 [DYNAREC] Added 64 F3 0F 11 opcode 2021-05-23 09:11:55 +02:00
ptitSeb 537ca9f724 Added 64 F3 0F 10 opcode ([DYNAREC] too) 2021-05-23 09:09:04 +02:00
ptitSeb fc5f5dab29 Added a few libc wrapped functions 2021-05-22 16:32:57 +02:00
ptitSeb 4be307820b Added 64 80 opcodes ([DYNAREC] too) 2021-05-21 10:05:36 +02:00
ptitSeb 15227bbc06 Added a couple of wrapped functions to libc 2021-05-19 14:37:01 +02:00
ptitSeb d0da2c24fb Added some more libc wrapped functions 2021-05-19 11:18:27 +02:00
ptitSeb 152a8a4666 Removed useless GetFS in F0 prefix interpretor 2021-05-19 10:10:36 +02:00
ptitSeb 86669beb7a [DYNAREC] Fixed a warning 2021-05-19 09:58:38 +02:00
ptitSeb ba2a70a484 Fixed a warning on non-trace dynarec build 2021-05-19 09:58:22 +02:00
ptitSeb 88ffcf6396 Fixed compile options for PI4 profile 2021-05-19 09:57:59 +02:00
ptitSeb 4d347f9ff0 Added a few wrapped function to libc and pthreads 2021-05-19 08:45:37 +02:00
ptitSeb 252258d138 Added %zd support in myalign varg hadnling 2021-05-19 08:45:13 +02:00
ptitSeb e35b25015b Added signal mask handling in setjmp/longjmp functions 2021-05-18 11:13:18 +02:00
ptitSeb 422844f842 Added wrapped pthread_getname_np function 2021-05-18 11:10:01 +02:00
ptitSeb 61725c8b49 Small fixes to my_backtrace function 2021-05-17 21:23:14 +02:00
ptitSeb 727178df57 [DYNAREC] Added 0F 50/52/53 opcodes 2021-05-17 20:42:36 +02:00
ptitSeb 66b3303f22 [DYNAREC] Added 66 0F D3/F3 opcodes 2021-05-17 20:42:01 +02:00
ptitSeb 47c3fad83b [DYNAREC] More emitters 2021-05-17 20:41:41 +02:00
ptitSeb 3928222395 Small fixed to 0F 50 opcode 2021-05-17 20:40:53 +02:00
ptitSeb 414d33a46c [DYNAREC] Fixed F2 0F 10/11 opcodes 2021-05-17 20:39:18 +02:00
ptitSeb 40a2c8393e [DYNAREC] Added F0 FF opcodes 2021-05-17 16:26:36 +02:00
ptitSeb 48fe298a36 Added wcsnlen wrapped function 2021-05-17 16:26:07 +02:00
ptitSeb 2865f0eab2 Added some wrapped function for libSDL2 and libGL 2021-05-17 12:59:49 +02:00
ptitSeb a5780632ca Added fwprintf wrapped function 2021-05-17 10:15:19 +02:00
ptitSeb bd5d29a825 Fixed epoll_wait alignment 2021-05-17 10:09:13 +02:00
ptitSeb 5255935a31 Added 2 more wrapped libc functions 2021-05-16 17:07:55 +02:00
ptitSeb a31ee062b6 Added 66 0F B6 opcode ([DYNAREC] too) 2021-05-16 16:57:39 +02:00
ptitSeb c56c991bf7 Added wrapped libexpat (for torchlight2) 2021-05-16 10:55:51 +02:00
ptitSeb 5ea4b796a5 [DYNAREC] Fix ROL/ROR 8bits opcodes 2021-05-16 10:55:27 +02:00
ptitSeb 8fe7378f86 Small hack on elfloader (for Torchlight2 and Unity3D and Dosbox) 2021-05-16 10:54:44 +02:00
ptitSeb 1224ffa7cd Fixed a 64bit issue with end pointer for emulated lib symbols 2021-04-26 11:01:14 +02:00
ptitSeb 56766df719 Aligned struct epoll 2021-04-26 10:14:29 +02:00
ptitSeb e505e5e466 Morte improved functions traces 2021-04-26 10:14:16 +02:00
ptitSeb 4cdc3c62b2 Added wrapeed libcrypt.so 2021-04-25 09:24:28 +02:00
ptitSeb 4402f08245 Fixed some issue when GL is used via SDL2 only 2021-04-25 09:24:09 +02:00
ptitSeb 954830032b Added a couple of syscall 2021-04-25 09:14:00 +02:00
ptitSeb 6f3fad8a16 Fixed dirent conversion (for good) 2021-04-24 15:42:24 +02:00
ptitSeb 2bb956bb06 Improved ofconvert function a bit 2021-04-24 15:42:05 +02:00
ptitSeb 7fa2a273d0 Fixed linux dirent64 to linux dirent conversion 2021-04-24 15:01:46 +02:00
ptitSeb 52e125e35a Added 66 F0 83 opcode 2021-04-24 14:37:37 +02:00
ptitSeb 57bea35004 Added more flags to ofconvert functions 2021-04-24 14:37:24 +02:00
ptitSeb 890842286b Added one more wrapped libfontconfig function 2021-04-24 14:36:50 +02:00
ptitSeb aec0ad9128 Added more syscalls 2021-04-24 14:36:21 +02:00
ptitSeb 4f5b5a995b Added more libc wrapped functions 2021-04-24 12:17:51 +02:00
ptitSeb bcd07ff6c7 Added some more syscalls 2021-04-24 12:02:21 +02:00
ptitSeb 68d7188f3e Added 0F 0B UD2 opcode 2021-04-24 12:01:58 +02:00
ptitSeb a924a74d82 Added wrapped libatspi (empty) 2021-04-24 11:24:15 +02:00
ptitSeb a20b830379 Better trace for getenv 2021-04-24 11:23:55 +02:00
ptitSeb 12fe96b114 Added wrapped libatk and libatk-bridge 2021-04-24 10:14:45 +02:00
ptitSeb 3432721379 Added 2 more wrapped funciton to libc 2021-04-23 14:01:25 +02:00
ptitSeb b39b7fd374 Fixed some crash with wrapped libSDL_sound 2021-04-22 12:42:54 +02:00
ptitSeb 406ddff9a1 Added 1 more funciton to libSDL2 2021-04-21 15:32:42 +02:00
ptitSeb d16d985a48 More libc wrapped functions 2021-04-21 14:58:49 +02:00
ptitSeb 0a2ea72d72 Added special case for unaligned LOCK INC QWord ptr[ED] 2021-04-21 14:53:01 +02:00
ptitSeb 3b4de7152c Added special case for unaligned LOCK DEC QWord ptr[ED] 2021-04-21 13:42:15 +02:00
ptitSeb 5520dae2e7 Another small change to custommem MaxFreeblock handling 2021-04-20 12:16:43 +02:00
ptitSeb 7a7f26c80e Added a couple of wrapped libc functions 2021-04-19 14:33:18 +02:00
ptitSeb 35f4944afb Improvments to ElfLoader Reloc handling and Reload of memory 2021-04-19 14:23:37 +02:00
ptitSeb 0a107d10eb [DYNAREC] Added F3 0F 1E opcode 2021-04-19 14:23:09 +02:00
ptitSeb 2c56ccfabe Fixed a small issue with Custom Mem handler and MexFreeBlock calculation 2021-04-19 14:22:39 +02:00
ptitSeb d1497e98db Added handling of 3E prefix ([DYNAREC] too) 2021-04-18 13:24:08 +02:00
ptitSeb 7925a8e1b3 Added libOpenGL.so.0 as a synonym for libGL.so.1 2021-04-18 13:17:28 +02:00
ptitSeb d529bf3c0c Added wrapped libpng16 2021-04-18 13:16:54 +02:00
ptitSeb 802c5a9d5b [DYNAREC] Added 0F 64/65/66/6B/72/75/76/D3/F5 opcodes 2021-04-18 12:21:01 +02:00
ptitSeb 3a22c36d04 Added some libc wrapped functions 2021-04-18 11:04:18 +02:00
ptitSeb 512ee40dbc Added a few more FreeType wrapped functions 2021-04-18 10:51:30 +02:00
ptitSeb d84e1f49ce Fixed GetNativeFnc 2021-04-18 09:03:20 +02:00
ptitSeb c4abaf8c8d Added wrapped libXft 2021-04-17 18:47:22 +02:00
ptitSeb 59fe5f3572 Fixed handling of * in scnaf/printf Stack argument handling 2021-04-17 18:47:09 +02:00
ptitSeb 18320e19bc Added 91..96 opcode and fixe REX.B 99 one ([DYNAREC] too) 2021-04-17 14:40:19 +02:00
ptitSeb 248cd2e749 Fixed nexttoward(f) wrapped functions, and improved long double handling 2021-04-17 10:50:33 +02:00
ptitSeb 3b550eeed3 [DYNAREC] Hack to handle FLD/FSTP tbytes sequence faster 2021-04-17 10:49:53 +02:00
ptitSeb 097c0ac0b7 Added wrapped libFLAC 2021-04-16 19:39:29 +02:00
ptitSeb 7a95dcd6b6 Added E0..E3 opcodes ([DYNAREC] too) 2021-04-16 15:46:03 +02:00
ptitSeb 47d0c04b30 Added more libc wrapped functions 2021-04-16 15:45:31 +02:00
ptitSeb 16be2bd305 [DYNAREC] Smal fix on the x86 size computation for sons of dynablocks 2021-04-16 15:44:54 +02:00
ptitSeb 7cf6ee06a1 [DYNAREC] Small printer fix for LDRSW 2021-04-16 15:43:55 +02:00
ptitSeb dd4c413e41 Use curl4 wrapper fro libcurl.so.3 2021-04-16 15:43:16 +02:00
ptitSeb 08d2ac41f6 Some improvement to custommem handling 2021-04-16 15:42:45 +02:00
ptitSeb fd939c6fce Also handle internal mutex in my_sighandler 2021-04-14 18:06:04 +02:00
ptitSeb 82755b5ef2 Added wrapped libSDL_net and libSDL_sound 2021-04-14 16:27:53 +02:00
ptitSeb 7b4cbee8e7 Improved elfloader 2021-04-14 16:27:26 +02:00
ptitSeb 5346f594d4 Fixed dynarec builds 2021-04-14 16:06:47 +02:00
ptitSeb 6f217d78da Merge pull request #10 from rajdakin/warnFixRefactor
Warnings and fixes
2021-04-14 14:54:30 +02:00
rajdakin cdf71c4cbc Oops-es 2021-04-14 14:25:02 +02:00
rajdakin e93a280d2c Third pass, bumped the minimal CMake version up to 3.4 2021-04-14 13:15:18 +02:00
rajdakin 51fa96c44b Second pass 2021-04-14 13:12:04 +02:00
rajdakin 48d6135106 First pass 2021-04-14 13:11:51 +02:00
ptitSeb 0d38b1cd91 Start of a new dev. cycle 2021-04-14 10:06:48 +02:00
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
322 changed files with 44109 additions and 6150 deletions

No files matched your search

+25
View File
@@ -1,3 +1,28 @@
v0.1.2
======
* OpenSource!
* A few more opcode added to the Interpretor and the Dynarec
* Improved Native Function calling
* Added some function to limit allocated memory to 47bits space (for Wine)
* Improved and Fixed the functions to limit allocated memory to 32bits space
* Wine is starting now, but not everything and every version works
v0.1.0
======
* Improvement to ElfLoader
* More opcode added to the Dynarec
* More lib wrapping
* Some fixes to a few function signature
* Improvement to Signal handling, and internal mutex handling
* A few fixes to some dynarec opcodes
* A few fixes to some interpretor opcodes
v0.0.8
======
* Improvement to SSE/x87 handling
* More opcode added to the Dynarec
* More lib wrapping
v0.0.6
======
* Added Dynarec for ARM64
+115 -20
View File
@@ -1,11 +1,15 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.4)
cmake_policy(SET CMP0065 NEW)
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" OFF)
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 "")
@@ -34,7 +38,7 @@ project(box64 C ASM)
enable_testing()
set(default_build_type "RelwithDebInfo")
set(default_build_type "RelWithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
@@ -44,9 +48,16 @@ endif()
if(RPI4ARM64)
add_definitions(-DRPI)
add_definitions(-DRPI4ARM64)
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")
add_definitions(-pipe -march=armv8-a+crc -mtune=cortex-a72)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc -mtune=cortex-a72")
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)
@@ -63,7 +74,8 @@ else()
set(BOX64 box64)
endif()
set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
#set(BOX64_ELF_ADDRESS "0x500062800000") #random load address...
set(BOX64_ELF_ADDRESS "0x64800000") #low address
if(LD80BITS)
add_definitions(-DHAVE_LD80BITS)
@@ -92,6 +104,8 @@ if(USE_CCACHE)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
else()
message(SEND_ERROR "ccache not found!")
endif()
endif()
@@ -128,12 +142,18 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64run6664.c"
"${BOX64_ROOT}/src/emu/x64run66d9.c"
"${BOX64_ROOT}/src/emu/x64run66dd.c"
"${BOX64_ROOT}/src/emu/x64run66f0.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"
@@ -144,6 +164,9 @@ set(ELFLOADER_SRC
"${BOX64_ROOT}/src/emu/x64trace.c"
"${BOX64_ROOT}/src/librarian/librarian.c"
"${BOX64_ROOT}/src/librarian/library.c"
"${BOX64_ROOT}/src/librarian/dictionnary.c"
"${BOX64_ROOT}/src/librarian/globalsymbols.c"
"${BOX64_ROOT}/src/librarian/symbols.c"
"${BOX64_ROOT}/src/libtools/auxval.c"
"${BOX64_ROOT}/src/libtools/myalign.c"
"${BOX64_ROOT}/src/libtools/sdl1rwops.c"
@@ -163,39 +186,95 @@ set(ELFLOADER_SRC
set(WRAPPEDS
"${BOX64_ROOT}/src/wrapped/wrappedalure.c"
"${BOX64_ROOT}/src/wrapped/wrappedalut.c"
"${BOX64_ROOT}/src/wrapped/wrappedatk.c"
"${BOX64_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX64_ROOT}/src/wrapped/wrappedatspi.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/wrappedexpat.c"
"${BOX64_ROOT}/src/wrapped/wrappedflac.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/wrappedlibcrypt.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibcups.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibdl.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibform.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibformw.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/wrappedlibncurses.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibncursesw.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibogg.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibpanel.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/wrappedlibtinfo.c"
"${BOX64_ROOT}/src/wrapped/wrappedlibtinfo6.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/wrappedlibxft.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/wrappedpng16.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulse.c"
"${BOX64_ROOT}/src/wrapped/wrappedpulsesimple.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1image.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1mixer.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1net.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1sound.c"
"${BOX64_ROOT}/src/wrapped/wrappedsdl1ttf.c"
"${BOX64_ROOT}/src/wrapped/wrappedsmpeg.c"
"${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/wrappedtcmallocminimal.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"
"${BOX64_ROOT}/src/wrapped/wrappedxml2.c"
)
#set(WRAPPEDS_HEAD "${BOX64_ROOT}/src/wrapped/wrappedd3dadapter9_gen.h")
@@ -209,9 +288,9 @@ set(WRAPPER "${BOX64_ROOT}/src/wrapped/generated/wrapper.c" "${BOX64_ROOT}/src/w
add_custom_command(
OUTPUT "${BOX64_ROOT}/src/wrapped/generated/functions_list.txt"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
COMMAND "${PYTHON_EXECUTABLE}" "${BOX64_ROOT}/rebuild_wrappers.py"
"${BOX64_ROOT}"
"PANDORA" "HAVE_LD80BITS" "NOALIGN" "HAVE_TRACE" "--"
${WRAPPEDS_HEAD}
MAIN_DEPENDENCY "${BOX64_ROOT}/rebuild_wrappers.py"
DEPENDS ${WRAPPEDS} ${WRAPPEDS_HEAD}
@@ -256,16 +335,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"
)
@@ -287,9 +367,9 @@ if(ARM_DYNAREC)
add_dependencies(arm64_pass2 WRAPPERS)
add_dependencies(arm64_pass3 WRAPPERS)
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_arm>
$<TARGET_OBJECTS:arm64_pass0>
add_library(dynarec STATIC
$<TARGET_OBJECTS:dynarec_arm>
$<TARGET_OBJECTS:arm64_pass0>
$<TARGET_OBJECTS:arm64_pass1>
$<TARGET_OBJECTS:arm64_pass2>
$<TARGET_OBJECTS:arm64_pass3>
@@ -313,6 +393,7 @@ else()
endif()
add_executable(${BOX64} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX64_ROOT}/src/git_head.h")
set_target_properties(${BOX64} PROPERTIES ENABLE_EXPORTS ON)
add_dependencies(${BOX64} WRAPPERS)
#add_dependencies(${BOX64} PRINTER)
target_link_libraries(${BOX64} m dl rt pthread)
@@ -321,10 +402,14 @@ 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 "-Wl,-Ttext-segment,${BOX64_ELF_ADDRESS}")
endif()
else()
target_link_options(${BOX64} PUBLIC -rdynamic)
target_link_options(${BOX64} PUBLIC -Wl,-Ttext-segment,${BOX64_ELF_ADDRESS})
# If symbols are missing, try this: target_link_options(${BOX64} PUBLIC -rdynamic)
if(NOT NOLOADADDR)
target_link_options(${BOX64} PUBLIC LINKER:-Ttext-segment,${BOX64_ELF_ADDRESS})
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
@@ -424,6 +509,16 @@ add_test(test15 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test16 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(test17 ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
+10 -9
View File
@@ -39,29 +39,31 @@ sudo systemctl restart systemd-binfmt
`mkdir build; cd build; cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j$(nproc)`
#### use ccmake
If you encounter some linking errors, try activating `NOLOADADDR` (`cmake -DNOLOADADDR=ON; make -j$(nproc)`).
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
### use ccmake
#### Customize your build
Alternatively, you can **use the curses-bases ccmake (or any other gui frontend for cmake)** to select wich platform to use interactively.
*use ccache if you have it*
### Customize your build
*Use ccache if you have it*
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
*have some debug info*
*To have some debug info*
The `-DCMAKE_BUILD_TYPE=RelWithDebInfo` argument makes a build that is both optimized for speed, and has debug information embedded. That way, if you have a crash or try to analyse performance, you'll have some symbols.
*to have a Trace Enabled build*
*To have a Trace Enabled build*
To have a trace enabled build ( ***it will be slower***), add `-DHAVE_TRACE=1` but you will need, at runtime, to have the [Zydis library](https://github.com/zyantific/zydis) library in your `LD_LIBRARY_PATH` or in the system library folders.
*to have ARM Dynarec*
*To have ARM Dynarec*
The Dynarec is only available on the ARM architecture(Right now, anyways.). Notes also that VFPv3 and NEON are required for the Dynarec. Activate it by using `-DARM_DYNAREC=1`. Also, be sure to use `-marm` in compilation flags (because many compileur use Thumb as default, and the dynarec will not work in this mode).
*not building from a git clone*
*Not building from a git clone*
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box64 print).
@@ -72,4 +74,3 @@ Testing
A few tests are included.
They can be launched with `ctest`
They are very basic and don't test much for now.
+4 -2
View File
@@ -7,9 +7,11 @@ Linux Userspace x86_64 Emulator with a twist
Box64 lets you run x86_64 Linux programs (such as games) on non-x86_64 Linux systems, like ARM (host system needs to be 64bit little-endian).
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in some cases.
You can find many more Box64 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter.
Because Box64 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Box64 integrates a DynaRec (dynamic recompiler) for the ARM64 platform, providing a speed boost between 5 to 10 times faster than only using the interpreter. Some high level information on how the Dynarec work can be found [here](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/).
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](src/emu/x86primop.c) for copyright details
+11
View File
@@ -31,6 +31,7 @@ Enables/Disables the logging of `dlsym` errors.
#### BOX64_TRACE_FILE
Send all log and trace to a file instead of `stdout`
Also, if name contains `%pid` then this is replaced by the actual PID of box64 instance
Use `stderr` to use this instead of default `stdout`
#### BOX64_TRACE
Only on build with trace enabled. Trace allow the logging of all instruction executed, along with register dump
@@ -53,6 +54,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.)
+773 -366
View File
File diff suppressed because it is too large. Load diff
+109 -18
View File
@@ -68,6 +68,76 @@ void free_tlsdatasize(void* p)
void x64Syscall(x64emu_t *emu);
int unlockMutex()
{
int ret = unlockCustommemMutex();
int i;
#define GO(A, B) \
i = checkUnlockMutex(&A); \
if(i) { \
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)
{
@@ -87,6 +157,7 @@ box64context_t *NewBox64Context(int argc)
context->maplib = NewLibrarian(context, 1);
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
// create vsyscall
context->vsyscall = AddBridge(context->system, vFv, x64Syscall, 0, NULL);
@@ -96,22 +167,15 @@ 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);
for (int i=0; i<8; ++i) context->canary[i] = 1 + getrand(255);
context->canary[getrand(4)] = 0;
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x14, value:%08X\n", *(uint32_t*)context->canary);
printf_log(LOG_DEBUG, "Setting up canary (for Stack protector) at FS:0x28, value:%08X\n", *(uint32_t*)context->canary);
initAllHelpers(context);
@@ -129,16 +193,17 @@ 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);
FreeDictionnary(&ctx->versym);
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 +239,6 @@ void FreeBox64Context(box64context_t** context)
FreeDLPrivate(&ctx->dlprivate);
free(ctx->stack);
free(ctx->fullpath);
free(ctx->box64path);
@@ -249,6 +312,9 @@ void add_neededlib(needed_libs_t* needed, library_t* lib)
{
if(!needed)
return;
for(int i=0; i<needed->size; ++i)
if(needed->libs[i] == lib)
return;
if(needed->size == needed->cap) {
needed->cap += 8;
needed->libs = (library_t**)realloc(needed->libs, needed->cap*sizeof(library_t*));
@@ -266,3 +332,28 @@ 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;
for(int i=0; i<depended->size; ++i)
if(depended->libs[i] == lib)
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;
}
+2 -2
View File
@@ -2,7 +2,7 @@
#define __BOX64_VERSION_H_
#define BOX64_MAJOR 0
#define BOX64_MINOR 0
#define BOX64_REVISION 6
#define BOX64_MINOR 1
#define BOX64_REVISION 2
#endif //__BOX64_VERSION_H_
+427 -111
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"
@@ -32,7 +33,7 @@ KHASH_MAP_INIT_INT64(dynablocks, dynablock_t*)
static dynablocklist_t*** dynmap123[1<<DYNAMAP_SHIFT]; // 64bits.. in 4x16bits array
static pthread_mutex_t mutex_mmap;
static mmaplist_t *mmaplist;
static int mmapsize;
static size_t mmapsize;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
static uintptr_t*** box64_jmptbl3[1<<JMPTABL_SHIFT];
static uintptr_t** box64_jmptbldefault2[1<<JMPTABL_SHIFT];
@@ -49,13 +50,13 @@ static int inited = 0;
typedef struct blocklist_s {
void* block;
int maxfree;
size_t maxfree;
size_t size;
} blocklist_t;
#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
@@ -72,14 +73,14 @@ typedef struct blockmark_s {
} blockmark_t;
// get first subblock free in block, stating at start (from block). return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, int maxsize, int* size)
// get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size
static void* getFirstBlock(void* block, size_t maxsize, size_t* size)
{
// get start of block
blockmark_t *m = (blockmark_t*)block;
while(m->next.x32) { // while there is a subblock
if(!m->next.fill && m->next.size>=maxsize+sizeof(blockmark_t)) {
*size = m->next.size;
*size = m->next.size-sizeof(blockmark_t);
return m;
}
m = (blockmark_t*)((uintptr_t)m + m->next.size);
@@ -88,24 +89,26 @@ static void* getFirstBlock(void* block, int maxsize, int* size)
return NULL;
}
static int getMaxFreeBlock(void* block, size_t block_size)
static size_t getMaxFreeBlock(void* block, size_t block_size)
{
// get start of block
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // styart with the end
blockmark_t *m = (blockmark_t*)((uintptr_t)block+block_size-sizeof(blockmark_t)); // start with the end
int maxsize = 0;
while(m->prev.x32) { // while there is a subblock
if(!m->prev.fill && m->prev.size>maxsize) {
maxsize = m->prev.size;
if((uintptr_t)block+maxsize>(uintptr_t)m)
return maxsize; // no block large enough left...
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0; // no block large enough left...
}
m = (blockmark_t*)((uintptr_t)m - m->prev.size);
}
return maxsize;
return (maxsize>=sizeof(blockmark_t))?(maxsize-sizeof(blockmark_t)):0;
}
static void* allocBlock(void* block, void *sub, int size)
static void* allocBlock(void* block, void *sub, size_t size)
{
(void)block;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
@@ -151,14 +154,17 @@ static void freeBlock(void *block, void* sub)
}
}
// return 1 if block has been expanded to new size, 0 if not
static int expandBlock(void* block, void* sub, int newsize)
static int expandBlock(void* block, void* sub, size_t newsize)
{
(void)block;
newsize = (newsize+3)&~3;
blockmark_t *s = (blockmark_t*)sub;
blockmark_t *n = (blockmark_t*)((uintptr_t)s + s->next.size);
if(s->next.fill)
return 0; // next block is filled
if(s->next.size + n->next.size < newsize)
// unsigned bitfield of this length gets "promoted" to *signed* int...
if((size_t)(s->next.size + n->next.size) < newsize)
return 0; // free space too short
// ok, doing the alloc!
s->next.size = newsize+sizeof(blockmark_t);
@@ -177,7 +183,7 @@ static int expandBlock(void* block, void* sub, int newsize)
return 1;
}
// return size of block
static int sizeBlock(void* sub)
static size_t sizeBlock(void* sub)
{
blockmark_t *s = (blockmark_t*)sub;
return s->next.size;
@@ -190,7 +196,7 @@ void* customMalloc(size_t size)
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
int rsize = 0;
size_t rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize);
if(sub) {
void* ret = allocBlock(p_blocks[i].block, sub, size);
@@ -252,17 +258,16 @@ void* customRealloc(void* p, size_t size)
pthread_mutex_unlock(&mutex_blocks);
return p;
}
pthread_mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
pthread_mutex_unlock(&mutex_blocks);
void* newp = customMalloc(size);
memcpy(newp, p, sizeBlock(sub));
customFree(p);
return newp;
}
}
pthread_mutex_unlock(&mutex_blocks);
if(n_blocks)
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for Realloc, Malloc'ng again without free\n", (void*)addr);
dynarec_log(LOG_NONE, "Warning, block %p not found in p_blocks for realloc, malloc'ing again without free\n", (void*)addr);
return customMalloc(size);
}
void customFree(void* p)
@@ -289,19 +294,19 @@ void customFree(void* p)
#ifdef DYNAREC
typedef struct mmaplist_s {
void* block;
int maxfree;
size_t maxfree;
size_t size;
kh_dynablocks_t* dblist;
uint8_t* helper;
} mmaplist_t;
uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
uintptr_t FindFreeDynarecMap(dynablock_t* db, size_t size)
{
// look for free space
void* sub = NULL;
for(int i=0; i<mmapsize; ++i) {
for(size_t i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size) {
int rsize = 0;
size_t rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size);
@@ -316,7 +321,7 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
for(int j=0; j<size; ++j)
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = (j<256)?j:255;
return ret;
}
@@ -325,15 +330,15 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
return 0;
}
uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
uintptr_t AddNewDynarecMap(dynablock_t* db, size_t size)
{
int i = mmapsize++;
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%d\n", mmapsize);
size_t i = mmapsize++;
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu\n", mmapsize);
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapsize*sizeof(mmaplist_t));
#ifndef USE_MMAP
void *p = NULL;
if(posix_memalign(&p, box64_pagesize, MMAPSIZE)) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
--mmapsize;
return 0;
}
@@ -341,7 +346,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
#else
void* p = mmap(NULL, MMAPSIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(p==(void*)-1) {
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%d\n", MMAPSIZE, i);
dynarec_log(LOG_INFO, "Cannot create memory map of %d byte for dynarec block #%zu\n", MMAPSIZE, i);
--mmapsize;
return 0;
}
@@ -369,16 +374,17 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
int ret;
k = kh_put(dynablocks, blocks, (uintptr_t)sub, &ret);
kh_value(blocks, k) = db;
for(int j=0; j<size; ++j)
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
return sub;
}
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size)
{
(void)db;
if(!addr || !size)
return;
for(int i=0; i<mmapsize; ++i) {
for(size_t i=0; i<mmapsize; ++i) {
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
@@ -389,20 +395,20 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
khint_t k = kh_get(dynablocks, blocks, (uintptr_t)sub);
if(k!=kh_end(blocks))
kh_del(dynablocks, blocks, k);
for(int j=0; j<size; ++j)
for(size_t j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block+j] = 0;
}
return;
}
}
if(mmapsize)
dynarec_log(LOG_NONE, "Warning, block %p (size %d) not found in mmaplist for Free\n", (void*)addr, size);
dynarec_log(LOG_NONE, "Warning, block %p (size %zu) not found in mmaplist for Free\n", (void*)addr, size);
}
dynablock_t* FindDynablockFromNativeAddress(void* addr)
{
// look in actual list
for(int i=0; i<mmapsize; ++i) {
for(size_t i=0; i<mmapsize; ++i) {
if ((uintptr_t)addr>=(uintptr_t)mmaplist[i].block
&& ((uintptr_t)addr<(uintptr_t)mmaplist[i].block+mmaplist[i].size)) {
if(!mmaplist[i].helper)
@@ -421,22 +427,23 @@ dynablock_t* FindDynablockFromNativeAddress(void* addr)
return FindDynablockDynablocklist(addr, dblist_oversized);
}
uintptr_t AllocDynarecMap(dynablock_t* db, int size)
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size)
{
if(!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);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
mprotect(p, size, PROT_READ | PROT_WRITE | PROT_EXEC);
#else
void* p = mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
if(p==(void*)-1) {
dynarec_log(LOG_INFO, "Cannot create dynamic map of %d bytes\n", size);
dynarec_log(LOG_INFO, "Cannot create dynamic map of %zu bytes\n", size);
return 0;
}
#endif
@@ -450,14 +457,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)
@@ -468,9 +472,12 @@ uintptr_t AllocDynarecMap(dynablock_t* db, int size)
return ret;
}
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_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 +489,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);
@@ -505,7 +513,7 @@ dynablocklist_t* getDB(uintptr_t idx)
// each dynmap is 64k of size
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
void addDBFromAddressRange(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
@@ -514,16 +522,33 @@ 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);
}
}
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
static int dynmapempty(void** mem)
{
for (int i=0; i<(1<<DYNAMAP_SHIFT); ++i)
if(mem[i])
return 0;
return 1;
}
void cleanDBFromAddressRange(uintptr_t addr, size_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
@@ -535,9 +560,26 @@ void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
if(dynmap123[idx3] && dynmap123[idx3][idx2]) {
dynablocklist_t* dblist = dynmap123[idx3][idx2][idx1];
if(dblist) {
if(destroy)
FreeRangeDynablock(dblist, addr, size);
else
if(destroy) {
if(FreeRangeDynablock(dblist, addr, size) && 0) { // dblist is empty, check if we can delete more...
// disabling this for now. It seems to cause random crash in Terraria
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2][idx1], NULL, dblist)) {
dynablocklist_t** p = dynmap123[idx3][idx2];
if(dynmapempty((void**)p)) {
if(!arm64_lock_storeifref(&dynmap123[idx3][idx2], NULL, p)) {
dynablocklist_t*** p2 = dynmap123[idx3];
if(dynmapempty((void**)p2)) {
if(!arm64_lock_storeifref(&dynmap123[idx3], NULL, p2)) {
free(p2);
}
}
free(p);
}
}
FreeDynablockList(&dblist);
}
}
} else
MarkRangeDynablock(dblist, addr, size);
}
}
@@ -559,23 +601,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 +638,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,41 +663,42 @@ 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];
}
// Remove the Write flag from an adress range, so DB can be executed
// no log, as it can be executed inside a signal handler
void protectDB(uintptr_t addr, uintptr_t size)
// Remove the Write flag from an adress range, so DB can be executed safely
void protectDBnolock(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "protectDB %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);
@@ -650,32 +712,15 @@ 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);
}
void protectDBnolock(uintptr_t addr, uintptr_t size)
void protectDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "protectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
int ret;
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);
uint8_t prot = kh_value(memprot, k)[ii];
if(!prot)
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);
}
pthread_mutex_lock(&mutex_prot);
protectDBnolock(addr, size);
pthread_mutex_unlock(&mutex_prot);
}
void lockDB()
@@ -690,7 +735,7 @@ void unlockDB()
// Add the Write flag from an adress range, and mark all block as dirty
// no log, as it can be executed inside a signal handler
void unprotectDB(uintptr_t addr, uintptr_t size)
void unprotectDB(uintptr_t addr, size_t size)
{
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>MEMPROT_SHIFT);
@@ -708,7 +753,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);
}
}
@@ -717,12 +762,14 @@ void unprotectDB(uintptr_t addr, uintptr_t size)
#endif
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void updateProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "updateProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1LL)>>MEMPROT_SHIFT);
int ret;
uintptr_t last = idx<<MEMPROT_SHIFT;
uint8_t oldprot = 0xff;
pthread_mutex_lock(&mutex_prot);
for (uintptr_t i=idx; i<=end; ++i) {
const uint32_t key = (i>>MEMPROT_SHIFT2)&0xffffffff;
@@ -731,16 +778,33 @@ void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
uint8_t *m = (uint8_t*)calloc(1, MEMPROT_SIZE);
kh_value(memprot, k) = m;
}
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;
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
for(uintptr_t ii = start; ii<=finish; ++ii) {
uint32_t dyn = block[ii]&PROT_DYNAREC;
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
if(oldprot!=prot) {
if(oldprot!=0xff)
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i<<MEMPROT_SHIFT;
oldprot = prot;
}
} else if(prot!=0xff) {
mprotect((void*)last, (i<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
last = i << MEMPROT_SHIFT;
oldprot = 0xff;
}
block[ii] = prot|dyn|PROT_ALLOC;
}
i+=finish-start; // +1 from the "for" loop
}
if(oldprot!=0xff)
mprotect((void*)last, (end<<MEMPROT_SHIFT)-last, oldprot&~PROT_CUSTOM); // need to optimize
pthread_mutex_unlock(&mutex_prot);
}
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
void setProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "setProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
@@ -754,8 +818,87 @@ void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
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] = prot;
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
memset(kh_value(memprot, k)+start, prot|PROT_ALLOC, finish-start+1);
i+=finish-start; // +1 from the "for" loop
}
pthread_mutex_unlock(&mutex_prot);
}
void allocProtection(uintptr_t addr, size_t size, uint32_t prot)
{
dynarec_log(LOG_DEBUG, "allocProtection %p:%p 0x%x\n", (void*)addr, (void*)(addr+size-1), prot);
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 start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t* block = kh_value(memprot, k);
for(uintptr_t ii = start; ii<=finish; ++ii) {
if(!block[ii])
block[ii] = prot;
}
i+=finish-start; // +1 from the "for" loop
}
pthread_mutex_unlock(&mutex_prot);
}
void loadProtectionFromMap()
{
char buf[500];
FILE *f = fopen("/proc/self/maps", "r");
if(!f)
return;
while(!feof(f)) {
char* ret = fgets(buf, sizeof(buf), f);
(void)ret;
char r, w, x;
uintptr_t s, e;
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
}
}
fclose(f);
}
static int blockempty(uint8_t* mem)
{
for (int i=0; i<(MEMPROT_SIZE); ++i)
if(mem[i])
return 0;
return 1;
}
void freeProtection(uintptr_t addr, size_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);
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_get(memprot, memprot, key);
if(k!=kh_end(memprot)) {
const uintptr_t start = i&(MEMPROT_SIZE-1);
const uintptr_t finish = (((i|(MEMPROT_SIZE-1))<end)?(MEMPROT_SIZE-1):end)&(MEMPROT_SIZE-1);
uint8_t *block = kh_value(memprot, k);
memset(block+start, 0, finish-start+1);
if(blockempty(block)) {
free(block);
kh_del(memprot, memprot, k);
}
i+=finish-start; // +1 from the "for" loop
}
}
pthread_mutex_unlock(&mutex_prot);
}
@@ -775,15 +918,186 @@ uint32_t getProtection(uintptr_t addr)
return ret;
}
#define LOWEST (void*)0x20000
int availableBlock(uint8_t* p, size_t n)
{
for (size_t i=0; i<n; ++i, ++p)
if(*p)
return 0;
return 1;
}
static uintptr_t nextFree(uintptr_t addr)
{
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
return addr;
}
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
return (addr&~0xffffffffLL)+(i<<MEMPROT_SHIFT);
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
} while(1);
}
static uintptr_t maxFree(uintptr_t addr, uintptr_t sz)
{
uintptr_t mfree = 0;
do {
const uint32_t key = (addr>>32)&0xffffffff;
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
mfree+=0x100000000LL;
if(mfree>sz) {
return addr;
}
} else {
uint8_t *block = kh_value(memprot, k);
for (uintptr_t i=(addr&0xffffffffLL)>>MEMPROT_SHIFT; i<MEMPROT_SIZE; ++i)
if(!block[i]) {
mfree+=1<<MEMPROT_SHIFT;
} else
return mfree;
}
addr += 0x100000000LL;
addr &= ~0xffffffffLL;
} while(1);
}
void* find32bitBlock(size_t size)
{
return findBlockNearHint(LOWEST, size);
}
void* find47bitBlock(size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = 0x100000000LL;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x800000000000LL);
// search in 32bits as a backup
addr = (uintptr_t)LOWEST;
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 47bits address space\n", size);
return NULL;
}
void* find47bitBlockNearHint(void* hint, size_t size)
{
// slow iterative search... Would need something better one day
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x800000000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx 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
uintptr_t addr = (uintptr_t)hint;
pthread_mutex_lock(&mutex_prot);
do {
addr = nextFree(addr);
uintptr_t sz = maxFree(addr, size);
if(sz>=size) {
pthread_mutex_unlock(&mutex_prot);
return (void*)addr;
}
addr += sz;
} while(addr<0x100000000LL);
pthread_mutex_unlock(&mutex_prot);
printf_log(LOG_NONE, "Warning: cannot find a 0x%zx block in 32bits address space\n", size);
return NULL;
}
#undef LOWEST
int unlockCustommemMutex()
{
int ret = 0;
int i = 0;
#define GO(A, B) \
i = checkUnlockMutex(&A); \
if(i) { \
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)
{
(void)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,17 +1110,19 @@ 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)
{
(void)ctx;
if(!inited)
return;
inited = 0;
#ifdef DYNAREC
if(box64_dynarec) {
dynarec_log(LOG_DEBUG, "Free global Dynarecblocks\n");
for (int i=0; i<mmapsize; ++i) {
for (size_t i=0; i<mmapsize; ++i) {
if(mmaplist[i].block)
#ifdef USE_MMAP
munmap(mmaplist[i].block, mmaplist[i].size);
@@ -870,5 +1186,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);
}
+555 -38
View File
@@ -110,8 +110,9 @@
#define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)imm16)&0xffff, Rd))
#define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)imm16)&0xffff, Rd))
// This macro will give a -Wsign-compare warning, probably bug #38341
#define MOV32w(Rd, imm32) \
if(~((uint32_t)(imm32))<0xffff) { \
if(~((uint32_t)(imm32))<0xffffu) { \
MOVNw(Rd, (~(uint32_t)(imm32))&0xffff); \
} else { \
MOVZw(Rd, (imm32)&0xffff); \
@@ -137,6 +138,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))
@@ -209,14 +211,14 @@
#define LDRSW_S9_preindex(Rt, Rn, imm9) EMIT(LDRS_gen(0b10, 0b00, (imm9)&0x1ff, 0b11, Rn, Rt))
#define LD_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b01<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)(imm12>>(2+rex.w)))&0xfff, Rn, Rt))
#define LDRx_U12(Rt, Rn, imm12) EMIT(LD_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
#define LDRw_U12(Rt, Rn, imm12) EMIT(LD_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
#define LDRB_U12(Rt, Rn, imm12) EMIT(LD_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
#define LDRH_U12(Rt, Rn, imm12) EMIT(LD_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
#define LDRxw_U12(Rt, Rn, imm12) EMIT(LD_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
#define LDS_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b10<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
#define LDRSW_U12(Rt, Rn, imm12) EMIT(LDS_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
#define LDR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b01<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
#define LDRx_REG(Rt, Rn, Rm) EMIT(LDR_REG_gen(0b11, Rm, 0b011, 0, Rn, Rt))
@@ -250,10 +252,10 @@
#define STRH_S9_postindex(Rt, Rn, imm9) EMIT(STR_gen(0b01, 0b00, (imm9)&0x1ff, 0b01, Rn, Rt))
#define ST_gen(size, op1, imm12, Rn, Rt) ((size)<<30 | 0b111<<27 | (op1)<<24 | 0b00<<22 | (imm12)<<10 | (Rn)<<5 | (Rt))
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)(imm12>>3))&0xfff, Rn, Rt))
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)(imm12>>2))&0xfff, Rn, Rt))
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)(imm12))&0xfff, Rn, Rt))
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)(imm12>>1))&0xfff, Rn, Rt))
#define STRx_U12(Rt, Rn, imm12) EMIT(ST_gen(0b11, 0b01, ((uint32_t)((imm12)>>3))&0xfff, Rn, Rt))
#define STRw_U12(Rt, Rn, imm12) EMIT(ST_gen(0b10, 0b01, ((uint32_t)((imm12)>>2))&0xfff, Rn, Rt))
#define STRB_U12(Rt, Rn, imm12) EMIT(ST_gen(0b00, 0b01, ((uint32_t)((imm12)))&0xfff, Rn, Rt))
#define STRH_U12(Rt, Rn, imm12) EMIT(ST_gen(0b01, 0b01, ((uint32_t)((imm12)>>1))&0xfff, Rn, Rt))
#define STRxw_U12(Rt, Rn, imm12) EMIT(ST_gen((rex.w)?0b11:0b10, 0b01, ((uint32_t)((imm12)>>(2+rex.w)))&0xfff, Rn, Rt))
#define STR_REG_gen(size, Rm, option, S, Rn, Rt) ((size)<<30 | 0b111<<27 | 0b00<<22 | 1<<21 | (Rm)<<16 | (option)<<13 | (S)<<12 | (0b10)<<10 | (Rn)<<5 | (Rt))
@@ -306,6 +308,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 +329,26 @@
#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))
#define PST_L1_STREAM_U12(Rn, imm12) EMIT(PRFM_imm(((imm12)>>3)&0xfff, Rn, 0b01001))
// 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))
@@ -403,11 +433,16 @@
#define ORRx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
#define ORRx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRxw_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, lsl, Rn, Rd))
#define ORRx_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(1, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
#define ORRw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(0, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
#define ORRxw_REG_LSR(Rd, Rn, Rm, lsr) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b01, 0, Rm, lsr, Rn, Rd))
#define ORRxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
#define ORRw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 0, Rm, 0, Rn, Rd))
#define ORNx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
#define ORNw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
#define ORNxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b01, 0b00, 1, Rm, 0, Rn, Rd))
#define ORNx_REG_LSL(Rd, Rn, Rm, lsl) EMIT(LOGIC_REG_gen(1, 0b01, 0b00, 1, Rm, lsl, Rn, Rd))
#define EORx_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(1, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
#define EORw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(0, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
#define EORxw_REG(Rd, Rn, Rm) EMIT(LOGIC_REG_gen(rex.w, 0b10, 0b00, 0, Rm, 0, Rn, Rd))
@@ -420,6 +455,12 @@
#define MOVx_REG(Rd, Rm) ORRx_REG(Rd, xZR, Rm)
#define MOVw_REG(Rd, Rm) ORRw_REG(Rd, xZR, Rm)
#define MOVxw_REG(Rd, Rm) ORRxw_REG(Rd, xZR, Rm)
#define LSLw_IMM(Rd, Rm, lsl) ORRw_REG_LSL(Rd, xZR, Rm, lsl)
#define LSLx_IMM(Rd, Rm, lsl) ORRx_REG_LSL(Rd, xZR, Rm, lsl)
#define LSLxw_IMM(Rd, Rm, lsl) ORRxw_REG_LSL(Rd, xZR, Rm, lsl)
#define LSRw_IMM(Rd, Rm, lsr) ORRw_REG_LSR(Rd, xZR, Rm, lsr)
#define LSRx_IMM(Rd, Rm, lsr) ORRx_REG_LSR(Rd, xZR, Rm, lsr)
#define LSRxw_IMM(Rd, Rm, lsr) ORRxw_REG_LSR(Rd, xZR, Rm, lsr)
#define MVNx_REG(Rd, Rm) ORNx_REG(Rd, xZR, Rm)
#define MVNx_REG_LSL(Rd, Rm, lsl) ORNx_REG_LSL(Rd, xZR, Rm, lsl)
#define MVNw_REG(Rd, Rm) ORNw_REG(Rd, xZR, Rm)
@@ -548,13 +589,27 @@
#define UMULH(Xd, Xn, Xm) EMIT(MULH_gen(1, Xm, Xn, Xd))
#define SMULH(Xd, Xn, Xm) EMIT(MULH_gen(0, Xm, Xn, Xd))
#define MADD_gen(sf, Rm, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (Ra)<<10 | (Rn)<<5 | (Rd))
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, Ra, Rn, Rd))
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, Ra, Rn, Rd))
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, Ra, Rn, Rd))
#define MADD_gen(sf, Rm, o0, Ra, Rn, Rd) ((sf)<<31 | 0b11011<<24 | (Rm)<<16 | (o0)<<15 | (Ra)<<10 | (Rn)<<5 | (Rd))
#define MADDx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 0, Ra, Rn, Rd))
#define MADDw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 0, Ra, Rn, Rd))
#define MADDxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 0, Ra, Rn, Rd))
#define MULx(Rd, Rn, Rm) MADDx(Rd, Rn, Rm, xZR)
#define MULw(Rd, Rn, Rm) MADDw(Rd, Rn, Rm, xZR)
#define MULxw(Rd, Rn, Rm) MADDxw(Rd, Rn, Rm, xZR)
#define MSUBx(Rd, Rn, Rm, Ra) EMIT(MADD_gen(1, Rm, 1, Ra, Rn, Rd))
#define MSUBw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(0, Rm, 1, Ra, Rn, Rd))
#define MSUBxw(Rd, Rn, Rm, Ra) EMIT(MADD_gen(rex.w, Rm, 1, Ra, Rn, Rd))
#define MNEGx(Rd, Rn, Rm) EMIT(MADD_gen(1, Rm, 1, xZR, Rn, Rd))
#define MNEGw(Rd, Rn, Rm) EMIT(MADD_gen(0, Rm, 1, xZR, Rn, Rd))
#define MNEGxw(Rd, Rn, Rm) EMIT(MADD_gen(rex.w, Rm, 1, xZR, Rn, Rd))
// DIV
#define DIV_gen(sf, Rm, o1, Rn, Rd) ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b00001<<11 | (o1)<<10 | (Rn)<<5 | (Rd))
#define UDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 0, Wn, Wd))
#define UDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 0, Xn, Xd))
#define SDIVw(Wd, Wn, Wm) EMIT(DIV_gen(0, Wm, 1, Wn, Wd))
#define SDIVx(Xd, Xn, Xm) EMIT(DIV_gen(1, Xm, 1, Xn, Xd))
// CLZ
#define CL_gen(sf, op, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | 0b00010<<11 | (op)<<10 | (Rn)<<5 | (Rd))
@@ -584,9 +639,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 +679,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 +722,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 +763,32 @@
#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 USHL_R_64(Vd, Vn, Vm) EMIT(SHL_scalar(1, 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 USHL_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b00, Vm, 0, 0, Vn, Vd))
#define USHL_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b01, Vm, 0, 0, Vn, Vd))
#define USHL_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(0, 1, 0b10, Vm, 0, 0, Vn, Vd))
#define USHLQ_8(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b00, Vm, 0, 0, Vn, Vd))
#define USHLQ_16(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b01, Vm, 0, 0, Vn, Vd))
#define USHLQ_32(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 0b10, Vm, 0, 0, Vn, Vd))
#define USHLQ_64(Vd, Vn, Vm) EMIT(SHL_vector_vector(1, 1, 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 +805,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 +850,26 @@
#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))
#define NEGABS_vector_scalar(U, size, Rn, Rd) (0b01<<30 | (U)<<29 | 0b11110<<24 | (size)<<22 | 0b10000<<17 | 0b01011<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define NEG_64(Vd, Vn) EMIT(NEGABS_vector_scalar(1, 0b11, Vn, Vd))
#define ABS_64(Vd, Vn) EMIT(NEGABS_vector_scalar(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 +889,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 +917,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 +961,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))
@@ -834,6 +1002,16 @@
#define FDIVS(Sd, Sn, Sm) EMIT(FDIV_scalar(0b00, Sm, Sn, Sd))
#define FDIVD(Dd, Dn, Dm) EMIT(FDIV_scalar(0b01, Dm, Dn, Dd))
#define FRECPE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFRECPES(Vd, Vn) EMIT(FRECPE_vector(0, 0, Vn, Vd))
#define VFRECPEQS(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
#define VFRECPEQD(Vd, Vn) EMIT(FRECPE_vector(1, 0, Vn, Vd))
#define FRECPS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 0<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFRECPSS(Vd, Vn, Vm) EMIT(FRECPS_vector(0, 0, Vm, Vn, Vd))
#define VFRECPSQS(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
#define VFRECPSQD(Vd, Vn, Vm) EMIT(FRECPS_vector(1, 0, Vm, Vn, Vd))
// SQRT
#define FSQRT_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11111<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFSQRTS(Sd, Sn) EMIT(FSQRT_vector(0, 0, Sn, Sd))
@@ -844,6 +1022,16 @@
#define FSQRTS(Sd, Sn) EMIT(FSQRT_scalar(0b00, Sn, Sd))
#define FSQRTD(Dd, Dn) EMIT(FSQRT_scalar(0b01, Dn, Dd))
#define FRSQRTE_vector(Q, sz, Rn, Rd) ((Q)<<30 | 1<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 0b10000<<17 | 0b11101<<12 | 0b10<<10 | (Rn)<<5 | (Rd))
#define VFRSQRTES(Vd, Vn) EMIT(FRSQRTE_vector(0, 0, Vn, Vd))
#define VFRSQRTEQS(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
#define VFRSQRTEQD(Vd, Vn) EMIT(FRSQRTE_vector(1, 0, Vn, Vd))
#define FRSQRTS_vector(Q, sz, Rm, Rn, Rd) ((Q)<<30 | 0<<29 | 0b01110<<24 | 1<<23 | (sz)<<22 | 1<<21 | (Rm)<<16 | 0b11111<<11 | 1<<10 | (Rn)<<5 | (Rd))
#define VFRSQRTSS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(0, 0, Vm, Vn, Vd))
#define VFRSQRTSQS(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
#define VFRSQRTSQD(Vd, Vn, Vm) EMIT(FRSQRTS_vector(1, 0, Vm, Vn, Vd))
// CMP
#define FCMP_scalar(type, Rn, Rm, opc) (0b11110<<24 | (type)<<22 | 1<<21 | (Rm)<<16 | 0b1000<<10 | (Rn)<<5 | (opc)<<3)
#define FCMPS(Sn, Sm) EMIT(FCMP_scalar(0b00, Sn, Sm, 0b00))
@@ -1019,8 +1207,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 +1216,36 @@
#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))
// round toward 0 (truncate)
#define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd))
// round toward 0 (truncate)
#define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd))
// round with current FPCR mode
#define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd))
// round with current FPCR mode
#define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd))
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
#define FRINTRRS(Sd, Sn, mode) EMIT(FRINT_scalar(0b00, ((mode)&3), Sn, Sd))
// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero
#define FRINTRRD(Dd, Dn, mode) EMIT(FRINT_scalar(0b01, ((mode)&3), Dn, Dd))
// 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 +1306,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 +1335,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 +1356,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))
@@ -1166,12 +1410,31 @@
#define VCMGTQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b01, 0, Rm, Rn, Rd))
#define VCMGTQ_32(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b10, 0, Rm, Rn, Rd))
#define VCMGTQ_64(Rd, Rn, Rm) EMIT(CMG_vector(1, 0, 0b11, 0, Rm, Rn, Rd))
#define VCMGT_8(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b00, 0, Rm, Rn, Rd))
#define VCMGT_16(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b01, 0, Rm, Rn, Rd))
#define VCMGT_32(Rd, Rn, Rm) EMIT(CMG_vector(0, 0, 0b10, 0, Rm, Rn, Rd))
// Unsigned Higher
#define VCHIQQ_8(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b00, 0, Rm, Rn, Rd))
#define VCHIQQ_16(Rd, Rn, Rm) EMIT(CMG_vector(1, 1, 0b01, 0, Rm, Rn, Rd))
#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 +1443,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 -9
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:
@@ -42,15 +45,12 @@ arm64_lock_write_h:
arm64_lock_read_d:
// address is x0, return is x0
ldaxr w0, [x0]
#ldx w0,[x0]
ret
arm64_lock_write_d:
// address is x0, value is w1, return is x0
mov x2, x0
stlxr w0, w1, [x2]
#str w1, [x2]
mov w0, 0
ret
arm64_lock_read_dd:
@@ -64,24 +64,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__
+2
View File
@@ -19,6 +19,8 @@ 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
+291 -10
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"};
@@ -267,12 +278,20 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "STR%c %s, [%s]", size?'H':'B', Xt[Rt], XtSp[Rn]);
return buff;
}
if(isMask(opcode, "101110011xiiiiiiiiiiiinnnnnttttt", &a)) {
if(isMask(opcode, "1011100110iiiiiiiiiiiinnnnnttttt", &a)) {
int offset = imm<<2;
if(!offset)
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn]);
snprintf(buff, sizeof(buff), "LDRSW %s, [%s]", Xt[Rt], XtSp[Rn]);
else
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", a.x?Xt[Rt]:Wt[Rt], XtSp[Rn], offset);
snprintf(buff, sizeof(buff), "LDRSW %s, [%s, #%d]", Xt[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)) {
@@ -601,7 +620,7 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
else if(immr==0 && imms==0b001111)
snprintf(buff, sizeof(buff), "SXTH %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
else if(sf && immr==0 && imms==0b011111)
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Xt[Rn]);
snprintf(buff, sizeof(buff), "SXTW %s, %s", Xt[Rd], Wt[Rn]);
else if(imms>=immr)
snprintf(buff, sizeof(buff), "SBFX %s, %s, %d, %d", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], immr, imms-immr+1);
else
@@ -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)
@@ -758,6 +777,19 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "MADD %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
return buff;
}
if(isMask(opcode, "f0011011000mmmmm1aaaaannnnnddddd", &a)) {
if(Ra==31)
snprintf(buff, sizeof(buff), "MNEG %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
else
snprintf(buff, sizeof(buff), "MSUB %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], sf?Xt[Ra]:Wt[Ra]);
return buff;
}
// DIV
if(isMask(opcode, "f0011010110mmmmm00001onnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "%cDIV %s, %s, %s", option?'S':'U', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm]);
return buff;
}
// MRS / MSR
if(isMask(opcode, "110101010001opppnnnnmmmm222ttttt", &a)) {
@@ -840,6 +872,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 +973,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 +1001,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 +1033,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 +1073,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 +1090,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 +1131,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));
+44 -37
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);
@@ -165,10 +165,10 @@ void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t
MarkDynablock(db);
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
return 1;
if(dynablocks->direct) {
dynablock_t* db;
@@ -176,34 +176,38 @@ void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm64_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db);
);
kh_destroy(dynablocks, blocks);
// check emptyness
for(uintptr_t i=0; i<dynablocks->textsz; ++i)
if(dynablocks->direct[i])
return 0;
return 1;
}
return 1;
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
@@ -214,7 +218,7 @@ void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t s
uintptr_t new_size = size + dynablocks->maxsz;
MarkDirectDynablock(dynablocks, new_addr, new_size);
// the blocks check before
for(int idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
for(unsigned idx=(new_addr)>>DYNAMAP_SHIFT; idx<(addr>>DYNAMAP_SHIFT); ++idx)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
}
}
@@ -247,10 +251,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;
@@ -258,7 +258,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_DUMP, "Block already exist in Direct Map\n");
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
@@ -274,7 +274,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c
}
// create and add new block
dynarec_log(LOG_DUMP, "Ask for DynaRec Block creation @%p\n", (void*)addr);
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
@@ -323,22 +323,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 has not be writen
}
free(block);
block = NULL;
}
#if 1
#if 0
if(box64_dynarec_dump)
pthread_mutex_unlock(&my_context->mutex_dyndump);
#endif
@@ -347,7 +351,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
int blocksz = block->x64_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
for(unsigned idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
@@ -358,8 +362,11 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t
protectDBnolock((uintptr_t)block->x64_addr, block->x64_size);
// fill-in jumptable
addJumpTableIfDefault64(block->x64_addr, block->block);
for(int i=0; i<block->sons_size; ++i)
for(int i=0; i<block->sons_size; ++i) {
addJumpTableIfDefault64(block->sons[i]->x64_addr, block->sons[i]->block);
block->sons[i]->done = 1;
}
block->done = 1;
unlockDB();
}
+18 -10
View File
@@ -30,16 +30,14 @@ void arm64_epilog_fast() EXPORTDYN;
#endif
#ifdef DYNAREC
#ifdef HAVE_TRACE
uintptr_t getX64Address(dynablock_t* db, uintptr_t arm_addr);
#endif
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 +45,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;
}
@@ -64,6 +64,11 @@ void* LinkNext(x64emu_t* emu, uintptr_t addr, void* x2)
}
#endif
#ifdef __GNUC__
// Disable "clobbered" warnings
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wclobbered"
#endif
void DynaCall(x64emu_t* emu, uintptr_t addr)
{
// prepare setjump for signal handling
@@ -75,7 +80,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_RIP; // not sure if it should still be inside DynaCall!
}
@@ -124,7 +129,7 @@ void DynaCall(x64emu_t* emu, uintptr_t addr)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf)) {
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1)) {
printf_log(LOG_DEBUG, "Setjmp inner DynaCall, fs=0x%x\n", ejb->emu->segs[_FS]);
addr = R_RIP;
}
@@ -165,7 +170,7 @@ int DynaRun(x64emu_t* emu)
#ifdef DYNAREC
jmpbuf_reset = 1;
#endif
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
@@ -202,7 +207,7 @@ int DynaRun(x64emu_t* emu)
ejb->emu = emu;
ejb->jmpbuf_ok = 1;
jmpbuf_reset = 1;
if(setjmp((struct __jmp_buf_tag*)ejb->jmpbuf))
if(sigsetjmp((struct __jmp_buf_tag*)ejb->jmpbuf, 1))
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
@@ -213,4 +218,7 @@ int DynaRun(x64emu_t* emu)
ejb->jmpbuf_ok = 0;
return 0;
#endif
}
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
+41 -24
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); //end is 1byte after actual end
uint32_t hash = X31_hash_code((void*)addr, end-addr);
// 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;
@@ -376,10 +383,10 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
size_t sz = helper.arm_size + helper.table64size*sizeof(uint64_t);
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
free(helper.insts);
free(helper.next);
free(helper.table64);
@@ -394,15 +401,17 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
// pass 3, emit (log emit arm opcode)
if(box64_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
dynarec_log(LOG_NONE, "%s%04d|Emitting %zu bytes for %u x64 bytes", (box64_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box64_dynarec_dump>1)?"\e[m":"");
}
helper.arm_size = 0;
int oldtable64size = helper.table64size;
size_t 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)) {
printf_log(LOG_NONE, "BOX64: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", 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 (%zu) & pass3 (%zu)!\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);
for(int i=0; i<helper.size; ++i) {
@@ -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...
@@ -441,10 +451,15 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
block->need_test = 0;
//block->x64_addr = (void*)start;
block->x64_size = end-start;
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 +473,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->done = 1;
sons[sons_size++] = son;
son->size = sz + son->block - block->block; // update size count, for debugging
//son->done = 1;
if(!son->parent)
son->parent = block->parent;
sons[sons_size] = son;
++sons_size;
}
}
if(sons_size) {
@@ -472,6 +489,6 @@ void* FillBlock64(dynablock_t* block, uintptr_t addr) {
}
free(helper.sons_x64);
free(helper.sons_arm);
block->done = 1;
//block->done = 1;
return (void*)block;
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+472 -26
View File
@@ -22,17 +22,30 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETG gd = ((nextop&0x38)>>3)+(rex.r<<3)
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_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
int32_t j32;
uint8_t gd, ed;
uint8_t wback;
int64_t i64;
int fixedaddress;
MAYUSE(j32);
uint8_t u8;
uint8_t gd, ed, eb1, eb2;
uint8_t wback, wb1, wb2;
int64_t i64, j64;
int v0;
int q0;
int d0;
int64_t fixedaddress;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j64);
MAYUSE(d0);
MAYUSE(q0);
MAYUSE(v0);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
@@ -47,24 +60,231 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x03:
INST_NAME("ADD Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_add32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x0F:
opcode = F8;
switch(opcode) {
case 0x10:
switch(rep) {
case 1:
INST_NAME("MOVSD Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOVeD(v0, 0, d0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR64_U12(v0, x4, fixedaddress); // upper part reseted
}
break;
case 2:
INST_NAME("MOVSS Gx, Ex");
nextop = F8;
GETG;
if(MODREG) {
v0 = sse_get_reg(dyn, ninst, x1, gd);
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVeS(v0, 0, q0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
ADDx_REG(x4, x4, ed);
VLDR32_U12(v0, x4, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x11:
switch(rep) {
case 1:
INST_NAME("MOVSD Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOVeD(d0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR64_U12(v0, x4, fixedaddress);
}
break;
case 2:
INST_NAME("MOVSS Ex, Gx");
nextop = F8;
GETG;
v0 = sse_get_reg(dyn, ninst, x1, gd);
if(MODREG) {
q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
VMOVeS(q0, 0, v0, 0);
} else {
grab_segdata(dyn, addr, ninst, x4, seg);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
ADDx_REG(x4, x4, ed);
VSTR32_U12(v0, x4, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0xAF:
INST_NAME("IMUL Gd, Ed");
SETFLAGS(X_ALL, SF_PENDING);
nextop = F8;
grab_segdata(dyn, addr, ninst, x4, seg);
GETGD;
GETEDO(x4, 0);
if(rex.w) {
// 64bits imul
UFLAG_IF {
SMULH(x3, gd, ed);
MULx(gd, gd, ed);
UFLAG_OP1(x3);
UFLAG_RES(gd);
UFLAG_DF(x3, d_imul64);
} else {
MULxw(gd, gd, ed);
}
} else {
// 32bits imul
UFLAG_IF {
SMULL(gd, gd, ed);
UFLAG_RES(gd);
LSRx(x3, gd, 32);
UFLAG_OP1(x3);
UFLAG_DF(x3, d_imul32);
MOVw_REG(gd, gd);
} else {
MULxw(gd, gd, ed);
}
}
break;
default:
DEFAULT;
}
break;
case 0x33:
INST_NAME("XOR Gd, FS:Ed");
SETFLAGS(X_ALL, SF_SET);
grab_segdata(dyn, addr, ninst, x4, _FS);
INST_NAME("XOR Gd, Seg:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_segdata(dyn, addr, ninst, x4, seg);
nextop = F8;
GETGD;
GETEDO(x4, 0);
emit_xor32(dyn, ninst, rex, gd, ed, x3, x4);
break;
case 0x80:
nextop = F8;
grab_segdata(dyn, addr, ninst, x1, seg);
switch((nextop>>3)&7) {
case 0: //ADD
INST_NAME("ADD Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_add8c(dyn, ninst, x1, u8, x2, x4);
EBBACK;
break;
case 1: //OR
INST_NAME("OR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_or8c(dyn, ninst, x1, u8, x2, x4);
EBBACK;
break;
case 2: //ADC
INST_NAME("ADC Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK;
break;
case 3: //SBB
INST_NAME("SBB Eb, Ib");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK;
break;
case 4: //AND
INST_NAME("AND Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_and8c(dyn, ninst, x1, u8, x2, x4);
EBBACK;
break;
case 5: //SUB
INST_NAME("SUB Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5);
EBBACK;
break;
case 6: //XOR
INST_NAME("XOR Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
emit_xor8c(dyn, ninst, x1, u8, x2, x4);
EBBACK;
break;
case 7: //CMP
INST_NAME("CMP Eb, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEBO(x1, 1);
u8 = F8;
if(u8) {
MOV32w(x2, u8);
emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5);
} else {
emit_cmp8_0(dyn, ninst, x1, x3, x4);
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, _FS);
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
@@ -72,7 +292,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("OR Ed, Id");} else {INST_NAME("OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
@@ -81,7 +301,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2: //ADC
if(opcode==0x81) {INST_NAME("ADC Ed, Id");} else {INST_NAME("ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
@@ -91,7 +311,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 3: //SBB
if(opcode==0x81) {INST_NAME("SBB Ed, Id");} else {INST_NAME("SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
@@ -100,7 +320,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("AND Ed, Id");} else {INST_NAME("AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
@@ -108,7 +328,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("SUB Ed, Id");} else {INST_NAME("SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5);
@@ -116,7 +336,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("XOR Ed, Id");} else {INST_NAME("XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
@@ -124,7 +344,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("CMP Ed, Id");} else {INST_NAME("CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEDO(x6, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
@@ -137,8 +357,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x89:
INST_NAME("MOV FS:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, _FS);
INST_NAME("MOV Seg:Ed, Gd");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
@@ -150,8 +370,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x8B:
INST_NAME("MOV Gd, FS:Ed");
grab_segdata(dyn, addr, ninst, x4, _FS);
INST_NAME("MOV Gd, Seg:Ed");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
GETGD;
if(MODREG) { // reg <= reg
@@ -162,9 +382,32 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xC6:
INST_NAME("MOV Seg:Eb, Ib");
grab_segdata(dyn, addr, ninst, x4, seg);
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);
INST_NAME("MOV Seg:Ed, Id");
grab_segdata(dyn, addr, ninst, x4, seg);
nextop=F8;
if(MODREG) { // reg <= i32
i64 = F32S;
@@ -178,9 +421,212 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
break;
case 0xD1:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETEDO(x6, 0);
emit_rol32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
GETEDO(x6, 0);
emit_ror32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(ed!=x1) {MOVxw_REG(x1, ed);}
CALL_(rcl32, ed, x6);
WBACK;
break;
case 3:
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOV32w(x2, 1);
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(ed!=x1) {MOVxw_REG(x1, ed);}
CALL_(rcr32, ed, x6);
WBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO(x6, 0);
emit_shl32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 5:
INST_NAME("SHR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO(x6, 0);
emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
case 7:
INST_NAME("SAR Ed, 1");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
GETEDO(x6, 0);
emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4);
WBACKO(x6);
break;
}
break;
case 0xD3:
nextop = F8;
grab_segdata(dyn, addr, ninst, x6, seg);
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
MOV64xw(x4, (rex.w?64:32));
SUBx_REG(x3, x4, x3);
GETEDO(x6, 0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
RORxw_REG(ed, ed, x3);
WBACKO(x6);
UFLAG_IF { // calculate flags directly
CMPSw_U12(x3, rex.w?63:31);
B_MARK(cNE);
LSRxw(x4, ed, rex.w?63:31);
ADDxw_REG(x4, x4, ed);
BFIw(xFlags, x4, F_OF, 1);
MARK;
BFIw(xFlags, ed, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 1:
INST_NAME("ROR Ed, CL");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
RORxw_REG(ed, ed, x3);
WBACKO(x6);
UFLAG_IF { // calculate flags directly
CMPSw_U12(x3, 1);
B_MARK(cNE);
LSRxw(x2, ed, rex.w?62:30); // x2 = d>>30
EORw_REG_LSR(x2, x2, x2, 1); // x2 = ((d>>30) ^ ((d>>30)>>1))
BFIw(xFlags, x2, F_OF, 1);
MARK;
LSRxw(x2, ed, rex.w?63:31);
BFIw(xFlags, x2, F_CF, 1);
UFLAG_DF(x2, d_none);
}
break;
case 2:
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(rex.w) {
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
CALL_(rex.w?((void*)rcl64):((void*)rcl32), ed, x6);
WBACK;
break;
case 3:
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(rex.w) {
ANDSx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(wback) {ADDx_REG(x6, x6, wback); wback=x6;}
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
CALL_(rex.w?((void*)rcr64):((void*)rcr32), ed, x6);
WBACK;
break;
case 4:
case 6:
INST_NAME("SHL Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
emit_shl32(dyn, ninst, rex, ed, x3, x5, x4);
WBACKO(x6);
break;
case 5:
INST_NAME("SHR Ed, CL");
SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
emit_shr32(dyn, ninst, rex, ed, x3, x5, x4);
WBACKO(x6);
break;
case 7:
INST_NAME("SAR Ed, CL");
SETFLAGS(X_ALL, SF_PENDING);
if(rex.w) {
ANDSx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f
} else {
ANDSw_mask(x3, xRCX, 0, 0b00100); //mask=0x00000001f
}
GETEDO(x6, 0);
if(!rex.w && MODREG) {MOVw_REG(ed, ed);}
B_NEXT(cEQ);
UFLAG_OP12(ed, x3);
ASRxw_REG(ed, ed, x3);
WBACKO(x6);
UFLAG_RES(ed);
UFLAG_DF(x3, rex.w?d_sar64:d_sar32);
break;
}
break;
default:
DEFAULT;
}
return addr;
}
+125 -52
View File
@@ -27,15 +27,18 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
{
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, j32;
int16_t i16;
uint16_t u16;
uint64_t u64;
int32_t i32;
int64_t j64;
uint8_t gd, ed;
uint8_t wback, wb1;
int fixedaddress;
MAYUSE(u16);
int64_t fixedaddress;
MAYUSE(u8);
MAYUSE(j32);
MAYUSE(u16);
MAYUSE(u64);
MAYUSE(j64);
while((opcode==0x2E) || (opcode==0x66)) // ignoring CS: or multiple 0x66
opcode = F8;
@@ -51,10 +54,13 @@ 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");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -63,7 +69,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x03:
INST_NAME("ADD Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -72,7 +78,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x05:
INST_NAME("ADD AX, Iw");
SETFLAGS(X_ALL, SF_PENDING);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -82,7 +88,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x09:
INST_NAME("OR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -91,7 +97,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x0B:
INST_NAME("OR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -100,7 +106,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x0D:
INST_NAME("OR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -114,7 +120,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x11:
INST_NAME("ADC Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -124,7 +130,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x13:
INST_NAME("ADC Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -134,7 +140,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x15:
INST_NAME("ADC AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -145,7 +151,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x19:
INST_NAME("SBB Ew, Gw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -155,7 +161,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x1B:
INST_NAME("SBB Gw, Ew");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -165,7 +171,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x1D:
INST_NAME("SBB AX, Iw");
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i16 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i16);
@@ -175,7 +181,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x21:
INST_NAME("AND Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -184,7 +190,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x23:
INST_NAME("AND Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -193,7 +199,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x25:
INST_NAME("AND AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -203,7 +209,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x29:
INST_NAME("SUB Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -212,7 +218,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x2B:
INST_NAME("SUB Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -221,7 +227,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x2D:
INST_NAME("SUB AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -231,7 +237,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x31:
INST_NAME("XOR Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -240,7 +246,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x33:
INST_NAME("XOR Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -249,7 +255,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x35:
INST_NAME("XOR AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
MOV32w(x2, i32);
@@ -259,7 +265,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x39:
INST_NAME("CMP Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x2);
GETEW(x1, 0);
@@ -267,7 +273,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x3B:
INST_NAME("CMP Gw, Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGW(x1);
GETEW(x2, 0);
@@ -275,7 +281,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x3D:
INST_NAME("CMP AX, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
i32 = F16;
UXTHw(x1, xRAX);
if(i32) {
@@ -286,6 +292,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);
@@ -324,8 +338,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, (opcode==81)?2:1);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -333,8 +347,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -343,8 +357,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2: //ADC
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -353,8 +367,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 3: //SBB
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -362,8 +376,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -371,8 +385,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -380,8 +394,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
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);
@@ -389,8 +403,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
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);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, (opcode==0x81)?2:1);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(i16) {
MOV32w(x2, i16);
@@ -403,7 +417,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0x85:
INST_NAME("TEST Ew, Gw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETEW(x1, 0);
GETGW(x2);
@@ -444,6 +458,27 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("NOP");
break;
case 0x98:
INST_NAME("CBW");
SXTBw(x1, xRAX);
BFIw(xRAX, x1, 0, 16);
break;
case 0xA1:
INST_NAME("MOV EAX,Od");
u64 = F64;
MOV64x(x1, u64);
LDRH_U12(x2, x1, 0);
BFIx(xRAX, x2, 0, 16);
break;
case 0xA3:
INST_NAME("MOV Od,EAX");
u64 = F64;
MOV64x(x1, u64);
STRH_U12(xRAX, x1, 0);
break;
case 0xA5:
if(rep) {
INST_NAME("REP MOVSW");
@@ -473,13 +508,36 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xA9:
INST_NAME("TEST AX,Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
u16 = F16;
MOV32w(x2, u16);
UBFXx(x1, xRAX, 0, 16);
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:
@@ -500,6 +558,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
@@ -509,6 +568,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("ROR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
u8 = F8;
@@ -518,6 +578,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
INST_NAME("RCL Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
@@ -528,6 +589,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
INST_NAME("RCR Ew, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 1);
@@ -539,24 +601,26 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 4:
case 6:
INST_NAME("SHL Ew, Ib");
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
LSLw_REG(ed, ed, x2);
LSLw_IMM(ed, ed, u8&0x1f);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shl16);
break;
case 5:
INST_NAME("SHR Ed, Ib");
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 1);
u8 = F8;
MOV32w(x2, (u8&0x1f));
UFLAG_OP12(ed, x2)
LSRw_REG(ed, ed, x2);
LSRw_IMM(ed, ed, u8&0x1f);
EWBACK;
UFLAG_RES(ed);
UFLAG_DF(x3, d_shr16);
@@ -564,6 +628,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 7:
INST_NAME("SAR Ed, Ib");
SETFLAGS(X_ALL, SF_PENDING);
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
GETSEW(x1, 0);
u8 = F8;
MOV32w(x2, (u8&0x1f));
@@ -604,6 +669,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ROL Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 0);
CALL_(rol16, x1, x3);
@@ -617,6 +683,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("ROR Ew, CL");
ANDSw_mask(x2, xRCX, 0, 0b00100);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEW(x1, 0);
CALL_(ror16, x1, x3);
@@ -624,6 +691,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 2:
if(opcode==0xD1) {INST_NAME("RCL Ew, 1"); } else { INST_NAME("RCL Ew, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
@@ -633,6 +701,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
if(opcode==0xD1) {INST_NAME("RCR Ew, 1");} else {INST_NAME("RCR Ew, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD1) {MOV32w(x2, 1);} else {ANDSw_mask(x2, xRCX, 0, 0b00100);}
@@ -649,6 +718,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SHL Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
@@ -665,6 +735,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SHR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETEW(x1, 0);
UFLAG_OP12(ed, x4)
@@ -681,6 +752,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("SAR Ew, CL");
ANDSw_mask(x4, xRCX, 0, 0b00100);
}
UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");}
SETFLAGS(X_ALL, SF_PENDING);
GETSEW(x1, 0);
UFLAG_OP12(ed, x4)
@@ -698,7 +770,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0:
case 1:
INST_NAME("TEST Ew, Iw");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 2);
u16 = F16;
MOV32w(x2, u16);
@@ -712,7 +784,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 3:
INST_NAME("NEG Ew");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x1, 0);
emit_neg16(dyn, ninst, ed, x2, x4);
EWBACK;
@@ -741,12 +813,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6:
INST_NAME("DIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(div16, -1);
break;
case 7:
INST_NAME("IDIV Ew");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEW(x1, 0);
CALL(idiv16, -1);
@@ -766,7 +840,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
GETEW(x1, 0);
emit_dec16(dyn, ninst, x1, x2, x4);
EWBACK;
@@ -780,4 +854,3 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
return addr;
}
+717 -49
View File
@@ -44,30 +44,61 @@
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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop, u8;
int32_t i32, j32;
int32_t i32;
uint8_t gd, ed;
uint8_t wback, wb1;
uint8_t eb1, eb2;
int64_t j64;
uint64_t tmp64u, tmp64u2;
int v0, v1;
int q0, q1;
int d0;
int fixedaddress;
int d0, d1;
int64_t fixedaddress;
MAYUSE(d0);
MAYUSE(d1);
MAYUSE(q0);
MAYUSE(q1);
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(j32);
#if 0//STEP == 3
MAYUSE(j64);
#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 +150,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 +223,142 @@ 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;
case 0x20:
INST_NAME("PMOVSXBW Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
break;
case 0x21:
INST_NAME("PMOVSXBD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
SXTL_16(q0, q0); //16bits->32bits
break;
case 0x22:
INST_NAME("PMOVSXBQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_8(q0, q1); // 8bits->16bits
SXTL_16(q0, q0); //16bits->32bits
SXTL_32(q0, q0); //32bits->64bits
break;
case 0x23:
INST_NAME("PMOVSXWD Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_16(q0, q1); // 16bits->32bits
break;
case 0x24:
INST_NAME("PMOVSXWQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_16(q0, q1); // 16bits->32bits
SXTL_32(q0, q1); // 32bits->64bits
break;
case 0x25:
INST_NAME("PMOVSXDQ Gx, Ex"); // SSE4 opcode!
nextop = F8;
GETEX(q1, 0);
GETGX_empty(q0);
SXTL_32(q0, q1); // 32bits->64bits
break;
default:
DEFAULT;
}
break;
case 0x3A: // these are some more SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0B:
INST_NAME("ROUNDSD Gx, Ex, Ib");
nextop = F8;
GETGX(q0);
GETEX(q1, 1);
u8 = F8;
v1 = fpu_get_scratch(dyn);
if(u8&4) {
u8 = sse_setround(dyn, ninst, x1, x2, x3);
FRINTXD(v1, q1);
x87_restoreround(dyn, ninst, u8);
} else {
const uint8_t rounds[] = {0, 2, 1, 3};
MAYUSE(rounds);
FRINTRRD(v1, q1, rounds[u8&3]);
}
VMOVeD(q0, 0, v1, 0);
break;
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 +405,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 +451,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 +494,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 +527,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 +584,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 +629,72 @@ 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) {
// duplicate 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(u8==0x55) {
// duplicate slot 1 to all spot
if(v0!=v1) {
VMOVeS(v0, 1, v1, 1);
}
VMOVeS(v0, 0, v1, 1);
VMOVeD(v0, 1, v0, 0);
} else if(u8==0xAA) {
// duplicate slot 2 to all spot
if(v0!=v1) {
VMOVeS(v0, 2, v1, 2);
}
VMOVeS(v0, 3, v1, 2);
VMOVeD(v0, 0, v0, 1);
} else if(u8==0xFF) {
// duplicate slot 3 to all spot
if(v0!=v1) {
VMOVeS(v0, 3, v1, 3);
}
VMOVeS(v0, 2, v1, 3);
VMOVeD(v0, 0, v0, 1);
} 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);
tmp64u2 = swp[(u8>>(2*2))&3] | (swp[(u8>>(3*2))&3]<<32);
if(tmp64u2==tmp64u) {
VMOVQDfrom(d0, 1, x2);
} else {
MOV64x(x3, tmp64u2);
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) {
@@ -416,7 +707,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VLD1_32(v0, i, x2);
}
} else {
VLD1R_32(v0, ed);
VLDQ1R_32(v0, ed);
}
}
break;
@@ -591,6 +882,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;
@@ -628,10 +941,19 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xA3:
INST_NAME("BT Ew, Gw");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
SBFXw(x1, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x1, 1); //(&ed)+=r1*2;
LDRH_U12(x1, x3, fixedaddress);
ed = x1;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
@@ -645,6 +967,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SHLD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xA4)?1:0);
GETGW(x2);
@@ -658,10 +981,20 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xAB:
INST_NAME("BTS Ew, Gw");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
ed = x4;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
@@ -669,8 +1002,10 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
B_NEXT(cNE);
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
EORx_REG(ed, ed, x1);
if(wback) {
STRH_U12(ed, wback, fixedaddress);
}
break;
case 0xAC:
case 0xAD:
@@ -681,6 +1016,7 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
INST_NAME("SHRD Ew, Gw, CL");
UXTBw(x3, xRCX);
}
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
GETEWW(x4, x1, (opcode==0xAC)?1:0);
GETGW(x2);
@@ -706,10 +1042,21 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
case 0xB3:
INST_NAME("BTR Ew, Gw");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
wback = x3;
ed = x4;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
@@ -717,28 +1064,65 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
B_NEXT(cEQ);
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
EORx_REG(ed, ed, x1);
if(wback) {
STRH_U12(ed, wback, fixedaddress);
}
break;
case 0xB6:
INST_NAME("MOVZX Gw, Eb");
nextop = F8;
if(MODREG) {
if(rex.rex) {
eb1 = xRAX+(nextop&7)+(rex.b<<3);
eb2 = 0; \
} else {
ed = (nextop&7);
eb1 = xRAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
}
UBFXxw(x1, eb1, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0xfff, 0, rex, 0, 0);
LDRB_U12(x1, ed, fixedaddress);
}
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGW
BFIx(gd, x1, 0, 16); // insert in Gw
break;
case 0xBB:
INST_NAME("BTC Ew, Gw");
SETFLAGS(X_CF, SF_SET);
SETFLAGS(X_CF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3); // GETGD
GETEW(x4, 0);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xfff<<2, (1<<2)-1, rex, 0, 0);
SBFXw(x4, gd, 4, 12); // r1 = (gw>>4)
ADDx_REG_LSL(x3, wback, x4, 1); //(&ed)+=r1*2;
LDRH_U12(x4, x3, fixedaddress);
wback = x3;
ed = x4;
}
ANDw_mask(x2, gd, 0, 0b000011); // mask=0x0f
LSRw_REG(x1, ed, x2);
BFIw(xFlags, x1, F_CF, 1);
ANDw_mask(x1, x1, 0, 0); //mask=1
MOV32w(x1, 1);
LSLxw_REG(x1, x1, x2);
EORxw_REG(ed, ed, x1);
EWBACK;
EORx_REG(ed, ed, x1);
if(wback) {
STRH_U12(ed, wback, fixedaddress);
}
break;
case 0xBC:
INST_NAME("BSF Ew,Gw");
SETFLAGS(X_ZF, SF_SET);
SETFLAGS(X_ZF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
@@ -750,11 +1134,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBD:
INST_NAME("BSR Ew,Gw");
SETFLAGS(X_ZF, SF_SET);
SETFLAGS(X_ZF, SF_SUBSET);
SET_DFNONE(x1);
nextop = F8;
GETGD;
GETEW(x1, 0); // Get EW
@@ -768,7 +1152,6 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MARK;
CSETw(x1, cEQ); //ZF not set
BFIw(xFlags, x1, F_ZF, 1);
SET_DFNONE(x1);
break;
case 0xBE:
INST_NAME("MOVSX Gw, Eb");
@@ -792,7 +1175,66 @@ 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 0xD3:
INST_NAME("PSRLQ Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
NEG_64(v0, q1);
VMOVeD(v0, 1, v0, 0);
USHLQ_64(q0, q0, v0);
break;
case 0xD4:
INST_NAME("PADDQ Gx,Ex");
nextop = F8;
@@ -800,7 +1242,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 +1263,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 +1291,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 +1320,108 @@ 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("CVTTPD2DQ Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX_empty(v0);
VFCVTNSQD(v0, v1); // convert double -> int64
SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part
break;
case 0xE7:
INST_NAME("MOVNTDQ Ex, Gx");
nextop = F8;
GETGX(v0);
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 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 +1429,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 +1459,28 @@ 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 0xF3:
INST_NAME("PSLLQ Gx,Ex");
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
VMOVQ(v0, q1);
VMOVeD(v0, 1, v0, 0);
USHLQ_64(q0, q0, v0);
break;
case 0xF4:
INST_NAME("PMULUDQ Gx,Ex");
nextop = F8;
@@ -869,7 +1496,49 @@ 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 0xF7:
INST_NAME("MASKMOVDQU Gx, Ex")
nextop = F8;
GETGX(q0);
GETEX(q1, 0);
v0 = fpu_get_scratch(dyn);
VLDR128_U12(v0, xRDI, 0);
if(MODREG)
v1 = fpu_get_scratch(dyn); // need to preserve the register
else
v1 = q1;
VSSHRQ_8(v1, q1, 7); // get the mask
VBICQ(v0, v0, v1); // mask destination
VANDQ(v1, q0, v1); // mask source
VORRQ(v1, v1, v0); // combine
VSTR128_U12(v1, xRDI, 0); // put back
break;
case 0xF8:
INST_NAME("PSUBB Gx,Ex");
nextop = F8;
@@ -925,4 +1594,3 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
}
return addr;
}
+80
View File
@@ -0,0 +1,80 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int64_t 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;
}
+65 -3
View File
@@ -22,14 +22,26 @@
#include "dynarec_arm64_helper.h"
#include "dynarec_arm64_functions.h"
#define GETGX(a) \
gd = ((nextop&0x38)>>3)+(rex.r<<3); \
a = sse_get_reg(dyn, ninst, x1, gd)
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)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
uint8_t gd, ed;
int64_t fixedaddress;
int8_t i8;
int32_t i32, j32;
MAYUSE(j32);
int32_t i32;
int64_t j64;
int v0, s0;
MAYUSE(i32);
MAYUSE(j64);
MAYUSE(v0);
MAYUSE(s0);
// REX prefix before the 67 are ignored
rex.rex = 0;
@@ -37,9 +49,60 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
rex.rex = opcode;
opcode = F8;
}
rep = 0;
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
opcode = F8;
}
switch(opcode) {
case 0x0F:
opcode=F8;
switch(opcode) {
case 0x2E:
// no special check...
case 0x2F:
if(rep) {
DEFAULT;
} else {
if(opcode==0x2F) {INST_NAME("COMISS Gx, Ex");} else {INST_NAME("UCOMISS Gx, Ex");}
SETFLAGS(X_ALL, SF_SET);
nextop = F8;
GETGX(v0);
if(MODREG) {
s0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
} else {
s0 = fpu_get_scratch(dyn);
addr = geted32(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
VLDR32_U12(s0, ed, fixedaddress);
}
FCMPS(v0, s0);
FCOMI(x1, x2);
}
break;
default:
DEFAULT;
}
break;
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);\
@@ -99,4 +162,3 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
return addr;
}
+232
View File
@@ -0,0 +1,232 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
int64_t 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;
}
+356
View File
@@ -0,0 +1,356 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
int64_t 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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
// 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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1);
break;
case 0xF1:
INST_NAME("FYL2X");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1);
break;
case 0xF5:
INST_NAME("FPREM1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1);
break;
case 0xF9:
INST_NAME("FYL2XP1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fsincos, -1);
break;
case 0xFD:
INST_NAME("FSCALE");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fscale, -1);
break;
case 0xFE:
INST_NAME("FSIN");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_fsin, -1);
break;
case 0xFF:
INST_NAME("FCOS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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;
}
+306
View File
@@ -0,0 +1,306 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback;
uint8_t u8;
int64_t fixedaddress;
int v1, v2;
int s0;
int64_t j64;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j64);
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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTZD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
MARK3;
#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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
MARK3;
#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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
VSTR32_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x80000000);
STRw_U12(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
x87_do_pop(dyn, ninst);
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
// the FLD is immediatly followed by an FSTP
LDRx_U12(x5, ed, 0);
LDRH_U12(x6, ed, 8);
// no persistant scratch register, so unrool both instruction here...
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; //0xDB
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0);
STRx_U12(x5, ed, 0);
STRH_U12(x6, ed, 8);
} else {
if(ed!=x1) {
MOVx_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
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;
}
+205
View File
@@ -0,0 +1,205 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed;
int64_t 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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_purgecache(dyn, ninst, x1, x2, x3);
MOV32w(x1, nextop-0xC0);
CALL(fpu_do_free, -1);
break;
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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");
MESSAGE(LOG_DUMP, "Need Optimization\n");
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;
}
+294
View File
@@ -0,0 +1,294 @@
#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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t nextop = F8;
uint8_t ed, wback, u8;
int v1, v2;
int s0;
int64_t j64;
int64_t fixedaddress;
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j64);
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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
VFCVTZSd(s0, v1);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
MARK3;
#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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
MARK3;
#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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
SQXTN_S_D(s0, s0);
SQXTN_H_S(s0, s0);
VSTR16_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV32w(x5, 0x8000);
STRH_U12(x5, wback, fixedaddress);
MARK3;
#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
MRS_fpsr(x5);
BFCw(x5, FPSR_IOC, 1); // reset IOC bit
MSR_fpsr(x5);
FRINTXD(s0, v1);
VFCVTZSd(s0, s0);
VSTR64_U12(s0, wback, fixedaddress);
MRS_fpsr(x5); // get back FPSR to check the IOC bit
TBZ_MARK3(x5, FPSR_IOC);
MOV64x(x5, 0x8000000000000000LL);
STRx_U12(x5, wback, fixedaddress);
MARK3;
#endif
x87_restoreround(dyn, ninst, u8);
break;
default:
DEFAULT;
}
}
return addr;
}
+19 -10
View File
@@ -23,9 +23,10 @@
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// emit OR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit OR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_or32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -89,9 +90,10 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int
}
}
// emit XOR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit XOR32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_xor32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -155,9 +157,10 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
}
}
// emit AND32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit AND32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_and32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -227,9 +230,10 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
}
}
// emit OR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit OR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -292,9 +296,10 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
}
}
// emit XOR8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit XOR8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -357,9 +362,10 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
}
// emit AND8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit AND8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -429,9 +435,10 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
}
// emit OR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit OR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -507,9 +514,10 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// }
//}
// emit XOR16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit XOR16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -585,9 +593,10 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// }
//}
// emit AND16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
// emit AND16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch, s4 can be same as s2 (and so s2 destroyed)
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -667,4 +676,4 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
//}
+77 -84
View File
@@ -23,9 +23,10 @@
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// emit ADD32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit ADD32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -51,21 +52,17 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
LSRxw(s4, s3, 3);
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
Bcond(cCC, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCS);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
@@ -76,9 +73,10 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
}
// emit ADD32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit ADD32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
@@ -126,21 +124,17 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
LSRxw(s4, s3, 3);
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
Bcond(cCC, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCS);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
@@ -151,9 +145,10 @@ void emit_add32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
}
}
// emit SUB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit SUB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -180,22 +175,18 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
LSRxw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
@@ -206,9 +197,10 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
}
// emit SUB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SUB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5)
{
MAYUSE(s5);
if(s1==xRSP && (!dyn->insts || dyn->insts[ninst].x64.need_flags==X_PEND))
{
// special case when doing math on RSP and only PEND is needed: ignoring it!
@@ -256,22 +248,18 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
LSRxw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
@@ -282,9 +270,10 @@ void emit_sub32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int64_t c, in
}
}
// emit ADD8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADD8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -331,7 +320,7 @@ void emit_add8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit ADD8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADD8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
{
IFX(X_PEND) {
@@ -383,9 +372,10 @@ void emit_add8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
}
}
// emit SUB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit SUB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -434,9 +424,10 @@ void emit_sub8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SUB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SUB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
{
MAYUSE(s5);
IFX(X_ALL|X_PEND) {
MOV32w(s5, c&0xff);
}
@@ -491,9 +482,10 @@ void emit_sub8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
}
}
// emit ADD16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADD16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -541,7 +533,7 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit ADD16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADD16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
//void emit_add16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -608,9 +600,10 @@ void emit_add16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// }
//}
// emit SUB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit SUB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -659,7 +652,7 @@ void emit_sub16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SUB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SUB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sub16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -756,17 +749,13 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
LSRxw(s4, s3, 3);
BFIxw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, rex.w?63:31);
@@ -777,7 +766,7 @@ void emit_inc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
}
}
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit INC8 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
@@ -822,7 +811,7 @@ void emit_inc8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
}
// emit INC16 instruction, from s1 , store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit INC16 instruction, from s1, store result in s1 using s3 and s4 as scratch
void emit_inc16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
IFX(X_PEND) {
@@ -900,17 +889,13 @@ void emit_dec32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4
LSRxw(s4, s3, 3);
BFIw(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_OF));
BICx(xFlags, xFlags, s3);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, rex.w?63:31);
@@ -1009,9 +994,10 @@ void emit_dec16(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
}
}
// emit ADC32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit ADC32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1062,7 +1048,7 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
}
// emit ADC32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit ADC32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_adc32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -1132,9 +1118,10 @@ void emit_adc32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// }
//}
// emit ADC8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADC8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1185,9 +1172,10 @@ void emit_adc8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit ADC8 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADC8 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
{
MAYUSE(s5);
MOV32w(s5, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -1239,9 +1227,10 @@ void emit_adc8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
}
}
// emit ADC16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADC16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1257,7 +1246,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
@@ -1292,7 +1281,7 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit ADC16 instruction, from s1 , const c, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit ADC16 instruction, from s1, const c, store result in s1 using s3 and s4 as scratch
//void emit_adc16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -1359,9 +1348,10 @@ void emit_adc16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// }
//}
// emit SBB32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch
// emit SBB32 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1414,7 +1404,7 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
}
// emit SBB32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SBB32 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sbb32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -1486,9 +1476,10 @@ void emit_sbb32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
// }
//}
// emit SBB8 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit SBB8 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRB_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1540,9 +1531,10 @@ void emit_sbb8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SBB8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SBB8 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, int s5)
{
MAYUSE(s5);
MOV32w(s5, c&0xff);
IFX(X_PEND) {
STRB_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -1595,9 +1587,10 @@ void emit_sbb8c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4, in
}
}
// emit SBB16 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, with save_s4 is s4 need to be saved
// emit SBB16 instruction, from s1, s2, store result in s1 using s3 and s4 as scratch
void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
MAYUSE(s2);
IFX(X_PEND) {
STRH_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRH_U12(s2, xEmu, offsetof(x64emu_t, op2));
@@ -1649,7 +1642,7 @@ void emit_sbb16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SBB16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
// emit SBB16 instruction, from s1, constant c, store result in s1 using s3 and s4 as scratch
//void emit_sbb16c(dynarec_arm_t* dyn, int ninst, int s1, int c, int s3, int s4)
//{
// IFX(X_PEND) {
@@ -1853,4 +1846,4 @@ void emit_neg8(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
}
+124 -142
View File
@@ -26,8 +26,9 @@
// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2
void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int32_t j32;
MAYUSE(j32);
MAYUSE(s2);
int64_t j64;
MAYUSE(j64);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -60,9 +61,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
@@ -71,9 +71,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
IFX(X_OF) {
CMPSxw_U12(s2, 1); // if s2==1
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
Bcond(cNE, 4+3*4);
BFCw(xFlags, F_OF, 1);
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
CSELw(s4, s4, wZR, cEQ);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_PF) {
@@ -101,7 +100,7 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
}
return;
}
IFX(X_CF) {
IFX(X_CF|X_OF) {
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
}
@@ -112,9 +111,8 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
@@ -123,7 +121,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
IFX(X_OF) {
if(c==1) {
IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);}
Bcond(cNE, +12);
EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked
BFIw(xFlags, s4, F_OF, 1);
} else {
@@ -138,8 +135,9 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
// emit SHR32 instruction, from s1 , s2, store result in s1 using s3 and s4 as scratch, s2 can be same as s3
void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4)
{
int32_t j32;
MAYUSE(j32);
MAYUSE(s2);
int64_t j64;
MAYUSE(j64);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
@@ -167,9 +165,8 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
@@ -218,9 +215,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
@@ -255,19 +251,18 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
}
return;
}
IFX(X_CF) {
ASRxw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
}
ASRxw(s1, s1, c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTw_REG(s1, s1);
BFCx(xFlags, F_ZF, 1);
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
}
IFX(X_CF) {
ASRxw(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
@@ -281,6 +276,7 @@ void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
// emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -312,6 +308,7 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
// emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4)
{
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
@@ -343,119 +340,104 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
}
// emit SHRD32 instruction, from s1, fill s2 , constant c, store result in s1 using s3 and s4 as scratch
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
//{
// c&=0x1f;
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// // same flags calc as shr32
// SET_DF(s4, d_shr32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(!c) {
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// return;
// }
// IFX(X_CF) {
// MOVS_REG_LSR_IMM5(s1, s1, c);
// } else {
// MOV_REG_LSR_IMM5(s1, s1, c);
// }
// IFX(X_ZF|X_CF) {
// BIC_IMM8(xFlags, xFlags, (1<<F_ZF)|(1<<F_CF), 0);
// }
// IFX(X_CF) {
// ORR_IMM8_COND(cCS, xFlags, xFlags, 1<<F_CF, 0);
// }
// IFX(X_ZF) {
// ORRS_REG_LSL_IMM5(s1, s1, s2, 32-c);
// } else {
// ORR_REG_LSL_IMM5(s1, s1, s2, 32-c);
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 31);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_OF) {
// if(c==1) {
// MOV_REG_LSR_IMM5(s4, s1, 30);
// XOR_REG_LSR_IMM8(s4, s4, s4, 1);
// BFI(xFlags, s4, F_OF, 1);
// }
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
{
c&=(rex.w?0x3f:0x1f);
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
// same flags computation as with shl64/shl32
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(!c) {
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF) {
LSRxw_REG(s3, s1, c-1);
BFIw(xFlags, s3, 0, 1);
}
LSRxw(s1, s1, c);
ORRxw_REG_LSL(s1, s1, s2, (rex.w?64:32)-c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
LSRxw(s4, s1, rex.w?62:30);
EORw_REG_LSR(s4, s4, s4, 1);
BFIw(xFlags, s4, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4)
//{
// c&=0x1f;
// IFX(X_PEND) {
// MOVW(s3, c);
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, op1));
// STR_IMM9(s3, xEmu, offsetof(x64emu_t, op2));
// // same flags computation as with shl32
// SET_DF(s4, d_shl32);
// } else IFX(X_ALL) {
// SET_DFNONE(s4);
// }
// if(c==0) {
// IFX(F_OF) {
// BFC(xFlags, F_OF, 1);
// }
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// return;
// }
// IFX(X_CF) {
// MOV_REG_LSR_IMM5(s3, s1, 32-c);
// BFI(xFlags, s3, F_CF, 1);
// }
// IFX(X_OF) {
// MOVS_REG_LSL_IMM5(s1, s1, c);
// } else {
// MOV_REG_LSL_IMM5(s1, s1, c);
// }
// IFX(X_OF) {
// if(c==1) {
// UBFX(s3, s2, 0, 1);
// XOR_IMM8_COND(cCS, s3, s3, 1);
// BFI(xFlags, s3, F_OF, 1);
// } else {
// BFC(xFlags, F_OF, 1);
// }
// }
// IFX(X_ZF) {
// ORRS_REG_LSR_IMM5(s1, s1, s2, 32-c);
// } else {
// ORR_REG_LSR_IMM5(s1, s1, s2, 32-c);
// }
//
// IFX(X_PEND) {
// STR_IMM9(s1, xEmu, offsetof(x64emu_t, res));
// }
// IFX(X_ZF) {
// ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
// BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
// }
// IFX(X_SF) {
// MOV_REG_LSR_IMM5(s3, s1, 31);
// BFI(xFlags, s3, F_SF, 1);
// }
// IFX(X_PF) {
// emit_pf(dyn, ninst, s1, s3, s4);
// }
//}
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4)
{
c&=(rex.w?0x3f:0x1f);
IFX(X_PEND) {
MOV32w(s3, c);
STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1));
STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2));
// same flags computation as with shl64/shl32
SET_DF(s4, rex.w?d_shl64:d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
if(c==0) {
IFX(F_OF) {
BFCx(xFlags, F_OF, 1);
}
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
return;
}
IFX(X_CF|X_OF) {
LSRxw(s3, s1, (rex.w?64:32)-c);
BFIxw(xFlags, s3, F_CF, 1);
}
LSLxw(s1, s1, c);
ORRxw_REG_LSR(s1, s1, s2, (rex.w?64:32)-c);
IFX(X_PEND) {
STRxw_U12(s1, xEmu, offsetof(x64emu_t, res));
}
IFX(X_ZF) {
TSTxw_REG(s1, s1);
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_SF) {
LSRxw(s4, s1, (rex.w)?63:31);
BFIx(xFlags, s4, F_SF, 1);
}
IFX(X_OF) {
if(c==1) {
UBFXxw(s3, s1, rex.w?63:31, 1);
EORxw_REG(s3, s3, xFlags); // CF is set if OF is asked
BFIw(xFlags, s3, F_OF, 1);
} else {
BFCw(xFlags, F_OF, 1);
}
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
+41 -39
View File
@@ -23,10 +23,11 @@
#include "dynarec_arm64_functions.h"
#include "dynarec_arm64_helper.h"
// emit CMP32 instruction, from cmp s1 , s2, using s3 and s4 as scratch
// 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) {
MAYUSE(s1); MAYUSE(s2);
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 +39,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) {
@@ -47,22 +48,18 @@ void emit_cmp32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3
LSRxw(s4, s3, 3);
BFIx(xFlags, s4, F_AF, 1); // AF: bc & 0x08
}
IFX(X_ZF|X_CF|X_OF) {
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF));
BICx(xFlags, xFlags, s4);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
Bcond(cVC, +8);
ORRw_mask(xFlags, xFlags, 0b010101, 0); // mask=0x800
CSETw(s4, cVS);
BFIw(xFlags, s4, F_OF, 1);
}
IFX(X_SF) {
LSRxw(s3, s5, (rex.w)?63:31);
@@ -76,7 +73,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));
@@ -88,18 +85,18 @@ void emit_cmp32_0(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s3, int
SUBSxw_U12(s3, s1, 0); // res = s1 - 0
// and now the tricky ones (and mostly unused), PF and AF
// bc = (res & (~d | s)) | (~d & s) => is 0 here...
IFX(X_ZF|X_CF|X_OF|X_AF) {
MOV32w(s4, (1<<F_ZF)|(1<<F_CF)|(1<<F_OF)|(1<<F_AF));
IFX(X_OF|X_AF) {
MOV32w(s4, (1<<F_OF)|(1<<F_AF));
BICw(xFlags, xFlags, s4);
}
IFX(X_ZF) {
Bcond(cNE, +8);
ORRw_mask(xFlags, xFlags, 0b011010, 0); // mask=0x40
CSETw(s4, cEQ);
BFIw(xFlags, s4, F_ZF, 1);
}
IFX(X_CF) {
// inverted carry
Bcond(cCS, +8);
ORRw_mask(xFlags, xFlags, 0, 0); // mask=0x01
CSETw(s4, cCC);
BFIw(xFlags, s4, F_CF, 1);
}
IFX(X_SF) {
LSRxw(s3, s1, (rex.w)?63:31);
@@ -110,10 +107,11 @@ 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
// 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) {
MAYUSE(s1); MAYUSE(s2);
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 +119,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 +160,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));
@@ -189,10 +187,11 @@ void emit_cmp16_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit CMP8 instruction, from cmp s1 , s2, using s3 and s4 as scratch
// 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) {
MAYUSE(s1); MAYUSE(s2);
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 +203,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 +241,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));
@@ -252,8 +251,8 @@ void emit_cmp8_0(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
SET_DFNONE(s4);
}
// bc = (res & (~d | s)) | (~d & s) = 0
IFX(X_CF | X_AF | X_ZF | X_OF) {
MOV32w(s3, (1<<F_ZF)|(1<<F_CF)|(1<<F_AF)|(1<<F_OF));
IFX(X_CF | X_AF | X_OF) {
MOV32w(s3, (1<<F_CF)|(1<<F_AF)|(1<<F_OF));
BICw(xFlags, xFlags, s3);
}
IFX(X_ZF) {
@@ -270,10 +269,11 @@ 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
// 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) {
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3); MAYUSE(s4);
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) {
@@ -307,10 +307,11 @@ 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
// 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) {
MAYUSE(s1); MAYUSE(s2);
IFX_PENDOR0 {
SET_DF(s3, d_tst16);
} else {
SET_DFNONE(s4);
@@ -322,7 +323,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) {
@@ -339,10 +340,11 @@ 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
// 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) {
MAYUSE(s1); MAYUSE(s2);
IFX_PENDOR0 {
SET_DF(s3, d_tst8);
} else {
SET_DFNONE(s4);
@@ -354,7 +356,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) {
+361 -28
View File
@@ -25,17 +25,20 @@
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)
{
(void)ip; (void)rep; (void)need_epilog;
uint8_t opcode = F8;
uint8_t nextop;
int32_t j32;
uint8_t gd, ed;
uint8_t wback, wb2, gb1, gb2;
int64_t i64;
int fixedaddress;
uint8_t wback, wb1, wb2, gb1, gb2;
int32_t i32;
int64_t i64, j64;
int64_t fixedaddress;
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
MAYUSE(j32);
MAYUSE(j64);
while((opcode==0xF2) || (opcode==0xF3)) {
rep = opcode-0xF1;
@@ -51,7 +54,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
switch(opcode) {
case 0x00:
INST_NAME("LOCK ADD Eb, Gb");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGB(x2);
if((nextop&0xC0)==0xC0) {
@@ -77,7 +80,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 0x01:
INST_NAME("LOCK ADD Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if((nextop&0xC0)==0xC0) {
@@ -99,7 +102,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if(MODREG) {
@@ -120,8 +123,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,24 +134,22 @@ 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;
case 0xC1:
INST_NAME("LOCK XADD Gd, Ed");
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
nextop = F8;
GETGD;
if(MODREG) {
@@ -185,11 +185,257 @@ 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_SUBSET);
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_PENDING);
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 0x66:
opcode = F8;
switch(opcode) {
case 0x81:
case 0x83:
nextop = F8;
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Iw");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_add16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_add16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ew, Iw");} else {INST_NAME("LOCK OR Ew, Iw");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_or16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_or16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ew, Iw");} else {INST_NAME("LOCK ADC Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_adc16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_adc16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ew, Iw");} else {INST_NAME("LOCK SBB Ew, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sbb16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_sbb16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ew, Iw");} else {INST_NAME("LOCK AND Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_and16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_and16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ew, Iw");} else {INST_NAME("LOCK SUB Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_sub16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRH(x1, wback);
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK; // unaligned! also, not enough
LDRH_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIw(x1, x4, 0, 8); // re-inject
emit_sub16(dyn, ninst, x1, x5, x3, x4);
STLXRB(x3, x1, wback);
CBNZx_MARK(x3);
STRH_U12(x1, wback, 0); // put the whole value
}
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ew, Iw");} else {INST_NAME("LOCK XOR Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i32 = F16S; else i32 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_xor16(dyn, ninst, x6, x5, x3, x4);
BFIx(ed, x6, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?2:1);
if(opcode==0x81) i32 = F16S; else i32 = F8S;
MOV32w(x5, i32);
MARKLOCK;
LDAXRH(x1, wback);
emit_xor16(dyn, ninst, x1, x5, x3, x4);
STLXRH(x3, x1, wback);
CBNZx_MARKLOCK(x3);
}
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ew, Iw");} else {INST_NAME("(LOCK) CMP Ew, Ib");}
SETFLAGS(X_ALL, SF_SET_PENDING);
GETEW(x6, (opcode==0x81)?2:1);
(void)wb1;
// No need to LOCK, this is readonly
if(opcode==0x81) i32 = F16S; else i32 = F8S;
if(i32) {
MOV32w(x5, i32);
UXTHw(x6, ed);
emit_cmp16(dyn, ninst, x6, x5, x3, x4, x6);
BFIx(ed, x6, 0, 16);
} else {
emit_cmp16_0(dyn, ninst, ed, x3, x4);
}
break;
}
break;
default:
DEFAULT;
}
break;
case 0x81:
case 0x83:
nextop = F8;
@@ -200,7 +446,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else {
INST_NAME("LOCK ADD Ed, Ib");
}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -210,7 +456,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRxw(x1, wback);
@@ -230,7 +476,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 1: //OR
if(opcode==0x81) {INST_NAME("LOCK OR Ed, Id");} else {INST_NAME("LOCK OR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -250,7 +496,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 2: //ADC
if(opcode==0x81) {INST_NAME("LOCK ADC Ed, Id");} else {INST_NAME("LOCK ADC Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -270,7 +516,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
case 3: //SBB
if(opcode==0x81) {INST_NAME("LOCK SBB Ed, Id");} else {INST_NAME("LOCK SBB Ed, Ib");}
READFLAGS(X_CF);
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -289,7 +535,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 4: //AND
if(opcode==0x81) {INST_NAME("LOCK AND Ed, Id");} else {INST_NAME("LOCK AND Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -308,7 +554,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 5: //SUB
if(opcode==0x81) {INST_NAME("LOCK SUB Ed, Id");} else {INST_NAME("LOCK SUB Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -318,7 +564,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, (opcode==0x81)?4:1);
if(opcode==0x81) i64 = F32S; else i64 = F8S;
MOV64xw(x5, i64);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
TSTx_mask(wback, 1, 0, 0); // mask=1
B_MARK(cNE);
MARKLOCK;
LDAXRxw(x1, wback);
@@ -338,7 +584,7 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 6: //XOR
if(opcode==0x81) {INST_NAME("LOCK XOR Ed, Id");} else {INST_NAME("LOCK XOR Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
SETFLAGS(X_ALL, SF_SET_PENDING);
if(MODREG) {
if(opcode==0x81) i64 = F32S; else i64 = F8S;
ed = xRAX+(nextop&7)+(rex.b<<3);
@@ -357,8 +603,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
break;
case 7: //CMP
if(opcode==0x81) {INST_NAME("(LOCK) CMP Ed, Id");} else {INST_NAME("(LOCK) CMP Ed, Ib");}
SETFLAGS(X_ALL, SF_SET);
GETED(0);
SETFLAGS(X_ALL, SF_SET_PENDING);
GETED((opcode==0x81)?4:1);
// No need to LOCK, this is readonly
if(opcode==0x81) i64 = F32S; else i64 = F8S;
if(i64) {
@@ -371,9 +617,96 @@ 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;
case 0xFF:
nextop = F8;
switch((nextop>>3)&7)
{
case 0: // INC Ed
INST_NAME("LOCK INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_inc32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
LDAXRxw(x1, wback);
emit_inc32(dyn, ninst, rex, x1, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_inc32(dyn, ninst, rex, x1, x3, x4);
STLXRB(x3, x1, wback);
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
break;
case 1: //DEC Ed
INST_NAME("LOCK DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
if(MODREG) {
ed = xRAX+(nextop&7)+(rex.b<<3);
emit_dec32(dyn, ninst, rex, ed, x3, x4);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, rex, 0, 0);
TSTx_mask(wback, 1, 0, 1+rex.w); // mask=3 or 7
B_MARK(cNE); // unaligned
MARKLOCK;
LDAXRxw(x1, wback);
emit_dec32(dyn, ninst, rex, x1, x3, x4);
STLXRxw(x3, x1, wback);
CBNZx_MARKLOCK(x3);
B_NEXT_nocond;
MARK;
LDRxw_U12(x1, wback, 0);
LDAXRB(x4, wback);
BFIxw(x1, x4, 0, 8); // re-inject
emit_dec32(dyn, ninst, rex, x1, x3, x4);
STLXRB(x3, x1, wback);
CBNZw_MARK(x3);
STRxw_U12(x1, wback, 0);
}
break;
default:
DEFAULT;
}
break;
default:
DEFAULT;
}
return addr;
}
+90 -6
View File
@@ -37,16 +37,23 @@
#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)
{
(void)ip; (void)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;
int fixedaddress;
int64_t fixedaddress;
#ifdef PRECISE_CVT
int j32;
@@ -68,7 +75,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
ed = (nextop&7)+ (rex.b<<3);
v0 = sse_get_reg(dyn, ninst, x1, gd);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOV(v0, d0);
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);
@@ -83,12 +90,27 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
if(MODREG) {
ed = (nextop&7)+ (rex.b<<3);
d0 = sse_get_reg(dyn, ninst, x1, ed);
VMOV(d0, v0);
VMOVeD(d0, 0, v0, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
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 +210,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 +230,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 +239,29 @@ 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);
if(v0!=v1) {
VMOVeD(v0, 1, v1, 1);
}
break;
case 0x7C:
INST_NAME("HADDPS Gx, Ex");
nextop = F8;
@@ -231,9 +276,48 @@ 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;
}
return addr;
}
+122 -3
View File
@@ -42,14 +42,18 @@
uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog)
{
(void)ip; (void)need_epilog;
uint8_t opcode = F8;
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;
int64_t fixedaddress;
int64_t j64;
MAYUSE(d0);
MAYUSE(d1);
@@ -57,6 +61,7 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
MAYUSE(q1);
MAYUSE(v0);
MAYUSE(v1);
MAYUSE(j64);
switch(opcode) {
@@ -115,6 +120,12 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
VTRNQ2_32(q0, q1, q1);
break;
case 0x1E:
INST_NAME("NOP / ENDBR32 / ENDBR64");
nextop = F8;
FAKEED;
break;
case 0x2A:
INST_NAME("CVTSI2SS Gx, Ed");
nextop = F8;
@@ -136,7 +147,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 +181,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 +225,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 +285,28 @@ 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);
if(v0!=v1) {
VMOVeD(v0, 0, v1, 0);
}
break;
case 0x7E:
INST_NAME("MOVQ Gx, Ex");
@@ -257,6 +337,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_SUBSET);
SET_DFNONE(x1);
nextop = F8;
GETED(0);
GETGD;
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,9 +378,32 @@ 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;
}
return addr;
}
+10 -4
View File
@@ -36,7 +36,8 @@ void arm_fstp(x64emu_t* emu, void* p)
void arm_print_armreg(x64emu_t* emu, uintptr_t reg, uintptr_t n)
{
dynarec_log(LOG_DEBUG, "R%ld=0x%lx (%ld)\n", n, reg, reg);
(void)emu;
dynarec_log(LOG_DEBUG, "R%lu=0x%lx (%lu)\n", n, reg, reg);
}
void arm_f2xm1(x64emu_t* emu)
@@ -85,7 +86,8 @@ void arm_frndint(x64emu_t* emu)
}
void arm_fscale(x64emu_t* emu)
{
ST0.d *= exp2(trunc(ST1.d));
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
}
void arm_fsin(x64emu_t* emu)
{
@@ -118,7 +120,7 @@ void arm_fbstp(x64emu_t* emu, uint8_t* ed)
void arm_fistp64(x64emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
if(STll(0).ref==ST(0).q) {
if((uint64_t)STll(0).ref==ST(0).q) {
memcpy(ed, &STll(0).ll, sizeof(int64_t));
} else {
int64_t tmp;
@@ -244,6 +246,7 @@ void fpu_reset_reg(dynarec_arm_t* dyn)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta)
{
(void)dyn; (void)ninst;
uint32_t tested = (1<<parity)-1;
if((nextop&0xC0)==0xC0)
@@ -282,6 +285,8 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i
// Do the GETED, but don't emit anything...
uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
{
(void)dyn; (void)addr; (void)ninst;
if((nextop&0xC0)==0xC0)
return addr;
if(!(nextop&0xC0)) {
@@ -310,6 +315,8 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop)
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn)
{
(void)dyn;
#define PK(a) *(uint8_t*)(addr+a)
#define PK32(a) *(int32_t*)(addr+a)
@@ -332,4 +339,3 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
#undef PK32
#undef PK
}
+335 -67
View File
@@ -26,8 +26,10 @@
#include "dynarec_arm64_helper.h"
/* 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 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)
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
uint8_t ret = x2;
uint8_t scratch = x2;
*fixaddress = 0;
@@ -41,7 +43,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
uint8_t sib = F8;
int sib_reg = ((sib>>3)&7)+(rex.x<<3);
if((sib&0x7)==5) {
uint64_t tmp = F32S64;
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
MOV64x(scratch, tmp);
@@ -62,9 +64,21 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
}
} else if((nextop&7)==5) {
uint64_t tmp = F32S64;
MOV64x(ret, tmp);
GETIP(addr+delta);
ADDx_REG(ret, ret, xRIP);
if((tmp>=absmin) && (tmp<=absmax) && !(tmp&mask)) {
GETIP(addr+delta);
ret = xRIP;
*fixaddress = tmp;
} else if(tmp<0x1000) {
GETIP(addr+delta);
ADDx_U12(ret, xRIP, tmp);
} else if(tmp+addr+delta<0x1000000000000LL) { // 3 opcodes to load immediate is cheap enough
tmp += addr+delta;
MOV64x(ret, tmp);
} else {
MOV64x(ret, tmp);
GETIP(addr+delta);
ADDx_REG(ret, ret, xRIP);
}
} else {
ret = xRAX+(nextop&7)+(rex.b<<3);
}
@@ -140,9 +154,132 @@ 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, 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)
/* 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, int64_t* fixaddress, int absmax, uint32_t mask, rex_t rex, int s, int delta)
{
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(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) {
int64_t tmp = F32S;
if (sib_reg!=4) {
if(tmp && ((tmp<absmin) || (tmp>absmax) || (tmp&mask))) {
MOV64x(scratch, tmp);
ADDw_REG_LSL(ret, scratch, xRAX+sib_reg, (sib>>6));
} else {
LSLw(ret, xRAX+sib_reg, (sib>>6));
*fixaddress = tmp;
}
} else {
MOV64x(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, int64_t* fixaddress, int absmax, uint32_t mask, int s)
{
MAYUSE(dyn); MAYUSE(ninst);
uint8_t ret = x2;
uint8_t scratch = x3;
*fixaddress = 0;
@@ -151,7 +288,7 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
MAYUSE(scratch);
uint32_t m = nextop&0xC7;
uint32_t n = (m>>6)&3;
int32_t offset = 0;
int64_t offset = 0;
int absmin = 0;
if(s) absmin = -absmax;
if(!n && m==6) {
@@ -219,7 +356,9 @@ uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop,
void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MAYUSE(dyn); MAYUSE(ip); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Jump to epilog\n");
if(reg) {
if(reg!=xRIP) {
MOVx_REG(xRIP, reg);
@@ -233,6 +372,7 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst)
{
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Jump to next\n");
if(reg) {
@@ -263,12 +403,13 @@ 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)
{
MESSAGE(LOG_DUMP, "Ret next\n");
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Ret to epilog\n");
POP1(xRIP);
uintptr_t tbl = getJumpTable64();
MOV64x(x2, tbl);
@@ -281,12 +422,13 @@ 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)
{
MESSAGE(LOG_DUMP, "Retn epilog\n");
MAYUSE(dyn); MAYUSE(ninst);
MESSAGE(LOG_DUMP, "Retn to epilog\n");
POP1(xRIP);
if(n>0xfff) {
MOV32w(w1, n);
@@ -305,12 +447,14 @@ 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)
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits)
{
MESSAGE(LOG_DUMP, "IRet epilog\n");
#warning TODO: is64bits
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
// POP IP
POP1(xRIP);
// POP CS
@@ -331,12 +475,13 @@ void iret_to_epilog(dynarec_arm_t* dyn, int ninst)
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int savereg)
{
MAYUSE(fnc);
if(savereg==0)
savereg = 7;
if(saveflags) {
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
}
fpu_pushcache(dyn, ninst, reg);
fpu_pushcache(dyn, ninst, reg, 0);
if(ret!=-2) {
STPx_S7_preindex(xEmu, savereg, xSP, -16); // ARM64 stack needs to be 16byte aligned
STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller
@@ -366,17 +511,64 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
GO(R8, R9);
#undef GO
}
fpu_popcache(dyn, ninst, reg);
fpu_popcache(dyn, ninst, reg, 0);
if(saveflags) {
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
}
SET_NODF();
}
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w)
{
MAYUSE(fnc);
STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
fpu_pushcache(dyn, ninst, x3, 1);
// x9..x15, x16,x17,x18 those needs to be saved by caller
// RDI, RSI, RDX, RCX, R8, R9 are used for function call
STPx_S7_preindex(xEmu, xRBX, xSP, -16); // ARM64 stack needs to be 16byte aligned
STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP]));
// float and double args
if(abs(w)>1) {
MESSAGE(LOG_DUMP, "Getting %d XMM args\n", abs(w)-1);
for(int i=0; i<abs(w)-1; ++i) {
sse_get_reg(dyn, ninst, x7, i);
}
}
if(w<0) {
MESSAGE(LOG_DUMP, "Return in XMM0\n");
sse_get_reg_empty(dyn, ninst, x7, 0);
}
// prepare regs for native call
MOVx_REG(0, xRDI);
MOVx_REG(x1, xRSI);
MOVx_REG(x2, xRDX);
MOVx_REG(x3, xRCX);
MOVx_REG(x4, xR8);
MOVx_REG(x5, xR9);
// native call
TABLE64(16, (uintptr_t)fnc); // using x16 as scratch regs for call address
BLR(16);
// put return value in x86 regs
if(w>0) {
MOVx_REG(xRAX, 0);
MOVx_REG(xRDX, x1);
}
// all done, restore all regs
LDPx_S7_postindex(xEmu, xRBX, xSP, 16);
#define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
GO(RSP, RBP);
#undef GO
fpu_popcache(dyn, ninst, x3, 1);
LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));
SET_NODF();
}
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment)
{
int32_t j32;
MAYUSE(j32);
(void)addr;
int64_t j64;
MAYUSE(j64);
MESSAGE(LOG_DUMP, "Get %s Offset\n", (segment==_FS)?"FS":"GS");
int t1 = x1, t2 = x4;
if(reg==t1) ++t1;
@@ -400,45 +592,52 @@ void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int se
// x87 stuffs
static void x87_reset(dynarec_arm_t* dyn, int ninst)
{
(void)ninst;
#if STEP > 1
for (int i=0; i<8; ++i)
dyn->x87cache[i] = -1;
dyn->x87stack = 0;
#else
(void)dyn;
#endif
}
void x87_stackcount(dynarec_arm_t* dyn, int ninst, int scratch)
{
#if STEP > 1
MAYUSE(scratch);
if(!dyn->x87stack)
return;
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");
#else
(void)dyn; (void)ninst; (void)scratch;
#endif
}
int x87_do_push(dynarec_arm_t* dyn, int ninst)
{
(void)ninst;
#if STEP > 1
dyn->x87stack+=1;
// move all regs in cache, and find a free one
@@ -452,6 +651,7 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst)
}
return ret;
#else
(void)dyn;
return 0;
#endif
}
@@ -465,10 +665,13 @@ void x87_do_push_empty(dynarec_arm_t* dyn, int ninst, int s1)
++dyn->x87cache[i];
if(s1)
x87_stackcount(dyn, ninst, s1);
#else
(void)dyn; (void)ninst; (void)s1;
#endif
}
void x87_do_pop(dynarec_arm_t* dyn, int ninst)
{
(void)ninst;
#if STEP > 1
dyn->x87stack-=1;
// move all regs in cache, poping ST0
@@ -480,12 +683,16 @@ void x87_do_pop(dynarec_arm_t* dyn, int ninst)
dyn->x87reg[i] = -1;
}
}
#else
(void)dyn;
#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)
{
(void)ninst;
#if STEP > 1
MAYUSE(s1); MAYUSE(s2); MAYUSE(s3);
int ret = 0;
for (int i=0; i<8 && !ret; ++i)
if(dyn->x87cache[i] != -1)
@@ -498,15 +705,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 +721,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 +731,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,13 +747,15 @@ 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;
dyn->x87cache[i] = -1;
}
}
#else
(void)dyn; (void)s1; (void)s2; (void)s3;
#endif
}
@@ -554,6 +763,7 @@ static void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3
static void x87_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
MAYUSE(s2); MAYUSE(s3);
x87_stackcount(dyn, ninst, s1);
int ret = 0;
for (int i=0; (i<8) && (!ret); ++i)
@@ -569,16 +779,20 @@ 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);
}
#else
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)s3;
#endif
}
#endif
int x87_get_cache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
(void)ninst;
#if STEP > 1
MAYUSE(s1); MAYUSE(s2);
// search in cache first
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]==st)
@@ -601,13 +815,14 @@ 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);
return ret;
#else
(void)dyn; (void)s1; (void)s2; (void)st;
return 0;
#endif
}
@@ -617,6 +832,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
#if STEP > 1
return dyn->x87reg[x87_get_cache(dyn, ninst, s1, s2, a)];
#else
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)a;
return 0;
#endif
}
@@ -625,6 +841,7 @@ int x87_get_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a)
void x87_refresh(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
MAYUSE(s2);
x87_stackcount(dyn, ninst, s1);
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
@@ -640,16 +857,19 @@ 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);
#else
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
#endif
}
void x87_forget(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
#if STEP > 1
MAYUSE(s2);
x87_stackcount(dyn, ninst, s1);
int ret = -1;
for (int i=0; (i<8) && (ret==-1); ++i)
@@ -665,20 +885,24 @@ 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]);
dyn->x87cache[ret] = -1;
dyn->x87reg[ret] = -1;
#else
(void)dyn; (void)ninst; (void)s1; (void)s2; (void)st;
#endif
}
void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st)
{
(void)ninst;
#if STEP > 1
MAYUSE(s1); MAYUSE(s2);
// search in cache first
for (int i=0; i<8; ++i)
if(dyn->x87cache[i]==st) {
@@ -692,7 +916,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,59 +940,68 @@ 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);
#else
(void)dyn; (void)s1; (void)s2; (void)st;
#endif
}
static int round_map[] = {0, 2, 1, 3}; // map x64 -> arm round flag
// Set rounding according to cw flags, return reg to restore flags
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1); MAYUSE(s2);
LDRH_U12(s1, xEmu, offsetof(x64emu_t, cw));
UBFXx(s2, s1, 10, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
RBITw(s2, s1); // round is on bits 10-11 on x86,
LSRw(s2, s2, 20); // but we want the reverse of that
MRS_fpcr(s1); // get fpscr
MOVx_REG(s3, s1);
BFIx(s1, s2, 22, 2); // inject new round
VMSR(s1); // put new fpscr
BFIx(s1, s2, 22, 2); // inject new round
MSR_fpcr(s1); // put new fpscr
return s3;
}
// Set rounding according to mxcsr flags, return reg to restore flags
int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1); MAYUSE(s2);
LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr));
UBFXx(s2, s1, 13, 2); // extract round...
MOV64x(s1, (uintptr_t)round_map);
LDRw_REG_LSL2(s2, s1, s2);
VMRS(s1); // get fpscr
RBITw(s2, s1); // round is on bits 13-14 on x86,
LSRw(s2, s2, 17); // but we want the reverse of that
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
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1);
MSR_fpcr(s1); // put back fpscr
}
// MMX helpers
static void mmx_reset(dynarec_arm_t* dyn, int ninst)
{
(void)ninst;
#if STEP > 1
MAYUSE(dyn);
for (int i=0; i<8; ++i)
dyn->mmxcache[i] = -1;
#else
(void)dyn;
#endif
}
// get neon register for a MMX reg, create the entry if needed
int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
(void)ninst; (void)s1;
#if STEP > 1
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
@@ -776,24 +1009,28 @@ int mmx_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
VLDR64_U12(ret, xEmu, offsetof(x64emu_t, mmx87[a]));
return ret;
#else
(void)dyn; (void)a;
return 0;
#endif
}
// get neon register for a MMX reg, but don't try to synch it if it needed to be created
int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
(void)ninst; (void)s1;
#if STEP > 1
if(dyn->mmxcache[a]!=-1)
return dyn->mmxcache[a];
int ret = dyn->mmxcache[a] = fpu_get_reg_emm(dyn, a);
return ret;
#else
(void)dyn; (void)a;
return 0;
#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)
{
(void)ninst; (void)s1;
#if STEP > 1
int old = -1;
for (int i=0; i<8; ++i)
@@ -809,16 +1046,21 @@ static void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge MMX Cache\n");
}
#else
(void)dyn;
#endif
}
#ifdef HAVE_TRACE
static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
(void) ninst; (void)s1;
#if STEP > 1
for (int i=0; i<8; ++i)
if(dyn->mmxcache[i]!=-1) {
VLDR64_U12(dyn->mmxcache[i], xEmu, offsetof(x64emu_t, mmx87[i]));
}
#else
(void)dyn;
#endif
}
#endif
@@ -827,14 +1069,18 @@ static void mmx_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
// SSE / SSE2 helpers
static void sse_reset(dynarec_arm_t* dyn, int ninst)
{
(void)ninst;
#if STEP > 1
for (int i=0; i<16; ++i)
dyn->ssecache[i] = -1;
#else
(void)dyn;
#endif
}
// get neon register for a SSE reg, create the entry if needed
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
(void) ninst; (void)s1;
#if STEP > 1
if(dyn->ssecache[a]!=-1)
return dyn->ssecache[a];
@@ -842,24 +1088,28 @@ int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a)
VLDR128_U12(ret, xEmu, offsetof(x64emu_t, xmm[a]));
return ret;
#else
(void)dyn; (void)a;
return 0;
#endif
}
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
{
(void) ninst; (void)s1;
#if STEP > 1
if(dyn->ssecache[a]!=-1)
return dyn->ssecache[a];
int ret = dyn->ssecache[a] = fpu_get_reg_xmm(dyn, a);
return ret;
#else
(void)dyn; (void)a;
return 0;
#endif
}
// purge the SSE cache for XMM0..XMM7 (to use before function native call)
void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
{
(void) ninst; (void)s1;
#if STEP > 1
int old = -1;
for (int i=0; i<8; ++i)
@@ -875,12 +1125,15 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1)
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge XMM0..7 Cache\n");
}
#else
(void)dyn;
#endif
}
// purge the SSE cache only
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
{
(void) ninst; (void)s1;
#if STEP > 1
int old = -1;
for (int i=0; i<16; ++i)
@@ -896,55 +1149,68 @@ static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int s1)
if(old!=-1) {
MESSAGE(LOG_DUMP, "\t------ Purge SSE Cache\n");
}
#else
(void)dyn;
#endif
}
#ifdef HAVE_TRACE
static void sse_reflectcache(dynarec_arm_t* dyn, int ninst, int s1)
{
(void) ninst; (void)s1;
#if STEP > 1
for (int i=0; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
#else
(void)dyn;
#endif
}
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
(void) ninst; (void)s1;
#if STEP > 1
int start = not07?8:0;
// only SSE regs needs to be push back to xEmu
int n=0;
for (int i=0; i<16; i++)
for (int i=start; i<16; i++)
if(dyn->ssecache[i]!=-1)
++n;
if(!n)
return;
MESSAGE(LOG_DUMP, "\tPush XMM Cache (%d)------\n", n);
for (int i=0; i<16; ++i)
for (int i=start; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VSTR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
MESSAGE(LOG_DUMP, "\t------- Push XMM Cache (%d)\n", n);
#else
(void)dyn;
#endif
}
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07)
{
(void) ninst; (void)s1;
#if STEP > 1
int start = not07?8:0;
// only SSE regs needs to be pop back from xEmu
int n=0;
for (int i=0; i<16; i++)
for (int i=start; i<16; i++)
if(dyn->ssecache[i]!=-1)
++n;
if(!n)
return;
MESSAGE(LOG_DUMP, "\tPop XMM Cache (%d)------\n", n);
for (int i=0; i<16; ++i)
for (int i=start; i<16; ++i)
if(dyn->ssecache[i]!=-1) {
VLDR128_U12(dyn->ssecache[i], xEmu, offsetof(x64emu_t, xmm[i]));
}
MESSAGE(LOG_DUMP, "\t------- Pop XMM Cache (%d)\n", n);
#else
(void)dyn;
#endif
}
@@ -977,6 +1243,8 @@ void fpu_reset(dynarec_arm_t* dyn, int ninst)
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
{
MAYUSE(dyn); MAYUSE(ninst);
MAYUSE(s1); MAYUSE(s3); MAYUSE(s4);
// PF: (((emu->x64emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
ANDw_mask(s3, s1, 0b011011, 0b000010); // mask=0xE0
LSRw(s3, s3, 5);
@@ -986,4 +1254,4 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4)
LSRw_REG(s4, s4, s3);
MVNw_REG(s4, s4);
BFIw(xFlags, s4, F_PF, 1);
}
}
+190 -120
View File
@@ -47,7 +47,7 @@
ed = xRAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 3, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \
LDRx_U12(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -55,10 +55,20 @@
ed = xEAX+(nextop&7)+(rex.b<<3); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 2, rex, 0, D); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
LDRw_U12(x1, wback, fixedaddress); \
ed = x1; \
}
#define GETSEDw(D) if((nextop&0xC0)==0xC0) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
SXTWx(x1, ed); \
wb = x1; \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0xfff<<2, 3, rex, 0, D); \
LDRw_U12(x1, wback, fixedaddress); \
wb = ed = x1; \
}
//GETEDH can use hint for ed, and r1 or r2 for wback (depending on hint). wback is 0 if ed is xEAX..xEDI
#define GETEDH(hint, D) if(MODREG) { \
ed = xRAX+(nextop&7)+(rex.b<<3); \
@@ -166,19 +176,24 @@
ed = i; \
}
//GETEBO will use i for ed, i is also Offset, and can use r3 for wback.
#define GETEBO(i) if((nextop&0xC0)==0xC0) { \
wback = (nextop&7); \
wb2 = (wback>>2); \
wback = xEAX+(wback&3); \
UBFXx(i, wback, wb2, 8);\
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
#define GETEBO(i, D) if(MODREG) { \
if(rex.rex) { \
wback = xRAX+(nextop&7)+(rex.b<<3); \
wb2 = 0; \
} else { \
wback = (nextop&7); \
wb2 = (wback>>2)*8; \
wback = xRAX+(wback&3); \
} \
UBFXx(i, wback, wb2, 8); \
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, rex, 0, D); \
ADDx_REG(wback, wback, i); \
LDRB_U12(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
//GETSEB sign extend EB, will use i for ed, and can use r3 for wback.
#define GETSEB(i, D) if(MODREG) { \
@@ -211,7 +226,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); \
@@ -243,109 +258,126 @@
// R0 will not be pushed/popd if ret is -2. Flags are not save/restored
#define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0)
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = (uintptr_t)dyn->arm_size;}
#define MARK2 if(dyn->insts) {dyn->insts[ninst].mark2 = dyn->arm_size;}
#define GETMARK2 ((dyn->insts)?dyn->insts[ninst].mark2:(dyn->arm_size+4))
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = (uintptr_t)dyn->arm_size;}
#define MARK3 if(dyn->insts) {dyn->insts[ninst].mark3 = dyn->arm_size;}
#define GETMARK3 ((dyn->insts)?dyn->insts[ninst].mark3:(dyn->arm_size+4))
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = (uintptr_t)dyn->arm_size;}
#define MARKF if(dyn->insts) {dyn->insts[ninst].markf = dyn->arm_size;}
#define GETMARKF ((dyn->insts)?dyn->insts[ninst].markf:(dyn->arm_size+4))
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = (uintptr_t)dyn->arm_size;}
#define MARKSEG if(dyn->insts) {dyn->insts[ninst].markseg = dyn->arm_size;}
#define GETMARKSEG ((dyn->insts)?dyn->insts[ninst].markseg:(dyn->arm_size+4))
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = (uintptr_t)dyn->arm_size;}
#define MARKLOCK if(dyn->insts) {dyn->insts[ninst].marklock = dyn->arm_size;}
#define GETMARKLOCK ((dyn->insts)?dyn->insts[ninst].marklock:(dyn->arm_size+4))
// Branch to MARK if cond (use j32)
// Branch to MARK if cond (use j64)
#define B_MARK(cond) \
j32 = GETMARK-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK unconditionnal (use j32)
j64 = GETMARK-(dyn->arm_size); \
Bcond(cond, j64)
// Branch to MARK unconditionnal (use j64)
#define B_MARK_nocond \
j32 = GETMARK-(dyn->arm_size); \
B(j32)
// Branch to MARK if reg is not 0 (use j32)
j64 = GETMARK-(dyn->arm_size); \
B(j64)
// Branch to MARK if reg is 0 (use j64)
#define CBZxw_MARK(reg) \
j64 = GETMARK-(dyn->arm_size); \
CBZxw(reg, j64)
// Branch to MARK if reg is not 0 (use j64)
#define CBNZx_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
CBNZx(reg, j32)
// Branch to MARK if reg is not 0 (use j32)
j64 = GETMARK-(dyn->arm_size); \
CBNZx(reg, j64)
// Branch to MARK if reg is not 0 (use j64)
#define CBNZw_MARK(reg) \
j32 = GETMARK-(dyn->arm_size); \
CBNZw(reg, j32)
// Branch to MARK2 if cond (use j32)
j64 = GETMARK-(dyn->arm_size); \
CBNZw(reg, j64)
// Branch to MARK2 if cond (use j64)
#define B_MARK2(cond) \
j32 = GETMARK2-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK2 unconditionnal (use j32)
j64 = GETMARK2-(dyn->arm_size); \
Bcond(cond, j64)
// Branch to MARK2 unconditionnal (use j64)
#define B_MARK2_nocond \
j32 = GETMARK2-(dyn->arm_size); \
B(j32)
// Branch to MARK2 if reg is not 0 (use j32)
j64 = GETMARK2-(dyn->arm_size); \
B(j64)
// Branch to MARK2 if reg is not 0 (use j64)
#define CBNZx_MARK2(reg) \
j32 = GETMARK2-(dyn->arm_size); \
CBNZx(reg, j32)
j64 = GETMARK2-(dyn->arm_size); \
CBNZx(reg, j64)
// Test bit N of A and branch to MARK2 if set
#define TBNZ_MARK2(A, N) \
j32 = GETMARK2-(dyn->arm_size); \
TBNZ(A, N, j32)
// Branch to MARK3 if cond (use j32)
j64 = GETMARK2-(dyn->arm_size); \
TBNZ(A, N, j64)
// Branch to MARK3 if cond (use j64)
#define B_MARK3(cond) \
j32 = GETMARK3-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARK3 unconditionnal (use j32)
j64 = GETMARK3-(dyn->arm_size); \
Bcond(cond, j64)
// Branch to MARK3 unconditionnal (use j64)
#define B_MARK3_nocond \
j32 = GETMARK3-(dyn->arm_size); \
B(j32)
// Branch to MARK3 if reg is not 0 (use j32)
j64 = GETMARK3-(dyn->arm_size); \
B(j64)
// Branch to MARK3 if reg is not 0 (use j64)
#define CBNZx_MARK3(reg) \
j32 = GETMARK3-(dyn->arm_size); \
CBNZx(reg, j32)
j64 = GETMARK3-(dyn->arm_size); \
CBNZx(reg, j64)
// Test bit N of A and branch to MARK3 if set
#define TBNZ_MARK3(A, N) \
j32 = GETMARK3-(dyn->arm_size); \
TBNZ(A, N, j32)
j64 = GETMARK3-(dyn->arm_size); \
TBNZ(A, N, j64)
// Test bit N of A and branch to MARK3 if not set
#define TBZ_MARK3(A, N) \
j32 = GETMARK3-(dyn->arm_size); \
TBZ(A, N, j32)
// Branch to next instruction if cond (use j32)
j64 = GETMARK3-(dyn->arm_size); \
TBZ(A, N, j64)
// Branch to next instruction if cond (use j64)
#define B_NEXT(cond) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
Bcond(cond, j32)
// Branch to next instruction unconditionnal (use j32)
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
Bcond(cond, j64)
// Branch to next instruction unconditionnal (use j64)
#define B_NEXT_nocond \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
B(j32)
// Branch to next instruction if reg is 0 (use j32)
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0;\
B(j64)
// Branch to next instruction if reg is 0 (use j64)
#define CBZw_NEXT(reg) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZw(reg, j32)
// Branch to next instruction if reg is 0 (use j32)
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZw(reg, j64)
// Branch to next instruction if reg is 0 (use j64)
#define CBZx_NEXT(reg) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZx(reg, j32)
// Branch to MARKSEG if cond (use j32)
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBZx(reg, j64)
// Branch to next instruction if reg is not 0 (use j64)
#define CBNZx_NEXT(reg) \
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
CBNZx(reg, j64)
// Test bit N of A and branch to next instruction if not set
#define TBZ_NEXT(A, N) \
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
TBZ(A, N, j64)
// Test bit N of A and branch to next instruction if set
#define TBNZ_NEXT(A, N) \
j64 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \
TBNZ(A, N, j64)
// Branch to MARKSEG if cond (use j64)
#define B_MARKSEG(cond) \
j32 = GETMARKSEG-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARKSEG if reg is 0 (use j32)
j64 = GETMARKSEG-(dyn->arm_size); \
Bcond(cond, j64)
// Branch to MARKSEG if reg is 0 (use j64)
#define CBZw_MARKSEG(reg) \
j32 = GETMARKSEG-(dyn->arm_size); \
CBZw(reg, j32)
// Branch to MARKSEG if reg is not 0 (use j32)
j64 = GETMARKSEG-(dyn->arm_size); \
CBZw(reg, j64)
// Branch to MARKSEG if reg is not 0 (use j64)
#define CBNZw_MARKSEG(reg) \
j32 = GETMARKSEG-(dyn->arm_size); \
CBNZw(reg, j32)
// Branch to MARKLOCK if cond (use j32)
j64 = GETMARKSEG-(dyn->arm_size); \
CBNZw(reg, j64)
// Branch to MARKLOCK if cond (use j64)
#define B_MARKLOCK(cond) \
j32 = GETMARKLOCK-(dyn->arm_size); \
Bcond(cond, j32)
// Branch to MARKLOCK if reg is not 0 (use j32)
j64 = GETMARKLOCK-(dyn->arm_size); \
Bcond(cond, j64)
// Branch to MARKLOCK if reg is not 0 (use j64)
#define CBNZx_MARKLOCK(reg) \
j32 = GETMARKLOCK-(dyn->arm_size); \
CBNZx(reg, j32)
j64 = GETMARKLOCK-(dyn->arm_size); \
CBNZx(reg, j64)
#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 +385,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 +422,8 @@
#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 LDP_REGS(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A]))
#define STORE_XEMU_REGS(A) \
STORE_REG(RAX); \
STORE_REG(RCX); \
@@ -445,15 +479,26 @@
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));}
#define LOAD_XEMU_CALL(A) \
#define LOAD_XEMU_CALL(A) \
if(A) {LDPx_S7_offset(xFlags, A, xEmu, offsetof(x64emu_t, eflags));} \
else {LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags));}; \
if(A==xRIP) dyn->last_ip = 0
#define LOAD_XEMU_REM() \
LDP_REGS(R10, R11); \
LDP_REGS(R12, R13); \
LDP_REGS(R14, R15)
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVZw(S, d_none); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=1;}
#define SET_DF(S, N) if((N)!=d_none) {MOVZw(S, (N)); STRw_U12(S, xEmu, offsetof(x64emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->dfnone = 0
@@ -461,11 +506,11 @@
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET) { \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
if(dyn->state_flags!=SF_PENDING) { \
LDRw_U12(x3, xEmu, offsetof(x64emu_t, df)); \
j32 = (GETMARKF)-(dyn->arm_size); \
CBZw(x3, j32); \
j64 = (GETMARKF)-(dyn->arm_size); \
CBZw(x3, j64); \
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
@@ -475,9 +520,11 @@
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)|X_PEND)))) \
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A))); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET:B
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x64.need_flags&(~((A)/*|X_PEND*/)))) \
READFLAGS(dyn->insts[ninst].x64.need_flags&(~(A)|X_PEND)); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
((B==SF_SET_PENDING && !(dyn->insts[ninst].x64.need_flags&X_PEND)?SF_SET:B))
#endif
#ifndef JUMP
#define JUMP(A)
@@ -503,6 +550,9 @@
#ifndef TABLE64
#define TABLE64(A, V)
#endif
#ifndef FTABLE64
#define FTABLE64(A, V)
#endif
#if STEP < 2
#define GETIP(A)
@@ -518,14 +568,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,18 +622,21 @@ 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 geted16 STEPNAME(geted16_)
#define jump_to_epilog STEPNAME(jump_to_epilog_)
#define jump_to_next STEPNAME(jump_to_next_)
#define ret_to_epilog STEPNAME(ret_to_epilog_)
#define retn_to_epilog STEPNAME(retn_to_epilog_)
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define grab_segdata STEPNAME(grab_segdata_)
#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)
#define ret_to_epilog STEPNAME(ret_to_epilog)
#define retn_to_epilog STEPNAME(retn_to_epilog)
#define iret_to_epilog STEPNAME(iret_to_epilog)
#define call_c STEPNAME(call_c)
#define call_n STEPNAME(call_n)
#define grab_segdata STEPNAME(grab_segdata)
#define emit_cmp8 STEPNAME(emit_cmp8)
#define emit_cmp16 STEPNAME(emit_cmp16)
#define emit_cmp32 STEPNAME(emit_cmp32)
@@ -672,15 +731,20 @@ 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
/* 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);
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* 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);
uintptr_t geted32(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* 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, int64_t* fixaddress, int absmax, uint32_t mask, int s);
// generic x64 helper
@@ -688,8 +752,9 @@ void jump_to_epilog(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void jump_to_next(dynarec_arm_t* dyn, uintptr_t ip, int reg, int ninst);
void ret_to_epilog(dynarec_arm_t* dyn, int ninst);
void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is64bits);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg);
void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w);
void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
@@ -758,8 +823,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, in
void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int32_t c, int s3, int s4);
//void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
//void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int32_t c, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
@@ -808,28 +873,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);
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1, int not07);
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_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, 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);
@@ -941,4 +1011,4 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
, cNE, cEQ, X_SF|X_OF|X_ZF) \
break
#endif //__DYNAREC_ARM64_HELPER_H__
#endif //__DYNAREC_ARM64_HELPER_H__
+39 -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,25 @@ 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);
}
while(pk==0x3E) { //Branch Taken Hint ignored
++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 +115,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 +136,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);}
+3 -2
View File
@@ -28,7 +28,7 @@ typedef struct dynarec_arm_s {
uint32_t isize; // size in byte of x64 instructions included
void* block; // memory pointer where next instruction is emited
uintptr_t arm_start; // start of the arm code
int arm_size; // size of emitted arm code
size_t arm_size; // size of emitted arm code
int state_flags;// actual state for on-demand flags
uintptr_t last_ip; // last set IP in RIP (or NULL if unclean state)
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
@@ -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;
@@ -58,4 +59,4 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
int Table64(dynarec_arm_t *dyn, uint64_t val); // add a value to etable64 (if needed) and gives back the imm19 to use in LDR_literal
#endif //__DYNAREC_ARM_PRIVATE_H_
#endif //__DYNAREC_ARM_PRIVATE_H_
+3 -2
View File
@@ -15,8 +15,9 @@
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_MAYSET 3
#define SF_SUBSET 4
#define SF_SET_PENDING 3
#define SF_MAYSET 4
#define SF_SUBSET 5
typedef struct instruction_x64_s {
uintptr_t addr; //address of the instruction
+68 -65
View File
@@ -225,13 +225,14 @@ const char* DumpRelType(int t)
return buff;
}
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym)
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version)
{
static char buff[4096];
const char* vername = (version==-1)?"(none)":((version==0)?"*local*":((version==1)?"*global*":GetSymbolVersion(h, version)));
memset(buff, 0, sizeof(buff));
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d",
sprintf(buff, "\"%s\", value=%p, size=%ld, info/other=%d/%d index=%d (ver=%d/%s)",
h->DynStr+sym->st_name, (void*)sym->st_value, sym->st_size,
sym->st_info, sym->st_other, sym->st_shndx);
sym->st_info, sym->st_other, sym->st_shndx, version, vername);
return buff;
}
@@ -246,116 +247,118 @@ const char* IdxSymName(elfheader_t *h, int sym)
void DumpMainHeader(Elf64_Ehdr *header, elfheader_t *h)
{
if(box64_log>=LOG_DUMP) {
printf_log(LOG_DUMP, "ELF Dump main header\n");
printf_log(LOG_DUMP, " Entry point = %p\n", (void*)header->e_entry);
printf_log(LOG_DUMP, " Program Header table offset = %p\n", (void*)header->e_phoff);
printf_log(LOG_DUMP, " Section Header table offset = %p\n", (void*)header->e_shoff);
printf_log(LOG_DUMP, " Flags = 0x%X\n", header->e_flags);
printf_log(LOG_DUMP, " ELF Header size = %d\n", header->e_ehsize);
printf_log(LOG_DUMP, " Program Header Entry num/size = %d(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
printf_log(LOG_DUMP, " Section Header Entry num/size = %d(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
printf_log(LOG_DUMP, " Section Header index num = %d(%d)\n", h->SHIdx, header->e_shstrndx);
printf_log(LOG_DUMP, "ELF Dump ==========\n");
if(box64_dump) {
printf_dump(LOG_NEVER, "ELF Dump main header\n");
printf_dump(LOG_NEVER, " Entry point = %p\n", (void*)header->e_entry);
printf_dump(LOG_NEVER, " Program Header table offset = %p\n", (void*)header->e_phoff);
printf_dump(LOG_NEVER, " Section Header table offset = %p\n", (void*)header->e_shoff);
printf_dump(LOG_NEVER, " Flags = 0x%X\n", header->e_flags);
printf_dump(LOG_NEVER, " ELF Header size = %d\n", header->e_ehsize);
printf_dump(LOG_NEVER, " Program Header Entry num/size = %zu(%d)/%d\n", h->numPHEntries, header->e_phnum, header->e_phentsize);
printf_dump(LOG_NEVER, " Section Header Entry num/size = %zu(%d)/%d\n", h->numSHEntries, header->e_shnum, header->e_shentsize);
printf_dump(LOG_NEVER, " Section Header index num = %zu(%d)\n", h->SHIdx, header->e_shstrndx);
printf_dump(LOG_NEVER, "ELF Dump ==========\n");
printf_log(LOG_DUMP, "ELF Dump PEntries (%d)\n", h->numSHEntries);
for (int i=0; i<h->numPHEntries; ++i)
printf_log(LOG_DUMP, " PHEntry %04d : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_log(LOG_DUMP, "ELF Dump PEntries ====\n");
printf_dump(LOG_NEVER, "ELF Dump PEntries (%zu)\n", h->numPHEntries);
for (size_t i=0; i<h->numPHEntries; ++i)
printf_dump(LOG_NEVER, " PHEntry %04zu : %s\n", i, DumpPHEntry(h->PHEntries+i));
printf_dump(LOG_NEVER, "ELF Dump PEntries ====\n");
printf_log(LOG_DUMP, "ELF Dump Sections (%d)\n", h->numSHEntries);
for (int i=0; i<h->numSHEntries; ++i)
printf_log(LOG_DUMP, " Section %04d : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_log(LOG_DUMP, "ELF Dump Sections ====\n");
printf_dump(LOG_NEVER, "ELF Dump Sections (%zu)\n", h->numSHEntries);
for (size_t i=0; i<h->numSHEntries; ++i)
printf_dump(LOG_NEVER, " Section %04zu : %s\n", i, DumpSection(h->SHEntries+i, h->SHStrTab));
printf_dump(LOG_NEVER, "ELF Dump Sections ====\n");
}
}
void DumpSymTab(elfheader_t *h)
{
if(box64_log>=LOG_DUMP && h->SymTab) {
if(box64_dump && h->SymTab) {
const char* name = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump SymTab(%d)=\n", h->numSymTab);
for (int i=0; i<h->numSymTab; ++i)
printf_log(LOG_DUMP, " %s:SymTab[%d] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
printf_dump(LOG_NEVER, "ELF Dump SymTab(%zu)=\n", h->numSymTab);
for (size_t i=0; i<h->numSymTab; ++i)
printf_dump(LOG_NEVER, " %s:SymTab[%zu] = \"%s\", value=%p, size=%ld, info/other=%d/%d index=%d\n", name,
i, h->StrTab+h->SymTab[i].st_name, (void*)h->SymTab[i].st_value, h->SymTab[i].st_size,
h->SymTab[i].st_info, h->SymTab[i].st_other, h->SymTab[i].st_shndx);
printf_log(LOG_DUMP, "ELF Dump SymTab=====\n");
printf_dump(LOG_NEVER, "ELF Dump SymTab=====\n");
}
}
void DumpDynamicSections(elfheader_t *h)
{
if(box64_log>=LOG_DUMP && h->Dynamic) {
printf_log(LOG_DUMP, "ELF Dump Dynamic(%d)=\n", h->numDynamic);
for (int i=0; i<h->numDynamic; ++i)
printf_log(LOG_DUMP, " Dynamic %04d : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_log(LOG_DUMP, "ELF Dump Dynamic=====\n");
if(box64_dump && h->Dynamic) {
printf_dump(LOG_NEVER, "ELF Dump Dynamic(%zu)=\n", h->numDynamic);
for (size_t i=0; i<h->numDynamic; ++i)
printf_dump(LOG_NEVER, " Dynamic %04zu : %s\n", i, DumpDynamic(h->Dynamic+i));
printf_dump(LOG_NEVER, "ELF Dump Dynamic=====\n");
}
}
void DumpDynSym(elfheader_t *h)
{
if(box64_log>=LOG_DUMP && h->DynSym) {
if(box64_dump && h->DynSym) {
const char* name = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump DynSym(%d)=\n", h->numDynSym);
for (int i=0; i<h->numDynSym; ++i)
printf_log(LOG_DUMP, " %s:DynSym[%d] = %s\n", name, i, DumpSym(h, h->DynSym+i));
printf_log(LOG_DUMP, "ELF Dump DynSym=====\n");
printf_dump(LOG_NEVER, "ELF Dump DynSym(%zu)=\n", h->numDynSym);
for (size_t i=0; i<h->numDynSym; ++i) {
int version = h->VerSym?((Elf64_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
printf_dump(LOG_NEVER, " %s:DynSym[%zu] = %s\n", name, i, DumpSym(h, h->DynSym+i, version));
}
printf_dump(LOG_NEVER, "ELF Dump DynSym=====\n");
}
}
void DumpDynamicNeeded(elfheader_t *h)
{
if(box64_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
for (int i=0; i<h->numDynamic; ++i)
if(box64_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
for (size_t i=0; i<h->numDynamic; ++i)
if(h->Dynamic[i].d_tag==DT_NEEDED) {
printf_log(LOG_DUMP, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " Needed : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
printf_log(LOG_DUMP, "ELF Dump DT_NEEDED=====\n");
printf_dump(LOG_NEVER, "ELF Dump DT_NEEDED=====\n");
}
}
void DumpDynamicRPath(elfheader_t *h)
{
if(box64_log>=LOG_DUMP && h->DynStrTab) {
printf_log(LOG_DUMP, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (int i=0; i<h->numDynamic; ++i) {
if(box64_dump && h->DynStrTab) {
printf_dump(LOG_NEVER, "ELF Dump DT_RPATH/DT_RUNPATH=====\n");
for (size_t i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag==DT_RPATH) {
printf_log(LOG_DUMP, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " RPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
if(h->Dynamic[i].d_tag==DT_RUNPATH) {
printf_log(LOG_DUMP, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
printf_dump(LOG_NEVER, " RUNPATH : %s\n", h->DynStrTab+h->Dynamic[i].d_un.d_val + h->delta);
}
}
printf_log(LOG_DUMP, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
printf_dump(LOG_NEVER, "=====ELF Dump DT_RPATH/DT_RUNPATH\n");
}
}
void DumpRelTable(elfheader_t *h, int cnt, Elf64_Rel *rel, const char* name)
{
if(box64_log>=LOG_DUMP) {
if(box64_dump) {
const char* elfname = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
printf_dump(LOG_NEVER, "ELF Dump %s Table(%d) @%p\n", name, cnt, rel);
for (int i = 0; i<cnt; ++i)
printf_log(LOG_DUMP, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
printf_dump(LOG_NEVER, " %s:Rel[%d] = %p (0x%lX: %s, sym=0x%0lX/%s)\n", elfname,
i, (void*)rel[i].r_offset, rel[i].r_info, DumpRelType(ELF64_R_TYPE(rel[i].r_info)),
ELF64_R_SYM(rel[i].r_info), IdxSymName(h, ELF64_R_SYM(rel[i].r_info)));
printf_log(LOG_DUMP, "ELF Dump Rel Table=====\n");
printf_dump(LOG_NEVER, "ELF Dump Rel Table=====\n");
}
}
void DumpRelATable(elfheader_t *h, int cnt, Elf64_Rela *rela, const char* name)
{
if(box64_log>=LOG_DUMP && h->rela) {
if(box64_dump && h->rela) {
const char* elfname = ElfName(h);
printf_log(LOG_DUMP, "ELF Dump %s Table(%d) @%p\n", name, cnt, rela);
printf_dump(LOG_NEVER, "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_dump(LOG_NEVER, " %s:%s[%d] = %p (0x%lX: %s, sym=0x%lX/%s) Addend=0x%lx\n", elfname, name,
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);
printf_log(LOG_DUMP, "ELF Dump RelA Table=====\n");
printf_dump(LOG_NEVER, "ELF Dump %s Table=====\n", name);
}
}
@@ -366,24 +369,24 @@ void DumpBinary(char* p, int sz)
unsigned char* d = (unsigned char*)p;
int delta = ((uintptr_t)p)&0xf;
for (int i = 0; sz; ++i) {
printf_log(LOG_DUMP, "%p ", (void*)(((uintptr_t)d)&~0xf));
printf_dump(LOG_NEVER, "%p ", (void*)(((uintptr_t)d)&~0xf));
int n = 16 - delta;
if (n>sz) n = sz;
int fill = 16-sz;
for (int j = 0; j<delta; ++j)
printf_log(LOG_DUMP, " ");
printf_dump(LOG_NEVER, " ");
for (int j = 0; j<n; ++j)
printf_log(LOG_DUMP, "%02X ", d[j]);
printf_dump(LOG_NEVER, "%02X ", d[j]);
for (int j = 0; j<fill; ++j)
printf_log(LOG_DUMP, " ");
printf_log(LOG_DUMP, " | ");
printf_dump(LOG_NEVER, " ");
printf_dump(LOG_NEVER, " | ");
for (int j = 0; j<delta; ++j)
printf_log(LOG_DUMP, " ");
printf_dump(LOG_NEVER, " ");
for (int j = 0; j<n; ++j)
printf_log(LOG_DUMP, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
printf_dump(LOG_NEVER, "%c", (d[j]<32 || d[j]>127)?'.':d[j]);
for (int j = 0; j<fill; ++j)
printf_log(LOG_DUMP, " ");
printf_log(LOG_DUMP, "\n");
printf_dump(LOG_NEVER, " ");
printf_dump(LOG_NEVER, "\n");
d+=n;
sz-=n;
delta=0;
+408 -214
View File
File diff suppressed because it is too large. Load diff
+25 -20
View File
@@ -13,23 +13,28 @@ typedef struct needed_libs_s needed_libs_t;
struct elfheader_s {
char* name;
char* path; // Resolved path to file
int numPHEntries;
size_t numPHEntries;
Elf64_Phdr *PHEntries;
int numSHEntries;
size_t numSHEntries;
Elf64_Shdr *SHEntries;
int SHIdx;
int numSST;
size_t SHIdx;
size_t numSST;
char* SHStrTab;
char* StrTab;
Elf64_Sym* SymTab;
int numSymTab;
size_t numSymTab;
char* DynStr;
Elf64_Sym* DynSym;
int numDynSym;
size_t numDynSym;
Elf64_Dyn* Dynamic;
int numDynamic;
size_t numDynamic;
char* DynStrTab;
int szDynStrTab;
size_t szDynStrTab;
Elf64_Half* VerSym;
Elf64_Verneed* VerNeed;
int szVerNeed;
Elf64_Verdef* VerDef;
int szVerDef;
int e_type;
intptr_t delta; // should be 0
@@ -37,19 +42,19 @@ struct elfheader_s {
uintptr_t entrypoint;
uintptr_t initentry;
uintptr_t initarray;
int initarray_sz;
size_t initarray_sz;
uintptr_t finientry;
uintptr_t finiarray;
int finiarray_sz;
size_t finiarray_sz;
uintptr_t rel;
int relsz;
size_t relsz;
int relent;
uintptr_t rela;
int relasz;
size_t relasz;
int relaent;
uintptr_t jmprel;
int pltsz;
size_t pltsz;
int pltent;
uint64_t pltrel;
uintptr_t gotplt;
@@ -60,18 +65,18 @@ struct elfheader_s {
uintptr_t plt;
uintptr_t plt_end;
uintptr_t text;
int textsz;
size_t textsz;
uintptr_t paddr;
uintptr_t vaddr;
int align;
size_t align;
uint64_t memsz;
uint64_t stacksz;
int stackalign;
uint32_t tlssize;
int tlsalign;
size_t stackalign;
uint64_t tlssize;
size_t tlsalign;
int32_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
int64_t tlsbase; // the base of the tlsdata in the global tlsdata (always negative)
int init_done;
int fini_done;
@@ -133,4 +138,4 @@ struct elfheader_s {
elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec);
#endif //__ELFLOADER_PRIVATE_H_
#endif //__ELFLOADER_PRIVATE_H_
+146 -67
View File
@@ -43,7 +43,7 @@ int FindSection(Elf64_Shdr *s, int n, char* SHStrTab, const char* name)
return 0;
}
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
void LoadNamedSection(FILE *f, Elf64_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, size_t* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
@@ -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]);
}
@@ -136,7 +141,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
printf_log(LOG_DEBUG, "Read %zu Section header\n", h->numSHEntries);
h->SHEntries = (Elf64_Shdr*)calloc(h->numSHEntries, sizeof(Elf64_Shdr));
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf64_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
@@ -152,7 +157,7 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
}
}
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
printf_log(LOG_DEBUG, "Read %zu Program header\n", h->numPHEntries);
h->PHEntries = (Elf64_Phdr*)calloc(h->numPHEntries, sizeof(Elf64_Phdr));
fseeko64(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf64_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
@@ -167,68 +172,125 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->SHIdx = h->SHEntries[0].sh_link;
}
if(h->SHIdx > h->numSHEntries) {
printf_log(LOG_INFO, "Incoherent Section String Table Index : %d / %d\n", h->SHIdx, h->numSHEntries);
printf_log(LOG_INFO, "Incoherent Section String Table Index : %zu / %zu\n", h->SHIdx, h->numSHEntries);
FreeElfHeader(&h);
return NULL;
}
// load Section table
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
printf_log(LOG_DEBUG, "Loading Sections Table String (idx = %zu)\n", h->SHIdx);
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
FreeElfHeader(&h);
return NULL;
}
if(box64_log>=LOG_DUMP) DumpMainHeader(&header, h);
if(box64_dump) DumpMainHeader(&header, h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".strtab", "SymTab Strings", SHT_STRTAB, (void**)&h->StrTab, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".symtab", "SymTab", SHT_SYMTAB, (void**)&h->SymTab, &h->numSymTab);
if(box64_log>=LOG_DUMP && h->SymTab) DumpSymTab(h);
if(box64_dump && h->SymTab) DumpSymTab(h);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynamic", "Dynamic", SHT_DYNAMIC, (void**)&h->Dynamic, &h->numDynamic);
if(box64_log>=LOG_DUMP && h->Dynamic) DumpDynamicSections(h);
if(box64_dump && h->Dynamic) DumpDynamicSections(h);
// grab DT_REL & DT_RELA stuffs
// also grab the DT_STRTAB string table
{
for (int i=0; i<h->numDynamic; ++i) {
if(h->Dynamic[i].d_tag == DT_REL)
h->rel = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELSZ)
h->relsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELENT)
h->relent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELA)
h->rela = h->Dynamic[i].d_un.d_ptr;
else if(h->Dynamic[i].d_tag == DT_RELASZ)
h->relasz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_RELAENT)
h->relaent = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTGOT)
h->pltgot = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTREL)
h->pltrel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_PLTRELSZ)
h->pltsz = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_JMPREL)
h->jmprel = h->Dynamic[i].d_un.d_val;
else if(h->Dynamic[i].d_tag == DT_STRTAB)
h->DynStrTab = (char*)(h->Dynamic[i].d_un.d_ptr);
else if(h->Dynamic[i].d_tag == DT_STRSZ)
h->szDynStrTab = h->Dynamic[i].d_un.d_val;
for (size_t i=0; i<h->numDynamic; ++i) {
Elf64_Dyn d = h->Dynamic[i];
Elf64_Word val = d.d_un.d_val;
Elf64_Addr ptr = d.d_un.d_ptr;
switch (d.d_tag) {
case DT_REL:
h->rel = ptr;
break;
case DT_RELSZ:
h->relsz = val;
break;
case DT_RELENT:
h->relent = val;
break;
case DT_RELA:
h->rela = ptr;
break;
case DT_RELASZ:
h->relasz = val;
break;
case DT_RELAENT:
h->relaent = val;
break;
case DT_PLTGOT:
h->pltgot = ptr;
break;
case DT_PLTREL:
h->pltrel = val;
break;
case DT_PLTRELSZ:
h->pltsz = val;
break;
case DT_JMPREL:
h->jmprel = ptr;
break;
case DT_STRTAB:
h->DynStrTab = (char*)(ptr);
break;
case DT_STRSZ:
h->szDynStrTab = val;
break;
case DT_INIT: // Entry point
h->initentry = ptr;
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
break;
case DT_INIT_ARRAY:
h->initarray = ptr;
printf_log(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
break;
case DT_INIT_ARRAYSZ:
h->initarray_sz = val / sizeof(Elf64_Addr);
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %zu\n", h->initarray_sz);
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
break;
case DT_FINI_ARRAY:
h->finiarray = ptr;
printf_log(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
break;
case DT_FINI_ARRAYSZ:
h->finiarray_sz = val / sizeof(Elf64_Addr);
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %zu\n", h->finiarray_sz);
break;
case DT_VERNEEDNUM:
h->szVerNeed = val;
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
break;
case DT_VERNEED:
h->VerNeed = (Elf64_Verneed*)ptr;
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
break;
case DT_VERDEFNUM:
h->szVerDef = val;
printf_log(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
break;
case DT_VERDEF:
h->VerDef = (Elf64_Verdef*)ptr;
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
}
}
if(h->rel) {
if(h->relent != sizeof(Elf64_Rel)) {
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%lx)\n", h->relent, sizeof(Elf64_Rel));
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%zx)\n", h->relent, sizeof(Elf64_Rel));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
printf_log(LOG_DEBUG, "Rel Table @%p (0x%zx/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
}
if(h->rela) {
if(h->relaent != sizeof(Elf64_Rela)) {
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%lx)\n", h->relaent, sizeof(Elf64_Rela));
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%zx)\n", h->relaent, sizeof(Elf64_Rela));
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
printf_log(LOG_DEBUG, "RelA Table @%p (0x%zx/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
}
if(h->jmprel) {
if(h->pltrel == DT_REL) {
@@ -236,16 +298,16 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
} else if(h->pltrel == DT_RELA) {
h->pltent = sizeof(Elf64_Rela);
} else {
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%ld)\n", h->pltsz, h->pltrel);
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%zx, type=%ld)\n", h->pltsz, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
if((h->pltsz / h->pltent)*h->pltent != h->pltsz) {
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
printf_log(LOG_NONE, "PLT Table Entry size invalid (0x%zx, ent=0x%x, type=%ld)\n", h->pltsz, h->pltent, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
printf_log(LOG_DEBUG, "PLT Table @%p (type=%ld 0x%zx/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
}
if(h->DynStrTab && h->szDynStrTab) {
//DumpDynamicNeeded(h); cannot dump now, it's not loaded yet
@@ -270,44 +332,61 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// look for .init entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init");
// grab version of symbols
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
if(ii) {
h->initentry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .init is at address %p\n", (void*)h->initentry);
}
// and .init_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".init_array");
if(ii) {
h->initarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
h->initarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .init_array is at address %p, and have %d elements\n", (void*)h->initarray, h->initarray_sz);
}
// look for .fini entry point
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini");
if(ii) {
h->finientry = h->SHEntries[ii].sh_addr;
printf_log(LOG_DEBUG, "The .fini is at address %p\n", (void*)h->finientry);
}
// and .fini_array
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".fini_array");
if(ii) {
h->finiarray_sz = h->SHEntries[ii].sh_size / sizeof(Elf64_Addr);
h->finiarray = (uintptr_t)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .fini_array is at address %p, and have %d elements\n", (void*)h->finiarray, h->finiarray_sz);
h->VerSym = (Elf64_Half*)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
}
// grab .text for main code
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".text");
if(ii) {
h->text = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->textsz = h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
printf_log(LOG_DEBUG, "The .text is at address %p, and is %zu big\n", (void*)h->text, h->textsz);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynsym", "DynSym", SHT_DYNSYM, (void**)&h->DynSym, &h->numDynSym);
if(box64_log>=LOG_DUMP && h->DynSym) DumpDynSym(h);
}
return h;
}
const char* GetSymbolVersion(elfheader_t* h, int version)
{
if(!h->VerNeed || (version<2))
return NULL;
/*if(version==1)
return "*";*/
Elf64_Verneed *ver = (Elf64_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf64_Vernaux *aux = (Elf64_Vernaux*)((uintptr_t)ver + ver->vn_aux);
for(int j=0; j<ver->vn_cnt; ++j) {
if(aux->vna_other==version)
return h->DynStr+aux->vna_name;
aux = (Elf64_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf64_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
const char* GetParentSymbolVersion(elfheader_t* h, int index)
{
if(!h->VerDef || (index<1))
return NULL;
Elf64_Verdef *def = (Elf64_Verdef*)((uintptr_t)h->VerDef + h->delta);
while(def) {
if(def->vd_ndx==index) {
if(def->vd_cnt<1)
return NULL;
/*if(def->vd_flags&VER_FLG_BASE)
return NULL;*/
Elf64_Verdaux *aux = (Elf64_Verdaux*)((uintptr_t)def + def->vd_aux);
return h->DynStr+aux->vda_name; // return Parent, so 1st aux
}
def = def->vd_next?((Elf64_Verdef*)((uintptr_t)def + def->vd_next)):NULL;
}
return NULL;
}
+5
View File
@@ -1,6 +1,7 @@
#define F8 *(uint8_t*)(R_RIP++)
#define F8S *(int8_t*)(R_RIP++)
#define F16 *(uint16_t*)(R_RIP+=2, R_RIP-2)
#define F16S *(int16_t*)(R_RIP+=2, R_RIP-2)
#define F32 *(uint32_t*)(R_RIP+=4, R_RIP-4)
#define F32S *(int32_t*)(R_RIP+=4, R_RIP-4)
#define F32S64 (uint64_t)(int64_t)F32S
@@ -18,12 +19,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)
+58 -18
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
@@ -105,8 +109,10 @@ EXPORTDYN
void SetupX64Emu(x64emu_t *emu)
{
printf_log(LOG_DEBUG, "Setup X86_64 Emu\n");
(void)emu; // Not doing much here...
}
#ifdef HAVE_TRACE
void SetTraceEmu(uintptr_t start, uintptr_t end)
{
if(my_context->zydis) {
@@ -121,9 +127,12 @@ void SetTraceEmu(uintptr_t start, uintptr_t end)
trace_start = start;
trace_end = end;
}
#endif
void AddCleanup(x64emu_t *emu, void *p)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -135,6 +144,8 @@ void AddCleanup(x64emu_t *emu, void *p)
void AddCleanup1Arg(x64emu_t *emu, void *p, void* a)
{
(void)emu;
if(my_context->clean_sz == my_context->clean_cap) {
my_context->clean_cap += 4;
my_context->cleanups = (cleanup_t*)realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
@@ -173,7 +184,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 +323,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 +345,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 +359,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 +380,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 +420,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)
@@ -440,18 +478,20 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
uint64_t ReadTSC(x64emu_t* emu)
{
//TODO: implement hardware counter read?
(void)emu;
//TODO: implement hardware counter read? (only available in kernel space?)
// 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 +500,4 @@ void ResetSegmentsCache(x64emu_t *emu)
if(!emu)
return;
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
}
}
+6 -4
View File
@@ -30,7 +30,8 @@ typedef struct x64emu_s {
reg64_t regs[16];
x64flags_t eflags;
reg64_t ip;
uintptr_t old_ip;
// sse
sse_regs_t xmm[16];
// fpu / mmx
mmx87_regs_t mmx87[8];
uint16_t cw,cw_mask_all;
@@ -42,8 +43,8 @@ typedef struct x64emu_s {
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
// sse
sse_regs_t xmm[16];
// old ip
uintptr_t old_ip;
// defered flags
int dummy1; // to align on 64bits with df
defered_flags_t df;
@@ -52,6 +53,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 +93,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_
+109 -13
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"
@@ -91,21 +92,116 @@ void x64Int3(x64emu_t* emu)
char *tmp;
int post = 0;
int perr = 0;
uint32_t *pu32 = NULL;
uint64_t *pu64 = NULL;
const char *s = NULL;
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
} else if(strstr(s, "__open")==s || !strcmp(s, "open") || !strcmp(s, "open ")) {
} else if (!strcmp(s, "__open") || !strcmp(s, "open") || !strcmp(s, "open ")) {
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, "my___printf_chk")) {
} else if (!strcmp(s, "fopen") || !strcmp(s, "fopen64")) {
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 = 2;
} else if (!strcmp(s, "__openat64") || !strcmp(s, "openat64") || !strcmp(s, "__openat64_2")) {
tmp = (char*)(R_RSI);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, \"%s\", %d (,%d))", tid, *(void**)(R_RSP), s, (int)R_EDI, (tmp)?tmp:"(nil)", (int)(R_EDX), (int)(R_ECX));
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 (!strcmp(s, "read")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
perr = 1;
} else if (!strcmp(s, "write")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %zu)", tid, *(void**)(R_RSP), s, R_EDI, (void*)R_RSI, R_RDX);
perr = 1;
} else if (strstr(s, "access")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", 0x%x)", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)", R_ESI);
perr = 1;
} else if (!strcmp(s, "lseek64") || !strcmp(s, "my_lseek64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
perr = 1;
} else if (!strcmp(s, "lseek") || !strcmp(s, "my_lseek")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %ld, %d)", tid, *(void**)(R_RSP), s, (int)R_EDI, (int64_t)R_RSI, (int)R_EDX);
perr = 1;
} else if (strstr(s, "puts")==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, "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 (strstr(s, "getenv")==s) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
} 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") || !strcmp(s, "__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, "sscanf")) {
} else if (strstr(s, "my___snprintf_chk") || !strcmp(s, "__snprintf_chk")) {
tmp = (char*)(R_R8);
pu64 = (uint64_t*)R_RDI;
post = 3;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, R_EDX, R_RCX, (tmp)?tmp:"(nil)", (void*)(R_R9));
} else if (strstr(s, "my_snprintf") || !strcmp(s, "snprintf")) {
tmp = (char*)(R_RDX);
pu64 = (uint64_t*)R_RDI;
post = 3;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\" (,%p))", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI, (tmp)?tmp:"(nil)", (void*)(R_RCX));
} else if (!strcmp(s, "getcwd")) {
post = 2;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu)", tid, *(void**)(R_RSP), s, (void*)R_RDI, R_RSI);
} else if (!strcmp(s, "ftok")) {
tmp = (char*)(R_RDI);
perr = 1;
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_RSP), s, tmp?tmp:"nil", R_ESI);
} else if (!strcmp(s, "glXGetProcAddress") || !strcmp(s, "SDL_GL_GetProcAddress") || !strcmp(s, "glXGetProcAddressARB")) {
tmp = (char*)(R_RDI);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_RSP), s, (tmp)?tmp:"(nil)");
} else if (!strcmp(s, "glLabelObjectEXT")) {
tmp = (char*)(R_RCX);
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d, %d, \"%s\")", tid, *(void**)(R_RSP), s, R_EDI, R_ESI, R_ECX, (tmp)?tmp:"(nil)");
} else if (!strcmp(s, "glGetStringi")) {
post = 2;
snprintf(buff, 255, "%04d|%p: Calling %s(0x%x, %d)", tid, *(void**)(R_RSP), s, R_EDI, R_ESI);
} 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);
}
@@ -114,23 +210,23 @@ void x64Int3(x64emu_t* emu)
w(emu, addr); // some function never come back, so unlock the mutex first!
pthread_mutex_lock(&emu->context->mutex_trace);
if(post)
switch(post) {
case 1: snprintf(buff2, 63, " [%d sec %d nsec]", pu32?pu32[0]:-1, pu32?pu32[1]:-1);
switch(post) { // Only ever 2 for now...
case 1: snprintf(buff2, 63, " [%llu sec %llu nsec]", pu64?pu64[0]:~0ull, pu64?pu64[1]:~0ull);
break;
case 2: snprintf(buff2, 63, "(%s)", R_RAX?((char*)R_RAX):"nil");
break;
case 3: snprintf(buff2, 63, "(%s)", pu32?((char*)pu32):"nil");
case 3: snprintf(buff2, 63, "(%s)", pu64?((char*)pu64):"nil");
break;
case 4: snprintf(buff2, 63, " (%f)", ST0.d);
break;
case 5: {
uint32_t* p = (uint32_t*)R_RAX;
uint32_t* p = (uint32_t*)R_RAX; // uint64_t? (case never used)
if(p)
snprintf(buff2, 63, " size=%dx%d, pitch=%d, pixels=%p", p[2], p[3], p[4], p+5);
snprintf(buff2, 63, " size=%ux%u, pitch=%u, pixels=%p", p[2], p[3], p[4], p+5);
else
snprintf(buff2, 63, "NULL Surface");
}
break;
}
break;
}
if(perr==1 && ((int)R_EAX)<0)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
@@ -143,7 +239,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);
@@ -153,4 +249,4 @@ void x64Int3(x64emu_t* emu)
int GetTID()
{
return syscall(SYS_gettid);
}
}
+10 -10
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>
@@ -785,7 +785,7 @@ uint8_t rol8(x64emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << cnt) + ((d >> (8 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -808,7 +808,7 @@ uint16_t rol16(x64emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << cnt) + ((d >> (16 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -831,7 +831,7 @@ uint32_t rol32(x64emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << cnt) + ((d >> (32 - cnt)) & ((1 << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -854,7 +854,7 @@ uint64_t rol64(x64emu_t *emu, uint64_t d, uint8_t s)
if((cnt = s % 64) != 0) {
d = (d << cnt) + ((d >> (64 - cnt)) & ((1L << cnt) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = CF _XOR_ MSB of result */
if(s == 1) {
@@ -881,7 +881,7 @@ uint8_t ror8(x64emu_t *emu, uint8_t d, uint8_t s)
if((cnt = s % 8) != 0) {
d = (d << (8 - cnt)) + ((d >> (cnt)) & ((1 << (8 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -904,7 +904,7 @@ uint16_t ror16(x64emu_t *emu, uint16_t d, uint8_t s)
if((cnt = s % 16) != 0) {
d = (d << (16 - cnt)) + ((d >> (cnt)) & ((1 << (16 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -927,7 +927,7 @@ uint32_t ror32(x64emu_t *emu, uint32_t d, uint8_t s)
if((cnt = s % 32) != 0) {
d = (d << (32 - cnt)) + ((d >> (cnt)) & ((1 << (32 - cnt)) - 1));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -950,7 +950,7 @@ uint64_t ror64(x64emu_t *emu, uint64_t d, uint8_t s)
if((cnt = s % 64) != 0) {
d = (d << (64 - cnt)) + ((d >> (cnt)) & ((1L << (64 - cnt)) - 1L));
}
RESET_FLAGS(emu);
CHECK_FLAGS(emu);
/* OF flag is set if s == 1; OF = MSB _XOR_ (M-1)SB of result */
if(s == 1) {
@@ -1400,7 +1400,7 @@ void idiv64(x64emu_t *emu, uint64_t s)
}
quot = dvd/(int64_t)s;
mod = dvd%(int64_t)s;
if (llabs(quot) > 0x7fffffffffffffffL) {
if ((quot > 0x7fffffffffffffffLL) || (quot < -0x7fffffffffffffffLL)) {
INTR_RAISE_DIV0(emu);
return;
}
+5 -5
View File
@@ -235,21 +235,25 @@ static inline uint64_t neg64(x64emu_t *emu, uint64_t s)
static inline uint8_t not8(x64emu_t *emu, uint8_t s)
{
(void)emu; // No flags affected
return ~s;
}
static inline uint16_t not16(x64emu_t *emu, uint16_t s)
{
(void)emu; // No flags affected
return ~s;
}
static inline uint32_t not32(x64emu_t *emu, uint32_t s)
{
(void)emu; // No flags affected
return ~s;
}
static inline uint64_t not64(x64emu_t *emu, uint64_t s)
{
(void)emu; // No flags affected
return ~s;
}
@@ -353,8 +357,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 +369,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;
@@ -592,7 +592,7 @@ static inline void mul32_eax(x64emu_t *emu, uint32_t s)
static inline void mul64_rax(x64emu_t *emu, uint64_t s)
{
emu->df = d_mul64;
__int128 res = (__int128)R_RAX * s;
unsigned __int128 res = (unsigned __int128)R_RAX * s;
emu->res.u64 = R_RAX = (uint64_t)res;
emu->op1.u64 = R_RDX = (uint64_t)(res >> 64);
}
+151 -31
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:
@@ -70,6 +70,8 @@ x64emurun:
rep = opcode-0xF1;
opcode = F8;
}
while((opcode==0x3E)) //Branch Taken Hint ignored
opcode = F8;
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
@@ -234,19 +236,26 @@ x64emurun:
GD->sq[0] = ED->sdword[0];
else
if(MODREG)
GD->q[0] = ED->sdword[0];
GD->q[0] = ED->dword[0]; // not really a sign extension
else
GD->sdword[0] = ED->sdword[0]; // meh?
break;
case 0x64: /* FS: prefix */
if(Run64(emu, rex)) {
if(Run64(emu, rex, _FS)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0x65: /* GS: prefix */
if(Run64(emu, rex, _GS)) {
unimp = 1;
goto fini;
}
if(emu->quit)
goto fini;
break;
case 0x66: /* 16bits prefix */
if(Run66(emu, rex, rep)) {
unimp = 1;
@@ -256,7 +265,7 @@ x64emurun:
goto fini;
break;
case 0x67: /* reduce EASize prefix */
if(Run67(emu, rex)) {
if(Run67(emu, rex, rep)) {
unimp = 1;
goto fini;
}
@@ -274,10 +283,7 @@ x64emurun:
if(rex.w)
GD->q[0] = imul64(emu, ED->q[0], tmp64u);
else
if((nextop&0xC0)==0xC0)
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
else
GD->dword[0] = imul32(emu, ED->dword[0], tmp64u);
GD->q[0] = imul32(emu, ED->dword[0], tmp64u);
break;
case 0x6A: /* Push Ib */
tmp64s = F8S;
@@ -325,7 +331,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;
@@ -383,7 +389,7 @@ x64emurun:
#ifdef DYNAREC
GETEB(0);
GETGB;
if((nextop&0xC0)==0xC0) { // reg / reg: no lock
if(MODREG) { // reg / reg: no lock
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
@@ -397,12 +403,12 @@ x64emurun:
#else
GETEB(0);
GETGB;
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_lock(&emu->context->mutex_lock); // XCHG always LOCK (but when accessing memory only)
tmp8u = GB;
GB = EB->byte[0];
EB->byte[0] = tmp8u;
if((nextop&0xC0)!=0xC0)
if(!MODREG)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
@@ -411,7 +417,7 @@ x64emurun:
#ifdef DYNAREC
GETED(0);
GETGD;
if((nextop&0xC0)==0xC0) {
if(MODREG) {
if(rex.w) {
tmp64u = GD->q[0];
GD->q[0] = ED->q[0];
@@ -487,7 +493,11 @@ x64emurun:
else
GD->q[0] = ED->dword[0];
break;
case 0x8C: /* MOV Ed, Seg */
nextop = F8;
GETED(0);
ED->dword[0] = emu->segs[((nextop&0x38)>>3)];
break;
case 0x8D: /* LEA Gd,M */
nextop = F8;
GETED(0);
@@ -495,7 +505,7 @@ x64emurun:
if(rex.w)
GD->q[0] = (uint64_t)ED;
else
GD->q[0] = (uint32_t)(uintptr_t)ED;
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
break;
case 0x8F: /* POP Ed */
@@ -510,7 +520,26 @@ x64emurun:
R_ESP += sizeof(void*);
}
break;
case 0x90: /* NOP */
case 0x90: /* NOP or XCHG R8, RAX*/
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97: /* XCHG reg,EAX */
tmp8u = _AX+(opcode&7)+(rex.b<<3);
if(tmp8u!=_AX) {
if(rex.w) {
tmp64u = R_RAX;
R_RAX = emu->regs[tmp8u].q[0];
emu->regs[tmp8u].q[0] = tmp64u;
} else {
tmp64u = R_EAX;
R_RAX = emu->regs[tmp8u].dword[0];
emu->regs[tmp8u].q[0] = tmp64u;
}
}
break;
case 0x98: /* CWDE */
@@ -538,7 +567,38 @@ 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 */
CHECK_FLAGS(emu);
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_RAX = *(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 +949,6 @@ x64emurun:
else
emu->regs[(opcode&7)+(rex.b<<3)].q[0] = F32;
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GETEB(1);
@@ -992,6 +1051,14 @@ x64emurun:
if(emu->quit) goto fini;
break;
case 0xCF: /* IRET */
R_RIP = Pop(emu);
emu->segs[_CS] = Pop(emu);
emu->segs_serial[_CS] = 0;
emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
RESET_FLAGS(emu);
goto fini; // exit, to recompute CS if needed
break;
case 0xD0: /* GRP2 Eb,1 */
case 0xD2: /* GRP2 Eb,CL */
nextop = F8;
@@ -1085,7 +1152,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 +1168,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;
@@ -1103,6 +1184,35 @@ x64emurun:
if(emu->quit)
goto fini;
break;
case 0xE0: /* LOOPNZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX && !ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
STEP
break;
case 0xE1: /* LOOPZ */
CHECK_FLAGS(emu);
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX && ACCESS_FLAG(F_ZF))
R_RIP += tmp8s;
STEP
break;
case 0xE2: /* LOOP */
tmp8s = F8S;
--R_RCX; // don't update flags
if(R_RCX)
R_RIP += tmp8s;
STEP
break;
case 0xE3: /* JECXZ */
tmp8s = F8S;
if(!R_RCX)
R_RIP += tmp8s;
STEP
break;
case 0xE8: /* CALL Id */
tmp32s = F32S; // call is relative
@@ -1131,6 +1241,10 @@ x64emurun:
goto fini;
break;
case 0xF5: /* CMC */
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
break;
case 0xF6: /* GRP3 Eb(,Ib) */
nextop = F8;
tmp8u = (nextop>>3)&7;
@@ -1220,18 +1334,17 @@ x64emurun:
break;
case 6: /* DIV Ed */
div32(emu, ED->dword[0]);
emu->regs[_AX].dword[1] = 0;
emu->regs[_DX].dword[1] = 0;
//emu->regs[_AX].dword[1] = 0; // already put high regs to 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;
//emu->regs[_AX].dword[1] = 0;
//emu->regs[_DX].dword[1] = 0;
break;
}
}
break;
case 0xF8: /* CLC */
CHECK_FLAGS(emu);
CLEAR_FLAG(F_CF);
@@ -1274,14 +1387,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]);
@@ -1318,7 +1439,6 @@ x64emurun:
} else {
R_RIP = ED->q[0];
R_CS = (ED+1)->word[0];
STEP
goto fini; // exit loop to recompute CS...
}
break;
+301 -59
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;
@@ -48,6 +49,22 @@ int Run0F(x64emu_t *emu, rex_t rex)
x64Syscall(emu);
break;
case 0x0B: /* UD2 */
emit_signal(emu, SIGILL, (void*)R_RIP, 0);
break;
case 0x0D:
nextop = F8;
GETED(0);
switch((nextop>>3)&7) {
case 1: //PREFETCHW
__builtin_prefetch((void*)ED, 1, 0);
break;
default: //???
return 1;
}
break;
case 0x10: /* MOVUPS Gx,Ex */
nextop = F8;
GETEX(0);
@@ -104,6 +121,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 +221,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;
@@ -202,7 +304,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETEX(0);
GETGD;
GD->dword[0] = 0;
GD->q[0] = 0;
for(int i=0; i<4; ++i)
GD->dword[0] |= ((EX->ud[i]>>31)&1)<<i;
break;
@@ -443,13 +545,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 +678,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;
@@ -516,19 +712,19 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
tmp32s = GD->sdword[0];
tmp8u=tmp32s&(rex.w?63:31);
tmp32s >>= (rex.w?6:5);
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
@@ -546,8 +742,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
tmp8u = R_CL;
if(rex.w)
ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u);
else
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
else {
if(MODREG)
ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
else
ED->dword[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);
}
break;
case 0xAB: /* BTS Ed,Gd */
@@ -555,13 +755,14 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
tmp32s = GD->sdword[0];
tmp8u=tmp32s&(rex.w?63:31);
tmp32s >>= (rex.w?6:5);
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
@@ -569,7 +770,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
@@ -588,8 +788,12 @@ int Run0F(x64emu_t *emu, rex_t rex)
tmp8u = (opcode==0xAC)?(F8):R_CL;
if(rex.w)
ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u);
else
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
else {
if(MODREG)
ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
else
ED->dword[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);
}
break;
case 0xAE: /* Grp Ed (SSE) */
nextop = F8;
@@ -622,6 +826,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;
}
@@ -633,7 +842,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
if(rex.w)
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
else
GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]);
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
break;
case 0xB0: /* CMPXCHG Eb,Gb */
nextop = F8;
@@ -659,13 +868,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;
@@ -674,20 +882,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
tmp32s = GD->sdword[0];
tmp8u=tmp32s&(rex.w?63:31);
tmp32s >>= (rex.w?6:5);
if(!MODREG)
{
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
ED->dword[0] ^= (1<<tmp8u);
@@ -718,8 +926,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
@@ -738,8 +944,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
@@ -762,8 +966,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
@@ -784,8 +986,6 @@ int Run0F(x64emu_t *emu, rex_t rex)
CHECK_FLAGS(emu);
GETED(1);
tmp8u = F8;
if(!MODREG)
ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
@@ -812,23 +1012,20 @@ int Run0F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETED(0);
GETGD;
tmp8u = GD->byte[0];
tmp32s = GD->sdword[0];
tmp8u=tmp32s&(rex.w?63:31);
tmp32s >>= (rex.w?6:5);
if(!MODREG)
{
if(rex.w)
ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6));
else
ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));
ED=(reg64_t*)(((uintptr_t)(ED))+(tmp32s<<(rex.w?3:2)));
}
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=31;
if(ED->dword[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
@@ -960,6 +1157,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 +1289,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 +1320,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 +1364,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 +1385,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 +1490,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 +1527,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:
+269 -9
View File
@@ -22,18 +22,20 @@
#include "modrm.h"
int Run64(x64emu_t *emu, rex_t rex)
int Run64(x64emu_t *emu, rex_t rex, int seg)
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int16_t tmp16s;
uint16_t tmp16u;
uint8_t tmp8u; (void)tmp8u;
int16_t tmp16s; (void)tmp16s;
uint16_t tmp16u; (void)tmp16u;
int32_t tmp32s;
uint32_t tmp32u;
uint64_t tmp64u;
reg64_t *oped, *opgd;
uintptr_t tlsdata = GetFSBaseEmu(emu);
sse_regs_t *opex, *opgx;
int rep;
uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);
opcode = F8;
// REX prefix before the F0 are ignored
@@ -42,19 +44,230 @@ 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 0x10:
switch(rep) {
case 1: /* MOVSD Gx, FS:Ex */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
GX->q[0] = EX->q[0];
if((nextop&0xC0)!=0xC0) {
// EX is not a register
GX->q[1] = 0;
}
break;
case 2: /* MOVSS Gx, FS:Ex */
nextop = F8;
GETEX_OFFS(0, tlsdata);
GETGX;
GX->ud[0] = EX->ud[0];
if((nextop&0xC0)!=0xC0) {
// EX is not a register (reg to reg only move 31:0)
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
}
break;
default:
return 1;
}
break;
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;
case 0xAF: /* IMUL Gd,Ed */
nextop = F8;
GETED_OFFS(0, tlsdata);
GETGD;
if(rex.w)
GD->q[0] = imul64(emu, GD->q[0], ED->q[0]);
else
GD->q[0] = imul32(emu, GD->dword[0], ED->dword[0]);
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 0x80: /* GRP Eb,Ib */
nextop = F8;
GETEB_OFFS(1, tlsdata);
tmp8u = F8;
switch((nextop>>3)&7) {
case 0: EB->byte[0] = add8(emu, EB->byte[0], tmp8u); break;
case 1: EB->byte[0] = or8(emu, EB->byte[0], tmp8u); break;
case 2: EB->byte[0] = adc8(emu, EB->byte[0], tmp8u); break;
case 3: EB->byte[0] = sbb8(emu, EB->byte[0], tmp8u); break;
case 4: EB->byte[0] = and8(emu, EB->byte[0], tmp8u); break;
case 5: EB->byte[0] = sub8(emu, EB->byte[0], tmp8u); break;
case 6: EB->byte[0] = xor8(emu, EB->byte[0], tmp8u); break;
case 7: cmp8(emu, EB->byte[0], tmp8u); break;
}
break;
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
@@ -134,6 +347,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);
@@ -146,8 +364,50 @@ int Run64(x64emu_t *emu, rex_t rex)
ED->dword[0] = F32;
break;
case 0xD1: /* GRP2 Ed,1 */
case 0xD3: /* GRP2 Ed,CL */
nextop = F8;
GETED_OFFS(0, tlsdata);
tmp8u = (opcode==0xD1)?1:R_CL;
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;
default:
return 1;
}
return 0;
}
}
+48 -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 */
@@ -222,6 +246,20 @@ int Run66(x64emu_t *emu, rex_t rex, int rep)
R_DX=((R_AX & 0x8000)?0xFFFF:0x0000);
break;
case 0xA1: /* MOV EAX,Od */
if(rex.w)
R_RAX = *(uint64_t*)F64;
else
R_AX = *(uint16_t*)F64;
break;
case 0xA3: /* MOV Od,EAX */
if(rex.w)
*(uint64_t*)F64 = R_RAX;
else
*(uint16_t*)F64 = R_AX;
break;
case 0xA5: /* (REP) MOVSW */
tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
tmp64u = (rep)?R_RCX:1L;
@@ -527,6 +565,15 @@ 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 0xF0: /* LOCK: */
return Run66F0(emu, rex);
case 0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
tmp8u = (nextop>>3)&7;
+290 -16
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,194 @@ 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;
case 0x20: /* PMOVSXBW Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=7; i>=0; --i)
GX->sw[i] = EX->sb[i];
break;
case 0x21: /* PMOVSXBD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->sd[i] = EX->sb[i];
break;
case 0x22: /* PMOVSXBQ Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sb[i];
break;
case 0x23: /* PMOVSXWD Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->sd[i] = EX->sw[i];
break;
case 0x24: /* PMOVSXWQ Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sw[i];
break;
case 0x25: /* PMOVSXDQ Gx, Ex */
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sd[i];
break;
default:
return 1;
}
break;
case 0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0B: // ROUNDSD Gx, Ex, u8
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8; // ignoring bit 3 interupt thingy
if(tmp8u&4)
tmp8u = (emu->mxcsr>>13)&3;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest:
GX->d[0] = floor(EX->d[0]+0.5);
break;
case ROUND_Down:
GX->d[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GX->d[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GX->d[0] = EX->d[0];
break;
}
break;
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);
@@ -624,13 +824,20 @@ int Run660F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
if(EW->word[0] & (1<<(GW->word[0]&15)))
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
@@ -656,18 +863,25 @@ int Run660F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<(GW->q[0]&63)))
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
EW->q[0] |= (1LL<<(GW->q[0]&63));
EW->q[0] |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
if(EW->word[0] & (1<<(GW->word[0]&15)))
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
EW->word[0] |= (1<<(GW->word[0]&15));
EW->word[0] |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
@@ -723,31 +937,60 @@ int Run660F(x64emu_t *emu, rex_t rex)
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<(GW->q[0]&63))) {
if(EW->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
EW->q[0] ^= (1LL<<(GW->q[0]&63));
EW->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
if(EW->word[0] & (1<<(GW->word[0]&15))) {
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<(GW->word[0]&15));
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
break;
case 0xB6: /* MOVZX Gw,Eb */
nextop = F8;
GETEB(0);
GETGW;
GW->word[0] = EB->byte[0];
break;
case 0xBB: /* BTC Ew,Gw */
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
if(EW->word[0] & (1<<(GW->word[0]&15)))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<(GW->word[0]&15));
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->q[0] ^= (1LL<<tmp8u);
} else {
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
}
break;
case 0xBC: /* BSF Ew,Gw */
CHECK_FLAGS(emu);
@@ -848,6 +1091,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 +1277,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);
+120
View File
@@ -0,0 +1,120 @@
#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 "dynarec/arm64_lock.h"
#include "modrm.h"
int Run66F0(x64emu_t *emu, rex_t rex)
{
uint8_t opcode;
uint8_t nextop;
uint16_t tmp16u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2;
reg64_t *oped;
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 0x81: /* GRP Ew,Iw */
case 0x83: /* GRP Ew,Ib */
nextop = F8;
GETED((opcode==0x83)?1:2);
tmp64s = (opcode==0x83)?(F8S):(F16S);
tmp64u = (uint64_t)tmp64s;
#ifdef DYNAREC
if(rex.w) {
switch((nextop>>3)&7) {
case 0: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = add64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 1: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = or64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 2: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = adc64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 3: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sbb64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 4: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = and64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 5: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = sub64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 6: do { tmp64u2 = arm64_lock_read_dd(ED); tmp64u2 = xor64(emu, tmp64u2, tmp64u);} while(arm64_lock_write_dd(ED, tmp64u2)); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
if(MODREG)
switch((nextop>>3)&7) {
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
else
switch((nextop>>3)&7) {
case 0: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = add16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 1: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = or16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 2: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = adc16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 3: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sbb16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 4: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = and16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 5: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = sub16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 6: do { tmp16u2 = arm64_lock_read_h(ED); tmp16u2 = xor16(emu, tmp16u2, tmp64u);} while(arm64_lock_write_h(ED, tmp16u2)); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
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;
case 2: ED->q[0] = adc64(emu, ED->q[0], tmp64u); break;
case 3: ED->q[0] = sbb64(emu, ED->q[0], tmp64u); break;
case 4: ED->q[0] = and64(emu, ED->q[0], tmp64u); break;
case 5: ED->q[0] = sub64(emu, ED->q[0], tmp64u); break;
case 6: ED->q[0] = xor64(emu, ED->q[0], tmp64u); break;
case 7: cmp64(emu, ED->q[0], tmp64u); break;
}
} else {
switch((nextop>>3)&7) {
case 0: ED->word[0] = add16(emu, ED->word[0], tmp64u); break;
case 1: ED->word[0] = or16(emu, ED->word[0], tmp64u); break;
case 2: ED->word[0] = adc16(emu, ED->word[0], tmp64u); break;
case 3: ED->word[0] = sbb16(emu, ED->word[0], tmp64u); break;
case 4: ED->word[0] = and16(emu, ED->word[0], tmp64u); break;
case 5: ED->word[0] = sub16(emu, ED->word[0], tmp64u); break;
case 6: ED->word[0] = xor16(emu, ED->word[0], tmp64u); break;
case 7: cmp16(emu, ED->word[0], tmp64u); break;
}
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
}
return 0;
}
+235 -3
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;
@@ -47,7 +167,48 @@ int Run67(x64emu_t *emu, rex_t rex)
if(rex.w)
GD->q[0] = (uint64_t)ED;
else
GD->q[0] = (uint32_t)(uintptr_t)ED;
GD->q[0] = ((uintptr_t)ED)&0xffffffff;
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 */
@@ -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;
}
+72
View File
@@ -0,0 +1,72 @@
#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)
{
(void)rep;
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u; (void)tmp8u;
int8_t tmp8s; (void)tmp8s;
int32_t tmp32s, tmp32s2; (void)tmp32s; (void)tmp32s2;
uint32_t tmp32u, tmp32u2; (void)tmp32u; (void)tmp32u2;
uint64_t tmp64u, tmp64u2; (void)tmp64u; (void)tmp64u2;
reg64_t *oped, *opgd; (void)oped; (void)opgd;
sse_regs_t *opex, *opgx, eax1; (void)eax1;
mmx87_regs_t *opem, *opgm, eam1; (void)opem; (void)opgm; (void)eam1;
opcode = F8;
switch(opcode) {
case 0x2E: /* UCOMISS Gx, Ex */
// same for now
case 0x2F: /* COMISS Gx, Ex */
if(rep) {
return 1;
}
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;
}
+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 Run6766(x64emu_t *emu, rex_t rex, int rep)
{
// Hmmmm....
(void)rep;
uint8_t opcode;
uint8_t nextop; (void)nextop;
int8_t tmp8s; (void)tmp8s;
uint8_t tmp8u, tmp8u2; (void)tmp8u; (void)tmp8u2;
int16_t tmp16s; (void)tmp16s;
uint16_t tmp16u, tmp16u2; (void)tmp16u; (void)tmp16u2;
int32_t tmp32s; (void)tmp32s;
int64_t tmp64s; (void)tmp64s;
uint64_t tmp64u, tmp64u2, tmp64u3; (void)tmp64u; (void)tmp64u2; (void)tmp64u3;
reg64_t *oped, *opgd; (void)oped; (void)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 66 are ignored
rex.rex = 0;
while(opcode>=0x40 && opcode<=0x4f) {
rex.rex = opcode;
opcode = F8;
}
switch(opcode) {
case 0x0F: /* more opcodes */
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;
int8_t tmp8s; (void)tmp8s;
uint8_t tmp8u; (void)tmp8u;
int16_t tmp16s; (void)tmp16s;
uint16_t tmp16u; (void)tmp16u;
int32_t tmp32s; (void)tmp32s;
uint32_t tmp32u; (void)tmp32u;
int64_t tmp64s; (void)tmp64s;
uint64_t tmp64u; (void)tmp64u;
reg64_t *oped, *opgd; (void)oped; (void)opgd;
sse_regs_t *opex, *opgx;
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;
}
+55 -13
View File
@@ -30,8 +30,8 @@
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
(void)argc; (void)ubp_av; (void)fini; (void)rtld_fini; (void)stack_end;
// let's cheat and set all args...
if(init) {
PushExit(emu);
@@ -44,14 +44,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 +927,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);
@@ -940,7 +946,7 @@ uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg)
const char* getAddrFunctionName(uintptr_t addr)
{
static char ret[1000];
uint32_t sz = 0;
uint64_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
@@ -955,7 +961,7 @@ const char* getAddrFunctionName(uintptr_t addr)
void printFunctionAddr(uintptr_t nextaddr, const char* text)
{
uint32_t sz = 0;
uint64_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, nextaddr), (void*)nextaddr, &start, &sz);
if(symbname && nextaddr>=start && (nextaddr<(start+sz) || !sz)) {
@@ -987,6 +993,7 @@ void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec)
my_context->trace_dynarec = dynarec;
}
#else
(void)dynarec;
if(my_context->trace_tid != tid) {
printf_log(LOG_NONE, "Thread %04d|\n", tid);
my_context->trace_tid = tid;
@@ -1003,10 +1010,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 +1072,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 +1098,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,10 +1164,25 @@ 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)
{
(void)rex;
uint8_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)];
@@ -1188,6 +1210,8 @@ 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)
{
(void)rex;
uint32_t m = v&0xC7; // filter Ed
if(m>=0xC0) {
return &emu->regs[(m&0x07)];
@@ -1229,6 +1253,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,14 +1278,16 @@ 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];
}
mmx87_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v)
{
(void)rex;
uint8_t m = (v&0x38)>>3;
return &emu->mmx87[m&7];
}
+13 -9
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);
@@ -98,28 +102,28 @@ void UpdateFlags(x64emu_t *emu);
#define RESET_FLAGS(emu) emu->df = d_none
int Run0F(x64emu_t *emu, rex_t rex);
int Run64(x64emu_t *emu, rex_t rex);
int Run64(x64emu_t *emu, rex_t rex, int seg);
int Run66(x64emu_t *emu, rex_t rex, int rep);
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 Run66F0(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);
int RunF30F(x64emu_t *emu, rex_t rex);
//void Run66D9(x64emu_t *emu); // x87
//void Run6766(x64emu_t *emu);
//void RunGS(x64emu_t *emu);
//void RunFS(x64emu_t *emu);
//void RunFS66(x64emu_t *emu, uintptr_t tlsdata);
//void RunLock66(x64emu_t *emu);
void x64Syscall(x64emu_t *emu);
void x64Int3(x64emu_t* emu);
@@ -137,4 +141,4 @@ const char* GetNativeName(void* p);
void PrintTrace(x64emu_t* emu, uintptr_t ip, int dynarec);
#endif
#endif //__X86RUN_PRIVATE_H_
#endif //__X86RUN_PRIVATE_H_
+2 -1
View File
@@ -191,7 +191,8 @@ int RunD9(x64emu_t *emu, rex_t rex)
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
ST0.d *= exp2(trunc(ST1.d));
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
break;
case 0xFE: /* FSIN */
ST0.d = sin(ST0.d);
+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;
}
+2 -2
View File
@@ -162,7 +162,7 @@ int RunDF(x64emu_t *emu, rex_t rex)
break;
case 7: /* FISTP i64 */
GETED(0);
if(STll(0).ref==ST(0).q)
if(STll(0).ref==ST(0).sq)
ED->sq[0] = STll(0).ll;
else {
if(isgreater(ST0.d, (double)(int64_t)0x7fffffffffffffffLL) || isless(ST0.d, -(double)(int64_t)0x7fffffffffffffffLL) || !isfinite(ST0.d))
@@ -177,4 +177,4 @@ int RunDF(x64emu_t *emu, rex_t rex)
}
}
return 0;
}
}
+419 -20
View File
@@ -31,7 +31,7 @@ int RunF0(x64emu_t *emu, rex_t rex)
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int32_t tmp32s;
int32_t tmp32s; (void)tmp32s;
uint32_t tmp32u, tmp32u2;
int64_t tmp64s;
uint64_t tmp64u, tmp64u2;
@@ -168,33 +168,159 @@ 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_dd(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);
GETGD;
#ifdef DYNAREC
if(rex.w)
do {
tmp64u = arm64_lock_read_dd(ED);
cmp64(emu, R_RAX, tmp64u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
} else {
R_RAX = tmp64u;
tmp32s = 0;
}
} while(tmp32s);
else
if(((uintptr_t)ED)&7) {
do {
tmp64u = ED->q[0] & ~0xffLL;
tmp64u |= arm64_lock_read_b(ED);
cmp64(emu, R_RAX, tmp64u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_b(ED, GD->q[0]&0xff);
if(!tmp32s)
ED->q[0] = GD->q[0];
} else {
R_RAX = tmp64u;
tmp32s = 0;
}
} while(tmp32s);
} else
do {
tmp64u = arm64_lock_read_dd(ED);
cmp64(emu, R_RAX, tmp64u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_dd(ED, GD->q[0]);
} else {
R_RAX = tmp64u;
tmp32s = 0;
}
} while(tmp32s);
else {
do {
tmp32u = arm64_lock_read_d(ED);
cmp32(emu, R_EAX, tmp32u);
if(ACCESS_FLAG(F_ZF)) {
tmp32s = arm64_lock_write_d(ED, GD->dword[0]);
} else {
R_RAX = tmp32u;
R_EAX = tmp32u;
tmp32s = 0;
}
} while(tmp32s);
emu->regs[_AX].dword[1] = 0;
if(MODREG)
ED->dword[1] = 0;
}
#else
pthread_mutex_lock(&emu->context->mutex_lock);
if(rex.w) {
@@ -211,6 +337,69 @@ int RunF0(x64emu_t *emu, rex_t rex)
} else {
R_EAX = ED->dword[0];
}
emu->regs[_AX].dword[1] = 0;
if(MODREG)
ED->dword[1] = 0;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#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);
if(MODREG)
ED->dword[1] = 0;
}
#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
@@ -224,14 +413,23 @@ int RunF0(x64emu_t *emu, rex_t rex)
if(rex.w) {
do {
tmp64u = arm64_lock_read_dd(ED);
tmp64u2 = add64(emu, tmp64u, GD->dword[0]);
tmp64u2 = add64(emu, tmp64u, GD->q[0]);
} 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,11 +452,77 @@ 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_RAX = tmp32u;
R_RDX = tmp32u2;
}
}
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
return 1;
}
break;
case 0x66:
return Run66F0(emu, rex); // more opcode F0 66 and 66 F0 is the same
case 0x81: /* GRP Ed,Id */
case 0x83: /* GRP Ed,Ib */
nextop = F8;
@@ -344,9 +608,144 @@ 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)
if(((uintptr_t)ED)&7) {
// unaligned
do {
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
tmp64u |= arm64_lock_read_b(ED);
tmp64u = inc64(emu, tmp64u);
} while(arm64_lock_write_b(ED, tmp64u&0xff));
ED->q[0] = tmp64u;
}
else
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)
if(((uintptr_t)ED)&7) {
// unaligned
do {
tmp64u = ED->q[0] & 0xffffffffffffff00LL;
tmp64u |= arm64_lock_read_b(ED);
tmp64u = dec64(emu, tmp64u);
} while(arm64_lock_write_b(ED, tmp64u&0xff));
ED->q[0] = tmp64u;
}
else
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;
}
return 0;
}
}
+15 -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;
@@ -110,6 +116,7 @@ int RunF20F(x64emu_t *emu, rex_t rex)
GD->sdword[0] = EX->d[0];
break;
}
GD->dword[1] = 0;
}
break;
@@ -254,7 +261,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;
+45 -2
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;
@@ -41,7 +43,7 @@ int RunF30F(x64emu_t *emu, rex_t rex)
GETEX(0);
GETGX;
GX->ud[0] = EX->ud[0];
if((nextop&0xC0)!=0xC0) {
if(!MODREG) {
// EX is not a register (reg to reg only move 31:0)
GX->ud[1] = GX->ud[2] = GX->ud[3] = 0;
}
@@ -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;
}
}
+264 -16
View File
@@ -34,18 +34,23 @@
#include "x64tls.h"
typedef struct x64_sigaction_s x64_sigaction_t;
typedef struct x64_stack_s x64_stack_t;
int mkdir(const char *path, mode_t mode);
//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);
ssize_t my_readlink(x64emu_t* emu, void* path, void* buf, size_t sz);
int my_stat(x64emu_t *emu, void* filename, void* buf);
//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);
void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
@@ -56,19 +61,84 @@ int fcntl(int fd, int cmd, ... /* arg */ );
// Syscall table for x86_64 can be found
typedef struct scwrap_s {
int x64s;
uint32_t x64s; // 32 bits?
int nats;
int nbpars;
} 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
//{ 4, __NR_stat, 2 }, // Need to align struct stat
//{ 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
{ 14, __NR_rt_sigprocmask, 4},
{ 16, __NR_ioctl, 3},
{ 20, __NR_writev, 3},
#ifdef __NR_access
{ 21, __NR_access, 2},
#endif
#ifdef __NR_pipe
{ 22, __NR_pipe, 1},
#endif
#ifdef __NR_select
{ 23, __NR_select, 5},
#endif
//{ 25, __NR_mremap, 5}, // wrapped to track protection
{ 39, __NR_getpid, 0},
{ 46, __NR_sendmsg, 3},
{ 47, __NR_recvmsg, 3},
{ 53, __NR_socketpair, 4},
#ifdef __NR_fork
{ 57, __NR_fork, 0 }, // should wrap this one, because of the struct pt_regs (the only arg)?
#endif
{ 61, __NR_wait4, 4},
{ 66, __NR_semctl, 4},
#ifdef __NR_getdents
{ 78, __NR_getdents, 3},
#endif
#ifdef __NR_mkdir
{ 83, __NR_mkdir, 2},
#endif
#ifdef __NR_unlink
{ 87, __NR_unlink, 1},
#endif
//{ 89, __NR_readlink, 3}, // not always existing, better use the wrapped version anyway
{ 96, __NR_gettimeofday, 2},
{ 97, __NR_getrlimit, 2},
{ 101, __NR_ptrace, 4},
{ 125, __NR_capget, 2},
{ 126, __NR_capset, 2},
{ 127, __NR_rt_sigpending, 2},
//{ 131, __NR_sigaltstack, 2}, // wrapped to use my_sigaltstack
{ 157, __NR_prctl, 5 }, // needs wrapping?
//{ 158, __NR_arch_prctl, 2}, //need wrapping
{ 186, __NR_gettid, 0 }, //0xBA
{ 200, __NR_tkill, 2 },
#ifdef __NR_time
{ 201, __NR_time, 1},
#endif
{ 202, __NR_futex, 6},
{ 217, __NR_getdents64, 3},
{ 220, __NR_semtimedop, 4},
{ 228, __NR_clock_gettime, 2},
{ 229, __NR_clock_getres, 2},
{ 230, __NR_clock_nanosleep, 4},
{ 234, __NR_tgkill, 3},
#ifdef __NR_inotify_init
{ 253, __NR_inotify_init, 0}, //0xFD
#endif
{ 254, __NR_inotify_add_watch, 3},
{ 255, __NR_inotify_rm_watch, 2},
{ 274, __NR_get_robust_list, 3},
{ 294, __NR_inotify_init1, 1},
{ 298, __NR_perf_event_open, 5},
{ 318, __NR_getrandom, 3},
};
struct mmap_arg_struct {
@@ -80,6 +150,45 @@ struct mmap_arg_struct {
unsigned long offset;
};
#ifndef __NR_getdents
typedef struct x86_linux_dirent_s {
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[];
} x86_linux_dirent_t;
typedef struct nat_linux_dirent64_s {
ino64_t d_ino;
off64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
} nat_linux_dirent64_t;
ssize_t DirentFromDirent64(void* dest, void* source, ssize_t count)
{
nat_linux_dirent64_t *src = (nat_linux_dirent64_t*)source;
x86_linux_dirent_t *dst = (x86_linux_dirent_t*)dest;
ssize_t ret = count;
while(count>0) {
dst->d_ino = src->d_ino;
dst->d_reclen = src->d_reclen+1;
strcpy(dst->d_name, src->d_name);
dst->d_off = src->d_off?(src->d_off+1):0;
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -2) = 0;
*(uint8_t*)((uintptr_t)dst + dst->d_reclen -1) = src->d_type;
count -= src->d_reclen;
ret += 1;
src = (nat_linux_dirent64_t*)(((uintptr_t)src) + src->d_reclen);
dst = (x86_linux_dirent_t*)(((uintptr_t)dst) + dst->d_reclen);
}
return ret;
}
#endif
//struct x86_pt_regs {
// long ebx;
// long ecx;
@@ -113,7 +222,7 @@ struct mmap_arg_struct {
void EXPORT x64Syscall(x64emu_t *emu)
{
RESET_FLAGS(emu);
uint32_t s = R_EAX;
uint32_t s = R_EAX; // EAX? (syscalls only go up to 547 anyways)
printf_log(LOG_DEBUG, "%p: Calling syscall 0x%02X (%d) %p %p %p %p %p %p", (void*)R_RIP, s, s, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8, (void*)R_R9);
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
@@ -123,7 +232,7 @@ void EXPORT x64Syscall(x64emu_t *emu)
switch(syscallwrap[i].nbpars) {
case 0: *(int64_t*)&R_RAX = syscall(sc); break;
case 1: *(int64_t*)&R_RAX = syscall(sc, R_RDI); break;
case 2: if(s==33) {printf_log(LOG_DUMP, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
case 2: if(s==33) {printf_dump(LOG_DEBUG, " => sys_access(\"%s\", %ld)\n", (char*)R_RDI, R_RSI);}; *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI); break;
case 3: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX); break;
case 4: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10); break;
case 5: *(int64_t*)&R_RAX = syscall(sc, R_RDI, R_RSI, R_RDX, R_R10, R_R8); break;
@@ -152,6 +261,84 @@ void EXPORT x64Syscall(x64emu_t *emu)
case 3: // sys_close
R_EAX = (uint32_t)close((int)R_EDI);
break;
case 4: // sys_stat
R_EAX = (uint32_t)my_stat(emu, (void*)R_RDI, (void*)R_RSI);
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_access
case 21: // sys_access
R_EAX = (uint32_t)access((void*)R_RDI, R_ESI);
break;
#endif
#ifndef __NR_pipe
case 22:
R_EAX = (uint32_t)pipe((void*)R_RDI);
break;
#endif
#ifndef __NR_select
case 23: // sys_select
R_EAX = (uint32_t)select(R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_R10, (void*)R_R8);
break;
#endif
case 25: // sys_mremap
R_RAX = (uintptr_t)my_mremap(emu, (void*)R_RDI, R_RSI, R_RDX, R_R10d, (void*)R_R8);
break;
#ifndef __NR_fork
case 57:
R_RAX = fork();
break;
#endif
#ifndef __NR_getdents
case 78:
{
size_t count = R_RDX;
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
ssize_t ret = syscall(__NR_getdents64, R_EDI, d64, count);
ret = DirentFromDirent64((void*)R_RSI, d64, ret);
R_RAX = (uint64_t)ret;
}
break;
#endif
#ifndef __NR_mkdir
case 83: // sys_mkdir
R_EAX = (uint32_t)mkdir((void*)R_RDI, R_ESI);
break;
#endif
#ifndef __NR_unlink
case 87: //sys_unlink
R_EAX = (uint32_t)unlink((void*)R_RDI);
break;
#endif
case 89: // sys_readlink
R_RAX = (ssize_t)my_readlink(emu,(void*)R_RDI, (void*)R_RSI, (size_t)R_RDX);
break;
case 131: // sys_sigaltstack
R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
break;
case 158: // sys_arch_prctl
R_EAX = (uint32_t)my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
break;
#ifndef __NR_time
case 201: // sys_time
R_RAX = (uintptr_t)time((void*)R_RDI);
break;
#endif
#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,13 +351,14 @@ 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);
printf_dump(LOG_DEBUG, "%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);
// check wrapper first
int cnt = sizeof(syscallwrap) / sizeof(scwrap_t);
for (int i=0; i<cnt; i++) {
@@ -200,6 +388,66 @@ 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 4: // sys_stat
return (uint32_t)my_stat(emu, (void*)R_RSI, (void*)R_RDX);
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_access
case 21: // sys_access
return (uint32_t)access((void*)R_RSI, R_EDX);
#endif
#ifndef __NR_pipe
case 22:
return (uint32_t)pipe((void*)R_RSI);
#endif
#ifndef __NR_select
case 23: // sys_select
return (uint32_t)select(R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9);
#endif
case 25: // sys_mremap
return (uintptr_t)my_mremap(emu, (void*)R_RSI, R_RDX, R_RCX, R_R8d, (void*)R_R9);
#ifndef __NR_fork
case 57:
return fork();
#endif
#ifndef __NR_getdents
case 78:
{
size_t count = R_RCX;
nat_linux_dirent64_t *d64 = (nat_linux_dirent64_t*)alloca(count);
ssize_t ret = syscall(__NR_getdents64, R_ESI, d64, count);
ret = DirentFromDirent64((void*)R_RDX, d64, ret);
return (uint64_t)ret;
}
#endif
#ifndef __NR_mkdir
case 83: // sys_mkdir
return (uint32_t)mkdir((void*)R_RSI, R_EDX);
#endif
#ifndef __NR_unlink
case 87: //sys_unlink
return (uint32_t)unlink((void*)R_RSI);
#endif
case 89: // sys_readlink
return (uintptr_t)my_readlink(emu,(void*)R_RSI, (void*)R_RDX, (size_t)R_RCX);
case 131: // sys_sigaltstack
return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
case 158: // sys_arch_prctl
return (uint32_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX);
#ifndef __NR_time
case 201: // sys_time
return (uintptr_t)time((void*)R_RSI);
#endif
#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;
+59 -8
View File
@@ -8,6 +8,7 @@
#include "debug.h"
#include "box64context.h"
#include "x64emu.h"
#include "x64emu_private.h"
#include "x64tls.h"
#include "elfloader.h"
@@ -27,6 +28,7 @@ typedef struct thread_area_s
static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
static pthread_once_t thread_key_once3 = PTHREAD_ONCE_INIT;
static void thread_key_alloc0() {
pthread_key_create(&my_context->segtls[0].key, NULL);
@@ -37,6 +39,9 @@ static void thread_key_alloc1() {
static void thread_key_alloc2() {
pthread_key_create(&my_context->segtls[2].key, NULL);
}
static void thread_key_alloc3() {
pthread_key_create(&my_context->segtls[3].key, NULL);
}
uint32_t my_set_thread_area(thread_area_t* td)
{
@@ -123,12 +128,57 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
pthread_setspecific(my_context->segtls[idx].key, (void*)my_context->segtls[idx].base);
*/
ResetSegmentsCache(thread_get_emu());
ResetSegmentsCache(emu);
return 0;
}
#define POS_TLS 0x50
int my_arch_prctl(x64emu_t *emu, int code, void* addr)
{
#define ARCH_SET_GS 0x1001
#define ARCH_GET_GS 0x1004
switch(code) {
case ARCH_GET_GS:
*(void**)addr = GetSegmentBase(emu->segs[_GS]);
return 0;
case ARCH_SET_GS:
if(emu->segs[_GS]!=(0xa<<3)) {
pthread_once(&thread_key_once3, thread_key_alloc3);
emu->segs[_GS] = 0xa<<3;
if(!default_gs)
default_gs = 0xa<<3;
}
my_context->segtls[3].base = (uintptr_t)addr;
my_context->segtls[3].limit = 0;
my_context->segtls[3].present = 1;
pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
return 0;
}
// other are unsupported
printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
return -1;
}
#define POS_TLS 0x200
/*
tls record should looks like:
void* tcb 0x00
void* dtv 0x08
void* self 0x10
int multiple 0x18
int gscope 0x1c
void* sysinfo 0x20
uintptr_t stack_guard 0x28
uitnptr_t pointer_guard 0x30
uint64_t vgetcpu[2] 0x38
uint32_t features 0x48
int unused 0x4c
void* private[4] 0x50
void* private_ss 0x70
uintptr_t ssp_base 0x78
.... padding .... 0x200?
*/
static tlsdatasize_t* setupTLSData(box64context_t* context)
{
@@ -142,20 +192,21 @@ static tlsdatasize_t* setupTLSData(box64context_t* context)
pthread_setspecific(context->tlskey, data);
// copy canary...
memset((void*)((uintptr_t)ptr+context->tlssize), 0, POS_TLS+dtsize); // set to 0 remining bytes
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x14), context->canary, sizeof(void*)); // put canary in place
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x28), context->canary, sizeof(void*)); // put canary in place
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, sizeof(void*));
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &tlsptr, sizeof(void*)); // set tcb and self same address
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
memcpy((void*)(tlsptr+sizeof(void*)), &dtp, sizeof(void*));
if(dtsize) {
for (size_t i=0; i<context->elfsize; ++i) {
for (int i=0; i<context->elfsize; ++i) {
// set pointer
dtp = (uintptr_t)ptr + (context->tlssize + GetTLSBase(context->elfs[i]));
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16), &dtp, sizeof(void*));
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8), &i, sizeof(void*)); // index
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16) = dtp;
*(uint64_t*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*16+8) = i; // index
}
}
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, sizeof(void*)); // address of vsyscall
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x20), &context->vsyscall, sizeof(void*)); // address of vsyscall
return data;
}
@@ -203,7 +254,7 @@ void* GetSegmentBase(uint32_t desc)
if(base==0x6)
return GetSeg33Base();
if(base>6 && base<10 && my_context->segtls[base-7].present) {
if(base>6 && base<11 && my_context->segtls[base-7].present) {
void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
return ptr;
}
+25
View File
@@ -9,6 +9,16 @@
#include "x87emu_private.h"
//#include "x64run_private.h"
void fpu_do_free(x64emu_t* emu, int i)
{
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
// check if all empty
for(int j=0; j<8; ++j)
if(emu->p_regs[j].tag != 0b11)
return;
emu->fpu_stack = 0;
}
void reset_fpu(x64emu_t* emu)
{
memset(emu->mmx87, 0, sizeof(emu->mmx87));
@@ -196,6 +206,21 @@ double FromLD(void* ld)
return ret;
}
#ifndef HAVE_LD80BITS
long double LD2localLD(void* ld)
{
// local implementation may not be try Quad precision, but double-double precision, so simple way to keep the 80bits precision in the conversion
double ret;
LD2D(ld, &ret);
return ret;
}
#else
long double LD2localLD(void* ld)
{
return *(long double*)ld;
}
#endif
void fpu_loadenv(x64emu_t* emu, char* p, int b16)
{
emu->cw = *(uint16_t*)p;
+1 -13
View File
@@ -14,10 +14,6 @@ typedef struct x64emu_s x64emu_t;
#define LN2 0.69314718055994531
#define LG2 0.3010299956639812
//void Run66D9(x64emu_t *emu);
//void Run66DD(x64emu_t *emu);
//void RunDF(x64emu_t *emu);
#define ST0 emu->mmx87[emu->top]
#define ST1 emu->mmx87[(emu->top+1)&7]
#define ST(a) emu->mmx87[(emu->top+(a))&7]
@@ -54,15 +50,7 @@ static inline void fpu_do_pop(x64emu_t* emu)
emu->top = (emu->top+1)&7;
}
static inline void fpu_do_free(x64emu_t* emu, int i)
{
emu->p_regs[(emu->top+i)&7].tag = 0b11; // empty
// check if all empty
for(int i=0; i<8; ++i)
if(emu->p_regs[i].tag != 0b11)
return;
emu->fpu_stack = 0;
}
void fpu_do_free(x64emu_t* emu, int i);
void reset_fpu(x64emu_t* emu);
+1 -1
View File
@@ -8,6 +8,6 @@ int init_auxval(int argc, const char **argv, const char **env);
#endif
unsigned long real_getauxval(unsigned long type);
//unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
unsigned long my_getauxval(x64emu_t* emu, unsigned long type);
#endif //__AUXVAL_H__
+17 -11
View File
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <pthread.h>
#include "pathcoll.h"
#include "dictionnary.h"
typedef struct elfheader_s elfheader_t;
typedef struct cleanup_s cleanup_t;
@@ -31,7 +32,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 +50,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 +72,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,10 +81,10 @@ 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;
uint64_t stacksz;
size_t stackalign;
void* stack; // alocated stack
elfheader_t **elfs; // elf headers and memory
@@ -96,6 +98,7 @@ typedef struct box64context_s {
lib_t *maplib; // lib and symbols handling
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
dic_t *versym; // dictionnary of versionned symbols
kh_threadstack_t *stacksizes; // stack sizes attributes for thread (temporary)
bridge_t *system; // other bridges
@@ -106,9 +109,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;
@@ -146,6 +146,7 @@ typedef struct box64context_s {
library_t *asound;
library_t *pulse;
library_t *d3dadapter9;
library_t *libglu;
int deferedInit;
elfheader_t **deferedInitList;
@@ -154,8 +155,8 @@ typedef struct box64context_s {
pthread_key_t tlskey; // then tls key to have actual tlsdata
void* tlsdata; // the initial global tlsdata
int32_t tlssize; // wanted size of tlsdata
base_segment_t segtls[3]; // only handling 0/1/2 descriptors
int64_t tlssize; // wanted size of tlsdata
base_segment_t segtls[4]; // only handling 0/1/2 descriptors (3 is internal use)
uintptr_t *auxval_start;
@@ -198,4 +199,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_
+25 -11
View File
@@ -20,33 +20,47 @@ void customFree(void* p);
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
// custom protection flag to mark Page that are Write protected for Dynarec purpose
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
uintptr_t AllocDynarecMap(dynablock_t* db, size_t size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, size_t size);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
void addDBFromAddressRange(uintptr_t addr, size_t size);
void cleanDBFromAddressRange(uintptr_t addr, size_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
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
#define PROT_DYNAREC 0x80
#define PROT_ALLOC 0x40
#define PROT_CUSTOM (PROT_DYNAREC|PROT_ALLOC)
void updateProtection(uintptr_t addr, size_t size, uint32_t prot);
void setProtection(uintptr_t addr, size_t size, uint32_t prot);
void freeProtection(uintptr_t addr, size_t size);
uint32_t getProtection(uintptr_t addr);
void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(uintptr_t addr, uintptr_t size);
void protectDBnolock(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
void protectDB(uintptr_t addr, size_t size);
void protectDBnolock(uintptr_t addr, size_t size);
void unprotectDB(uintptr_t addr, size_t size);
void lockDB();
void unlockDB();
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
void* find47bitBlock(size_t size);
void* find47bitBlockNearHint(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);
#endif //__CUSTOM_MEM__H_
#endif //__CUSTOM_MEM__H_
+14 -7
View File
@@ -4,6 +4,7 @@
typedef struct box64context_s box64context_t;
extern int box64_log; // log level
extern int box64_dump; // dump elf or not
extern int box64_dynarec_log;
extern int box64_dynarec;
extern int box64_pagesize;
@@ -11,19 +12,22 @@ extern int box64_pagesize;
extern int box64_dynarec_dump;
extern int box64_dynarec_trace;
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_wine;
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
@@ -31,12 +35,15 @@ extern int box64_tcmalloc_minimal; // when using tcmalloc_minimal
#define LOG_NONE 0
#define LOG_INFO 1
#define LOG_DEBUG 2
#define LOG_DUMP 3
#define LOG_NEVER 3
#define LOG_VERBOSE 3
extern FILE* ftrace;
#define printf_log(L, ...) do {if(L<=box64_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define printf_dump(L, ...) do {if(box64_dump || (L<=box64_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box64_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define EXPORT __attribute__((visibility("default")))
+13
View File
@@ -0,0 +1,13 @@
#ifndef __DICTIONNARY_H_
#define __DICTIONNARY_H_
#include <stdint.h>
typedef void dic_t;
dic_t *NewDictionnary();
void FreeDictionnary(dic_t **dic);
const char* AddDictionnary(dic_t* dic, const char* s);
int ExistDictionnary(dic_t* dic, const char* s);
#endif //__DICTIONNARY_H_
+2 -1
View File
@@ -11,7 +11,8 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db);
void MarkDynablock(dynablock_t* db);
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
//return 1 if Dynareblock is empty
int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box64context.h
+1 -1
View File
@@ -6,7 +6,7 @@ typedef struct elfheader_s elfheader_t;
const char* DumpSection(Elf64_Shdr *s, char* SST);
const char* DumpDynamic(Elf64_Dyn *s);
const char* DumpPHEntry(Elf64_Phdr *e);
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym);
const char* DumpSym(elfheader_t *h, Elf64_Sym* sym, int version);
const char* DumpRelType(int t);
const char* SymName(elfheader_t *h, Elf64_Sym* sym);
const char* IdxSymName(elfheader_t *h, int sym);
+9 -5
View File
@@ -26,11 +26,11 @@ int LoadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
int ReloadElfMemory(FILE* f, box64context_t* context, elfheader_t* head);
int RelocateElf(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
int RelocateElfPlt(lib_t *maplib, lib_t* local_maplib, elfheader_t* head);
void CalcStack(elfheader_t* h, uint32_t* stacksz, int* stackalign);
void CalcStack(elfheader_t* h, uint64_t* stacksz, size_t* stackalign);
uintptr_t GetEntryPoint(lib_t* maplib, elfheader_t* h);
uintptr_t GetLastByte(elfheader_t* h);
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h);
int LoadNeededLibs(elfheader_t* h, lib_t *maplib, needed_libs_t* neededlibs, 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);
@@ -41,11 +41,11 @@ void* GetElfDelta(elfheader_t* h);
uint32_t GetBaseSize(elfheader_t* h);
int IsAddressInElfSpace(elfheader_t* h, uintptr_t addr);
elfheader_t* FindElfAddress(box64context_t *context, uintptr_t addr);
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint32_t* sz);
const char* FindNearestSymbolName(elfheader_t* h, void* p, uintptr_t* start, uint64_t* sz);
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);
@@ -55,5 +55,9 @@ void CreateMemorymapFile(box64context_t* context, int fd);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
const char* GetSymbolVersion(elfheader_t* h, int version);
const char* GetParentSymbolVersion(elfheader_t* h, int index);
const char* VersionnedName(const char* name, int ver, const char* vername);
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
#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
+17
View File
@@ -0,0 +1,17 @@
#ifndef _GLOBAL_SYMBOLS_H_
#define _GLOBAL_SYMBOLS_H_
//GTK stuff
//void my_checkGlobalGdkDisplay();
//void my_setGlobalGThreadsInit();
//void** my_GetGTKDisplay();
//void** my_GetGthreadsGotInitialized(); // defined in wrappedgthread2
// NCurse / TInfo
void my_checkGlobalTInfo();
// getopt
void my_checkGlobalOpt();
#endif //_GLOBAL_SYMBOLS_H_
+13 -19
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,28 +24,22 @@ 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** paths, int npath, 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);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self);
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name);
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername);
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername);
int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername);
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
int GetNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername);
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername);
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername);
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // replace if already there
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name);
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz); // don't add if already there
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end);
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, const char** libname, void** base);
const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint64_t* sz, const char** libname, void** base);
void AddOffsetSymbol(lib_t *maplib, void* offs, const char* name);
const char* GetNameOffset(lib_t *maplib, void* offs);
#endif //__LIBRARIAN_H_
#endif //__LIBRARIAN_H_
+7 -6
View File
@@ -1,6 +1,7 @@
#ifndef __LIBRARY_H_
#define __LIBRARY_H_
#include <stdint.h>
#include "symbols.h"
typedef struct library_s library_t;
typedef struct lib_s lib_t;
@@ -9,18 +10,18 @@ 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)
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end);
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
void fillGLProcWrapper(box64context_t* context);
void freeGLProcWrapper(box64context_t* context);
void fillALProcWrapper(box64context_t* context);
@@ -33,4 +34,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_
+25
View File
@@ -89,9 +89,34 @@ 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);
// defined in wrapperlibc.c
int of_convert(int); // x86->arm
int of_unconvert(int); // arm->x86
void UnalignEpollEvent(void* dest, void* source, int nbr); // Arm -> x86
void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm
void UnalignSemidDs(void *dest, const void* source);
void AlignSemidDs(void *dest, const void* source);
+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
+4
View File
@@ -247,6 +247,7 @@ typedef union {
} mmx87_regs_t;
typedef union {
__uint128_t u128;
uint64_t q[2];
int64_t sq[2];
double d[2];
@@ -285,6 +286,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
+24
View File
@@ -0,0 +1,24 @@
#ifndef __SYMBOLS_PRIVATE_H_
#define __SYMBOLS_PRIVATE_H_
#include <stdint.h>
#include "custommem.h"
#include "khash.h"
typedef struct versymbols_s versymbols_t;
KHASH_MAP_DECLARE_STR(mapsymbols, versymbols_t)
kh_mapsymbols_t* NewMapSymbols();
void FreeMapSymbols(kh_mapsymbols_t** map);
// replace if already there
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local);
// don't add if already there
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local);
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
#endif //__SYMBOLS_PRIVATE_H_
+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 and unlock if a mutex is locked by current thread (works only for PTHREAD_MUTEX_ERRORCHECK typed mutex)
int checkUnlockMutex(void* m);
#endif //_THREADS_H_
+2 -3
View File
@@ -7,7 +7,7 @@ typedef struct box64context_s box64context_t;
typedef int (*wrappedlib_init_t)(library_t * lib, box64context_t* box64); // 0 = success
typedef void (*wrappedlib_fini_t)(library_t * lib);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uintptr_t *sz, int version, const char* vername, int local);
typedef struct wrappedlib_s {
const char* name;
@@ -15,7 +15,6 @@ typedef struct wrappedlib_s {
wrappedlib_fini_t fini;
wrappedlib_get_t get;
wrappedlib_get_t getnoweak;
wrappedlib_get_t getlocal;
} wrappedlib_t;
#endif //__WRAPPEDLIBS_H__
#endif //__WRAPPEDLIBS_H__
+2
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);
@@ -54,6 +55,7 @@ void UnimpOpcode(x64emu_t* emu);
uint64_t ReadTSC(x64emu_t* emu);
double FromLD(void* ld); // long double (80bits pointer) -> double
long double LD2localLD(void* ld); // long double (80bits pointer) -> long double (80 or 128bits)
void LD2D(void* ld, void* d); // long double (80bits) -> double (64bits)
void D2LD(void* d, void* ld); // double (64bits) -> long double (64bits)
+2
View File
@@ -10,4 +10,6 @@ void* fillTLSData(box64context_t *context);
void* resizeTLSData(box64context_t *context, void* oldptr);
void* GetSegmentBase(uint32_t desc);
int my_arch_prctl(x64emu_t *emu, int code, void* addr);
#endif //__X64_TLS_H__
+48
View File
@@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "dictionnary.h"
#include "custommem.h"
#include "khash.h"
KHASH_SET_INIT_STR(dic);
dic_t *NewDictionnary()
{
dic_t *dic = kh_init(dic);
return dic;
}
void FreeDictionnary(dic_t **d)
{
if(!d || !*d)
return;
kh_dic_t* dic = (kh_dic_t*)*d;
const char* k;
kh_foreach_key(dic, k, free((void*)k));
kh_destroy(dic, dic);
*d = NULL;
}
const char* AddDictionnary(dic_t* d, const char* s)
{
kh_dic_t* dic = (kh_dic_t*)d;
khint_t k = kh_get(dic, dic, s);
if(k!=kh_end(dic))
return kh_key(dic, k);
char* n = strdup(s);
int ret;
k = kh_put(dic, dic, n, &ret);
return n;
}
int ExistDictionnary(dic_t* d, const char* s)
{
kh_dic_t* dic = (kh_dic_t*)d;
khint_t k = kh_get(dic, dic, s);
if(k!=kh_end(dic))
return 1;
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "wrappedlibs.h"
#include "debug.h"
#include "wrapper.h"
#include "bridge.h"
#include "callback.h"
#include "box64context.h"
#include "librarian.h"
#include "library.h"
// workaround for Globals symbols
#define GLOB(A) \
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, #A, &globoffs, &globend, -1, NULL)) { \
printf_log(LOG_DEBUG, "Global " #A " workaround, @%p <= %p\n", (void*)globoffs, &A); \
memcpy((void*)globoffs, &A, sizeof(A)); \
}
// *********** GTK *****************
#if 0
EXPORT void* gdk_display = NULL; // in case it's used...
void my_checkGlobalGdkDisplay()
{
uintptr_t globoffs, globend;
GLOB(gdk_display)
}
void my_setGlobalGThreadsInit()
{
int val = 1;
uintptr_t globoffs, globend;
if (GetGlobalNoWeakSymbolStartEnd(my_context->maplib, "g_threads_got_initialized", &globoffs, &globend, -1, NULL)) {
printf_log(LOG_DEBUG, "Global g_threads_got_initialized workaround, @%p <= %p\n", (void*)globoffs, (void*)val);
memcpy((void*)globoffs, &val, sizeof(val));
}
}
char* getGDKX11LibName();
void** my_GetGTKDisplay()
{
if(gdk_display)
return &gdk_display;
char* name = getGDKX11LibName();
library_t * lib = GetLibInternal(name?name:"libgtk-1.2.so.0");
if(!lib) return &gdk_display; // mmm, that will crash later probably
void* s = dlsym(GetHandle(lib), "gdk_display");
gdk_display = *(void**)s;
return s;
}
#endif
// **************** NCurses ****************
EXPORT int COLS;
EXPORT int LINES;
EXPORT int TABSIZE;
EXPORT void* curscr;
EXPORT void* newscr;
EXPORT void* stdscr;
EXPORT void* acs_map[128];
EXPORT void* UP;
EXPORT void* BC;
EXPORT uint8_t PC;
EXPORT uint16_t ospeed;
EXPORT void* ttytype;
void my_checkGlobalTInfo()
{
uintptr_t globoffs, globend;
GLOB(COLS)
GLOB(LINES)
GLOB(TABSIZE)
GLOB(curscr)
GLOB(newscr)
GLOB(stdscr)
GLOB(acs_map)
GLOB(UP)
GLOB(BC)
GLOB(PC)
GLOB(ospeed)
GLOB(ttytype)
}
// **************** getopts ****************
EXPORT char *optarg;
EXPORT int optind, opterr, optopt;
void my_checkGlobalOpt()
{
uintptr_t globoffs, globend;
GLOB(optarg);
GLOB(optind);
GLOB(opterr);
GLOB(optopt);
}
Loaded 100 of 322 files, more files were not shown because too many files have changed in this diff. Show more