Compare commits

...
587 Commits
Author SHA1 Message Date
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
318 changed files with 43393 additions and 6071 deletions

No files matched your search

+16
View File
@@ -1,3 +1,19 @@
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
+108 -19
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" ${NO_LOADAADR})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(RK3399 OR RPI4ARM64)
if(RK3399 OR RPI4ARM64 OR RK3326)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -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)
@@ -92,6 +103,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 +141,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 +163,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 +185,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 +287,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 +334,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 +366,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 +392,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 +401,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 +508,11 @@ 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 )
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.
+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.)
+770 -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 0
#endif //__BOX64_VERSION_H_
+322 -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,42 @@ 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);
}
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 +873,126 @@ 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;
}
void* find32bitBlock(size_t size)
{
// slow iterative search... Would need something better one day
const uint32_t key = 0; // upper value is 0 by request
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
return LOWEST;
}
uint8_t *prot = kh_val(memprot, k);
pthread_mutex_unlock(&mutex_prot);
void* p = (void*)LOWEST;
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
do {
const uintptr_t idx = ((uintptr_t)p)>>MEMPROT_SHIFT;
if(availableBlock(prot+idx, pages))
return p;
p += 0x10000;
} while(p!=(void*)0xffff0000);
printf_log(LOG_NONE, "Warning: cannot find a 0x%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
if(!hint) hint=LOWEST;
const uint32_t key = (((uintptr_t)hint)>>32)&0xffffffff;
pthread_mutex_lock(&mutex_prot);
khint_t k = kh_get(memprot, memprot, key);
if(k==kh_end(memprot)) {
pthread_mutex_unlock(&mutex_prot);
return hint;
}
uint8_t *prot = kh_val(memprot, k);
pthread_mutex_unlock(&mutex_prot);
void* p = hint;
void* end = (void*)((uintptr_t)hint+0x100000000LL);
uintptr_t step = (size+0xfff)&~0xfff;
int pages = (size+MEMPROT_SIZE-1)>>MEMPROT_SHIFT;
do {
const uintptr_t idx = (((uintptr_t)p)&0xffffffff)>>MEMPROT_SHIFT;
if(availableBlock(prot+idx, pages))
return p;
p += step;
} while(p!=end);
printf_log(LOG_NONE, "Warning: cannot find a 0x%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 +1005,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 +1081,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__
+1
View File
@@ -19,6 +19,7 @@ arm64_next:
stp x14, x15, [sp, (8 * 6)]
stp x16, x17, [sp, (8 * 8)]
str x18, [sp, (8 * 10)]
mov x2, lr // "from" is in lr, so put in x2
// call the function
bl LinkNext
// preserve return value
+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
+235 -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,198 @@ 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;
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 +259,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 +268,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 +278,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 +287,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 +295,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 +303,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 +311,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 +324,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 +337,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 +349,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;
@@ -183,4 +393,3 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
}
return addr;
}
+119 -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,21 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
INST_NAME("NOP");
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 +502,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 +552,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 +562,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 +572,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 +583,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 +595,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 +622,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 +663,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 +677,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 +685,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 +695,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 +712,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 +729,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 +746,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 +764,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 +778,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 +807,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 +834,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 +848,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
}
+277 -58
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,13 @@ 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)
{
MESSAGE(LOG_DUMP, "IRet epilog\n");
MAYUSE(ninst);
MESSAGE(LOG_DUMP, "IRet to epilog\n");
// POP IP
POP1(xRIP);
// POP CS
@@ -331,6 +474,7 @@ 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) {
@@ -375,8 +519,9 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save
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 +545,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 +604,7 @@ int x87_do_push(dynarec_arm_t* dyn, int ninst)
}
return ret;
#else
(void)dyn;
return 0;
#endif
}
@@ -465,10 +618,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 +636,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 +658,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 +674,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 +684,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 +700,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 +716,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 +732,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 +768,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 +785,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 +794,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 +810,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 +838,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 +869,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 +893,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 +962,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 +999,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 +1022,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 +1041,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 +1078,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,22 +1102,28 @@ 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) ninst; (void)s1;
#if STEP > 1
// only SSE regs needs to be push back to xEmu
int n=0;
@@ -926,11 +1138,14 @@ void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1)
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) ninst; (void)s1;
#if STEP > 1
// only SSE regs needs to be pop back from xEmu
int n=0;
@@ -945,6 +1160,8 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1)
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 +1194,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 +1205,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);
}
}
+185 -117
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,20 @@ 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 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 +730,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
@@ -758,8 +821,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 +871,33 @@ void sse_purge07cache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_reset(dynarec_arm_t* dyn, int ninst);
// purge the FPU cache (needs 3 scratch registers)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// purge MMX cache
void mmx_purgecache(dynarec_arm_t* dyn, int ninst, int s1);
// purge x87 cache
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
#endif
void fpu_pushcache(dynarec_arm_t* dyn, int ninst, int s1);
void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
uintptr_t dynarec64_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 +1009,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;
+406 -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));
}
}
+2 -1
View File
@@ -52,6 +52,7 @@ typedef struct x64emu_s {
multiuint_t res;
uint32_t *x64emu_parity_tab; // helper
#ifdef HAVE_TRACE
reg64_t oldregs[16];
uintptr_t prev2_ip;
#endif
// segments
@@ -91,4 +92,4 @@ typedef struct x64emu_s {
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
#endif //__X86EMU_PRIVATE_H_
#endif //__X86EMU_PRIVATE_H_
+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);
}
+143 -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);
@@ -1085,7 +1144,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 +1160,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 +1176,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 +1233,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 +1326,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 +1379,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 +1431,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:
+217 -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,220 @@ 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;
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 +337,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);
@@ -150,4 +358,4 @@ int Run64(x64emu_t *emu, rex_t rex)
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_
+22 -11
View File
@@ -20,33 +20,44 @@ 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);
#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);
// 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_
+13 -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,21 @@ 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_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 +34,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
+3
View File
@@ -285,6 +285,9 @@ typedef union {
#define R_ESI emu->regs[_SI].dword[0]
#define R_ESP emu->regs[_SP].dword[0]
#define R_EBP emu->regs[_BP].dword[0]
#define R_R8d emu->regs[_R8].dword[0]
#define R_R9d emu->regs[_R9].dword[0]
#define R_R10d emu->regs[_R10].dword[0]
#define R_AX emu->regs[_AX].word[0]
#define R_BX emu->regs[_BX].word[0]
#define R_CX emu->regs[_CX].word[0]
+4 -4
View File
@@ -1,7 +1,7 @@
#ifndef __SDL2RWOPS_H__
#define __SDL2RWOPS_H__
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL1 SDL_RWops
typedef struct SDL2_RWops_s SDL2_RWops_t; // the actual SDL2 SDL_RWops
typedef struct x64emu_s x64emu_t;
typedef SDL2_RWops_t* (*sdl2_allocrw)();
@@ -20,12 +20,12 @@ typedef struct SDL2RWSave_s {
// each function will be added to dictionary, and each native functions will be wrapped so they run in emulated world
SDL2_RWops_t* AddNativeRW2(x64emu_t* emu, SDL2_RWops_t* ops);
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put Native RW function, wrapping emulated (callback style) ones if needed
void RWNativeEnd2(SDL2_RWops_t* ops); // put back emulated function back in place
SDL2_RWops_t* RWNativeStart2(x64emu_t* emu, SDL2_RWops_t* ops); // put native RW functions, wrapping the emulated (callback style) ones if needed
void RWNativeEnd2(SDL2_RWops_t* ops); // put emulated function back in place
int64_t RWNativeSeek2(SDL2_RWops_t *ops, int64_t offset, int32_t whence);
uint32_t RWNativeRead2(SDL2_RWops_t* ops, void* ptr, uint32_t size, uint32_t maxnum);
int32_t RWNativeWrite2(SDL2_RWops_t *ops, const void *ptr, int32_t size, int32_t num);
int32_t RWNativeClose2(SDL2_RWops_t* ops);
#endif
#endif
+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);
}
+219 -171
View File
@@ -14,18 +14,17 @@
#include "bridge.h"
KHASH_MAP_IMPL_STR(mapsymbols, onesymbol_t);
KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
lib_t *NewLibrarian(box64context_t* context, int ownlibs)
{
lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t));
maplib->mapsymbols = kh_init(mapsymbols);
maplib->weaksymbols = kh_init(mapsymbols);
maplib->localsymbols = kh_init(mapsymbols);
maplib->mapsymbols = NewMapSymbols();
maplib->weaksymbols = NewMapSymbols();
maplib->localsymbols = NewMapSymbols();
maplib->mapoffsets = kh_init(mapoffsets);
maplib->globaldata = kh_init(mapsymbols);
maplib->globaldata = NewMapSymbols();
maplib->bridge = NewBridge();
maplib->context = context;
@@ -34,37 +33,73 @@ lib_t *NewLibrarian(box64context_t* context, int ownlibs)
return maplib;
}
void FreeLibrarian(lib_t **maplib)
static void freeLibraryRecurse(lib_t *maplib, x64emu_t *emu, int idx, char *freed, library_t* owner) {
if (freed[idx]) return; // Already freed
freed[idx] = 1; // Avoid infinite loops
library_t *lib = maplib->libraries[idx];
if(lib==owner) return; // don't free owner of maplib
printf_log(LOG_DEBUG, "Free %s\n", lib->name);
for (int i = lib->depended.size - 1; i >= 0; --i) {
int j;
for (j = 0; j < maplib->libsz; ++j) {
if (lib->depended.libs[i] == maplib->libraries[j]) break;
}
if (j == maplib->libsz) {
printf_log(LOG_INFO, "Library %s (%p) needs %p, but it was not found. Ignoring.\n", lib->name, lib, lib->depended.libs[i]);
continue;
}
if (freed[j] == 1) {
printf_log(LOG_DEBUG, "Cyclic dependancy detected (cycle is between %s and %s)\n", lib->name, lib->depended.libs[i]->name);
continue;
}
freeLibraryRecurse(maplib, emu, j, freed, owner);
if (freed[idx] != 1) {
printf_log(LOG_DEBUG, "Library cleared (cyclic dependancy break)\n");
return;
}
}
library_t *ptr = maplib->libraries[idx];
if(maplib->ownlibs)
Free1Library(&ptr, emu);
freed[idx] = 2;
}
void FreeLibrarian(lib_t **maplib, x64emu_t *emu)
{
// should that be in reverse order?
if(!maplib || !*maplib)
return;
if((*maplib)->ownlibs) {
library_t* owner = (*maplib)->owner;
(*maplib)->owner = NULL; // to avoid recursive free
if((*maplib)->ownlibs && (*maplib)->libsz) {
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
for (int i=0; i<(*maplib)->libsz; ++i) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i].lib->name);
Free1Library(&(*maplib)->libraries[i].lib);
char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
if (!freed) {
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
for (int i=(*maplib)->libsz-1; i>=0; --i)
if((*maplib)->libraries[i]!=owner) {
printf_log(LOG_DEBUG, "Unloading %s\n", (*maplib)->libraries[i]->name);
Free1Library(&(*maplib)->libraries[i], emu);
}
} else {
for (int i=(*maplib)->libsz-1; i>=0; --i) {
freeLibraryRecurse(*maplib, emu, i, freed, owner);
}
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
(*maplib)->libsz = 0;
free(freed);
}
}
free((*maplib)->libraries);
(*maplib)->libraries = NULL;
if((*maplib)->mapsymbols) {
kh_destroy(mapsymbols, (*maplib)->mapsymbols);
}
if((*maplib)->weaksymbols) {
kh_destroy(mapsymbols, (*maplib)->weaksymbols);
}
if((*maplib)->localsymbols) {
kh_destroy(mapsymbols, (*maplib)->localsymbols);
}
FreeMapSymbols(&(*maplib)->mapsymbols);
FreeMapSymbols(&(*maplib)->weaksymbols);
FreeMapSymbols(&(*maplib)->localsymbols);
if((*maplib)->mapoffsets) {
kh_destroy(mapoffsets, (*maplib)->mapoffsets);
}
if((*maplib)->globaldata) {
kh_destroy(mapsymbols, (*maplib)->globaldata);
}
FreeMapSymbols(&(*maplib)->globaldata);
(*maplib)->libsz = (*maplib)->libcap = 0;
if((*maplib)->bridge)
@@ -103,9 +138,9 @@ kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
library_t* getLib(lib_t* maplib, const char* path)
{
for(int i=0; i<maplib->libsz; ++i) {
onelib_t *onelib = &maplib->libraries[i];
if(IsSameLib(onelib->lib, path)) {
return onelib->lib;
library_t *lib = maplib->libraries[i];
if(IsSameLib(lib, path)) {
return lib;
}
}
return NULL;
@@ -116,19 +151,20 @@ static int libraryInMapLib(lib_t* maplib, library_t* lib)
if(!maplib)
return 0;
for(int i=0; i<maplib->libsz; ++i)
if(maplib->libraries[i].lib==lib)
if(maplib->libraries[i]==lib)
return 1;
return 0;
}
void MapLibAddLib(lib_t* maplib, library_t* lib)
{
if(libraryInMapLib(maplib, lib))
return;
if (maplib->libsz == maplib->libcap) {
maplib->libcap += 8;
maplib->libraries = (onelib_t*)realloc(maplib->libraries, maplib->libcap*sizeof(onelib_t));
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
}
maplib->libraries[maplib->libsz].lib = lib;
maplib->libraries[maplib->libsz].name = GetNameLib(lib);
maplib->libraries[maplib->libsz] = lib;
++maplib->libsz;
}
@@ -137,15 +173,14 @@ void MapLibAddMapLib(lib_t* dest, lib_t* src)
if(!src)
return;
for(int i=0; i<src->libsz; ++i) {
library_t* lib = src->libraries[i].lib;
if(!lib) continue;
library_t* lib = src->libraries[i];
if(!lib || libraryInMapLib(dest, lib)) continue;
MapLibAddLib(dest, lib);
if(lib->maplib && src!=lib->maplib) { //TODO: find why is src!=lib->maplib needed
MapLibAddMapLib(dest, lib->maplib);
free(lib->maplib);
lib->maplib = NULL;
}
if(!libraryInMapLib(dest, lib))
MapLibAddLib(dest, lib);
}
}
@@ -154,24 +189,39 @@ void MapLibRemoveLib(lib_t* maplib, library_t* lib)
if(!maplib || !lib)
return;
int idx = 0;
while(idx<maplib->libsz && maplib->libraries[idx].lib!=lib) ++idx;
while(idx<maplib->libsz && maplib->libraries[idx]!=lib) ++idx;
if(idx==maplib->libsz) //not found
return;
--maplib->libsz;
if(idx!=(maplib->libsz))
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(onelib_t)*(maplib->libsz-idx));
maplib->libraries[maplib->libsz].lib = NULL;
maplib->libraries[maplib->libsz].name = NULL;
memmove(&maplib->libraries[idx], &maplib->libraries[idx+1], sizeof(library_t*)*(maplib->libsz-idx));
}
EXPORTDYN
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char* path, box64context_t* box64, x64emu_t* emu)
static void MapLibRemoveMapLib(lib_t* dest, lib_t* src)
{
if(!src)
return;
//library_t *owner = src->owner;
for(int i=0; i<src->libsz; ++i) {
library_t* lib = src->libraries[i];
if(!lib || !libraryInMapLib(dest, lib)) continue;
MapLibRemoveLib(dest, lib);
if(lib->maplib && src!=lib->maplib && dest!=lib->maplib) {
MapLibRemoveMapLib(dest, lib->maplib);
if(lib->maplib && src==my_context->local_maplib)
lib->maplib = NULL;
}
}
}
int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, const char* path, box64context_t* box64, x64emu_t* emu)
{
printf_log(LOG_DEBUG, "Trying to add \"%s\" to maplib%s\n", path, local?" (local)":"");
// first check if lib is already loaded
library_t *lib = getLib(my_context->maplib, path);
if(lib) {
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
printf_log(LOG_DEBUG, "Already present in maplib => success\n");
return 0;
}
@@ -187,6 +237,8 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
}
if(!libraryInMapLib(maplib, lib))
MapLibAddLib(maplib, lib);
if(maplib->ownlibs)
MapLibRemoveMapLib(my_context->local_maplib, maplib);
}
} else {
// promote lib from local to global...
@@ -198,9 +250,10 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
}
if(!libraryInMapLib(my_context->maplib, lib))
MapLibAddLib(my_context->maplib, lib);
MapLibRemoveLib(my_context->local_maplib, lib);
MapLibRemoveMapLib(my_context->local_maplib, my_context->maplib);
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
return 0;
}
// load a new one
@@ -211,6 +264,7 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
}
add_neededlib(neededlibs, lib);
if (lib && deplib) add_dependedlib(&lib->depended, deplib);
// add lib now
if(local) {
@@ -226,33 +280,38 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
}
return 0;
}
int AddNeededLib_init(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, library_t* lib, box64context_t* box64, x64emu_t* emu)
{
if(!maplib)
maplib = (local)?lib->maplib:my_context->maplib;
int mainelf = GetElfIndex(lib);
if(mainelf==-1) {
// It's a native libs, just add wrapped symbols to global map
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
}
// It's a native libs, nothing else to do
} else {
// it's an emulated lib,
// lets load dependancies before adding symbols and launch init sequence
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, 0, box64, emu)) {
// load dependancies and launch init sequence
if(LoadNeededLibs(box64->elfs[mainelf], maplib, &lib->needed, lib, 0, box64, emu)) {
printf_log(LOG_DEBUG, "Failure to Add dependant lib => fail\n");
return 1;
}
// some special case, where dependancies may not be correct
if(!strcmp(GetNameLib(lib), "libCgGL.so")) {
AddNeededLib(maplib, &lib->needed, 0, "libGL.so.1", box64, emu);
const char* libs[] = {"libGL.so.1"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 1, box64, emu);
}
if(!strcmp(GetNameLib(lib), "libmss.so.6")) {
AddNeededLib(maplib, &lib->needed, 0, "libSDL-1.2.so.0", box64, emu);
AddNeededLib(maplib, &lib->needed, 0, "libdl.so.2", box64, emu);
}
// add symbols
if(AddSymbolsLibrary(maplib, lib, emu)) { // also add needed libs
printf_log(LOG_DEBUG, "Failure to Add lib => fail\n");
return 1;
const char* libs[] = {"libSDL-1.2.so.0", "libdl.so.2"};
AddNeededLib(maplib, &lib->needed, lib, 0, libs, 2, box64, emu);
}
// finalize the lib
@@ -267,6 +326,31 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, int local, const char
return 0;
}
EXPORTDYN
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)
{
if(!neededlibs) {
neededlibs = alloca(sizeof(needed_libs_t));
memset(neededlibs, 0, sizeof(needed_libs_t));
}
int idx = neededlibs->size;
// Add libs and symbol
for(int i=0; i<npath; ++i) {
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box64, emu)) {
printf_log(LOG_INFO, "Error loading needed lib %s\n", paths[i]);
return 1;
}
}
int idx_end = neededlibs->size;
// add dependant libs and init them
for (int i=idx; i<idx_end; ++i)
if(AddNeededLib_init(maplib, neededlibs, deplib, local, neededlibs->libs[i], box64, emu)) {
printf_log(LOG_INFO, "Error initializing needed lib %s\n", neededlibs->libs[i]->name);
if(!allow_missing_libs) return 1;
}
return 0;
}
library_t* GetLibMapLib(lib_t* maplib, const char* name)
{
printf_log(LOG_DEBUG, "Trying to Get \"%s\" to maplib\n", name);
@@ -282,44 +366,53 @@ library_t* GetLibInternal(const char* name)
}
EXPORTDYN
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name)
uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start = 0, end = 0;
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end))
if(GetGlobalSymbolStartEnd(maplib, name, &start, &end, (void*)1, version, vername))
return start;
return 0;
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self)
static int isLocal(elfheader_t* self, library_t* l)
{
if(GetElfIndex(l)==-1)
return 1;
if(my_context->elfs[GetElfIndex(l)]==self)
return 1;
return 0;
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
//excude self if defined
if(maplib->context->elfs[0]!=self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 0))
if(*start)
return 1;
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 0))
if(*start)
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]!=self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 0))
if(*start)
return 1;
}
// if self defined, give it another chance with self...
if(self) {
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
if(*start)
return 1;
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 1))
if(*start)
return 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start)
return 1;
}
@@ -327,48 +420,48 @@ int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
// nope, not found
return 0;
}
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
if(*start)
return 1;
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
// search in needed libs from neededlibs first, in order
for(int i=0; i<my_context->neededlibs.size; ++i)
if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end))
if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
if(*start)
return 1;
// search in global symbols
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
return 1;
}
// library from newer to older, weak only now
for(int i=maplib->libsz-1; i>=0; --i) {
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end)) // only weak symbol haven't been found yet
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
if(*start)
return 1;
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) // only weak symbol haven't been found yet
if(*start)
return 1;
}
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end))
if(*start)
return 1;
// nope, not found
return 0;
}
//void** my_GetGTKDisplay();
//void** my_GetGthreadsGotInitialized();
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end)
int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end)) {
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2)) {
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
if(end2>*end && start2==end2)
*end = end2;
}
@@ -377,35 +470,35 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
return 1;
}
// some special case symbol, defined inside box64 itself
// if(!strcmp(name, "gdk_display")) {
// *start = (uintptr_t)my_GetGTKDisplay();
// *end = *start+sizeof(void*);
// printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
// return 1;
// }
// if(!strcmp(name, "g_threads_got_initialized")) {
// *start = (uintptr_t)my_GetGthreadsGotInitialized();
// *end = *start+sizeof(int);
// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
// return 1;
// }
//if(!strcmp(name, "gdk_display")) {
// *start = (uintptr_t)my_GetGTKDisplay();
// *end = *start+sizeof(void*);
// printf_log(LOG_INFO, "Using global gdk_display for gdk-x11 (%p:%p)\n", start, *(void**)start);
// return 1;
//}
//if(!strcmp(name, "g_threads_got_initialized")) {
// *start = (uintptr_t)my_GetGthreadsGotInitialized();
// *end = *start+sizeof(int);
// printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
// return 1;
//}
// not found...
return 0;
}
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start = 0;
uintptr_t end = 0;
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end, version, vername, 1))
return maplib->context->elfs[0];
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end))
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end, version, vername, 1))
return maplib->context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end)) {
int idx = GetElfIndex(maplib->libraries[i].lib);
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i].lib));
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
return maplib->context->elfs[idx];
@@ -415,26 +508,25 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name)
return NULL;
}
int GetGlobalNoWeakSymbolStartEnd(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 version, const char* vername)
{
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
for(int i=0; i<maplib->libsz; ++i)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
// nope, not found
return 0;
}
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start=0;
uintptr_t end=0;
uintptr_t start, end;
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i].lib)==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, &start, &end))
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1))
if(start || end)
return 1;
// nope, not found
@@ -442,18 +534,18 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name)
}
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self)
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
{
if(maplib->context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
if(self)
return 0;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start)
return 1;
if(self)
@@ -463,16 +555,16 @@ int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, ui
return 0;
}
int GetSelfSymbolStartEnd(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 version, const char* vername)
{
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
}
@@ -480,78 +572,28 @@ int GetSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uin
return 0;
}
int GetNoWeakSymbolStartEnd(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, int version, const char* vername)
{
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end))
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
if(*start || *end)
return 1;
} else {
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i].lib)!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i].lib)]==self))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i].lib, name, start, end))
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(*start || *end)
return 1;
}
}
return 0;
}
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
kh_value(mapsymbols, k).offs = addr;
kh_value(mapsymbols, k).sz = sz;
}
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name)
{
khint_t k = kh_get(mapsymbols, mapsymbols, name);
if(k==kh_end(mapsymbols))
return 0;
return kh_val(mapsymbols, k).offs;
}
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
if(ret==0)
return; // Symbol already there, don't touch it
kh_value(mapsymbols, k).offs = addr;
kh_value(mapsymbols, k).sz = sz;
}
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end)
{
khint_t k = kh_get(mapsymbols, mapsymbols, name);
if(k==kh_end(mapsymbols))
return 0;
*start = kh_val(mapsymbols, k).offs;
*end = *start + kh_val(mapsymbols, k).sz;
return 1;
}
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* start, uint32_t* sz)
{
uintptr_t addr = (uintptr_t)p;
onesymbol_t *one;
kh_foreach_value_ref(mapsymbols, one,
if((one->offs >= addr) && (one->offs+one->sz<addr)) {
*start = one->offs;
*sz = one->sz;
return kh_key(mapsymbols, __i);
}
);
return NULL;
}
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)
{
// first, search in self...
const char* ret = NULL;
uintptr_t offs = 0;
uint32_t size = 0;
uint64_t size = 0;
elfheader_t* h = FindElfAddress(my_context, (uintptr_t)p);
if(h) {
ret = FindNearestSymbolName(h, p, &offs, &size);
@@ -567,7 +609,13 @@ const char* FindSymbolName(lib_t *maplib, void* p, void** start, uint32_t* sz, c
*base = GetBaseAddress(h);
return ret;
}
// TODO: then search in the other libs...
// TODO: find if cyclic references exists (should also fix MapLibAddMapLib)
(void)maplib;
/* for (int i = 0; i < maplib->libsz; ++i) {
// if (maplib == maplib->libraries[i]->maplib) continue;
const char *nameInLib = FindSymbolName(maplib->libraries[i]->maplib, p, start, sz, libname, base);
if (nameInLib) return nameInLib;
} */
return NULL;
}
Loaded 100 of 318 files, more files were not shown because too many files have changed in this diff. Show more