Author SHA1 Message Date
ptitSeb 9c6f99f583 Merge branch 'master' into remove_dynablocklist 2022-11-11 22:35:37 +01:00
ptitSeb caf0bb9d4d [DYNAREC] Beter test when looking at CALL destination 2022-11-11 22:35:26 +01:00
ptitSeb 753f738368 Fix an issue with dynarec build when running without dynarec 2022-11-11 21:00:32 +01:00
ptitSeb 5eb76327ff Merge branch 'master' into remove_dynablocklist 2022-11-11 19:51:07 +01:00
ptitSeb 06a19ba790 Fix x86 build 2022-11-11 19:49:54 +01:00
ptitSeb 795dd3b305 Merge branch 'master' into remove_dynablocklist 2022-11-11 18:47:11 +01:00
ptitSeb d63a846748 Improved cpu cores detection and reporting 2022-11-11 18:46:57 +01:00
ptitSeb 3b389b979a Merge branch 'master' into remove_dynablocklist 2022-11-11 00:41:42 +01:00
ptitSeb 3f46f9fb68 Reworked vulkan structure wrapping 2022-11-11 00:41:28 +01:00
ptitSeb ff92ae2db5 [DYNAREC] Fixed a small issue with a potential harmless invalid read 2022-11-11 00:38:04 +01:00
ptitSeb 20cae21475 Merge branch 'master' into remove_dynablocklist 2022-11-08 21:58:35 +01:00
ptitSeb 521dae4695 Added some more Vulkan wrapped functions and aligned structures 2022-11-08 21:58:22 +01:00
ptitSeb dfc63d3e46 Small improvment to customMem manager 2022-11-08 20:47:09 +01:00
ptitSeb af78a2e58b Merge branch 'master' into remove_dynablocklist 2022-11-07 14:57:12 +01:00
ptitSeb 4b7a3046ce Changed again how mmap with NULL hint works (fixes some Wine programs/games, linux Witcher2 still working) 2022-11-07 14:56:56 +01:00
ptitSeb babbcab3da Merge branch 'master' into remove_dynablocklist 2022-11-03 16:30:01 +01:00
ptitSeb b0ac567e7a Synbol with version 0 also look for default versionned one 2022-11-03 16:27:29 +01:00
ptitSeb 455fce9ff5 Added special case for GeminiRue (same as A Golden Wake) 2022-11-03 12:05:09 +01:00
ptitSeb 363851f9d2 Fixed non-Dynarec build 2022-11-03 09:43:13 +01:00
ptitSeb 905043012e Removed dynablocklist and introduced hotpages 2022-11-03 09:16:00 +01:00
ptitSeb e0ba315761 Fixed alignment of XIDeviceEvent structure in some case of XGetEventData call (fixed SuperHexagon GLUT issues) 2022-11-02 21:29:00 +01:00
ptitSeb e41be11e9f Update box86syscall.c to use box_malloc and not __libc_malloc 2022-11-01 23:23:39 +01:00
ptitSeb 9f0c33016f Fixed a warning 2022-11-01 23:05:14 +01:00
ptitSeb faa13945eb [ANDROID] And more fixes for android 2022-11-01 23:04:10 +01:00
ptitSeb 989952a873 [ANDROID] And more fixes. 2022-11-01 21:43:43 +01:00
ptitSeb bc9f8df2c2 [ANDROID] Well, removed the memory overloading from Android build. 2022-11-01 20:58:47 +01:00
ptitSeb ddface22a8 [ANDROID] Yet another fix for Android 2022-11-01 20:43:54 +01:00
ptitSeb cf18090431 [DYNAREC] Small change to use alloca instead of calloc 2022-11-01 20:38:01 +01:00
ptitSeb cd27cf03e1 Added a bunch of wrapped function to nss3 and co (for Garry's mod, but still not working) 2022-11-01 18:30:59 +01:00
ptitSeb c0f643dcbe Another fix for Android build 2022-11-01 18:22:02 +01:00
ptitSeb 84ffab7354 [ANDROID] Fixed build 2022-11-01 17:58:18 +01:00
ptitSeb cbfd949756 Fixed libudev.so.1 dependancy for wrapped libudev.so.0 2022-11-01 17:35:30 +01:00
ptitSeb 55ce03844f Added support Malloc override and libtbbmalloc_proxy, backported from box64 (fixed Hacknet, probably other stuff based on libcef too) 2022-11-01 15:13:22 +01:00
ptitSeb 1451fa8c65 Added support for MOVBE extension ([DYNAREC] too) 2022-11-01 13:19:56 +01:00
ptitSeb d87f90dca3 [DYNAREC] Reprotect bridge when emu is running 2022-11-01 12:22:29 +01:00
ptitSeb 6f8164da52 Update README_CN.md 2022-11-01 12:20:52 +01:00
ptitSeb aace0531ab Update README.md with new sponsors
Thx for keeping this project alive!
2022-11-01 12:20:15 +01:00
ptitSeb 91609788d4 Better fix, again, for dlsym(RTLD_NEXT, ...) 2022-10-29 16:48:16 +02:00
ptitSeb b5b7019b79 Better fix for dlsym(RTLD_NEXT, ...) 2022-10-29 16:28:09 +02:00
ptitSeb 2bcafd6ef7 Some handling of execve with unexpected argv[0] (backported from box64) 2022-10-29 15:58:14 +02:00
ptitSeb 0f1092200c Try to get a cleaner exit 2022-10-29 14:08:30 +02:00
ptitSeb ccf612a711 Fix for dlsym(RTLD_NEXT, ...) 2022-10-29 13:52:04 +02:00
ptitSeb d8ec77da69 Added custom implementation of pthread_once (backported from box64) 2022-10-29 13:49:00 +02:00
ptitSeb aa3efd01cc Imrpoved Bridges, again 2022-10-29 10:09:25 +02:00
ptitSeb 58ca96e2a5 Try to fix a strange SIGILL on RPI2 build 2022-10-28 13:38:35 +02:00
ptitSeb 5bf7a15f8e Fixed some issue with bridge memory protection handling 2022-10-27 18:44:00 +02:00
ptitSeb 7d863efcf8 [DYNAREC] Last fix was a bit taxing on the performances, fixed that 2022-10-24 14:56:29 +02:00
ptitSeb 6f43a14ddd [DYNAREC] Fixed a potential issue with new flag handling 2022-10-24 10:34:31 +02:00
ptitSeb 369aa14bff [DYNAREC] Better (defered) flag handling in dynarec (gives between 5% and 10% speedup) 2022-10-23 16:16:20 +02:00
ptitSeb 4bd4f320bc Added setutxent/getutxent wrapped functions 2022-10-23 15:35:54 +02:00
ptitSeb e0340b2a74 Small fixes and improvments to last symbol refactor 2022-10-22 21:35:14 +02:00
ptitSeb 508b2aa580 Forgot to return the value in wrapped __libc_start_main 2022-10-19 21:49:38 +02:00
ptitSeb b8ec0f910c Refactored, again, elfloader symbol fetching (fixing issues like when libc++ and libstdc++ are both loaded) 2022-10-19 10:37:14 +02:00
ptitSeb c716b3b481 [DYNAREC] Initialize dynmap, it's cleaner 2022-10-19 10:37:14 +02:00
ptitSeb ddecd61771 Rename private field nlib to elib, for Emulated 2022-10-19 10:37:14 +02:00
ptitSeb 88c490b843 More library struture refactor and simplifications 2022-10-19 10:37:14 +02:00
ptitSeb 5998ae57ea Refactored library a bit to better seperate emulated and native private fields 2022-10-19 10:37:14 +02:00
Alex 94c99353fa disable modern login and pass arguments to client (#700)
disables the new react ui because the browser isn't available for now and passes the additional command line arguments to the main client
2022-10-16 21:06:05 +02:00
ptitSeb b993866def Added 0F 0E FEMMS opcode to rise SIGILL (for #440 and the Legacy of Kain game serie) 2022-10-13 22:47:54 +02:00
ptitSeb b292efc741 Use prefere emulated lib when detecting A Golden Wake (fix the random freeze) 2022-10-13 15:29:26 +02:00
ptitSeb bc78375816 Improved brk handling (for statically linked program) 2022-10-13 13:57:28 +02:00
ptitSeb 82e4997624 Fixed a warning 2022-10-13 13:57:04 +02:00
ptitSeb 51c64e7dce Improved support for older program on pthread kill/join 2022-10-13 12:11:52 +02:00
ptitSeb 294adeae11 Added some special case for sc3u to patch a bug in the code 2022-10-13 12:11:21 +02:00
ptitSeb 95c4c277a1 Fixed gtk-x11 GCallback callback definition 2022-10-13 12:10:36 +02:00
ptitSeb 3d517c0bf5 Added 2 gnutls wrapped functions (for #677) 2022-10-12 22:45:05 +02:00
ptitSeb 2bd3a670e8 Added wrapped XftNameUnparse function (for #424) 2022-10-12 21:52:22 +02:00
ptitSeb a621a2b61f Improved test11 a bit (for #604) 2022-10-12 21:37:29 +02:00
ptitSeb bc810d16f1 Added sigsetjmp wrapped function (for #578) 2022-10-12 20:50:16 +02:00
ptitSeb fd3f8f5990 Better support for brk syscall (helps #472) 2022-10-12 18:41:47 +02:00
ptitSeb c713f64d7e [DYNAREC] Remade lock cmpxchg opcode 2022-10-12 17:47:36 +02:00
ptitSeb ed2a8ff73d [DYNAREC] Don't try to extend a block that will not be extended 2022-10-12 17:47:11 +02:00
ptitSeb 31524ed90b Made main use Dynarec if available for 1st run call 2022-10-12 15:46:17 +02:00
ptitSeb 1c5aef19ae Fixed syscall 55 and added a bunch of new ones, includding a squeleton for 117 (ipc) 2022-10-12 15:45:39 +02:00
ptitSeb 1932f8320a Made custommalloc to use malloc for now, instead of mmap (helps #423) 2022-10-12 14:25:07 +02:00
Trass3r ae590d8378 Add atomic add opcodes (#695)
* [DYNAREC] Improve logging in case of missing opcode

* [DYNAREC] Added 66 F0 81/83 (lock add) opcodes
2022-10-12 11:51:15 +02:00
ptitSeb 124ca7fdc2 Added one more wrapped function libgtk-x11 (for #466) 2022-10-11 19:04:36 +02:00
ptitSeb 21128f51f5 Added 64 70..7F opcodes 2022-10-11 18:16:32 +02:00
ptitSeb 1af9666622 Added a couple of wrapped function to libnm 2022-10-11 14:35:46 +02:00
ptitSeb abf66a9cd7 Added some more dbusmenuglib wrapped functions 2022-10-11 14:24:23 +02:00
ptitSeb 5ba8672ac8 Fixed a warning 2022-10-11 14:00:59 +02:00
ptitSeb 4616ed9bc3 Added some more glib2/gio2 wrapped functions 2022-10-11 13:59:23 +02:00
ptitSeb 047b9f2eac Added some more gtk2 wrapped functions 2022-10-11 13:43:04 +02:00
ptitSeb 14113faaba Fixed shell script detection not always working 2022-10-10 23:28:34 +02:00
ptitSeb 03b20c3f52 [DYNAREC] Fixed mmap that was not intializing dynarec block properly like mmap64 (will speedup the few software that use mmap instead of mmap64 for their JIT/Dynarec) 2022-10-10 21:01:05 +02:00
ptitSeb 26a6eb1922 [DYNAREC] Added VARAFM and VARASAT to the auto-detection of VARA familly software that needs SAFEFLAGS to 2 2022-10-10 10:39:06 +02:00
ptitSeb a2f00c5c91 Merge pull request #689 from WheezyE/patch-2
Updated wine install for RPiOS bullseye 32/64bit
2022-10-10 08:14:48 +02:00
Eric Wiessner (KI7POL) dea480e10f Updated wine install for RPiOS bullseye 32/64bit 2022-10-09 17:44:39 -06:00
ptitSeb b7fc2cd5ba Slightly better help 2022-10-09 20:53:47 +02:00
ptitSeb 2aad95726c Better way to find box64 if present 2022-10-09 20:47:32 +02:00
ptitSeb 105c56a817 [DYNAREC] Added BOX86_DYNAREC_SAFEFLAGS, and added autodetection for Vara.exe (this helps #673) 2022-10-09 18:28:57 +02:00
ptitSeb 3da1ed0a8e [DYNAREC] Fixed one access to mxcsr for sse_round (fixed Withcer2 linux light/shadows blinking) 2022-10-09 16:36:56 +02:00
ptitSeb f46068314c Small change with GetNativeFnc to only call dladdr if the address is out of loaded elf space 2022-10-09 09:17:01 +02:00
ptitSeb 914df83ba5 Added 64 A8 opcode ([DYNAREC] too) 2022-10-09 09:16:06 +02:00
ptitSeb d7f5290f14 Merge pull request #685 from WheezyE/patch-1
Add libc6:armhf install to RPi4 aarch64 build info
2022-10-08 09:04:51 +02:00
Eric Wiessner (KI7POL) 9d37471e4e Add libc6:armhf install to RPi4 aarch64 build info
to make compile/use easier for new users (regarding https://github.com/ptitSeb/box86/issues/465 & https://github.com/ptitSeb/box86/issues/682).
Also tried to simplify comments/code a little in the RPi sections

EDIT: fixed typo in -DRPi flag
2022-10-07 16:34:21 -06:00
ptitSeb 57e75a2fa3 Improved the shell script detection 2022-10-07 12:53:37 +02:00
ptitSeb 3fab879089 [PANDORA] Foce x11color16 when detetcting steam on Pandora 2022-10-07 12:53:15 +02:00
ptitSeb 16cb3d36ba Fixed a warning 2022-10-07 12:52:30 +02:00
ptitSeb 74ef17ee94 Changed a bit how mmap with NULL hint works (fixes linux Witcher2) 2022-10-02 18:47:20 +02:00
ptitSeb f1c540d877 Small change in failsafe of dynarec pblock builder 2022-10-02 18:46:47 +02:00
ptitSeb 6018e65ab9 Shuffle the cw and sw x87 regs in x86emu_t struct (fixed PlantsVsZombies wonkiness, but not sure why) 2022-10-02 16:59:31 +02:00
ptitSeb 43190d413c Remove this detection of Crysis in favour of the one in pctrl 2022-10-01 10:14:50 +02:00
ptitSeb a156166a8e Added a redzone on signal with no alt stack 2022-10-01 10:14:20 +02:00
ptitSeb c8141c63ad Fixed ROUND in x87 CW register 2022-09-28 21:26:09 +02:00
ptitSeb 8dd940804c Improve signal handling on fpu and memory protection tracking (should help #672) 2022-09-28 21:00:02 +02:00
ptitSeb d16f956068 [DYNAREC] Fixed BOX86_ROLLING_LOG not working on dynarec 2022-09-28 15:50:29 +02:00
ptitSeb 082b25d81f Fixed some issue with memory protection tracking (should help #672) 2022-09-28 15:10:41 +02:00
ptitSeb a0e29198f6 Added detection of wine program (and detect Crysis to force x87 double on [DYNAREC]) 2022-09-27 13:52:59 +02:00
ptitSeb b4c5a4c531 This should not be needed anymore 2022-09-27 13:51:46 +02:00
ptitSeb 3a1e6ae5df Added some Vulkan extensions and structures definition 2022-09-27 13:51:14 +02:00
ptitSeb 3f7464bf6c [DYNAREC] Fixed potential issue with CF handling on INC/DEC opcodes 2022-09-26 10:38:31 +02:00
ptitSeb 6aef4501f8 Fixed vkGetRandROutputDisplayEXT wrapped function signature 2022-09-25 22:35:50 +02:00
ptitSeb 3024f27b7a Added BOX86_ROLLING_LOG (backported from box64) 2022-09-24 19:06:58 +02:00
ptitSeb e8e1b52a9b [TRACE] Improved trace with jmp/call indirect 2022-09-24 10:17:31 +02:00
ptitSeb 1c8c76d389 [DYNAREC] Added a small optim to 66 0F 70 opcode 2022-09-22 16:28:39 +02:00
ptitSeb a30eedf1e2 Improved a bit test17 2022-09-22 13:36:35 +02:00
ptitSeb 0b3314607f Added __pread_chk wrapped function to libc 2022-09-22 13:24:47 +02:00
ptitSeb 8e7c203772 Small fix to protection tracking on signal handling (should help #672) 2022-09-19 12:57:39 +02:00
ptitSeb 399854342f Improved bash handling 2022-09-19 10:36:36 +02:00
ptitSeb bb692f26d0 Improved usage of x86 bash with BOX86_BASH env var 2022-09-15 15:39:55 +02:00
ptitSeb da5a4c9fbe Added special case for pthread_kill because behaviour changed with glibc 2.34 (fixed steam stuck at login) 2022-09-10 11:09:44 +02:00
ptitSeb 37fc3d0daf When running x86 bash, using x86 bash to run script automaticaly 2022-09-08 09:23:50 +02:00
ptitSeb 76a86e2e45 [DYNAREC] Improve memory protection tracking (should improved program/games using JITs) 2022-09-04 17:45:55 +02:00
ptitSeb a25c32a60b Fixed x86/x86_64 binary detection 2022-08-31 08:50:07 +02:00
ptitSeb 4946642fc4 Added 1 libxi wrapped function 2022-08-28 18:11:55 +02:00
ptitSeb 2ac59458f3 Added 1 wrapped function to gtk3 2022-08-28 17:57:58 +02:00
ptitSeb 6d329e885f Fixed some cases were a lib is wrapped but it shouldn't 2022-08-28 17:57:42 +02:00
ptitSeb 902da5c619 Added wraped libFAudio (backported from box64) 2022-08-28 14:28:08 +02:00
ptitSeb e9fcef3de5 Forced emulated SDL2 when detecting steam to help BigPicture mode (for #663) 2022-08-15 22:03:41 +02:00
ptitSeb b43ddd46ea Added wrapped XGetWMProtocols (for #663) 2022-08-15 22:02:30 +02:00
ptitSeb 9c3002928a Merge pull request #660 from Moldytzu/mention-cross-toolchain
mention gcc-arm-linux-gnueabihf in compile.md
2022-08-02 09:39:02 +02:00
Alex 17ec8d8a75 fix my misunderstanding 2022-08-02 10:35:42 +03:00
Alex d241c818df mention gcc-arm-linux-gnueabihf in compile.md 2022-08-01 21:01:42 +03:00
ptitSeb 6ff1375e44 Merge pull request #659 from Moldytzu/armhf-libs-on-arm64
automatically install 32 bit libraries if 64 bit OS is detected in install_steam.sh
2022-08-01 19:59:08 +02:00
Alex bb3a13db3b install 32 bit libraries only on 64 bit arm debian 2022-08-01 20:55:41 +03:00
Alex ea439a7183 install armhf libs if detected 64 bit os in steam 2022-08-01 20:25:24 +03:00
ptitSeb fa8355eccc A few more wrapped functions for libnss3 2022-07-16 17:00:39 +02:00
ptitSeb 62340ea5d8 Let RTLD_LAZY loaded lib have missing dependancies 2022-07-16 17:00:06 +02:00
ptitSeb e6deec89f8 Added a few wrapped function libnss3 2022-07-16 16:19:44 +02:00
ptitSeb 65fae25715 Improved wrapping of MetaFrames in gtk2 2022-07-16 15:50:31 +02:00
ptitSeb f735f2cbdd Better error handling for querying too large signal 2022-07-16 15:39:05 +02:00
ptitSeb f5658a6079 I don't like Android, it's not a linux 2022-07-15 18:49:44 +02:00
ptitSeb 2b1580b73f No backtrace on Android 2022-07-15 18:35:14 +02:00
ptitSeb 3c519517c7 Added an extension to vulkan wrapper 2022-07-15 18:33:51 +02:00
ptitSeb 7389dc616b Added BOX86_BACKTRACE option to try show some backtrace on segfault 2022-07-15 18:18:39 +02:00
ptitSeb 2ff0562a82 Added one wrapped function to fontconfig 2022-07-15 16:11:59 +02:00
ptitSeb 2ecdc3bb09 Fixed sigaction libc syscall 2022-07-15 15:39:17 +02:00
ptitSeb c1eb7cbfa8 Some fixed to a few libc wrapped functions so bash can run (a copy is in tests folder) 2022-07-15 10:20:45 +02:00
ptitSeb 45d2ac757e Use a bigger TLSData by default with forcing emulated gtk (helps steam, I think) 2022-07-14 16:24:33 +02:00
ptitSeb 875f1d094d Added a couple of wrapped freetype functions 2022-07-14 15:05:21 +02:00
ptitSeb dc1c986c2c Added some more NOP opcode detection 2022-07-14 11:20:24 +02:00
ptitSeb 32db820b3d Added syscall 184 and 185 2022-07-14 10:02:56 +02:00
ptitSeb 7bde8a55b4 Added 1 fontconfig wrapped function 2022-07-14 09:59:18 +02:00
ptitSeb dd083b1e66 Improved handling of fixed memory LOCK opcodes, and made DYNAREC_STRONGMEM=2 much more effective (too many DMB are emited for now, will be improved again in the future) 2022-07-14 09:37:54 +02:00
ptitSeb 6199c17441 Fixed BOX86_ENVx handling 2022-07-14 08:51:45 +02:00
ptitSeb 064eb2112d Misc fixes on libc wrapping 2022-07-13 14:48:25 +02:00
ptitSeb 10578fb7ee Added __wcsncat_chk wrapped function (for #273) 2022-07-11 16:42:15 +02:00
ptitSeb ea57c6a212 Added BOX86_ENV to create env. var. at load time 2022-07-11 13:50:29 +02:00
ptitSeb d38c59d3a0 Double the min size of TLS data to 8k (help Keep Talking and Nobody Explode, and probably other too) 2022-07-10 15:46:03 +02:00
ptitSeb 36f82eb364 Improved BOX86_LOAD_ADDR env. var. to help having reproducible runs 2022-07-10 15:09:35 +02:00
ptitSeb 9d01904145 [DYNAREC] Dump regs and memory around ESP on Signal dump 2022-07-10 14:29:09 +02:00
ptitSeb bb74a811e8 [DYNAREC] More color for DYNAREC_DUMP=2 2022-07-10 14:28:32 +02:00
ptitSeb d70961afa3 Chnaged various log level for dlsym_error logs 2022-07-10 10:21:44 +02:00
ptitSeb 3c8bd9c0fb Added one more wrapped function to vulkan 2022-07-09 21:37:13 +02:00
ptitSeb e0f37bdde9 Fixed potential issue with new loaded lib comparison 2022-07-09 17:48:30 +02:00
ptitSeb b638262e12 [DYNAREC] Fix ARM>X86 instruction unwind in signal 2022-07-09 17:30:49 +02:00
ptitSeb 9cd4e70a42 Refined comparing lib to be loaded with loaded one 2022-07-09 17:27:34 +02:00
ptitSeb c7a4d7dc6f Merge pull request #654 from theofficialgman/master
add TEGRAX1 and TEGRAX1ARM32 targets on ubuntu-18.04
2022-07-08 23:53:40 +02:00
theofficialgman 582503697e add TEGRAX1 and TEGRAX1ARM32 targets on ubuntu-18.04 2022-07-08 16:51:34 -04:00
ptitSeb 308a546cc7 Restored workaround for Linux GOG installer on SBCs 2022-07-07 21:28:21 +02:00
ptitSeb 3a8ea7de1e Merge pull request #652 from wannacu/master
Added 66 0F 7D HSUBPD opcode
2022-07-04 09:47:45 +02:00
wannacu e2690480d9 Added 66 0F 7D HSUBPD opcode 2022-07-04 07:39:59 +00:00
ptitSeb a48a0499b7 Reworked TLS to limit resizing, as it tends to break Unity3D games 2022-07-03 00:08:35 +02:00
ptitSeb 1bc817c48a [DYNAREC] More work on BOX86_DYNAREC_FASTNAN=0 2022-07-01 13:06:42 +02:00
ptitSeb 317c2f0bf4 [DYNAREC] Fixed BOX86_DYNAREC_FASTNAN=0 and some Flot->Int SSE/X87 opcodes 2022-07-01 12:19:52 +02:00
ptitSeb c4aacb4348 Merge pull request #651 from wannacu/master
Align address when call mprotect
2022-07-01 09:22:49 +02:00
wannacu 978ed8da50 Align address when call mprotect 2022-07-01 07:12:27 +00:00
ptitSeb 13b7202dbb Merge pull request #649 from ptitSeb/test-wine-preload
Test wine preload
2022-06-30 18:40:05 +02:00
ptitSeb 70280b7346 Fixed a regression preventing wine-preloader to work correctly 2022-06-30 18:39:19 +02:00
ptitSeb f00653f216 Fixed some potential issue for eroneous execv call 2022-06-26 18:36:29 +02:00
ptitSeb 70982f4807 Another attempt to limit the case where return address of a signal is modified 2022-06-26 10:08:59 +02:00
ptitSeb b629bd409b [DYNAREC] Remove assert, the test is not relevent anymore (for #648) 2022-06-25 16:57:51 +02:00
ptitSeb 68c7902bf3 [DYNAREC] Fixed an issue with fillPredecessor that would undersize the predecessor array 2022-06-25 14:20:48 +02:00
ptitSeb 721b4bbaf8 Rollback the signal/return address change limit 2022-06-21 10:05:20 +02:00
ptitSeb 67aa570b4d Change process name (hidding box86, helps mesa find the correct hack for some binaries) 2022-06-19 20:50:02 +02:00
ptitSeb 4be1b75a89 Merge pull request #645 from Jai-JAP/patch-1
Fix grammar
2022-06-19 17:52:29 +02:00
Jai A P 05d499d99b Update main.c 2022-06-19 21:16:54 +05:30
ptitSeb 432e09c37b Added some libnm and libgio2 wrapped functions 2022-06-19 15:27:30 +02:00
ptitSeb c33683c9df Try some workaround for the libpng16 setjmp handling 2022-06-19 14:37:51 +02:00
ptitSeb b0ea5de0ae Better handling of PreLoaded libs 2022-06-19 14:33:33 +02:00
ptitSeb 3e3744cb94 Basicaly rollback commit #ea49f740c0b4fb271e53f4fea34a9db7c2fa1418 as WBACK was correct (but added some comment on why) 2022-06-19 10:22:38 +02:00
ptitSeb 9a7fe334b5 Restricted the singal hack to change return value only on longjump to wine only 2022-06-18 13:47:19 +02:00
ptitSeb 11c5982a26 Added faked weak _Unwind_Find_FDE incse it's missing on libgcc_s 2022-06-18 13:06:01 +02:00
ptitSeb d91fdc0dcd Better libc signal handling (only longjump can change return address) 2022-06-18 13:05:09 +02:00
ptitSeb 5f4f7bec6c [DYNAREC] Added F2 0F 80..8F opcodes 2022-06-17 15:22:17 +02:00
ptitSeb 4a2ff61fc8 Merge pull request #642 from Jai-JAP/patch-1
Fix Typo in readme x86_64 -> x86
2022-06-13 15:50:48 +02:00
Jai A P 3606ef8814 Update README.md 2022-06-13 19:17:08 +05:30
ptitSeb 734aa87904 Added fstatat64 and fstat64 wrapped function (for #640) 2022-06-11 20:09:14 +02:00
ptitSeb 367235dbd3 Fixed a potential crash with previous commit 2022-06-11 14:47:56 +02:00
ptitSeb 8050fbd3ca Added support to load different libs with same name from different folders 2022-06-11 13:43:19 +02:00
ptitSeb b4c664b979 Added __cxa_pure_virtual wrapped function 2022-06-11 10:56:34 +02:00
ptitSeb 22b66a71f4 Added some of the new _time64 symbol (untested) 2022-06-11 10:48:57 +02:00
ptitSeb 2ed43c3c16 Merge pull request #637 from ye-yeshun/master
some floating point instructions
2022-06-07 08:45:14 +02:00
YeshunYe 2b3983b2e2 add: roundsd instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:16:20 +08:00
YeshunYe b85fd74144 add: roundss instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:15:54 +08:00
YeshunYe 58565cb40f add: roundpd instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:15:28 +08:00
YeshunYe 2e9ce77612 add: roundps instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:14:44 +08:00
YeshunYe 6925b89c13 add: PINSRB instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:06:58 +08:00
YeshunYe 7c75cc3af8 add: PMULLD instruction
Signed-off-by: YeshunYe <[email protected]>
2022-06-07 14:01:46 +08:00
ptitSeb 56c540ae13 Fixed some issue with TLS data not beeing updated correctly after ElfInit 2022-06-06 17:13:45 +02:00
ptitSeb da19b4461f Fixed an issue with GetNoSelfSymbolStartEnd function that would find in self first 2022-06-05 18:55:31 +02:00
ptitSeb c1c3674519 Merge pull request #634 from rajdakin/master
Fix #610
2022-05-29 13:39:52 +02:00
rajdakin e5297fa81a Tried to fix issue #610 2022-05-29 13:26:02 +02:00
rajdakin 7fcbbbe5b6 Forced the use of python3 when running python script 2022-05-29 13:24:25 +02:00
ptitSeb ea49f740c0 [DYNAREC] Some small fixes to a few opcodes 2022-05-26 18:53:05 +02:00
ptitSeb d29fcfa667 Added XGetTextProperty wrapped function 2022-05-26 14:13:22 +02:00
ptitSeb b1c8e3dc93 Fixed XRenderComposite wrapped function signature 2022-05-26 13:32:13 +02:00
ptitSeb 3c8b70f224 Merge pull request #632 from cjy880927/master
Add 6 wrapped function to libdrm, and 2 to libexpat.
2022-05-25 08:12:20 +02:00
chenjiangyi 0600886d22 Add 6 wrapped function to libdrm, and 2 to libexpat.
Signed-off-by: chenjiangyi <[email protected]>
2022-05-25 11:42:55 +08:00
ptitSeb 6af8045c46 Merge pull request #630 from ye-yeshun/master
fix: the first parameter of realpath may be null
2022-05-20 08:13:26 +02:00
YeshunYe 582977f20e fix: the first parameter of realpath may be null
Signed-off-by: YeshunYe <[email protected]>
2022-05-20 11:39:54 +08:00
ptitSeb 4c72e3c910 Set minimum cmake version to 3.10 2022-05-11 19:54:48 +02:00
ptitSeb a0aa2e2458 Merge pull request #624 from ryanfortner/patch-4
docs: remove unnecessary newline
2022-05-10 15:08:02 +02:00
Ryan Fortner f6a92d6909 docs: remove unnecessary newline 2022-05-10 08:52:09 -04:00
ptitSeb 11c6afa687 Fixed wrapped lib dependancies not loading (for #623) 2022-05-10 13:55:02 +02:00
ptitSeb 062207c1fe Merge pull request #620 from ryanfortner/patch-1
Various improvements to install_steam.sh
2022-05-10 12:31:22 +02:00
ptitSeb f49b70750a Merge pull request #621 from ryanfortner/patch-2
Fix typoes in readme
2022-05-10 07:47:46 +02:00
ptitSebandItai Nelken 15be8fb329 Update docs/README.md
Co-authored-by: Itai Nelken <[email protected]>
2022-05-10 07:47:37 +02:00
ptitSeb 0c96d9ecde Merge pull request #622 from ryanfortner/patch-3
docs: add instructions for Debian-based Linux
2022-05-10 07:46:29 +02:00
Ryan Fortner e01134a9c0 docs: add instructions for Debian-based Linux 2022-05-09 22:26:24 -04:00
Ryan Fortner 770f709a24 Fix typoes in readme 2022-05-09 22:09:28 -04:00
Ryan Fortner e2a37141da Various improvements to install_steam.sh 2022-05-09 22:04:48 -04:00
ptitSeb 5accd2f847 Added a script to help install steam, with some doc too 2022-05-09 21:11:37 +02:00
ptitSeb 46eaabf722 Small change to avoid wlib_t declaration in wrappedlibs.h 2022-05-09 20:05:06 +02:00
ptitSeb 807da66d87 Some refactor on wrapped lib handling, to limit calloc/free used and get more straight forward usage of native wrapped functions 2022-05-08 16:00:34 +02:00
ptitSeb 06861f8577 [DYNAREC] Add some -NAN handling to FDIVP opcode 2022-05-07 09:09:25 +02:00
ptitSeb 44ee38a868 Added 66 3E prefix ([DYNAREC] too) (for #619) 2022-05-02 10:37:05 +02:00
ptitSeb 89652e9ff2 Updated README 2022-05-01 09:02:50 +02:00
ptitSeb 6f1f35217f Merge pull request #617 from derryktutt/patch-1
Update README.md
2022-05-01 07:50:37 +02:00
derryktutt 22c6e81e68 Update README.md
"is safer to add it to your system if you intend to play those game" makes no sense. I have made it plural.
2022-04-30 18:49:59 -05:00
ptitSeb ab57dfc5c7 Added mtrace and muntrace wrapped function (for #616) 2022-04-30 23:38:32 +02:00
ptitSeb 8d609ed881 Improved initial stack build 2022-04-24 15:11:42 +02:00
ptitSeb 0e9a422335 Fixed a potential issue with stack overwritten on sigaction call 2022-04-24 15:03:42 +02:00
ptitSeb 5cdd2d4947 Added wrapped libpcap.so.0.8 2022-04-24 11:40:08 +02:00
ptitSeb f946cddd45 Added wrapped libappindicator3 2022-04-24 11:10:06 +02:00
ptitSeb d45aa0dae9 Merge pull request #615 from Radiicall/patch-1
Grammar and formatting COMPILE.md
2022-04-21 07:49:42 +02:00
Radical 464c7e6b47 Update COMPILE.md 2022-04-21 01:02:06 +02:00
Radical 9e4468acb6 Merge branch 'ptitSeb:master' into patch-1 2022-04-21 00:53:28 +02:00
ptitSeb dcb49fe731 Improved GTK3 wrapping, along with some other improvement in udev and xcb 2022-04-18 22:50:03 +02:00
ptitSeb 03259e67d9 Need to unaligneNGValue in my_signal_emission_hook (fixes hterm crash at launch) 2022-04-18 22:48:08 +02:00
ptitSeb 0ea662f57f Fixed alignNGValue and unalignNGValue for n>1 2022-04-18 22:47:14 +02:00
ptitSeb 4b629b9b28 Do not use alloca here, it's not temporary storage 2022-04-18 21:12:22 +02:00
ptitSeb a8b5ebba18 Fixed wrapping for g_object_get_property and g_object_set_property 2022-04-18 18:52:15 +02:00
ptitSeb c904d9f66c Wrapped a feked _r_data structure 2022-04-18 16:04:51 +02:00
ptitSeb f52c5bc6da [DYNAREC] No need to save op1 and op2 for defered flag computation on logic operations 2022-04-18 13:31:55 +02:00
ptitSeb a074ea8ba6 [DYNAREC] Simpler writing fr this test 2022-04-18 13:31:55 +02:00
ptitSeb 3a3f55f9a2 [DYNAREC] Small optim on flags barrier handling 2022-04-18 13:31:55 +02:00
ptitSeb 490cabcbe3 Merge pull request #612 from lizthegrey/patch-1
add LX2160A config
2022-04-17 09:36:10 +02:00
ptitSeb 367c5bcfb1 Start of a new dev. cycle 2022-04-17 09:33:33 +02:00
Liz Fong-Jones d10de8d7df add LX2160A config 2022-04-16 15:16:56 -07:00
ptitSeb 41749db028 Bumped version to v0.2.6 2022-04-16 17:15:42 +02:00
ptitSeb e30f302de9 Updated CHANGELOG 2022-04-16 12:26:08 +02:00
ptitSeb d119ed10b9 Added libdl as a dependancy for libXext 2022-04-16 10:37:27 +02:00
ptitSeb 9281289a1b [DYNAREC] Some more -NAN generation handling forwhen not using FASTNAN 2022-04-16 09:02:22 +02:00
ptitSeb 1683c0c679 Fixed interpreted SUBPD opcode 2022-04-16 09:01:46 +02:00
ptitSeb 88a8b9569d Merge pull request #611 from Jai-JAP/master
Fix pkgver in PKGBUILDS
2022-04-16 08:33:56 +02:00
Jai-JAP 18aaa03381 Fix pkgver 2022-04-16 11:35:51 +05:30
ptitSeb aa3474d06e Fixed some callback with 64bits args (help wngstreamer lib, for games like OutCast 1.1) 2022-04-13 11:56:14 +02:00
ptitSeb 0accab638f [DYNAREC] BOX86_DYNAREC_FASTNAN is default now 2022-04-11 10:09:16 +02:00
ptitSeb 29b52bc12e Fined-tune build to get test17 passing on x86 2022-04-10 20:55:57 +02:00
ptitSeb 5840cd3402 Some more NAN bordercase handlin ([DYN?AREC] too, but made FASTNAN default) 2022-04-10 16:20:56 +02:00
ptitSeb 926ff0f4f8 Added better handling of SSE float/double border case ([DYNAREC] too, with BOX86_DYNAREC_FASTNAN) 2022-04-10 15:42:36 +02:00
ptitSeb 13689e7eac Try to fix the flakyness of test11 2022-04-10 14:49:58 +02:00
ptitSeb e4ed4ad3a8 Added 66 0F 38 39/3D and 66 0F 3A 0E opcodes 2022-04-10 10:57:32 +02:00
Radical 25e4072fef Update COMPILE.md
Refined version (Still needs a few changes)
2022-04-08 15:18:51 +02:00
ptitSeb 1e6037019e Added some libx11 and co. wrapped libs (shoud help #607) 2022-04-07 11:17:26 +02:00
ptitSeb da083aaab4 Merge pull request #605 from Jai-JAP/patch-1
Update PKGBUILDS
2022-04-06 07:47:47 +02:00
Jai A P 7a7853d434 Update PKGBUILD-x86 2022-04-06 10:52:37 +05:30
Jai A P eebe12ca27 Update PKGBUILD-rk3399 2022-04-06 10:52:11 +05:30
Jai A P 7aaade8780 Update PKGBUILD-raspberrypi 2022-04-06 10:51:46 +05:30
Jai A P cb185d4d44 Update PKGBUILD-pyra 2022-04-06 10:51:08 +05:30
Jai A P 3f691dc4f0 Update PKGBUILD-pandora 2022-04-06 10:50:35 +05:30
Jai A P d4c33f71eb Update PKGBUILD-odroid 2022-04-06 10:50:07 +05:30
Jai A P ad106a07ea Update PKGBUILD-gameshell 2022-04-06 10:49:37 +05:30
Jai A P 2ad3a0a7f5 Update PKGBUILD-arm 2022-04-06 10:48:52 +05:30
ptitSeb dc461d4de6 Backported improved and enhanced test17 from box64 2022-03-30 13:19:12 +02:00
ptitSeb d1a9b50dfe Added 66 0F 38 20..25/30..35 opcodes 2022-03-30 13:18:45 +02:00
ptitSeb 9a0da8d011 Added 66 0F 38 14/17 and 66 0F 3A 14/16/20 opcodes 2022-03-30 13:14:26 +02:00
ptitSeb 2d7e3877e7 Added some more wrapped libs, mostly empty for now 2022-03-27 15:33:41 +02:00
ptitSeb 0248ae0a96 [DYNAREC] Added 65 01 and 65 C6 opcodes 2022-03-27 14:39:12 +02:00
ptitSeb 9fd27f3b2c Added BOX86_PREFER_WRAPPED and BOX86_PREFER_EMULATED handling 2022-03-27 11:52:16 +02:00
ptitSeb 4152fcc934 Aded more debug info on SIGILL signal 2022-03-27 11:51:33 +02:00
ptitSeb 53c887a06a [DYNAREC] Fix an issue with neoncache transform when loading a single reg over a quad reg on add position (fixes Garfield Kart) 2022-03-27 11:48:07 +02:00
ptitSeb 316e10baa0 More work around steam and proton/SteamPlay 2022-03-26 13:17:52 +01:00
ptitSeb 8a71c6bc4a Added wrapped libgmp (backported from box64) and libgcrypt (empty for now) 2022-03-20 12:00:04 +01:00
ptitSeb 9b806de7b0 Added some gstreamer-1.0 wrapping (backported from box64) 2022-03-20 11:46:26 +01:00
ptitSeb a14dadc228 And even more work on GTK wrapping 2022-03-19 21:17:03 +01:00
ptitSeb ca850b3d30 Some more gtk wrapping work 2022-03-19 20:33:06 +01:00
ptitSeb c01dbbea0e Better link command 2022-03-19 20:08:04 +01:00
ptitSeb b883307881 Fix Pandora build 2022-03-19 19:40:30 +01:00
ptitSeb ab9bcb1e0b Fixed a warning 2022-03-19 19:40:12 +01:00
ptitSeb 3dc22ff0b8 [DYNAREC] Reworked 0F C6 opcode for better readability 2022-03-19 18:32:20 +01:00
ptitSeb 5e382e12ad More work on GTK wrapping (for #590, but some option dialog still crashes) 2022-03-19 15:10:30 +01:00
ptitSeb 103e55ff97 Fixed some potential issues with LOG=2 trace 2022-03-19 15:09:19 +01:00
ptitSeb 6140b3eee8 Added 66 F5 opcode ([DYNAREC] too) 2022-03-19 15:08:55 +01:00
ptitSeb 09574a69e9 Small fixes to some wrapped X11 functions (should help #591) 2022-03-19 09:08:35 +01:00
ptitSeb c53f961e12 Fixed, again, the mmap block selection (shoudl help #587) 2022-03-18 11:40:08 +01:00
ptitSeb a1d370fc04 Improve findBlockNearHint function, again 2022-03-17 12:18:46 +01:00
ptitSeb 471b679d3f Fixed wrapped mprotect not always working properly (should help #587) 2022-03-17 11:59:29 +01:00
ptitSeb e60caa8648 Fixed a warning 2022-03-17 11:59:29 +01:00
ptitSeb ccfc8a8d30 Merge pull request #589 from wannacu/master
[DYNAREC] Added check of dyn's size
2022-03-17 10:51:49 +01:00
wannacu 6a7b7bec6a [DYNAREC] Added check of dyn's size 2022-03-17 09:30:30 +00:00
ptitSeb 0926c48aea Fixed the new memmap tracking 2022-03-13 17:10:53 +01:00
ptitSeb d10a9e40ed Fixed some LOG=2 improved trace 2022-03-13 17:10:06 +01:00
ptitSeb 4df12ee5ea Fixed some issues with the mapmem tracking (might help #587) 2022-03-13 15:50:37 +01:00
ptitSeb 433294fb40 [DYNAREC] Small cosmetic changes 2022-03-13 15:42:28 +01:00
ptitSeb 298fe50dd1 Merge pull request #585 from wannacu/master
Add some function wrapper of libx11
2022-03-11 16:49:15 +01:00
wannacu 1717fffe8f Add some function wrapper of libx11 2022-03-11 18:19:22 +08:00
ptitSeb 41521913d5 Change method for the mmap free bloc search for a faster one 2022-03-09 11:17:14 +01:00
ptitSeb e75ca5d2ff Change de verbose level of a custommem message 2022-03-08 18:50:22 +01:00
ptitSeb 0d2081ed30 Merge pull request #583 from wannacu/master
Added wrapped libvkd3d
2022-03-08 13:23:04 +01:00
ptitSeb d6abdc2a55 Disabling test14 (conditionalThreads) for now on x86 arch, it's a bit flacky and gives too many false-positive 2022-03-08 11:54:38 +01:00
wannacu 0a0cf77461 Added wrapped libvkd3d 2022-03-08 17:56:29 +08:00
ptitSeb a5c438068c Fix some special case on mmap64 wrapping 2022-03-08 10:18:33 +01:00
ptitSeb d2c8839a69 Added 1 more wrapped function to libx11 2022-03-08 10:18:08 +01:00
ptitSeb 21b560a3b9 Merge pull request #582 from wannacu/master
Added dummy wrapped libharfbuzz and libcairo-gobject
2022-03-07 16:00:27 +01:00
wannacu b1d8de62d4 Added dummy wrapped libharfbuzz and libcairo-gobject 2022-03-07 22:46:05 +08:00
ptitSeb 1e41857d37 Small change is symbol gathering for wrapped libs (help some java versions 2022-03-07 13:42:34 +01:00
ptitSeb 63920e95d3 Improved handling of env. var. for wrapped execve 2022-03-07 11:22:53 +01:00
ptitSeb 7856b2b7ee [TRACE] Better trace for putenv 2022-03-07 11:22:04 +01:00
ptitSeb 5daf34ba29 Added [stack] to the generated maps file (should help #533) 2022-03-07 11:21:36 +01:00
ptitSeb e513cbeaaa Added an option to always show SIGSEGV messages 2022-03-06 19:27:03 +01:00
ptitSeb c782ba2429 Fixed dlinfo (helps wine) 2022-03-06 19:26:52 +01:00
ptitSeb 50dae3f5d8 Added some vulkan extentions 2022-03-06 17:10:01 +01:00
ptitSeb d3e6551b40 Remove a debug trace leftover 2022-03-06 16:44:27 +01:00
ptitSeb 0e1d1a788d Improved speed of mmap changes 2022-03-06 16:27:23 +01:00
ptitSeb dfafce7f05 Change on mmap64 to help some stagging version of wine (for #580) 2022-03-06 15:23:38 +01:00
ptitSeb eb7381457a Detect wine, just in case 2022-03-06 13:54:51 +01:00
ptitSeb 2f8baf9559 Improve a bit when box86 launch program natively or with box64 2022-03-06 11:34:53 +01:00
ptitSeb 34cb03c7df Try to improve the clone syscall (backported from box64) 2022-03-06 11:29:03 +01:00
ptitSeb d76ecb8a38 [ANDROID] Try, again and again, to fix build 2022-03-05 21:48:08 +01:00
ptitSeb 943c2a0bd9 [ANDROID] Try, again, to fix build 2022-03-05 21:28:11 +01:00
ptitSeb a7552c8bb8 [ANDROID] Try to fix build 2022-03-05 21:12:49 +01:00
ptitSeb 8cd78041a2 Improve wrapping of readlinkat function 2022-03-05 20:35:02 +01:00
ptitSeb 3fe3499ec2 Added dladdr1 handling (backported from box64) 2022-03-05 20:30:34 +01:00
ptitSeb 70c49f67c4 [DYNAREC] Fixed GETEBO and GETEDO2 macros 2022-03-05 18:41:38 +01:00
ptitSeb 308c316dbf Backported some improvment on wrapped libx11 from box64 2022-03-05 18:16:53 +01:00
ptitSeb c660b3a9aa Added 1 more wrapped function to libfontconfig (steam BigPicture seems to works now) 2022-03-05 13:39:02 +01:00
ptitSeb 642bb357d3 Put libpangoft2 to the list of gtk wrapped libs 2022-03-04 22:40:31 +01:00
ptitSeb 4978177584 Some wrapped pango / pangocairo / xi functions 2022-03-04 20:14:23 +01:00
ptitSeb ae8a69a840 Improve trace, again, a bit 2022-03-04 16:48:30 +01:00
ptitSeb 383c2be9fc Some work on the basic linux libs 2022-03-03 19:34:10 +01:00
ptitSeb 1cc4653672 [ANDROID] Put back old mutex mothod for android only 2022-03-03 17:25:37 +01:00
ptitSeb 6b6daba17a Some work on gtk wrapped libs 2022-03-03 16:53:09 +01:00
ptitSeb d8eb090a7a [TRACE] Improve trace when symbol there is no symbol name 2022-03-03 16:52:42 +01:00
ptitSeb eb2e96f13b Add possibility to fail loading a lib if a R_386_PC32 reloc fail (help Source engine options menu) 2022-03-03 16:51:57 +01:00
ptitSeb 41201cbb96 Added some more wrapped pulse functions 2022-03-01 11:10:40 +01:00
ptitSeb 151115ed10 Remove special case for hl_linux 2022-03-01 10:02:25 +01:00
ptitSeb 7d4154e0d4 Merge pull request #579 from Mzed3D/patch-1
Update CMakeLists.txt
2022-02-27 14:50:42 +01:00
Mzed3D 7a470daa26 Update CMakeLists.txt
Added Odroid-N2 specific profile
2022-02-27 14:34:07 +01:00
ptitSeb a4e40d06ac Added wrapped (empty) libmimalloc 2022-02-26 18:02:52 +01:00
ptitSeb 875efd2a42 Added 65 39 opcode ([DYNAREC] too) 2022-02-25 21:34:01 +01:00
ptitSeb 9ee0ac92c3 Fixed interpreted 0F 38 00 opcode 2022-02-13 14:40:30 +01:00
ptitSeb c7f554bebb [DYNAREC] Added 0F 3A 0F opcode 2022-02-13 12:50:00 +01:00
ptitSeb 6fe8d71e61 Small fix to 0F 3A 0F opcode 2022-02-13 12:49:37 +01:00
ptitSeb f6f24bce25 [DYNAREC] Added F3 0F D6 opcode 2022-02-13 12:30:33 +01:00
ptitSeb 8b81151ec1 Added wrapped SDL_UpdateWindowSurfaceRects function 2022-02-13 12:29:48 +01:00
ptitSeb 55033ed25e [DYNAREC] Added F2 0F D6 opcode 2022-02-13 12:21:22 +01:00
ptitSeb a829a60341 Undo last commit 2022-02-11 19:14:03 +01:00
ptitSeb 0a25e78964 Fixed wrapped function IMG_SavePNG_RW from SDL2-image 2022-02-11 19:05:46 +01:00
ptitSeb dec1acdfb1 Merge branch 'master' of https://github.com/ptitSeb/box86 2022-02-11 17:45:26 +01:00
ptitSeb 4f0970138b Added 66 0F BF opcode ([DYNAREC] too) 2022-02-11 17:45:15 +01:00
ptitSeb 4707997aec Merge pull request #573 from WheezyE/patch-1
Add note to use box64 to run x86_64 applications
2022-02-10 21:34:50 +01:00
Eric Wiessner (KI7POL) ae5a4b5f4f Add note to use box64 to run x86_64 applications 2022-02-10 13:32:29 -07:00
ptitSeb 5187b55a2e Added wrapped stat64 and lstat64 2022-02-06 20:07:51 +01:00
ptitSeb 60078852bd Merge pull request #564 from MichaIng/imgbot
[ImgBot] Optimize images
2022-02-01 18:53:57 +01:00
ptitSeb 580bacaf93 Merge pull request #563 from MichaIng/patch-1
Make postinst script failsafe
2022-02-01 16:50:30 +01:00
MichaIng eb1ab920cf Make postinst script failsafe
"systemctl restart systemd-binfmt" can only succeed when systemd is the used init system and when the binfmt_misc kernel module is available. The kernel module may not be available right after a kernel upgrade or within a container where it needs to be loaded on the host. 

The common check for whether systemd is used or not is to check for the directory "/run/systemd/system" which is hereby added.

Since modprobe may not be available and within a container always fails (regardless whether the host provides it), the service restart is allowed to fail without failing the postinst script and hence the package install. If the service restart fails, Box86 support in binfmt becomes effective on next system restart, given binfmt_misc is generally available. Furthermore binfmt is a convenience feature while generally Box86 can be used without it. It is hence no reason to hard fail the package install when systemd-binfmt fails for any reason.

Signed-off-by: MichaIng <[email protected]>
2022-02-01 16:30:37 +01:00
ImgBotApp 6c0aabd36e [ImgBot] Optimize images
*Total -- 238.68kb -> 226.88kb (4.94%)

/docs/img/Box86Icon.png -- 67.71kb -> 57.69kb (14.8%)
/docs/img/Box86Logo.png -- 170.97kb -> 169.20kb (1.04%)

Signed-off-by: ImgBotApp <[email protected]>
2022-02-01 15:12:34 +00:00
ptitSeb a3d2443b70 Added 2 wrapped function to gtk3 (for #562) 2022-01-30 14:16:46 +01:00
ptitSeb 313ca172a5 [DYNAREC] Improved potential son detections 2022-01-30 13:14:10 +01:00
ptitSeb ceb4e53f15 [DYNAREC] Added option to force Double for x87 emulation, and added some detection of Crysis to force this option (needed for Crysis physics engine) 2022-01-30 12:28:37 +01:00
ptitSeb 4510b4997a Added 2 wrapped function to libpng12, and 1 to libpng16 (for #560) 2022-01-25 22:48:55 +01:00
ptitSeb 12cc43bd7c Fix(?) of the better wrapping for g_option_context_add_main_entries 2022-01-23 22:11:52 +01:00
ptitSeb 21069c107a Better wrapping for g_option_context_add_main_entries 2022-01-23 20:53:57 +01:00
ptitSeb 93032afe0f More work on symbol versionning of elfloader (for #559, but might help others) 2022-01-23 18:23:20 +01:00
ptitSeb f422fe13f4 Added hl2_linux for the same special case as hl_linux 2022-01-23 18:22:31 +01:00
ptitSeb ed551d1eb3 Don't allow to small stack for native thread 2022-01-23 16:34:58 +01:00
ptitSeb 58cd4119a6 Added a few wrapped function to libnspr4 and libnss3 (but libnspr4 needs more work on special cases) 2022-01-23 16:34:06 +01:00
ptitSeb c8147ce3d4 Added BOX86_ALLOWMISSING_SYMBOLS option, rename BOX86_ALLOWINGLIBS, and added a special case for hl_linux (for #559) 2022-01-23 16:33:00 +01:00
ptitSeb 00df171604 Install i386 libpng12.so.0 with 'make install' along side libstdc++ and libgcc_s 2022-01-23 13:58:01 +01:00
ptitSeb 50ca38d4d0 Added 2 more wrapped function libxcb 2022-01-22 09:27:06 +01:00
ptitSeb e31e5c1a5b Added dprintf and __dprintf_chk wrapped functions (for #558) 2022-01-21 08:47:24 +01:00
ptitSeb c80356a90a Merge pull request #556 from ryanfortner/master
Various packaging improvements
2022-01-18 22:12:22 +01:00
Ryan Fortner 4909b039c0 Update rules 2022-01-18 14:31:07 -05:00
Ryan Fortner dc8ee2718b Update COMPILE.md 2022-01-18 14:09:44 -05:00
Ryan Fortner 8118f4ad18 Update rules 2022-01-18 14:08:14 -05:00
Ryan Fortner de422a0d93 Update rules 2022-01-18 12:58:59 -05:00
Ryan Fortner cbffa01014 Update rules 2022-01-18 12:47:46 -05:00
Ryan Fortner f8688c33a0 test nostrip option 2022-01-18 12:16:32 -05:00
Ryan Fortner 6e0e56b85e add lintian-override 2022-01-18 12:11:34 -05:00
Ryan Fortner 7e81522ed4 Update COMPILE.md 2022-01-18 12:06:58 -05:00
Ryan Fortner 0c8a76fceb fix copyright formatting again (fixes build error) 2022-01-18 12:04:06 -05:00
Ryan Fortner 35273abff7 use quilt instead of native 2022-01-18 11:59:44 -05:00
Ryan Fortner 6c1f3ea4bf Update rules 2022-01-18 11:58:26 -05:00
ptitSeb 5e261e0d7f Merge pull request #555 from ryanfortner/master
Add Debian packaging files
2022-01-18 17:49:49 +01:00
Ryan Fortner 53553ece6f fix formatting in debian/changelog 2022-01-18 11:37:50 -05:00
Ryan Fortner 33d47ff1c8 upload base debianization 2022-01-18 11:35:21 -05:00
ptitSeb 16b8657a47 |DYNAREC] Small optim on cmpxchg opcode 2022-01-16 15:19:09 +01:00
ptitSeb 264c834c2c [DYNAREC] Fixed a typo in previous commit (help steam) 2022-01-16 15:18:16 +01:00
ptitSeb 28b05465ea Too much fun with SHUFPD, fixed '6' part, and fir PSHUFD too (fixed 007 NightFire, maybe others) 2022-01-16 10:43:01 +01:00
ptitSeb b903e57ef9 [DYNAREC] Forgot to also fix the x87 full purge optim 2022-01-15 22:47:56 +01:00
ptitSeb d5ffba47a2 [DYNAREC] Fixed a last bug (again), on x87 purge optim (help nfs3, probably other too) 2022-01-15 22:44:04 +01:00
ptitSeb 34b99bfede Reverted the change on dn_expand / res_query symbol from libresolv 2022-01-15 17:31:44 +01:00
ptitSeb 4f5aac8f50 Fixed issue with dl_vsym internal use (will help #548 and others) 2022-01-15 17:23:32 +01:00
ptitSeb fe53eeb010 Merge pull request #553 from io12/android-ci
Add Android builds to GitHub Actions
2022-01-13 23:02:07 +01:00
Benjamin Levy 67b6f69926 Add Android to CI 2022-01-13 16:10:44 -05:00
ptitSeb 6bf62a3d4e Merge pull request #551 from io12/fix-android
Fix Android build
2022-01-13 07:41:14 +01:00
Benjamin Levy 54b911550f Fix Android build 2022-01-12 21:24:16 -05:00
ptitSeb 31a988877a [DYNAREC] Add one more bug from the x87 optimization squashed (help Freedom Planet) 2022-01-09 23:13:02 +01:00
ptitSeb 88642d81c0 Another attempt to make the function to find versionned symbol more resiliant (should help #548) 2022-01-08 19:12:57 +01:00
ptitSeb 135e8d98e9 [DYNAREC] Fixed a typo in PSHUFD optim (fixes steam, maybe others) 2022-01-08 12:50:38 +01:00
ptitSeb bd5c8fd403 [DYNAREC] Fixed a typo in a x87 optim (for #548 and all windows gog installer in general) 2022-01-08 11:24:07 +01:00
ptitSeb 3b112793aa Added wrapped libselinux with a few functions 2022-01-08 10:23:46 +01:00
ptitSeb 2fc8d9ae4f Move libatk back to the list of exclude libs when using NOGTK (helps steam) 2022-01-07 18:28:28 +01:00
ptitSeb afe63f02fa Merge pull request #547 from Seas0/master
Minor fix in action configuration
2022-01-07 10:16:17 +01:00
Seas0 6aa744dff9 Minor fix in action configuration 2022-01-07 16:45:22 +08:00
ptitSeb 095b04d31c Merge pull request #546 from Seas0/master
Remove temporary test output file
2022-01-07 09:26:08 +01:00
Seas0 6136fe0c8b Fix expansion test case output file 2022-01-07 16:15:38 +08:00
Seas0 e2f3752018 Remove test temporary file 2022-01-07 16:02:08 +08:00
ptitSeb 5d0fdf01f3 Fixed (F0) 0F C7 opcode, only /1 is CMPXCHG8B 2022-01-06 21:46:39 +01:00
ptitSeb cb4b6bc76d Added 66 F0 FF /0 and /1 opcodes ([DYNAREC] too) 2022-01-06 21:14:24 +01:00
ptitSeb bb0f57b5ab Don't abort when try to execute an unsupported syscall 2022-01-06 20:33:54 +01:00
ptitSeb c23981b97f Added one x11 wrapped function (for #545) 2022-01-06 19:27:37 +01:00
ptitSeb c005fc6754 Added deprecated libpng12.so, because it's more and more difficult to have a native version of it 2022-01-06 18:20:04 +01:00
ptitSeb 8d24048c26 [DYNAREC] Improved 66 0F D1/D2 opcodes 2022-01-06 18:20:04 +01:00
ptitSeb ac1ae9f9db [PANDORA] Fix build 2022-01-06 13:18:05 +01:00
ptitSeb 53e8a40e1b (re)Set default log to NONE 2022-01-06 11:53:22 +01:00
ptitSeb a7d803bc82 Made the missing symbol workaround more resiliant 2022-01-05 22:51:53 +01:00
ptitSeb 944ae100fa Added some workaround for program that calls 'uname -m' to get the architecture of the host (also using box64 if present) 2022-01-05 21:20:24 +01:00
ptitSeb b68fd36476 Change default banner and log to be silent if stdout is beeing redirected 2022-01-05 21:20:24 +01:00
ptitSeb 74d530d65e Merge pull request #543 from asppsa/pkgbuild-followup
Update PKGBUILD files to match rk3399 one
2022-01-05 15:03:43 +01:00
Alastair Pharo b5cf71c7af Update other pkgbuild files to match rk3399 one 2022-01-06 00:29:30 +11:00
Alastair Pharo 8d663f80bd Fix package stage of rk3399 pkgbuild 2022-01-05 23:37:34 +11:00
ptitSeb 77257e2532 Merge pull request #541 from asppsa/rk3399-gcc-fix
Don't use cross-compile GCC on 32-bit systems
2022-01-05 08:33:12 +01:00
ptitSeb 44d6719107 Merge pull request #542 from asppsa/pkgbuild-fix
Fix rk3399 PKGBUILD
2022-01-05 08:32:48 +01:00
Alastair Pharo 05ddaa6356 Fix rk3399 PKGBUILD 2022-01-05 17:57:49 +11:00
Alastair Pharo d8a6b6528a Don't use cross-compile GCC on 32-bit systems
If the OS is not aarch64, then use the normal GCC.  This allows
compilation for work on devices like the RK3399 when running in a 32-bit
chroot, instead of using a multilib setup.
2022-01-05 15:53:18 +11:00
ptitSeb 478c781822 [DYNAREC] Detect ARMv8, because VRINT opcodes doesn't exist on ARMv7 2022-01-04 21:55:40 +01:00
ptitSeb 93039252f2 Removed special case for pow10, it's automaticaly handled now) 2022-01-04 20:05:01 +01:00
ptitSeb 3efc3ebe25 Added a warning if launching a binary with a preinit array 2022-01-04 20:04:39 +01:00
ptitSeb 1f5824a55b Added a Workaround when dlsym a native (versionned) symbol without default version fails 2022-01-04 20:04:06 +01:00
ptitSeb d364c2f53e [DYNAREC] Some more various x87 optimizations 2022-01-04 13:20:41 +01:00
ptitSeb 7d0bc98e3e SDmall precision on a x87 opcode 2022-01-04 13:20:18 +01:00
ptitSeb 85e0b26a53 [DYNAREC] Small fixes for some x87 functions 2022-01-04 09:45:42 +01:00
ptitSeb c3f21c8af2 [DYNAREC] Optimized PSHUFD too 2022-01-02 18:26:13 +01:00
ptitSeb 8bd2148ae4 [DYNAREC] Small optim for some case of packssdw opcode 2022-01-02 17:32:27 +01:00
ptitSeb 2c74cef483 [DYNAREC] Remade SHUFPD opcode 2022-01-02 17:26:55 +01:00
ptitSeb 3a1911f5cd [DYNAREC] Fun with shufps 2022-01-02 17:17:40 +01:00
ptitSeb d871886ec5 [DYNAREC] Small improvement to F3 0F 10/11 opcodes 2022-01-02 17:05:29 +01:00
ptitSeb 146a2e8aae Revert most of top8 commit, it seems unstable 2022-01-02 14:15:20 +01:00
ptitSeb 727784d90a More work on x87 handling, using top=8 for empty stack ([DYNAREC] too) 2022-01-01 11:03:26 +01:00
ptitSeb 67647bc51e Merge pull request #539 from Seas0/master
Some improvement on Github Action configuration
2021-12-31 19:15:15 +01:00
Seas0 3ce9d84669 Add test to Github Action 2022-01-01 01:54:30 +08:00
Seas0 af6ed6c296 Add custom build option in Github Action 2022-01-01 01:45:07 +08:00
ptitSeb 3f65c0593f Merge pull request #536 from Seas0/master
Making ctest -j$(nproc) work as intended and fix a typo in github action configuration
2021-12-31 17:22:21 +01:00
Seas0 98e7941371 Fix Github Action event trigger for CMakeLists.txt 2022-01-01 00:15:28 +08:00
Seas0 3fb5eb3ec9 Making ctest -j$(nproc) work as intended
Change the temporary file name of each test in order to prevent the conflict when running ctest with multiple processes enabled
2022-01-01 00:10:05 +08:00
ptitSeb 497c748955 Removed libatk from the NOGTK filter, and added some more libatk wrapped functions 2021-12-31 14:34:32 +01:00
ptitSeb 230247af17 Changed how libresolv is used (for latest libc version) and change 2 symbol bindings 2021-12-31 13:38:17 +01:00
ptitSeb bbea40833b Added one more libgnutls wrapped function (should help steam) 2021-12-31 13:19:53 +01:00
ptitSeb 146ca6a9c9 Added some libgnutls wrapped function (should help steam) 2021-12-31 13:13:41 +01:00
ptitSeb fb7e8c730c Added one libresolv as a dependancy for libglib2 2021-12-31 13:13:19 +01:00
ptitSeb e5135ae67b Added one libc wrapped function (should help steam) 2021-12-31 12:03:44 +01:00
ptitSeb f1b524460e Added 3 x11 wrapped function (should help steam) 2021-12-31 12:03:14 +01:00
ptitSeb 9c9c910fa8 Added a couple of fontconfig wrapped function (should help steam) 2021-12-31 11:58:42 +01:00
ptitSeb 63330cbb84 Added some cairo wrapped function (should help steam) 2021-12-31 11:57:39 +01:00
ptitSeb 5c6816f8ab Small change to the handling of some x87 opcodes 2021-12-30 17:20:46 +01:00
ptitSeb 4c0366e340 [DYNAREC] Improve exchange of st regs, plus some fixes on x87 optim, again (help linux Witcher2 intro video) 2021-12-30 14:27:44 +01:00
ptitSeb 38e2e4e16a [DYNAREC] Added BOX86_DYNAREC_BIGBLOCK=2 option 2021-12-30 11:47:29 +01:00
ptitSeb 430b24c0f3 Added a comment on PREFETCHW opcode 2021-12-28 15:07:16 +01:00
ptitSeb b22b187ce0 Small change on bridge memory protection handling 2021-12-28 15:06:49 +01:00
ptitSeb cc32d6cb98 Added 0F 0D /1 (faked) opcode (for #533) 2021-12-27 11:12:01 +01:00
ptitSeb 66332ae9e2 [DYNAREC] Fixed (again, for the last time?) the x87 load/unload cache optim (should help Witcher2, maybe more) 2021-12-25 12:15:21 +01:00
ptitSeb b6dd3acfea Added 16bits PUSH DS ocpode ([DYNAREC] too) (for #529) 2021-12-23 20:46:03 +01:00
ptitSeb b655e89af0 [DYNAREC] Fixed idiv optimisation, and added a new test about idiv opcode 2021-12-22 11:44:11 +01:00
ptitSeb 2879cf51cd Merge pull request #526 from Seas0/master
Move all _GNU_SOURCE defination to the file head
2021-12-22 11:22:38 +01:00
Seas0 725dabea88 Move all _GNU_SOURCE defination to the file head
Accroding to man 7 feature_test_macros' guide line
2021-12-22 17:23:58 +08:00
ptitSeb 35f133cacd [DYNAREC] Fixed one last issue with x87 optimizations 2021-12-19 16:14:44 +01:00
ptitSeb b0e4f2c696 [DYNAREC] Fixed another issue with x87 optimizations 2021-12-19 15:47:32 +01:00
ptitSeb 65c423917e [DYNAREC] Fixed an incorect assert in fillPredecessors 2021-12-19 14:53:19 +01:00
ptitSeb f128af26ec [DYNAREC] Fixed some issue with x87 optimizations 2021-12-19 13:57:02 +01:00
ptitSeb 1bf955baa8 [TRACE] Changed a bit x87 trace 2021-12-19 13:56:36 +01:00
ptitSeb cee2ff2641 Changed a bit the behavior of elfloader with local symbol on global binding (to fix Unreal loading) 2021-12-19 11:43:23 +01:00
ptitSeb 819cd6c3e2 Don't resolve program name if not needed 2021-12-18 20:55:56 +01:00
ptitSeb 67da32857a [DYNAREC] Disable some IDIV optimisatin, there are some precision issue it seems (helps X3Reunion) 2021-12-18 17:41:40 +01:00
ptitSeb 6796145fa9 Added special case for X3Reunion to use emulated libjpeg.so.62 2021-12-18 15:07:13 +01:00
ptitSeb fea1bcc123 Added some special wrapper for pow10f and pow10 2021-12-18 14:57:10 +01:00
ptitSeb b6125b8063 Added a few gtk wrapped function (for X3R_config) 2021-12-18 14:23:18 +01:00
ptitSeb ad397bb1b6 [DYNAREC@ Fixed some regression with previous commit (like with Icconoclast) 2021-12-16 20:46:14 +01:00
ptitSeb dc333f052d [DYNAREC] Fixed 2 warnings 2021-12-16 08:40:54 +01:00
ptitSeb a77e120fc2 [DYNAREC] Fixed a warning 2021-12-16 08:38:41 +01:00
ptitSeb 07166e591e [DYNAREC] Improve jump internal to a dynablock (should also fix the regression introduced with cc69471576) 2021-12-15 20:44:02 +01:00
ptitSeb a1aac43a4e [DYNAREC] Cleaner flag tracking 2021-12-11 18:27:52 +01:00
ptitSeb cc69471576 [DYNAREC] Improved neon and flag tracking and fixed regression with barrier introduced with commit 5a8a4bb25b 2021-12-11 12:27:52 +01:00
ptitSeb ed8e01ea0c Merge pull request #517 from Seas0/master
Chores: Chinese doc refine and some code refine
2021-12-09 11:52:13 +01:00
Seas0 4fb847196c Minor Chinese doc refine 2021-12-09 18:37:31 +08:00
Seas0 40ee2cb868 Minor readability fix 2021-12-09 17:54:44 +08:00
ptitSeb 8d0b2edba2 Added wprintw to all wrapped ncurses libs (for #215) 2021-12-09 08:05:00 +01:00
ptitSeb 3b6e10a1f9 Added a couple of function to wrapped libc (for #215) 2021-12-09 08:01:38 +01:00
ptitSeb 4d4a849c9b Small change in fcntl, mainly for clarity 2021-12-09 08:00:22 +01:00
ptitSeb 58f94fe9ec [DYNAREC] Added noion of next and predecessor, for later use 2021-12-08 20:31:17 +01:00
ptitSeb ebff6f995a Added better trace for read 2021-12-08 20:11:47 +01:00
ptitSeb 5a8a4bb25b [DYNAREC] Cleaner BARRIER macro and handling 2021-12-08 19:15:08 +01:00
ptitSeb 6d8e781c72 [DYNAREC] Small change on how add_next/get_closest_next works 2021-12-05 17:31:13 +01:00
ptitSeb 834374d0f2 [DYNAREC] Changed NOP emiter and added VSTL_64_W for later use 2021-12-05 17:23:11 +01:00
ptitSeb f0d17b1f86 [DYNAREC] Fixed a rare possible segfault 2021-12-04 16:42:26 +01:00
ptitSeb 5478879a37 Fixed some issue with Find386CopyRel in elfloader 2021-11-30 22:39:17 +01:00
ptitSeb 4e2f50eee7 Backported some of box64 elfloader improvments 2021-11-30 18:48:34 +01:00
ptitSeb c47e25bef3 Changed how wrapped ldlinux, libc, libm and libpthread are load to help with newer glibc version (also should help static build of box86) 2021-11-30 11:40:48 +01:00
ptitSeb b5203b97bb [DYNAREC] Fixed XADD 16bits opcode 2021-11-29 11:58:30 +01:00
ptitSeb a7ac9a0aa8 [DYNAREC] Fixed CMPPD opcode 2021-11-29 11:26:41 +01:00
ptitSeb 0540efa171 [DYNAREC] Fixed and refined SQRTPS, RSRQTPS, RCPPS and DIVPS opcodes 2021-11-29 10:59:21 +01:00
ptitSeb b3b274acf7 [DYNAREC] Small fix on rcr defered flags calculation 2021-11-29 00:31:17 +01:00
ptitSeb 944ffcb788 [DYNAREC] Added missing defered flags functions 2021-11-29 00:27:03 +01:00
ptitSeb 865baf0d5f [DYNAREC] Fixed RCR Ed, 1 opcode 2021-11-29 00:25:21 +01:00
ptitSeb 8b555503c1 Fixed warning on wrapped libdbus 2021-11-29 00:16:44 +01:00
ptitSeb 11bb6bb2aa Fixed warning on wrapped libsdl2 2021-11-29 00:14:10 +01:00
ptitSeb 63864adbda [DYNAREC] Fixed remaining issue for SOFTFP build (for Pandora) 2021-11-29 00:13:52 +01:00
ptitSeb 0d89989c20 Fixed a warning 2021-11-28 23:37:57 +01:00
ptitSeb 59d4821bdc [DYNAREC] More tweaks to SOFTFP build for Pandora 2021-11-28 23:37:42 +01:00
ptitSeb 24ecba3e9e [DYNAREC] Fixed potential issue with FISTP64 and issue with SOFTFP (so Pandora mainly) 2021-11-28 23:32:11 +01:00
ptitSeb d9f9b86996 [DYNAREC] Fixed shld32 opcode 2021-11-28 19:37:26 +01:00
ptitSeb c27febf172 [DYNAREC] Fixed some warning 2021-11-28 18:14:44 +01:00
ptitSeb d18af9daf8 [DYNAREC] Fixed 66 F7 /6 DIV opcode 2021-11-28 17:09:15 +01:00
ptitSeb 4813a35eec [DYNAREC] Fixed an old issue with (quite rare) 66 AF STOSW opcode 2021-11-25 19:55:24 +01:00
ptitSeb 5bd33084dd Improved test17 a bit 2021-11-25 19:54:52 +01:00
ptitSeb 939c54792f Small optim on test8 that need PF 2021-11-24 22:37:41 +01:00
ptitSeb 28f6f58dd7 [DYNAREC] Small optim on FNCLEX opcode 2021-11-24 22:37:22 +01:00
ptitSeb 27fd1d11b8 Update COMPILE.md 2021-11-23 12:49:43 +01:00
ptitSeb 39355d3bd6 Merge pull request #508 from ryanfortner/improve-readme
Improve readme
2021-11-23 01:03:40 +01:00
Ryan Fortner 1582b486db Update readme.md 2021-11-22 18:45:57 -05:00
Ryan Fortner e4d58dd9cb Update README.md 2021-11-22 13:39:50 -05:00
Ryan Fortner f417d640e0 Improve readme 2021-11-22 13:35:42 -05:00
ptitSeb f79e16f48d [DYNAREC] Small changes, mostly cosmetics, on Barriers 2021-11-21 21:04:29 +01:00
ptitSeb 365daab33c [DYNAREC] Improved D9 FC FRNDINT and DF /7 FISTP opcodes 2021-11-21 18:37:00 +01:00
ptitSeb 62fceaaa3c Improve test19 2021-11-21 18:35:38 +01:00
ptitSeb 5af78fb18a [DYNAREC] Optimised D1 /3 RCR Ed, 1 opcode 2021-11-21 14:09:14 +01:00
ptitSeb 2dae632d24 [DYNAREC] Optimized shld32 2021-11-21 13:56:48 +01:00
ptitSeb 680e460ecd [DYNAREC] Small optim for DIV opcode 2021-11-21 11:21:35 +01:00
ptitSeb 07e715bb6d Fixed a warning 2021-11-21 11:21:10 +01:00
ptitSeb e255bc0874 Merge pull request #505 from Moldytzu/master
Fix broken link in pkgbuilds
2021-11-20 17:42:43 +01:00
Alex 0d0129e7c3 fix broken link 2021-11-20 18:40:32 +02:00
ptitSeb 3ca24bd45c Merge pull request #504 from Seas0/master
[DOC] Chinese doc and some typo fix
2021-11-20 10:45:43 +01:00
ptitSeb a627363afa Start of a new dev. cycle 2021-11-20 10:45:27 +01:00
Seas0 bcf6ca9e52 [DOC] Adding Chinese doc, partially referenced box64's
Reference: https://github.com/ptitSeb/box64/blob/main/docs/README_CN.md
2021-11-20 17:39:20 +08:00
Seas0 561579a7d6 [DOC] minor typo fix 2021-11-20 17:39:08 +08:00
481 changed files with 25469 additions and 10684 deletions

No files matched your search

+100
View File
@@ -0,0 +1,100 @@
### Manual build Box86 with Github Action
name: Custom build Box86
on:
workflow_dispatch:
inputs:
platform:
description: 'Target platform name'
required: true
default: 'GENERIC_ARM'
type: choice
options:
- I386
- GENERIC_ARM
- A64
- GAMESHELL
- ODROID
- PANDORA
- PHYTIUM
- PYRA
- RK3288
- RK3399
- RPI4
- RPI4ARM64
- SD845
build_type:
description: 'Build type'
required: true
default: 'RelWithDebInfo'
type: choice
options:
- RelWithDebInfo
- Release
- Debug
- MinSizeRel
dynarec:
description: 'Enable dynarec'
required: false
default: 'true'
type: boolean
trace:
description: 'Enable trace'
required: false
default: 'false'
type: boolean
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
- name: "Environment preparation"
run: |
sudo apt-get update
if [[ ${{ github.event.inputs.platform }} != 'I386' && ${{ github.event.inputs.platform }} != 'GENERIC_ARM' ]]; then
echo "BOX86_PLATFORM_MARCRO=-D${{ github.event.inputs.platform }}=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
else
if [[ ${{ github.event.inputs.platform }} == 'I386' ]]; then
echo "BOX86_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=/bin/i686-linux-gnu-gcc-10" >> $GITHUB_ENV
sudo apt-get -y install git libc6-dev-i386-amd64-cross gcc-10-i686-linux-gnu cmake make python3
else
echo "BOX86_PLATFORM_MARCRO=-DCMAKE_C_FLAGS=-marm" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
fi
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX86_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX86_COMPILER }}"
echo "Build type: ${{ github.event.inputs.build_type }}"
echo "Dynarec Enabled: ${{ github.event.inputs.dynarec }}"
echo "Trace Enabled: ${{ github.event.inputs.trace }}"
- name: "Build Box86"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }} ${{ env.BOX86_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }}\
-DARM_DYNAREC:BOOL=${{ github.event.inputs.dynarec }}\
-DHAVE_TRACE:BOOL=${{ github.event.inputs.trace }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ github.event.inputs.platform }}-${{ github.event.inputs.build_type }}
path: build/box86
+47 -15
View File
@@ -1,7 +1,7 @@
### Auto build Box86 and release its binary with Github Action
name: Build and Release Box86
on:
on:
workflow_dispatch:
release:
push:
@@ -10,16 +10,16 @@ on:
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "CMakeLists.txt"
- "**/*.yml"
pull_request:
pull_request:
types: [assigned, opened, synchronize, reopened]
paths:
- "**/*.c"
- "**/*.h"
- "**/*.S"
- "**/*.py"
- "CMakeList.txt"
- "CMakeLists.txt"
- "**/*.yml"
jobs:
@@ -27,10 +27,25 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM]
platform: [I386, OTHER_ARM, PANDORA, PYRA, GAMESHELL, RPI4, RPI4ARM64, ODROID, RK3399, RK3288, A64, SD845, PHYTIUM, ANDROID]
type: [Release, Trace]
os: [ubuntu-latest]
include:
- platform: TEGRAX1
type: Release
os: ubuntu-18.04
- platform: TEGRAX1
type: Trace
os: ubuntu-18.04
- platform: TEGRAX1ARM32
type: Release
os: ubuntu-18.04
- platform: TEGRAX1ARM32
type: Trace
os: ubuntu-18.04
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- name: "Checkout Box86 Repository"
uses: actions/checkout@v2
@@ -40,15 +55,22 @@ jobs:
sudo apt-get update
if [[ ${{ matrix.platform }} != 'I386' && ${{ matrix.platform }} != 'OTHER_ARM' ]]; then
echo "BOX86_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
sudo apt-get -y install git gcc-arm-linux-gnueabihf cmake make python3
sudo apt-get -y install git cmake make python3
if [[ ${{ matrix.platform }} == 'ANDROID' ]]; then
wget https://dl.google.com/android/repository/android-ndk-r23b-linux.zip
unzip android-ndk-r23b-linux.zip
echo "BOX86_COMPILER=$PWD/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi31-clang" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-DANDROID=1 -DNOLOADADDR=1" >> $GITHUB_ENV
else
sudo apt-get -y install gcc-arm-linux-gnueabihf
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
echo "BOX86_PLATFORM_MARCRO=-D${{ matrix.platform }}=1" >> $GITHUB_ENV
fi
else
if [[ ${{ matrix.platform }} == 'I386' ]]; then
echo "BOX86_PLATFORM_MARCRO=-DLD80BITS=1 -DNOALIGN=1" >> $GITHUB_ENV
echo "BOX86_COMPILER=/bin/i686-linux-gnu-gcc-10" >> $GITHUB_ENV
sudo apt-get -y install git libc6-dev-i386-amd64-cross gcc-10-i686-linux-gnu cmake make python3
ls /bin/*gcc*
else
echo BOX86_PLATFORM_MARCRO="-DARM_DYNAREC=ON -DCMAKE_C_FLAGS=-marm" >> $GITHUB_ENV
echo "BOX86_COMPILER=arm-linux-gnueabihf-gcc" >> $GITHUB_ENV
@@ -63,26 +85,36 @@ jobs:
echo BOX86_BUILD_TYPE=RelWithDebInfo >> $GITHUB_ENV
echo BOX86_HAVE_TRACE=1 >> $GITHUB_ENV
fi
- name: "Display Build info"
run: |
echo "CMake Platform Macro: ${{ env.BOX86_PLATFORM_MARCRO }}"
echo "CMake C Compiler: ${{ env.BOX86_COMPILER }}"
echo "Build type: ${{ env.BOX86_BUILD_TYPE }}"
echo "Trace Enabled: ${{ env.BOX86_HAVE_TRACE }}"
- name: "Build Box86"
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }} ${{ env.BOX86_PLATFORM_MARCRO }} -DCMAKE_BUILD_TYPE=${{ env.BOX86_BUILD_TYPE }} -DHAVE_TRACE=${{ env.BOX86_HAVE_TRACE }} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
cmake .. -DCMAKE_C_COMPILER=${{ env.BOX86_COMPILER }}\
${{ env.BOX86_PLATFORM_MARCRO }}\
-DCMAKE_BUILD_TYPE=${{ env.BOX86_BUILD_TYPE }}\
-DHAVE_TRACE=${{ env.BOX86_HAVE_TRACE }}\
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
make -j$(nproc) VERBOSE=1
- name: "Test Box86"
if: ${{ matrix.platform == 'I386' }}
run: |
cd build
ctest -j$(nproc)
- name: "Upload Artifact"
uses: actions/upload-artifact@v2
with:
name: box86-${{ matrix.platform }}-${{ matrix.type }}
path: build/box86
+95 -36
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.10)
option(PANDORA "Set to ON if targeting an OpenPandora device" ${PANDORA})
option(PYRA "Set to ON if targeting an OpenPandora device" ${PYRA})
@@ -9,19 +9,23 @@ option(RPI4ARM64 "Set to ON if targeting an RaspberryPI4 device with multiarch a
option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gameforce Chi, RGB10..." ${GOA_CLONE})
option(RK3288 "Set to ON if targeting an Rockchip RK3288 based device" ${RK3288})
option(RK3399 "Set to ON if targeting an Rockchip RK3399 based device" ${RK3399})
option(ODROIDN2 "Set to ON if targeting an Odroid-N2 device" ${ODROIDN2})
option(TEGRAX1 "Set to ON if targeting an Tegra X1 (ARM64) based device" ${TEGRAX1})
option(TEGRAX1ARM32 "Set to ON if targeting an Tegra X1 (ARM32) based device" ${TEGRAX1ARM32})
option(PHYTIUM "Set to ON if targeting an Phytium (D2000 or FT2000/4) based device" ${PHYTIUM})
option(GAMESHELL "Set to ON if targeting a GameShell device" ${GAMESHELL})
option(ODROID "Set to ON if targeting an ODroid device" ${ODROID})
option(POWER9 "Set to ON if targeting a POWER9 processor" ${POWER9})
option(SD845 "Set to ON if targeting a Snapragon 845 based device" ${SD845})
option(A64 "Set to ON if targeting an Allwinner A64 based device" ${A64})
option(LX2160A "Set to ON if targeting an LX2160A based device" ${LX2160A})
option(ANDROID "Set to ON if targeting an Android device" ${ANDROID})
option(USE_CCACHE "Set to ON to use ccache if present in the system" ${USE_CCACHE})
option(HAVE_TRACE "Set to ON to have Trace ability (needs ZydisInfo library)" ${HAVE_TRACE})
option(NOLOADADDR "Set to ON to avoid fixing the load address of Box86" ${NO_LOADAADR})
option(NOGETCLOCK "Set to ON to avoid using clock_gettime with CLOCK_MONOTONIC_COARSE for RDTSC opcode (use gltimeofday instead)" ${NOGETCLOCK})
option(NOGIT "Set to ON if not building from a git clone repo (like when building from a zip download from github)" ${NOGIT})
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
if(PANDORA OR PYRA OR RPI2 OR RPI3 OR RPI4 OR GAMESHELL OR ODROID OR GOA_CLONE OR RK3288 OR RK3399 OR ODROIDN2 OR TEGRAX1 OR TEGRAX1ARM32 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A)
set(LD80BITS OFF CACHE BOOL "")
set(NOALIGN OFF CACHE BOOL "")
set(ARM_DYNAREC ON CACHE BOOL "")
@@ -51,7 +55,13 @@ else()
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE} CACHE INTERNAL "The Python3 executable" FORCE)
endif()
if(RK3399 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64)
cmake_host_system_information(RESULT CMAKE_HOST_SYSTEM_PROCESSOR QUERY OS_PLATFORM)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
if(_aarch64 AND (RK3399 OR ODROIDN2 OR TEGRAX1 OR RPI4ARM64 OR PHYTIUM OR SD845 OR A64 OR LX2160A))
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
#set(CMAKE_ASM_COMPILER arm-linux-gnueabihf-as) #will use gcc in fact
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
@@ -123,10 +133,28 @@ elseif(RK3399)
add_definitions(-DRK3399)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ODROIDN2)
add_definitions(-DODROIDN2)
add_definitions(-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crc+simd+crypto -mcpu=cortex-a73.cortex-a53+crypto -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard")
elseif(TEGRAX1)
add_definitions(-DTEGRAX1)
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(TEGRAX1ARM32)
add_definitions(-DTEGRAX1ARM32)
add_definitions(-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-marm -pipe -march=armv8-a+crc -mcpu=cortex-a57 -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(PHYTIUM)
add_definitions(-DPHYTIUM)
add_definitions(-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8.1-a+simd+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(LX2160A)
add_definitions(-DLX2160A)
add_definitions(-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard)
set(CMAKE_ASM_FLAGS "-pipe -march=armv8-a+crypto+crc -mcpu=cortex-a72+crypto -mfpu=neon-fp-armv8 -mfloat-abi=hard")
elseif(ANDROID)
add_definitions(-DANDROID)
elseif(ARM_DYNAREC)
#if DYNAREC is selected alone, without any arch
set(CMAKE_ASM_FLAGS "-pipe -march=armv7-a+simd -mfpu=neon")
@@ -157,6 +185,7 @@ endif()
if(NOALIGN)
add_definitions(-DNOALIGN)
add_definitions(-pipe -march=core2 -msse2)
endif()
if(HAVE_TRACE)
@@ -223,6 +252,7 @@ set(ELFLOADER_SRC
"${BOX86_ROOT}/src/box86context.c"
"${BOX86_ROOT}/src/build_info.c"
"${BOX86_ROOT}/src/custommem.c"
"${BOX86_ROOT}/src/mallochook.c"
"${BOX86_ROOT}/src/tools/bridge.c"
"${BOX86_ROOT}/src/tools/pathcoll.c"
"${BOX86_ROOT}/src/tools/fileutils.c"
@@ -358,6 +388,8 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedlibpanel.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibncurses6.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibtinfo6.c"
"${BOX86_ROOT}/src/wrapped/wrappedgmp.c"
"${BOX86_ROOT}/src/wrapped/wrappedgcrypt.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgdkx112.c"
"${BOX86_ROOT}/src/wrapped/wrappedgtk3.c"
@@ -370,9 +402,16 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedgconf2.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstinterfaces010.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstreamer.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstaudio.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstvideo.c"
"${BOX86_ROOT}/src/wrapped/wrappedgsttag.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstbase.c"
"${BOX86_ROOT}/src/wrapped/wrappedgstapp.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenugtk.c"
"${BOX86_ROOT}/src/wrapped/wrappeddbusmenuglib.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator.c"
"${BOX86_ROOT}/src/wrapped/wrappedappindicator3.c"
"${BOX86_ROOT}/src/wrapped/wrappedatk.c"
"${BOX86_ROOT}/src/wrapped/wrappedatkbridge.c"
"${BOX86_ROOT}/src/wrapped/wrappedpangoft2.c"
@@ -409,8 +448,20 @@ set(WRAPPEDS
"${BOX86_ROOT}/src/wrapped/wrappedplds4.c"
"${BOX86_ROOT}/src/wrapped/wrappedplc4.c"
"${BOX86_ROOT}/src/wrapped/wrappedssl3.c"
"${BOX86_ROOT}/src/wrapped/wrappedsoftokn3.c"
"${BOX86_ROOT}/src/wrapped/wrappedfreebl3.c"
"${BOX86_ROOT}/src/wrapped/wrappedsecret1.c"
"${BOX86_ROOT}/src/wrapped/wrappedtbbmalloc.c"
"${BOX86_ROOT}/src/wrapped/wrappedmimalloc.c"
"${BOX86_ROOT}/src/wrapped/wrappedselinux.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibharfbuzz.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibcairogobject.c"
"${BOX86_ROOT}/src/wrapped/wrappedlibvkd3d.c"
"${BOX86_ROOT}/src/wrapped/wrappedgomp.c"
"${BOX86_ROOT}/src/wrapped/wrappedcap.c"
"${BOX86_ROOT}/src/wrapped/wrappedpcap.c"
"${BOX86_ROOT}/src/wrapped/wrappedfaudio.c"
"${BOX86_ROOT}/src/wrapped/wrappedtbbmallocproxy.c"
)
if(ANDROID)
list(APPEND WRAPPEDS
@@ -465,6 +516,7 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/dynarec_arm.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_functions.c"
"${BOX86_ROOT}/src/dynarec/arm_printer.c"
"${BOX86_ROOT}/src/dynarec/arm_jmpnext.c"
"${BOX86_ROOT}/src/dynarec/arm_prolog.S"
"${BOX86_ROOT}/src/dynarec/arm_epilog.S"
@@ -495,6 +547,7 @@ if(ARM_DYNAREC)
"${BOX86_ROOT}/src/dynarec/dynarec_arm_df.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f0.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_660f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_66f0.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f20f.c"
"${BOX86_ROOT}/src/dynarec/dynarec_arm_f30f.c"
)
@@ -552,7 +605,7 @@ if(ARM_DYNAREC)
if(ANDROID)
target_link_libraries(${BOX86} dynarec m dl)
else()
target_link_libraries(${BOX86} dynarec m dl rt pthread)
target_link_libraries(${BOX86} dynarec m dl rt pthread resolv)
endif()
endif()
if(${CMAKE_VERSION} VERSION_LESS "3.13")
@@ -572,9 +625,10 @@ add_executable(${BOX86} ${ELFLOADER_SRC} ${WRAPPEDS} "${BOX86_ROOT}/src/git_head
add_dependencies(${BOX86} WRAPPERS)
add_dependencies(${BOX86} PRINTER)
if(ANDROID)
target_link_libraries(${BOX86} m dl)
target_link_libraries(${BOX86} c m dl)
else()
target_link_libraries(${BOX86} m dl rt pthread)
#target_link_libraries(${BOX86} c m dl rt pthread resolv)
set_target_properties(${BOX86} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed -lc -lm -ldl -lrt -lpthread -lresolv -Wl,--as-needed -pthread")
endif()
if(ARM_DYNAREC)
target_link_libraries(${BOX86} dynarec)
@@ -593,11 +647,6 @@ else()
endif()
endif()
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "i686" _x86)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "x86_64" _x86_64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "aarch64" _aarch64)
string(COMPARE EQUAL "${CMAKE_HOST_SYSTEM_PROCESSOR}" "armhf" _armhf)
if(NOT _x86 AND NOT _x86_64)
install(TARGETS ${BOX86}
RUNTIME DESTINATION bin)
@@ -606,6 +655,7 @@ if(NOT _x86 AND NOT _x86_64)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.6 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libstdc++.so.5 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libgcc_s.so.1 DESTINATION /usr/lib/i386-linux-gnu/)
install(FILES ${CMAKE_SOURCE_DIR}/x86lib/libpng12.so.0 DESTINATION /usr/lib/i386-linux-gnu/)
endif()
if(NOT TARGET uninstall)
@@ -649,105 +699,114 @@ set(CPACK_DEBIAN_FILE_NAME "${BOX86}-${BOX86_MAJOR}.${BOX86_MINOR}.${BOX86_REVIS
INCLUDE(CPack)
add_test(NAME bootSyscall COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test01 -D TEST_OUTPUT=tmpfile01.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref01.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME bootSyscallC COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test02 -D TEST_OUTPUT=tmpfile02.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref02.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME printf COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test03 -D TEST_OUTPUT=tmpfile03.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref03.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME args COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test04 -D TEST_ARGS2=yeah -D TEST_OUTPUT=tmpfile04.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref04.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME maths1 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test05 -D TEST_ARGS2=7 -D TEST_OUTPUT=tmpfile05.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref05.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME threadsStart COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test06 -D TEST_OUTPUT=tmpfile06.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref06.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME trig COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test07 -D TEST_OUTPUT=tmpfile07.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref07.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME pi COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test08 -D TEST_OUTPUT=tmpfile08.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref08.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fork COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test09 -D TEST_OUTPUT=tmpfile09.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref09.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME cppThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test10 -D TEST_OUTPUT=tmpfile10.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref10.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME tlsData COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test11 -D TEST_OUTPUT=tmpfile11.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref11.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME fpu COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test12 -D TEST_OUTPUT=tmpfile12.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref12.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME contexts COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test13 -D TEST_OUTPUT=tmpfile13.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref13.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME conditionalThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
if(NOT LD80BITS)
add_test(NAME conditionalThreads COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test14 -D TEST_OUTPUT=tmpfile14.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref14.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
endif()
add_test(NAME linkingIndirectNoversion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test15 -D TEST_OUTPUT=tmpfile15.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref15.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME linkingIndirectVersion COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test16 -D TEST_OUTPUT=tmpfile16.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref16.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME ucomiss COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile.txt
add_test(NAME sse COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test17 -D TEST_OUTPUT=tmpfile17.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref17.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
set_tests_properties(sse PROPERTIES ENVIRONMENT "BOX86_DYNAREC_FASTNAN=0")
add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test18 -D TEST_OUTPUT=tmpfile18.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile.txt
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile19.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref19.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test20 -D TEST_OUTPUT=tmpfile20.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)
add_test(NAME "${testname}" COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile.txt
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/extensions/${testname} -D TEST_OUTPUT=tmpfile-${testname}.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/extensions/${testname}.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake)
endforeach()
+23
View File
@@ -0,0 +1,23 @@
box86 (0.2.6) unstable; urgency=low
* Added an option to get generated -NAN on SSE2 operation
* Many small fixes and improvement to get steam and SteamPlay working (along with box64)
* Added some workaround for program calling uname to mimic x86 system
* Added some more Vulkan extensions
* Added some granularity to mmap64, and generic memory protection tracking improvment, to mimic x86 system (for wine stagging and proton)
* Better clone syscall and libc implementation
* Improved wrapping of GTK libs
* More wrapped libs (more gtk libs, like gstreamer-1.0 among other non-gtk libs too)
* More wrapped functions(with some tricky one, like dladdr1)
* Some fixes and improvment to some wrapped functions
* Refactor Dynarec:
* - better handling of SSE/x87 registers
* - optimisation to limit float/double conversion
* - better handling of "internal" jump inside a dynablock
* Improved elfloader
* Improved some tests
* A few fixes in some Dynarec opcodes
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* A bit more optimisation in some Dynarec opcodes
-- Sebastien Chevalier <[email protected]> Tue, 18 Jan 2022 11:20:33 -0500
+1
View File
@@ -0,0 +1 @@
11
+14
View File
@@ -0,0 +1,14 @@
Source: box86
Section: utils
Priority: optional
Maintainer: Ryan Fortner <[email protected]>
Build-Depends: cmake, debhelper (>=11~)
Standards-Version: 4.1.4
Homepage: https://github.com/ptitSeb/box86
Package: box86
Architecture: any
Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems, like ARM (host system needs to be 32bit little-endian).
+26
View File
@@ -0,0 +1,26 @@
Format-Specification: http://dep.debian.net/deps/dep5/
Files: *
Copyright: © 2022 Sebastien Chevalier
License: MIT
License: MIT
Copyright (c) 2018-2021 Sebastien Chevalier ("ptitSeb")
.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+1
View File
@@ -0,0 +1 @@
box86: no-manual-page
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_configure:
dh_auto_configure -- \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DARM_DYNAREC=1
override_dh_shlibdeps:
dh_shlibdeps --exclude=libgcc_s.so.1 --exclude=libpng12.so.0 --exclude=libstdc++.so.5 --exclude=libstdc++.so.6
+1
View File
@@ -0,0 +1 @@
3.0 (quilt)
+5
View File
@@ -0,0 +1,5 @@
Bug-Database: https://github.com/ptitSeb/box86/issues
Bug-Submit: https://github.com/ptitSeb/box86/issues/new
Repository: https://github.com/ptitSeb/box86.git
Repository-Browse: https://github.com/ptitSeb/box86
Security-Contact: [email protected]
+1
View File
@@ -0,0 +1 @@
version=3
+22
View File
@@ -1,3 +1,25 @@
v0.2.6
======
* Added an option to get generated -NAN on SSE2 operation
* Many small fixes and improvement to get steam and SteamPlay working (along with box64)
* Added some workaround for program calling uname to mimic x86 system
* Added some more Vulkan extensions
* Added some granularity to mmap64, and generic memory protection tracking improvment, to mimic x86 system (for wine stagging and proton)
* Better clone syscall and libc implementation
* Improved wrapping of GTK libs
* More wrapped libs (more gtk libs, like gstreamer-1.0 among other non-gtk libs too)
* More wrapped functions(with some tricky one, like dladdr1)
* Some fixes and improvment to some wrapped functions
* Refactor Dynarec:
* better handling of SSE/x87 registers
* optimisation to limit float/double conversion
* better handling of "internal" jump inside a dynablock
* Improved elfloader
* Improved some tests
* A few fixes in some Dynarec opcodes
* Don't quit on unsupported syscall, return -1 / ENOSYS error
* A bit more optimisation in some Dynarec opcodes
v0.2.4
======
* Some work on Dynarec to limit the number of mutex use, and also allow smaller block to be built (for JIT'd programs)
+73 -26
View File
@@ -1,5 +1,17 @@
Compiling
Compiling/Installing
----
#### Debian-based Linux
You can use [@Itai-Nelken](https://github.com/Itai-Nelken)'s apt repository to install precompiled box86 debs, updated weekly.
```
sudo wget https://itai-nelken.github.io/weekly-box86-debs/debian/box86.list -O /etc/apt/sources.list.d/box86.list
wget -qO- https://itai-nelken.github.io/weekly-box86-debs/debian/KEY.gpg | sudo apt-key add -
sudo apt update && sudo apt install box86 -y
```
Alternatively, you can generate your own package using the [instructions below](https://github.com/ptitSeb/box86/blob/master/docs/COMPILE.md#debian-packaging).
#### for Pandora
`mkdir build; cd build; cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make`
@@ -14,26 +26,33 @@ Compiling
#### for Raspberry Pi
_a build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
_A build for model 2, 3 and 4 can be done. Model 1 and 0 cannot (at least not with Dynarec, as they lack NEON support)_
```
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
make
mkdir build; cd build; cmake .. -DRPI4=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4=1 for Pi4 (use `-DRPI2=1` etc for other models)
make # can use `make -j2`, `make -j3`, etc to speed up 1st build (but beware of running out of memory if going too high)
sudo make install
sudo systemctl restart systemd-binfmt
```
Note that you can use `make -j2` or more to speed up 1st build, but beware of the memory requirement if you go to high.
#### for Raspberry Pi on 64bits OS
#### for Raspberry Pi on 64bit OS
_For Pi4. Change to RPI2 or RPI3 for other models. Change `-DRPI4=1` to `-DRPI4ARM64=1` for compiling on arm64. (armhf multiarch or chroot required alongside armhf gcc. Install it with 'sudo apt install gcc-arm-linux-gnueabihf'.)_
_armhf multiarch or chroot required for running box86 (armhf) on aarch64_
```
# example of enabling multiarch & installing libc6:armhf (to run box86:armhf on aarch64)
# (running i386-wine on aarch64 requires more armhf libraries)
sudo dpkg --add-architecture armhf && sudo apt-get update
sudo apt-get install libc6:armhf -y
```
_Build box86:armhf on RPiOS 64-bit ARM (aarch64)_
```
sudo apt install gcc-arm-linux-gnueabihf # building 32-bit ARM code on aarch64 requires this armhf gcc cross-compiler toolchain
git clone https://github.com/ptitSeb/box86
cd box86
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
mkdir build; cd build; cmake .. -DRPI4ARM64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # -DRPI4ARM64=1 for Pi4 aarch64 (use `-DRPI2ARM64=1` etc for other models)
make -j2
sudo make install
sudo systemctl restart systemd-binfmt
@@ -47,7 +66,9 @@ sudo systemctl restart systemd-binfmt
`mkdir build; cd build; cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most RK3399 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for Tinker Board (1/1S) or RK3288
@@ -57,19 +78,23 @@ As most RK3399 device run AARCH64 OS, you'll need an `armhf` multiarch environme
`mkdir build; cd build; cmake .. -DA64=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
As most Allwinner A64 device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most Allwinner A64 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for Snapdragon 845
`mkdir build; cd build; cmake .. -DSD845=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Snapdragon 845 device run AARCH64 OS, in most cases you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most Snapdragon 845 devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On mobian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
#### for Phytium
`mkdir build; cd build; cmake .. -DPHYTIUM=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j4`
As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian/ubuntu, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
As most Phytium (D2000 or FT2000/4) devices run an AARCH64 OS, you'll need an `armhf` multiarch environment, and an armhf gcc: On debian, install it with `sudo apt install gcc-arm-linux-gnueabihf`.
Also, on armbian, you may need to install `libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other files not included with box86.
#### for Other ARM Linux platforms
@@ -79,42 +104,64 @@ As most Phytium (D2000 or FT2000/4) device run AARCH64 OS, you'll need an `armhf
`mkdir build; cd build; cmake .. -DCMAKE_C_FLAGS="-m32" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo; make -j3`
#### use ccmake
### use ccmake
Alternatively, you can use the curses-bases ccmake (or any other gui frontend for cmake) to select wich platform to use interactively.
#### Customize your build
### Customize your build
*use ccache if you have it*
#### use ccache if you have it
Add `-DUSE_CCACHE=1` if you have ccache (it's better if you plan to touch the sources)
*have some debug info*
#### To have 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 a trace enabled build (***the interpreter will be slightly slower***), add `-DHAVE_TRACE=1`. But you will need the [Zydis library](https://github.com/zyantific/zydis) in your `LD_LIBRARY_PATH` or in the system library folders at runtime.
*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). Note that compiling with `ARM_DYNAREC` but without hardware profile is not advise. If you get error building that "target CPU does not support ARM mode", then try to pick hardware profile (like ODROID for armv7 or PI4 for armv8). Also, if you are using a 64bits with armhf multiarch, it's much easier to pick one of the hardware profile like `RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
###### *Note: VFPv3 and NEON are required for Dynarec.*
*not building from a git clone*
###### *Note: Compiling with `ARM_DYNAREC` without selecting a hardware profile is not advised.*
If you are not building from a git clone (for example, downloading a release source zipped from github), you need to activate `-DNOGIT=1` from cmake to be able to build (normal process include git sha1 of HEAD in the version that box86 print).
Dynarec is only available on the ARM architecture (for the meantime anyways). Activate it by using `-DARM_DYNAREC=1`.
You will most likely need `-marm` in compilation flags (Many compilers default to the Thumb instruction set and Dynarec does not support this).
###### *Note: If you get error building that "target CPU does not support ARM mode", then try to pick a hardware profile (like ODROID for armv7 or PI4 for armv8).*
##### 64bit OS with Dynarec
If you are using a 64bit OS with armhf multiarch, it's much easier to pick one of the hardware profiles.
`RPI4ARM64`, `RK3399`, `PHYTIUM` or `SD845`.
#### Not building from a git clone
If you are not building from a git clone (for example, downloading a release source code zip from github), you need to use `-DNOGIT=1` from cmake to be able to build (box86 uses git SHA1 to show last commit in version number).
----
Testing
----
A few tests are included.
They can be launched with `ctest`
They are very basic and don't test much for now.
A few tests are included with box86.
They can be launched using the `ctest` command.
The tests are very basic and only tests some functionality for now.
----
Note about devices with Tegra X1 and newer.
Nvidia don't provide armhf libraries for their GPU drivers at this moment so there is no special variable to compile it for them as it would be missleading for many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. As instalation of Mesa can break Nvidia driver, safest option is usage of chroot.
NVIDIA doesn't provide armhf libraries for their GPU drivers at this time. There is no special variable to compile box86 for them, as it would be misleading to many people. If you still want to use it wihout GPU acceleration, building it with RPI4 configuration should work just fine. Installation of Mesa can break the NVIDIA driver, so the safest option is to use a chroot environment.
----
Debian Packaging
----
Box86 can also be packaged into a .deb file with `DEB_BUILD_OPTIONS=nostrip dpkg-buildpackage -us -uc -nc`.
+25 -20
View File
@@ -1,22 +1,18 @@
# box86
![Official logo](img/Box86Logo.png "Official Logo")
Linux Userspace x86 Emulator with a twist
[![Build Status](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master)](https://app.travis-ci.com/ptitSeb/box86)
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
Box86 lets you run x86 Linux programs (such as games) on non-x86 Linux systems, like ARM (host system needs to be 32bit little-endian).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environnement).
You *NEED* a 32-bit subsystem to run and build Box86. Box86 is useless on 64-bit only systems. Also, you *NEED* a 32-bit toolchain to build Box86. A toolchain that only supports 64-bit will not compile Box86, and you'll get errors (typically on aarch64, you get "-marm" not recognized, and you'll need a multiarch or chroot environment).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at thoses bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Because Box86 uses the native versions of some "system" libraries, like libc, libm, SDL, and OpenGL, it's easy to integrate and use with most applications, and performance can be surprisingly high in many cases. Take a look at those bench analysis for an example [here](https://box86.org/index.php/2021/06/game-performances/).
Most x86 Games need OpenGL, so on ARM platforms a solution like [gl4es](https://github.com/ptitSeb/gl4es) is usually necessary. (Most ARM platforms only support OpenGL ES and/or their OpenGL implementation is dodgy (see OpenGL on Android).)
@@ -29,13 +25,21 @@ To enable TRACE (i.e. dumping to stdout all individual x86 instructions executed
Some x86 internal opcodes use parts of "Realmode X86 Emulator Library", see [x86primop.c](../src/emu/x86primop.c) for copyright details
Here's 6 videos, the first 2 videos are videos of "Airline Tycoon Deluxe" and "Heretic 2" running on a GigaHertz OpenPandora (the second one is using the dynarec), and the next 2 videos are videos of of "Bit.Trip.Runner" and "Neverwinter Night" running on an ODroid XU4 (without dynarec), and the last 2 videos are on on a Pi4: Shovel Knight (video from @ITotalJustice) and Freedom Planet (video from @djazz), also without dynarec.
----
Compiling/Installation
----
> Compilation instructions can be found [here](COMPILE.md)
> Instructions for installing Wine for Box86 can be found [here](X86WINE.md)
----
Here are 6 videos, the first 2 videos are videos of "Airline Tycoon Deluxe" and "Heretic 2" running on a GigaHertz OpenPandora (the second one is using the dynarec), and the next 2 videos are videos of of "Bit.Trip.Runner" and "Neverwinter Night" running on an ODroid XU4 (without dynarec), and the last 2 videos are on on a Pi4: Shovel Knight (video from @ITotalJustice) and Freedom Planet (video from @djazz), also without dynarec.
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
You can find many more Box86 video on Youtube in the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) Channels
You can find many more Box86 videos on the [MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ), [Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g) or [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA) YouTube channels.
Compatibility list is there: https://github.com/ptitSeb/box86-compatibility-list/issues
Compatibility list is here: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
@@ -87,10 +91,11 @@ Notes about Steam
Linux Steam's can run now with box86. But it's still a bit unstable, and not everything works:
- First problem is Steam crashing after the sign-in window, if you encounter this issue, you may need to add libappindicator. To install it on Debian, run `sudo apt install libappindicator1`.
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm intalled. To install it on Debian, run `sudo apt install libnm0`.
- If you select to "Remember password", Steam is crashing on subsequent starts, unless you have libnm installed. To install it on Debian, run `sudo apt install libnm0`.
- If you have trouble installing Steam, you can find `install_steam.sh` in the root folder of the box86 repo. This simple script will download and install steam in your home folder, and then create a shortcut to steam in `/usr/local/bin` (and for this it will ask for sudo permission). Simply use `steam` to launch once it's installed. Note that the installation, being in the Home folder, will only work for a single user. Don't use this script if you need a multi-user installation.
- Once open, Steam will only work on "Small Mode" and in "Big Picture", not in the regular "Large Mode". This is because some Steam components used in the browser view are only 64-bit now. So go in the "View" menu and switch to "Small view", else the list will stay empty. Alternatively, Steam can be started in small mode directly by using `+open steam://open/minigameslist` command line arguments.
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables.
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aformentionned feature, it is safer to add it to your system if you intend to play those game. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
- To avoid the "libc.so.6 is absent" message, you can use `STEAMOS=1` and `STEAM_RUNTIME=1` as environment variables (it's automatically there if you used the `install_steam.sh` script)
- Some Steam games (most Source engine games, like "Portal" or "Half-Life 2") use libtcmalloc. Box86 will detect it and will try to LD_PRELOAD it, for better compatibility. While it should work without the aforementioned feature, it is safer to add it to your system if you intend to play those games. To install it on Debian, run `sudo apt install libtcmalloc-minimal4`.
Steam for Windows installs fine but doesn't work yet.
@@ -107,19 +112,19 @@ Note: if you plan to use box86 with Wine on Raspberry Pi 3 or earlier, those mod
Notes about Vulkan
----
Box86 already wrap vulikan. If your system has a 32bits vulkan driver, box86 will use it when needed. Note that vulkan wrapping has not been tested much, due to the limited vulkan support on the hardware I currently own. Profile 1.0 and 1.1, whith some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardxware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
Box86 already wrap Vulkan. If your system has a 32bits Vulkan driver, box86 will use it when needed. Note that Vulkan wrapping has not been tested much, due to the limited Vulkan support on the hardware I currently own. Profile 1.0 and 1.1, with some extension, should be OK. 1.2 is not really wrapped. I know some demos work on Pi4 (Sascha Willems demos build for x86 work the same as if build on armhf directly). Note that the Vulkan driver of the Pi4 DOES NOT support dxvk for now (wine DirectX->Vulkan wrapper). It's not a box86 issue, it's missing extensions (hardware support) and a few other things that make dxvk not working on pi4. On Panfrost side, PanVK is a bit young and I haven't tested dxvk with it yet.
----
Final word
----
I want to thank everyone who has contributed to box86 developpement.
I want to thank everyone who has contributed to box86 development.
There are many ways to contribute: code, financial, hardware and advertisement!
So, in no particular order, I want to thank:
* For their major code contribution: rajdakin, icecream95, M-HT
* For their major financial contribution: FlyingFathead, stormchaser3000
* For their major financial contribution: FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* For their hardware contribution: [Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* For their continous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
* For their continuous advertisement of box86 project: salva ([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
And I also thank the many other people who participated even once in the project.
+135
View File
@@ -0,0 +1,135 @@
![Official logo](img/Box86Logo.png "Official Logo")
Linux用户空间的x86应用模拟器
[更新历史](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [English](https://github.com/ptitSeb/box86/blob/master/docs/README.md) | [报告错误](https://github.com/ptitSeb/box86/issues/new)
![build](https://app.travis-ci.com/ptitSeb/box86.svg?branch=master) ![stars](https://img.shields.io/github/stars/ptitSeb/box86) ![forks](https://img.shields.io/github/forks/ptitSeb/box86) ![contributors](https://img.shields.io/github/contributors/ptitSeb/box86) ![prs](https://img.shields.io/github/issues-pr/ptitSeb/box86) ![issues](https://img.shields.io/github/issues/ptitSeb/box86)
----
使用Box86可以在ARM或其他非x86架构的Linux操作系统上运行x86 Linux程序(例如游戏),请注意,主机系统需要是**32位小端**的。
你需要一个**32位**的子系统来运行Box86,因为Box86在纯64位系统上无法使用,同时你也需要一个**32位**的Linux编译工具链来编译Box86,例如**arm-linux-gnueabihf-gcc**, 否则你将无法编译Box86 (一般的64位ARM编译工具链如 aarch64-linux-gnu-gcc 不支持"-marm"编译选项,会编译失败并报错)。
因为Box86使用了一些“系统”库的原生版本,例如libc、libm、SDL和OpenGL,所以在很多情况下性能很不错,也可以方便地与其他应用集成使用。点击[此处](https://box86.org/index.php/2021/06/game-performances/)查看Benchmark示例。
大多数x86游戏都用到了OpenGL,所以在ARM平台上类似于[gl4es](https://github.com/ptitSeb/gl4es)的解决方案通常是必要的。(许多ARM平台仅提供OpenGL ES支持,又或者他们的OpenGL实现很不可靠(例如Android上的OpenGL)。)
Box86为ARM平台集成了DynaRec(动态重编译器),比仅使用解释器提升5到10倍性能。关于Dynarec如何工作的更多信息,可以在[这里](https://box86.org/2021/07/inner-workings-a-high%e2%80%91level-view-of-box86-and-a-low%e2%80%91level-view-of-the-dynarec/)找到。
许多游戏已可在不做多少改动的情况下直接运行,例如:《粘粘世界》(WorldOfGoo)、《航空大亨豪华版》(Airline Tycoon Deluxe)、《超越光速》(FTL)等、基于GameMaker的游戏(《传说之下》(UNDERTALE)等)。
如果你想开发Box86,最好安装ccache,以缓存编译结果。
如果你需要启用Trace跟踪(例如输出寄存器值与各条被执行的x86指令),你也需要安装[Zydis](https://github.com/zyantific/zydis)。
一些x86内部操作码使用“Realmode X86 Emulator Library”的部分内容,请参阅[x86primop.c](../src/emu/x86primop.c)了解版权详情
----
编译与安装
----
> [Box86编译指南](COMPILE.md)
>
> [Box86 Wine安装指南](X86WINE.md)
一些示例视频
----
[![Play on Youtube](https://img.youtube.com/vi/bLt0hMoFDLk/3.jpg)](https://www.youtube.com/watch?v=bLt0hMoFDLk) [![Play on Youtube](https://img.youtube.com/vi/MM7kWYts7IA/3.jpg)](https://www.youtube.com/watch?v=MM7kWYts7IA) [![Play on Youtube](https://img.youtube.com/vi/8hr71S029Hg/1.jpg)](https://www.youtube.com/watch?v=8hr71S029Hg) [![Play on Youtube](https://img.youtube.com/vi/B4YN37z3-ws/1.jpg)](https://www.youtube.com/watch?v=B4YN37z3-ws) [![Play on Youtube](https://img.youtube.com/vi/xk8Q30mxqPg/1.jpg)](https://www.youtube.com/watch?v=xk8Q30mxqPg) [![Play on Youtube](https://img.youtube.com/vi/_QMRMVvYrqU/1.jpg)](https://www.youtube.com/watch?v=_QMRMVvYrqU)
在这几个Youtube频道可以找到更多Box86的相关视频
[MicroLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)
[Pi Labs](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)
[The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA)
程序兼容性列表: https://github.com/ptitSeb/box86-compatibility-list/issues
<img src="img/Box86Icon.png" width="96" height="96">
感谢制作Logo和图标的grayduck!
注意:
不要把本项目和[86box](https://github.com/86Box/86Box)搞混了,后者是一个"**全量**"的x86 PC模拟器。
----
使用方法
----
有若干环境变量可以设置Box86的行为。
点击[这里](USAGE.md)了解所有的环境变量和它们的作用。
请注意:Box86的Dynarec提供了一种包含"内存保护"和段错误信号处理程序的机制来处理JIT代码。简单来说,如果你想用GDB来调试一个使用JIT代码的运行程序(比如mono/Unity3D),就会触发很多“正常”的段错误。建议在GDB中使用类似于`handle SIGSEGV nostop`的命令,来防止在每个段错误时都停止程序运行,如果你想捕获段错误,可以在`signals.c`中的`my_memprotectionhandler`中放置一个断点。
----
关于64位平台的注意事项
----
Box86的工作原理是直接将函数调用从x86_转换到主机系统,主机系统(Box86运行的系统)需要有32位的库。Box86并不包括任何64位<->32位的转换。所以如果你需要在64位平台上运行Box86,那么你需要建立一个32位的库环境,并以32位ARM为目标系统编译Box86(例如使用arm-linux-gnueabihf-gcc工具链交叉编译或直接在armhf chroot环境中编译运行)。
如果你需要运行64位应用,请考虑使用[Box64](https://github.com/ptitSeb/box64),它可以在64位平台上运行x86_64程序,但请再一次注意运行x86程序需要Box86与32位库环境(就像在x86_64的Linux上运行x86程序需要x86 multiarch库一样)。
----
关于Unity游戏的注意事项
----
当前对于Unity游戏的模拟仍不完善。Unity使用Mono,但它所使用的信号机制还没有被完美模拟。理论上可以使用原生Mono库(在[这里](https://github.com/Unity-Technologies/mono)可以找到),但Mono的封装比较麻烦,现在还没完成,所以我们使用了模拟的Mono库,目前Mono的JIT动态编译代码已由"内存保护"(Protected memory)机制实现,应该能正常运行。
同时,一些Unity3D游戏需要OpenGL 3+,目前在大部分Arm开发板上提供OpenGL 3+是很困难的。
所以,并不是所有的Unity游戏都能运行,尤其是那些需要提供很高的OpenGL配置(3.2+)的游戏更有可能不行,但除此之外应该问题不大,而且能运行的游戏的性能应该不错。
提示:如果游戏开始后在显示任何东西之前退出,在Raspberry Pi4上使用`MESA_GL_VERSION_OVERRIDE=3.2`,在Panfrost上使用`PAN_MESA_DEBUG=gl3`来使用更高的配置文件。
----
关于Steam的注意事项
----
Linux Steam 现在可以在Box86上运行,但还是有点不稳定,而且有些功能可能不正常:
- 如果Steam在显示登录界面后崩溃,你可能需要安装libappindicator库,例如运行`sudo apt install libappindicator1`。
- 如果你选择记住密码,而Steam在下次启动时崩溃,你可能需要安装libnm库,例如运行`sudo apt install libnm0`。
- Steam不能在正常的大界面模式下工作,因为Steam在浏览器模式使用的一些组件只能在64位平台上运行。所以请在查看选项卡中选择"小模式",否则Steam将无法正常显示列表。或者在启动Steam添加`+open steam://open/minigameslist`参数,这样Steam将会直接在小模式下启动。
- 为了避免"libc.so.6 is absent"的错误,请添加环境变量`STEAMOS=1` 与 `STEAM_RUNTIME=1`。
- 一些游戏(例如基于起源引擎的游戏:《传送门》、《半衰期2》)使用了libtcmalloc库,Box86会尝试检测它们并通过LD_PRELOAD预加载它们来获得更好的兼容性,虽然应该可以在没有上述功能的情况下工作,但保险起见,我们还是建议你安装它,例如运行`sudo apt install libtcmalloc-minimal4`。
Windows Steam 可以安装但目前不能运行。
----
关于Wine的注意事项
----
Box86现在已经支持Wine。Wine的内建程序全部能运行,许多Windows 程序和游戏也运行良好。但是不要忘记大多数 Windows 游戏都使用 Direct3D,这可能需要完整的 OpenGL 驱动程序和尽可能高的配置文件(基于 ES2 后端的 gl4es 现在不能运行 Wine 的Direct3D组件)。
注意:如果你想在 Raspberry Pi 3 或更早版本上用 Box86 运行 Wine,由于这些设备的内核默认使用 2G/2G 虚拟内存分配(2G 空间用于用户态程序,2G 空间用于内核),与需要访问内存地址 > 2G 的 Wine 程序不兼容。 因此,你需要重新配置内核以使用 3G/1G 的内存分配方式。
----
关于Vulkan的注意事项
----
Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序,Box86会在需要时使用它。但请注意,由于作者目前拥有的硬件上的Vulkan支持有限,因此Vulkan封装库尚未经过太多测试。 Vulkan 1.0、1.1与一些扩展应该能工作。 但Vulkan 1.2还没有被实现。已经有一些在树莓派4上的Vulkan演示 (Sascha Willems 的演示中,为x86构建的demo与与直接为armhf构建的demo工作均正常)。但请注意,Pi4的Vulkan驱动程序目前不支持 dxvk(wine DirectX->Vulkan 兼容层),这不是Box86的问题,而是由于缺少扩展(硬件支持)与一些其他驱动问题。而在Panfrost上,PanVK尚不成熟,暂时没有用它测试dxvk。
----
结语
----
我要感谢所有为 box86 开发做出贡献的人。
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, icecream95, M-HT
* 财务帮助:FlyingFathead, stormchaser3000, dennis1248, sll00, [libre-computer-project](https://libre.computer/)
* 硬件捐赠:[Radxa](https://rockpi.org/), [Pine64](https://www.pine64.org/), [DragonBox](https://pyra-handheld.com/), [Novaspirit](https://www.youtube.com/channel/UCrjKdwxaQMSV_NDywgKXVmw), [HardKernel](https://www.hardkernel.com/), [TwisterOS team](https://twisteros.com/)
* 为本项目持续的宣传:([microLinux](https://www.youtube.com/channel/UCwFQAEj1lp3out4n7BeBatQ)), [PILab](https://www.youtube.com/channel/UCgfQjdc5RceRlTGfuthBs7g)/[TwisterOS team](https://twisteros.com/), [The Byteman](https://www.youtube.com/channel/UCEr8lpIJ3B5Ctc5BvcOHSnA), [NicoD](https://www.youtube.com/channel/UCpv7NFr0-9AB5xoklh3Snhg)
我还要感谢很多人,即使他们只参与了一次本项目。
(如果你的项目中使用了Box86,请不要忘记提及!)
+67 -3
View File
@@ -16,6 +16,11 @@ Controls the Dump of elf content
* 0: No dump of elf information (Default)
* 1: Dump elf sections and relocations and other information (also active if using `BOX86_LOG=3`)
#### BOX86_ROLLING_LOG
Show last few wrapped function call when a Signal is caught
* 0: No last function call printed (Default.)
* 1: Last few wrapped function call printed when a signal is printed. Incompatible with BOX86_LOG>1 (may need BOX86_SHOWSEGV=1 also)
#### BOX86_NOBANNER
Disables Box86 printing its version and build
* 0 : Enable printing its banner. (Default.)
@@ -119,6 +124,7 @@ Forbid dynablock creation in the interval specified (helpfull for debugging beha
Enables/Disables Box86's Dynarec building BigBlock.
* 0 : Don't try to build block as big as possible (can help program using lots of thread and a JIT, like C#/Unity) (Default when libmonobdwgc-2.0.so is loaded)
* 1 : Build Dynarec block as big as possible (Default.)
* 2 : Build Dynarec block bigger (don't stop when block overlaps)
#### BOX86_DYNAREC_STRONGMEM
Enable/Disable simulation of Strong Memory model
@@ -126,6 +132,22 @@ Enable/Disable simulation of Strong Memory model
* 1 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model while trying to limit performance impact (Default when libmonobdwgc-2.0.so is loaded)
* 2 : Enable some Memory Barrier when reading from memory (on some MOV opcode) to simulate Strong Memory Model
#### BOX86_DYNAREC_X87DOUBLE
Force the use of Double for x87 emulation
* 0 : Try to use float when possible for x87 emulation (faster, Default)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis were it's enable automatically)
#### BOX86_DYNAREC_FASTNAN
Enable/Disable generation of -NAN
* 0 : Generate -NAN like on x86 (slower, more x86 accurate)
* 1 : Don't do anything special with NAN, to go as fast as possible (Default)
#### BOX86_DYNAREC_SAFEFLAGS
Handling of flags on CALL/RET opcodes
* 0 : Treat CALL/RET as if it never needs any flags (faster but may have side-effects)
* 1 : most of RET will need flags, most of CALLS will not (Default)
* 2 : All CALL/RET will need flags (slower, but might be needed. Automatically enabled for Vara.exe)
#### BOX86_LIBGL
* libXXXX set the name for libGL (defaults to libGL.so.1).
* /PATH/TO/libGLXXX : Sets the name and path for libGL
@@ -140,11 +162,26 @@ Enable/Disable simulation of Strong Memory model
Some games uses an old version of some libraries, with an ABI incompatible with native version.
Note that LittleInferno for example is auto detected, and libvorbis.so.0 is automatical added to emulated libs, and same for Don't Starve (and Together / Server variant) that use an old SDL2 too
#### BOX86_ALLOWMISSINGLIBS
Allow Box86 to continue even if a library is missing.
#### BOX86_ALLOWMISSING_LIBS
Allow Box86 to continue even if a library is missing (renamed from BOX86_ALLOWMISSINGLIBS).
* 0 : Box86 will stop if a library cannot be loaded. (Default.)
* 1 : Continue even if a needed library cannot be loaded. Unadvised, this will, in most cases, crash later on.
#### BOX86_ALLOWMISSING_SYMBOLS
Allow dlopen with RTLD_NOW flag to not resolve all symbols.
* 0 : Box86 will stop if a library have unresolved symbols. (Default.)
* 1 : Continue even if a needed library have unresolved symbols (like symbols not yet wrapped).
#### BOX86_PREFER_WRAPPED
Box86 will use wrapped libs even if the lib is specified with absolute path
* 0 : Try to use emulated libs when they are defined with absolute path (Default.)
* 1 : Use Wrapped native libs even if path is absolute
#### BOX86_PREFER_EMULATED
Box86 will prefer emulated libs first (execpt for glibc, alsa, pulse, GL, vulkan and X11
* 0 : Native libs are prefered (Default.)
* 1 : Emulated libs are prefered (Default for program running inside pressure-vessel)
#### BOX86_NOPULSE
Disables the load of pulseaudio libraries.
* 0 : Load pulseaudio libraries if found. (Default.)
@@ -153,18 +190,45 @@ Disables the load of pulseaudio libraries.
#### BOX86_NOGTK
Disables the loading of wrapped GTK libraries.
* 0 : Load wrapped GTK libraries if found. (Default.)
* 1 : Disables loading wrapped GTK libraries (can be used with Steam, along with STEAM_RUNTIME=1 to use the i386 version of GTK).
* 1 : Disables loading wrapped GTK libraries.
#### BOX86_NOVULKAN
Disables the load of vulkan libraries.
* 0 : Load vulkan libraries if found.
* 1 : Disables the load of vulkan libraries, both the native and the i386 version (can be useful on Pi4, where the vulkan driver is not quite there yet.)
#### BOX86_ENV
* XXX=yyyy
will add XXX=yyyy env. var.
#### BOX86_ENV1
* XXX=yyyy
will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist
#### BOX86_FIX_64BIT_INODES
Fix/Don't fix 64bit inodes
* 0 : Don't fix 64bit inodes. (Default.)
* 1 : Fix 64bit inodes. Helps when running on Filesystems with 64bit inodes. Is useful when a program uses API functions which doesn't support it and the program doesn't use inodes information.
#### BOX86_SHOWSEGV
Show Segfault signal even if a signal handler is present
* 0 : Don't force segfault details when a signal handler is install (Default, to limit message spamming)
* 1 : Show segfault details
#### BOX86_BACKTRACE
Show a backtrace (native and emulated) on Signal
* 0 : Don't show any backtrace (Default.)
* 1 : Show native backtrace when a signal is dumped (not available on Andoid build)
#### BOX86_BASH
Define x86 bash to launch script
* yyyy
Will use yyyy as x86 bash to launch script. yyyy needs to be a full path to a valid x86 version of bash. Note that is Box64 is available, an x86_64 version of bash can also be used. Also, BOX64_BASH env. var. will also be read if BOX86_BASH is not defined.
#### BOX86_BOX64
Define where to find box64 binary
* yyyy
Will use yyyy as x86_64 interpretor, to launch x64_64 binaries
#### BOX86_JITGDB
* 0 : Just print the Segfault message on segfault (default)
+49 -12
View File
@@ -3,10 +3,11 @@ _TwisterOS users: Wine, winetricks, and Box86 are already installed in TwisterOS
_Raspberry Pi users: Wine requires a 3G/1G split memory kernel. Raspberry Pi OS for the Pi 4 already has a 3G/1G split kernel and works with Wine, but **the Pi 3B+ and earlier models have a 2G/2G kernel and require a custom-compiled 3G/1G kernel to get Wine working.**_
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (x64 is not yet implemented).
See installation steps below (in the [Examples](#examples) section).
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM devices other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
Using Wine with Box86 allows (x86) Windows programs to run on ARM Linux computers (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
Box86 needs `wine-i386` to be installed **manually** on ARM devices. Even though `wine-armhf` is available in many repo's on ARM devices (ie using _apt-get_ will attempt to install `wine-armhf` by default), `wine-armhf` will not work with Box86. Note that manual installation is required since using `multiarch` will result in your ARM device thinking it needs to install lots of i386 dependencies to make `wine-i386` work. The "twist" in Box86 is that Box86 "wraps" many of Wine's core Linux i386 libraries (.so files) so that their calls are interpretable by your ARM device's other armhf Linux system libraries. Also note that wrapping libraries is an ongoing process throughout Box86 development and that some programs may not run properly until all of their i386 library dependencies are wrapped.
Installation files for Wine can be found in the [WineHQ repository](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/), the [TwisterOS FAQ](https://twisteros.com/faq.html) page, or the [PlayOnLinux website repository](https://www.playonlinux.com/wine/). Box86 requires the "i386" (x86) version of Wine even though we are installing it on an ARM processor.
@@ -15,6 +16,7 @@ The general procedure for installing Wine for Box86 is to...
- Download all the install files (.deb, .zip, or even .pol files) for the version of Wine you wish to install
- Unzip or dpkg the install files into one folder
- Move that folder to the directory that you wish Wine to run from (in TwisterOS, this is `~/wine/` by default)
- If you are running box86/i386-wine on a 64bit ARM OS (aarch64), you will also have to install some extra armhf libraries.
- Go to `/usr/local/bin` and make symlinks or scripts that will point to your main wine binaries (`wine`, `winecfg`, and `wineserver`).
- Boot wine to create a new wineprefix (`wine wineboot`).
- Download winetricks (which is simply a very complicated bash script), make it executable, then copy it to `/usr/local/bin`.
@@ -50,11 +52,29 @@ sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg
wine wineboot
```
### Installing Wine for Box86 on Raspberry Pi OS Buster from WineHQ .deb files
### Installing Wine for Box86 on Raspberry Pi OS from WineHQ .deb files
_Links from the [WineHQ repo](https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/)_
This install method allows you to install different versions of Wine. You may install any version and any branch of Wine that you wish (wine-devel, wine-stable, or wine-staging).
This install method allows you to install different versions of Wine. You may install any version/branch of Wine that you wish.
```
### User-defined Wine version variables ################
# - Replace the variables below with your system's info.
# - Note that we need the i386 version for Box86 even though we're installing it on our ARM processor.
# - Wine download links from WineHQ: https://dl.winehq.org/wine-builds/
wbranch="devel" #example: devel, staging, or stable (wine-staging 4.5+ requires libfaudio0:i386 - see below)
wversion="7.1" #example: 7.1
wid="debian" #example: debian, ubuntu
wdist="bullseye" #example (for debian): bullseye, buster, jessie, wheezy, etc
wtag="-1" #example: -1 (some wine .deb files have -1 tag on the end and some don't)
########################################################
# Clean up any old wine instances
wineserver -k # stop any old wine installations from running
rm -rf ~/.cache/wine # remove old wine-mono/wine-gecko install files
rm -rf ~/.local/share/applications/wine # remove old program shortcuts
# Backup any old wine installations
sudo mv ~/wine ~/wine-old
sudo mv ~/.wine ~/.wine-old
@@ -64,14 +84,12 @@ sudo mv /usr/local/bin/winecfg /usr/local/bin/winecfg-old
sudo mv /usr/local/bin/wineserver /usr/local/bin/wineserver-old
# Download, extract wine, and install wine
# (Replace the links/versions below with links/versions from the WineHQ site for the version of wine you wish to install. Note that we need the i386 version for Box86 even though we're installing it on our ARM processor.)
# (Pick an i386 version of wine-devel, wine-staging, or wine-stable)
cd ~/Downloads
wget https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/wine-devel-i386_5.21~buster_i386.deb # NOTE: Replace this link with the version you want
wget https://dl.winehq.org/wine-builds/debian/dists/buster/main/binary-i386/wine-devel_5.21~buster_i386.deb # NOTE: Also replace this link with the version you want
dpkg-deb -xv wine-devel-i386_5.21~buster_i386.deb wine-installer # NOTE: Make sure these dpkg command matches the filename of the deb package you just downloaded
dpkg-deb -xv wine-devel_5.21~buster_i386.deb wine-installer
mv ~/Downloads/wine-installer/opt/wine* ~/wine
wget https://dl.winehq.org/wine-builds/${wid}/dists/${wdist}/main/binary-i386/wine-${wbranch}-i386_${wversion}~${wdist}${wtag}_i386.deb # download
wget https://dl.winehq.org/wine-builds/${wid}/dists/${wdist}/main/binary-i386/wine-${wbranch}_${wversion}~${wdist}${wtag}_i386.deb # (required for wine_i386 if no wine64 / CONFLICTS WITH wine64 support files)
dpkg-deb -x wine-${wbranch}-i386_${wversion}~${wdist}${wtag}_i386.deb wine-installer # extract
dpkg-deb -x wine-${wbranch}_${wversion}~${wdist}${wtag}_i386.deb wine-installer
mv wine-installer/opt/wine* ~/wine # install
rm wine*.deb # clean up
rm -rf wine-installer # clean up
@@ -83,7 +101,26 @@ sudo ln -s ~/wine/bin/winecfg /usr/local/bin/winecfg
sudo ln -s ~/wine/bin/wineserver /usr/local/bin/wineserver
sudo chmod +x /usr/local/bin/wine /usr/local/bin/wineboot /usr/local/bin/winecfg /usr/local/bin/wineserver
# These packages are needed for running wine-staging on RPi 4 (Credits: chills340)
# These packages are needed for running wine on a 64-bit RPiOS via multiarch
karch=$(uname -m)
if [ "$karch" = "aarch64" ] || [ "$karch" = "aarch64-linux-gnu" ] || [ "$karch" = "arm64" ] || [ "$karch" = "aarch64_be" ]; then
sudo dpkg --add-architecture armhf && sudo apt-get update # enable multi-arch
sudo apt-get install -y libasound2:armhf libc6:armhf libglib2.0-0:armhf libgphoto2-6:armhf libgphoto2-port12:armhf \
libgstreamer-plugins-base1.0-0:armhf libgstreamer1.0-0:armhf libldap-2.4-2:armhf libopenal1:armhf libpcap0.8:armhf \
libpulse0:armhf libsane1:armhf libudev1:armhf libusb-1.0-0:armhf libvkd3d1:armhf libx11-6:armhf libxext6:armhf \
libasound2-plugins:armhf ocl-icd-libopencl1:armhf libncurses6:armhf libncurses5:armhf libcap2-bin:armhf libcups2:armhf \
libdbus-1-3:armhf libfontconfig1:armhf libfreetype6:armhf libglu1-mesa:armhf libglu1:armhf libgnutls30:armhf \
libgssapi-krb5-2:armhf libkrb5-3:armhf libodbc1:armhf libosmesa6:armhf libsdl2-2.0-0:armhf libv4l-0:armhf \
libxcomposite1:armhf libxcursor1:armhf libxfixes3:armhf libxi6:armhf libxinerama1:armhf libxrandr2:armhf \
libxrender1:armhf libxxf86vm1 libc6:armhf libcap2-bin:armhf # to run wine-i386 through box86:armhf on aarch64
# This list found by downloading...
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel-i386_7.1~bullseye-1_i386.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/winehq-devel_7.1~bullseye-1_i386.deb
# wget https://dl.winehq.org/wine-builds/debian/dists/bullseye/main/binary-i386/wine-devel_7.1~bullseye-1_i386.deb
# then `dpkg-deb -I package.deb`. Read output, add `:armhf` to packages in dep list, then try installing them on Pi aarch64.
fi
# These packages are needed for running wine-staging on RPiOS (Credits: chills340)
sudo apt install libstb0 -y
cd ~/Downloads
wget -r -l1 -np -nd -A "libfaudio0_*~bpo10+1_i386.deb" http://ftp.us.debian.org/debian/pool/main/f/faudio/ # Download libfaudio i386 no matter its version number
Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 169 KiB

+40
View File
@@ -0,0 +1,40 @@
#!/bin/bash
# create necessary directories
mkdir -p ~/steam
mkdir -p ~/steam/tmp
cd ~/steam/tmp
# download latest deb and unpack
wget https://cdn.cloudflare.steamstatic.com/client/installer/steam.deb
ar x steam.deb
tar xf data.tar.xz
# remove deb archives, not needed anymore
rm ./*.tar.xz ./steam.deb
# move deb contents to steam folder
mv ./usr/* ../
cd ../ && rm -rf ./tmp/
# create run script
echo "#!/bin/bash
export STEAMOS=1
export STEAM_RUNTIME=1
~/steam/bin/steam -noreactlogin steam://open/minigameslist $@" > steam
# make script executable and move
chmod +x steam
sudo mv steam /usr/local/bin/
# detect if we're running on 64 bit Debian
MACHINE_TYPE=`uname -m`
if [ ${MACHINE_TYPE} == 'aarch64' ] && [ -f '/etc/debian_version' ]; then
echo "Detected 64 bit ARM Debian. Installing 32 bit libraries"
sudo dpkg --add-architecture armhf # enable installation of armhf libraries
sudo apt update # update package lists with the newly added arch
sudo apt install libc6:armhf libncurses5:armhf libsdl2*:armhf libopenal*:armhf libpng*:armhf libfontconfig*:armhf libXcomposite*:armhf libbz2-dev:armhf libXtst*:armhf # install the libraries that Steam requires
echo "Don't forget to compile/install Box64!"
fi
echo "Script complete."
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-arm-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-arm-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-arm-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-arm-git}" -DARM_DYNAREC=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-gameshell-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-gameshell-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-gameshell-git}" -DGAMESHELL=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-gameshell-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-odroid-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-odroid-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-odroid-git}" -DODROID=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-odroid-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pandora-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pandora-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pandora-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-pandora-git}" -DPANDORA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-pyra-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-pyra-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-pyra-git}" -DPYRA=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-pyra-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+6 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rpi-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -20,8 +20,7 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rpi-git}"
build() {
# Check for Pi version number
if [[ ${_pimodel} =~ "Raspberry Pi 4" ]]; then
_piversion=4
@@ -36,24 +35,11 @@ prepare() {
exit 1
fi
echo -e "\033[01m\033[01;34m==> INFO:\033[00;01m Your detected Pi verion number is: \033[01;31m${_piversion}\033[01m.\033[00m"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-rpi-git}" -DRPI${_piversion}=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-rpi-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-rk3399-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('armv7h')
@@ -19,26 +19,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-rk3399-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-rk3399-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-rk3399-git}" -DRK3399=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-arm-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+5 -20
View File
@@ -1,7 +1,7 @@
# Maintainer: Jai-JAP <parjailu@gmail.com>, SpacingBat3 <[email protected]>
# Maintainer: Jai-JAP <jai.jap.318@gmail.com>, SpacingBat3 <[email protected]>
# Author: Sebastien Chevalier <[email protected]>
pkgname=box86-x86-git
pkgver=3494.bedacef
pkgver=r3858.5368285
pkgrel=1
pkgdesc="Linux Userspace x86 Emulator with a twist, targeted at ARM Linux devices."
arch=('i386')
@@ -18,26 +18,11 @@ pkgver() {
printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
cd "${srcdir}/${pkgname%-x86-git}"
if [[ ! -d ./build ]]; then
mkdir build && cd build
cmake .. -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo
fi
}
build() {
cd "$srcdir/${pkgname%-x86-git}/build"
make -j$(nproc)
cmake -B build -S "${pkgname%-x86-git}" -DLD80BITS=1 -DNOALIGN=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr
make -C build
}
package() {
cd "$srcdir/${pkgname%-x86-git}/build"
make DESTDIR="${pkgdir}/" install
# /usr/local/bin isn't in PATH by the default,
# we should move it to /usr/bin
cd ${pkgdir}
mv usr/local/bin/ usr/bin/
# cleanup when dir is empty
rmdir usr/local || exit 0
make -C build DESTDIR="${pkgdir}/" install
}
+1 -1
View File
@@ -12,7 +12,7 @@ This will copy the PKGBUILD for your platform (where you type your platform name
In the future, I might try to do an unified PKGBUILD for all platforms that will recognize your platform automatically.
### 2. What platforms are currently supported.
All specified in [COMPILE.md](../COMPILE.md).
All specified in [COMPILE.md](../docs/COMPILE.md).
### 3. Any advantages with that sollution?
This might give you some advantages like those:
+3 -1
View File
@@ -1,2 +1,4 @@
#!/bin/sh
systemctl restart systemd-binfmt
if [ -d '/run/systemd/system' ]; then
systemctl restart systemd-binfmt || :
fi
+277 -285
View File
@@ -106,7 +106,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
alreadyChanged = 0
csp = 0
while csp < curSplt:
if spltln[csp] == '\x00':
if spltln[csp] == '\x01':
alreadyChanged = 1
curSplt = curSplt + 1
else:
@@ -119,7 +119,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
line = line + spltln[csp] + ">"
alreadyChanged = 1
csp = csp + 1
if spltln[csp] == '\x00':
if spltln[csp] == '\x01':
alreadyChanged = 1
curSplt = curSplt + 1
csp = csp + 1
@@ -134,7 +134,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
alreadyChanged = 1
csp = csp + 1
while csp < len(spltln):
if spltln[csp] == '\x00':
if spltln[csp] == '\x01':
alreadyChanged = 1
curSplt = curSplt + 1
else:
@@ -605,7 +605,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
instText = [itp for itp2 in instText for itp in itp2]
# Make the failures nicer
spltln = spltln[:curSplt] + ["\x00"] + instText
spltln = spltln[:curSplt] + ["\x01"] + instText
printf_args = ""
for idx, text in enumerate(instText):
@@ -858,7 +858,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
instText = [itp for itp2 in instText for itp in itp2]
# Make the failures nicer
spltln = spltln[:curSplt] + ["\x00"] + instText
spltln = spltln[:curSplt] + ["\x01"] + instText
printf_args = ""
for idx, text in enumerate(instText):
@@ -1156,7 +1156,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
instText = [itp for itp2 in instText for itp in itp2]
# Make the failures nicer
spltln = spltln[:curSplt] + ["\x00"] + instText
spltln = spltln[:curSplt] + ["\x01"] + instText
printf_args = ""
for idx, text in enumerate(instText):
@@ -1456,7 +1456,7 @@ def main(root, ver, __debug_forceAllDebugging=False):
instText = [itp for itp2 in instText for itp in itp2]
# Make the failures nicer
spltln = spltln[:curSplt] + ["\x00"] + instText
spltln = spltln[:curSplt] + ["\x01"] + instText
# inside '{, '...'}'?
hasOpened = False
@@ -1675,308 +1675,300 @@ def main(root, ver, __debug_forceAllDebugging=False):
# Now the files rebuilding part
# File header and guard
files_header = {
"arm_printer.c": """
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
header = """
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "arm_printer.h"
// conditions
#define cEQ (0b0000<<28)
#define cNE (0b0001<<28)
#define cCS (0b0010<<28)
#define cCC (0b0011<<28)
#define cMI (0b0100<<28)
#define cPL (0b0101<<28)
#define cVS (0b0110<<28)
#define cVC (0b0111<<28)
#define cHI (0b1000<<28)
#define cLS (0b1001<<28)
#define cGE (0b1010<<28)
#define cLT (0b1011<<28)
#define cGT (0b1100<<28)
#define cLE (0b1101<<28)
#define c__ (0b1110<<28) // means all
static const char* conds[16] = {
"EQ", "NE", "CS", "CC",
"MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT",
"GT", "LE", "", "##"
};
static const char* regname[16] = {
"r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9",
"r10", "r11", "r12", "SP", "LR", "PC"
};
// Single precision are V_:_
// Double and quad precision are _:V_
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
static const char* vecname[96] = {
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
};
static const char* dts[16] = {
"S8", "S16", "S32", "S64",
"U8", "U16", "U32", "U64",
"I8", "I16", "I32", "I64",
"F8", "F16", "F32", "F64"
};
static const char* shift_type[4] = {
"lsl ", "lsr ", "asr ", "ror "
};
const char* print_shift(int shift, int comma) {
static __thread char ret[20];
ret[0] = '\\0';
#include "arm_printer.h"
// conditions
#define cEQ (0b0000<<28)
#define cNE (0b0001<<28)
#define cCS (0b0010<<28)
#define cCC (0b0011<<28)
#define cMI (0b0100<<28)
#define cPL (0b0101<<28)
#define cVS (0b0110<<28)
#define cVC (0b0111<<28)
#define cHI (0b1000<<28)
#define cLS (0b1001<<28)
#define cGE (0b1010<<28)
#define cLT (0b1011<<28)
#define cGT (0b1100<<28)
#define cLE (0b1101<<28)
#define c__ (0b1110<<28) // means all
static const char* conds[16] = {
"EQ", "NE", "CS", "CC",
"MI", "PL", "VS", "VC",
"HI", "LS", "GE", "LT",
"GT", "LE", "", "##"
};
static const char* regname[16] = {
"r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9",
"r10", "r11", "r12", "SP", "LR", "PC"
};
// Single precision are V_:_
// Double and quad precision are _:V_
// So we always use _:V_ and invert the corresponding single-precision (cleaner? code)
static const char* vecname[96] = {
"S0", "S2", "S4", "S6", "S8", "S10", "S12", "S14",
"S16", "S18", "S20", "S22", "S24", "S26", "S28", "S30",
"S1", "S3", "S5", "S7", "S9", "S11", "S13", "S15",
"S17", "S19", "S21", "S23", "S25", "S27", "S29", "S31",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
"D16", "D17", "D18", "D19", "D20", "D21", "D22", "D23",
"D24", "D25", "D26", "D27", "D28", "D29", "D30", "D31",
"Q0", "!!!", "Q1", "!!!", "Q2", "!!!", "Q3", "!!!",
"Q4", "!!!", "Q5", "!!!", "Q6", "!!!", "Q7", "!!!",
"Q8", "!!!", "Q9", "!!!", "Q10", "!!!", "Q11", "!!!",
"Q12", "!!!", "Q13", "!!!", "Q14", "!!!", "Q15", "!!!"
};
static const char* dts[16] = {
"S8", "S16", "S32", "S64",
"U8", "U16", "U32", "U64",
"I8", "I16", "I32", "I64",
"F8", "F16", "F32", "F64"
};
static const char* shift_type[4] = {
"lsl ", "lsr ", "asr ", "ror "
};
const char* print_shift(int shift, int comma) {
static __thread char ret[20];
ret[0] = '\\0';
int sh_op = (shift >> 1) & 3;
if(shift & 1) {
int rs = shift >> 4;
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
} else {
uint8_t amount = shift >> 3;
if (!amount) {
switch (sh_op) {
case 0b00:
break;
case 0b01:
case 0b10:
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
break;
case 0b11:
sprintf(ret, "%srrx", (comma ? ", " : ""));
break;
}
} else {
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
int sh_op = (shift >> 1) & 3;
if(shift & 1) {
int rs = shift >> 4;
sprintf(ret, "%s%s%s", (comma ? ", " : ""), shift_type[sh_op], regname[rs]);
} else {
uint8_t amount = shift >> 3;
if (!amount) {
switch (sh_op) {
case 0b00:
break;
case 0b01:
case 0b10:
sprintf(ret, "%s%s#32", (comma ? ", " : ""), shift_type[sh_op]);
break;
case 0b11:
sprintf(ret, "%srrx", (comma ? ", " : ""));
break;
}
} else {
sprintf(ret, "%s%s#%u", (comma ? ", " : ""), shift_type[sh_op], amount);
}
return ret;
}
return ret;
}
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
const char* print_register_list(int list, int size) {
int last = -2;
int cnt = 0;
static __thread char ret[68];
#define print_modified_imm_ARM(imm12) (((imm12 & 0xFF) >> (2*(imm12 >> 8))) | ((imm12 & 0xFF) << (32 - 2*(imm12 >> 8))))
ret[0] = '{';
ret[1] = '\\0';
for (int i = 0; i < size; ++i) {
if (list & (1 << i)) {
if (last >= 0) {
++cnt;
} else {
if (last == -1)
strcat(ret, ", ");
strcat(ret, regname[i]);
last = i;
}
} else {
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[i - 1]);
}
if (last != -2) last = -1;
cnt = 0;
}
}
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[size - 1]);
}
strcat(ret, "}");
const char* print_register_list(int list, int size) {
int last = -2;
int cnt = 0;
static __thread char ret[68];
return ret;
}
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
static __thread char ret[68];
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
if (start + (double_prec + 1) * size > 32) {
return "!!!";
}
if (size == 0) {
return "!!!";
}
if (double_prec && (size % 2 == 1)) {
strcpy(ret, "!! {");
} else {
ret[0] = '{';
ret[1] = '\\0';
for (int i = 0; i < size; ++i) {
if (list & (1 << i)) {
if (last >= 0) {
++cnt;
} else {
if (last == -1)
strcat(ret, ", ");
strcat(ret, regname[i]);
last = i;
}
} else {
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[i - 1]);
}
if (last != -2) last = -1;
cnt = 0;
}
}
if (cnt) {
strcat(ret, "-");
strcat(ret, regname[size - 1]);
}
strcat(ret, "}");
return ret;
}
const char* print_register_list_fpu(uint8_t start, uint8_t size, uint8_t double_prec) {
static __thread char ret[68];
// Assume VFPSmallRegisterBank(), so no D16 and no S32 (and above)
if (start + (double_prec + 1) * size > 32) {
return "!!!";
}
if (size == 0) {
return "!!!";
}
if (double_prec && (size % 2 == 1)) {
strcpy(ret, "!! {");
} else {
ret[0] = '{';
ret[1] = '\\0';
}
char regChr;
if (double_prec) {
regChr = 'D';
size /= 2;
} else {
regChr = 'S';
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
}
sprintf(tmp, "%c%d}", regChr, start + size - 1);
char regChr;
if (double_prec) {
regChr = 'D';
size /= 2;
} else {
regChr = 'S';
start = (start >> 4) + ((start & 0xF) << 1);
}
char tmp[6];
for (int cur = start; cur < start + size - 1; ++cur) {
sprintf(tmp, "%c%d, ", regChr, cur);
strcat(ret, tmp);
return ret;
}
sprintf(tmp, "%c%d}", regChr, start + size - 1);
strcat(ret, tmp);
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
return ret;
}
static const char* _print_modified_imm_I64_bytes[2] = {"00", "FF"};
const char* print_modified_imm_NEON(int op_cmode, int imm) {
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
const char* print_modified_imm_NEON(int op_cmode, int imm) {
static __thread char ret[34] = "???\\0-"; // [dt: 4][imm: 30]
strcpy(&ret[4], "UNPREDICTABLE");
switch (op_cmode) {
case 0b00000: // VMOV.I32
case 0b00001: // VORR.I32
case 0b10000: // VMVN.I32
case 0b10001: // VBIC.I32
strcpy(&ret[4], "UNPREDICTABLE");
switch (op_cmode) {
case 0b00000: // VMOV.I32
case 0b00001: // VORR.I32
case 0b10000: // VMVN.I32
case 0b10001: // VBIC.I32
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b00010: // VMOV.I32
case 0b00011: // VORR.I32
case 0b10010: // VMVN.I32
case 0b10011: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b00010: // VMOV.I32
case 0b00011: // VORR.I32
case 0b10010: // VMVN.I32
case 0b10011: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b00100: // VMOV.I32
case 0b00101: // VORR.I32
case 0b10100: // VMVN.I32
case 0b10101: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X0000", imm);
}
break;
case 0b00110: // VMOV.I32
case 0b00111: // VORR.I32
case 0b10110: // VMVN.I32
case 0b10111: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X000000", imm);
}
break;
case 0b01000: // VMOV.I16
case 0b01001: // VORR.I16
case 0b11000: // VMVN.I16
case 0b11001: // VBIC.I16
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01010: // VMOV.I16
case 0b01011: // VORR.I16
case 0b11010: // VMVN.I16
case 0b11011: // VBIC.I16
if (imm) {
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b01100: // VMOV.I32
case 0b11100: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFF", imm);
}
break;
case 0b01101: // VMOV.I32
case 0b11101: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFFFF", imm);
}
break;
case 0b01110: // VMOV.I8
strcpy(ret, "I8");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01111: // VMOV.F32
strcpy(ret, "F32");
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
break;
case 0b11110: // VMOV.I64
{
strcpy(ret, "I64");
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
}
break;
case 0b11111: // V???.-
default:
strcpy(ret, "-");
strcpy(&ret[4], "UNDEFINED");
break;
sprintf(&ret[4], "0x%02X00", imm);
}
return ret;
break;
case 0b00100: // VMOV.I32
case 0b00101: // VORR.I32
case 0b10100: // VMVN.I32
case 0b10101: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X0000", imm);
}
break;
case 0b00110: // VMOV.I32
case 0b00111: // VORR.I32
case 0b10110: // VMVN.I32
case 0b10111: // VBIC.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02X000000", imm);
}
break;
case 0b01000: // VMOV.I16
case 0b01001: // VORR.I16
case 0b11000: // VMVN.I16
case 0b11001: // VBIC.I16
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01010: // VMOV.I16
case 0b01011: // VORR.I16
case 0b11010: // VMVN.I16
case 0b11011: // VBIC.I16
if (imm) {
strcpy(ret, "I16");
sprintf(&ret[4], "0x%02X00", imm);
}
break;
case 0b01100: // VMOV.I32
case 0b11100: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFF", imm);
}
break;
case 0b01101: // VMOV.I32
case 0b11101: // VMVN.I32
if (imm) {
strcpy(ret, "I32");
sprintf(&ret[4], "0x%02XFFFF", imm);
}
break;
case 0b01110: // VMOV.I8
strcpy(ret, "I8");
sprintf(&ret[4], "0x%02X", imm);
break;
case 0b01111: // VMOV.F32
strcpy(ret, "F32");
sprintf(&ret[4], "%e", (imm & 0x80 ? -1 : 1) * (1 << (((imm >> 4) & 0x7) ^ 0b100)) * (float) (16 + (imm & 0xF)) / 128.);
break;
case 0b11110: // VMOV.I64
{
strcpy(ret, "I64");
sprintf(&ret[4], "#0x%s%s%s%s%s%s%s%s",
_print_modified_imm_I64_bytes[(imm >> 7) & 1], _print_modified_imm_I64_bytes[(imm >> 6) & 1],
_print_modified_imm_I64_bytes[(imm >> 5) & 1], _print_modified_imm_I64_bytes[(imm >> 4) & 1],
_print_modified_imm_I64_bytes[(imm >> 3) & 1], _print_modified_imm_I64_bytes[(imm >> 2) & 1],
_print_modified_imm_I64_bytes[(imm >> 1) & 1], _print_modified_imm_I64_bytes[(imm >> 0) & 1]);
}
break;
case 0b11111: // V???.-
default:
strcpy(ret, "-");
strcpy(&ret[4], "UNDEFINED");
break;
}
const char* arm_print(uint32_t opcode) {
static __thread char ret[100];
memset(ret, 0, sizeof(ret));
"""
return ret;
}
files_guard = {
"arm_printer.c": """
{
strcpy(ret, "???");
}
return ret;
}
const char* arm_print(uint32_t opcode) {
static __thread char ret[100];
memset(ret, 0, sizeof(ret));
"""
footer = """
{
strcpy(ret, "???");
}
return ret;
}
"""
banner = "/*******************************************************" + ('*'*len(ver)) + "***\n" \
" * File automatically generated by rebuild_printer.py (v" + ver + ") *\n" \
" *******************************************************" + ('*'*len(ver)) + "***/\n"
trim = lambda string: '\n'.join(line[2:] for line in string.splitlines())[1:]
# Yes, the for loops are inverted. This is because both dicts should have the same keys.
for fhdr in files_guard:
files_header[fhdr] = banner + trim(files_header[fhdr])
for fhdr in files_header:
files_guard[fhdr] = trim(files_guard[fhdr])
trim = lambda string: '\n'.join(line[1:] for line in string.splitlines())[1:]
header = banner + trim(header)
footer = trim(footer)
for f in files_header:
with open(os.path.join(root, "src", "dynarec", f), 'w') as file:
file.write(files_header[f])
file.write(output)
file.write(files_guard[f])
with open(os.path.join(root, "src", "dynarec", "arm_printer.c"), 'w') as file:
file.write(header)
file.write(output)
file.write(footer)
# Save the string for the next iteration, writing was successful
with open(os.path.join(root, "src", "dynarec", "last_run.txt"), 'w') as file:
file.write('\n'.join(insts))
@@ -1988,6 +1980,6 @@ if __name__ == '__main__':
for i, v in enumerate(sys.argv):
if v == "--":
limit.append(i)
if main(sys.argv[1], "1.2.0.05") != 0:
if main(sys.argv[1], "1.2.0.06") != 0:
exit(2)
exit(0)
+20 -15
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import os
import sys
@@ -166,8 +166,8 @@ U = TypeVar('U')
Filename = str
class CustOrderedDict(Generic[T, U], Iterable[T]):
__keys__: List[T]
__actdict__: Dict[T, U]
__keys__: List[T] = []
__actdict__: Dict[T, U] = {}
def __init__(self, src: Optional[Dict[T, U]] = None) -> None:
if src is None:
@@ -195,7 +195,7 @@ class CustOrderedDictList(CustOrderedDict[T, List[U]]):
return super().__getitem__(k)
class FirstArgumentSingletonMeta(Generic[T], type):
_singletons: Dict[T, Type['FirstArgumentSingletonMeta']]
_singletons: Dict[T, Type['FirstArgumentSingletonMeta']] = {}
@classmethod
def __prepare__(metacls, __name: str, __bases: Tuple[type, ...], **kwds: Any) -> Dict[str, Any]:
@@ -227,10 +227,9 @@ class FileSpec:
values: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
rvalues: Sequence[str] = ['E', 'v', 'c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
validrepl: Sequence[str] = ['c', 'w', 'i', 'I', 'C', 'W', 'u', 'U', 'f', 'd', 'D', 'K', 'l', 'L', 'p', 'V', 'O', 'S', '2', 'P', 'G', 'N', 'M', 's']
structs: CustOrderedDict[str, Struct]
def __init__(self) -> None:
self.structs = CustOrderedDict()
self.structs: CustOrderedDict[str, FileSpec.Struct] = CustOrderedDict()
self.typedefs: CustOrderedDictList[_BareFunctionType, Function] = CustOrderedDictList()
self.structsuses: List[FunctionType] = []
@@ -441,8 +440,8 @@ class Function:
DefineType = NewType('DefineType', str)
@final
class Define:
name: DefineType
inverted_: bool
name: DefineType = DefineType("")
inverted_: bool = False
defines: List[DefineType] = []
@@ -480,7 +479,7 @@ class Define:
return isinstance(o, Define) and (self.name == o.name) and (self.inverted_ == o.inverted_)
@final
class Clause:
defines: List[Define]
defines: List[Define] = []
def __init__(self, defines: Union[List[Define], str] = []) -> None:
if isinstance(defines, str):
@@ -528,7 +527,7 @@ class Clauses:
Represent a list of clauses, aka a list of or-ed together and-ed "defined()"
conditions
"""
clauses: List[Clause]
clauses: List[Clause] = []
def __init__(self, clauses: Union[List[Clause], str] = []) -> None:
if isinstance(clauses, str):
@@ -748,9 +747,15 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
or match("sdl1ttf", "sdl2ttf") \
or match("smpeg", "smpeg2") \
or match("udev0", "udev1") \
or match("gstinterfaces010","gstvideo")\
or match("gstinterfaces010","gstaudio")\
or match("gstreamer010","gstreamer") \
or match("appindicator","appindicator3")\
\
or match("libc", "tcmallocminimal") \
or match("libc", "ldlinux") \
or match("libc", "ldlinux") \
or match("libc", "tbbmallocproxy") \
or match("tcmallocminimal","tbbmallocproxy") \
:
# libc and ldlinux have some "__libc_" data symbols in common... TODO check if ok
continue
@@ -1053,8 +1058,8 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
memcpy(value+4, v->data, 2*sizeof(double));
{rbr}
void* VulkanFromx86(void* src, void** save);
void VulkanTox86(void* src, void* save);
void* VulkanFromx86(void* src);
void VulkanTox86(void* src);
#define ST0val ST0.d
@@ -1254,7 +1259,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
delta = 4
for c in args:
if c == 'P':
f.write("void* save{d} = NULL; void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d}), &save{d}); ".format(d=delta))
f.write("void *arg{d} = VulkanFromx86(*(void**)(R_ESP + {d})); ".format(d=delta))
if c == 'G':
f.write("my_GValue_t arg{d}; alignGValue(&arg{d}, *(void**)(R_ESP + {d})); ".format(d=delta))
delta = delta + deltas[FileSpec.values.index(c)]
@@ -1262,7 +1267,7 @@ def generate_files(root: str, files: Iterable[str], ver: str, gbls: SortedGlobal
delta = 4
for c in args:
if c == 'P':
f.write("VulkanTox86(arg{d}, save{d}); ".format(d=delta))
f.write("VulkanTox86(arg{d}); ".format(d=delta))
if c == 'G':
f.write("unalignGValue(*(void**)(R_ESP + {d}), &arg{d}); ".format(d=delta))
delta = delta + deltas[FileSpec.values.index(c)]
+5
View File
@@ -52,5 +52,10 @@ if( TEST_RESULT )
message( FATAL_ERROR "Failed: The output of ${TEST_PROGRAM} did not match ${TEST_REFERENCE}")
endif( TEST_RESULT )
# remove the temporary files if they exist
if( EXISTS ${TEST_OUTPUT} )
file(REMOVE "${TEST_OUTPUT}")
endif()
# everything went fine...
message( "Passed: The output of ${TEST_PROGRAM} matches ${TEST_REFERENCE}" )
+37 -18
View File
@@ -74,8 +74,8 @@ void free_tlsdatasize(void* p)
if(!p)
return;
tlsdatasize_t *data = (tlsdatasize_t*)p;
free(data->tlsdata);
free(p);
box_free(data->ptr);
box_free(p);
}
int unlockMutex()
@@ -161,8 +161,13 @@ box86context_t *NewBox86Context(int argc)
}
#endif
// init and put default values
box86context_t *context = my_context = (box86context_t*)calloc(1, sizeof(box86context_t));
box86context_t *context = my_context = (box86context_t*)box_calloc(1, sizeof(box86context_t));
if(cycle_log)
for(int i=0; i<CYCLE_LOG; ++i) {
context->log_call[i] = (char*)box_calloc(256, 1);
context->log_ret[i] = (char*)box_calloc(128, 1);
}
#ifdef BUILD_LIB
context->deferedInit = 0;
#else
@@ -176,6 +181,8 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
@@ -187,7 +194,7 @@ box86context_t *NewBox86Context(int argc)
context->dlprivate = NewDLPrivate();
context->argc = argc;
context->argv = (char**)calloc(context->argc+1, sizeof(char*));
context->argv = (char**)box_calloc(context->argc+1, sizeof(char*));
init_mutexes(context);
pthread_atfork(NULL, NULL, atfork_child_box64context);
@@ -229,7 +236,7 @@ void FreeBox86Context(box86context_t** context)
for(int i=0; i<ctx->elfsize; ++i) {
FreeElfHeader(&ctx->elfs[i]);
}
free(ctx->elfs);
box_free(ctx->elfs);
FreeFTSMap(ctx);
@@ -243,16 +250,16 @@ void FreeBox86Context(box86context_t** context)
DeleteX86Trace(ctx);
if(ctx->deferedInitList)
free(ctx->deferedInitList);
box_free(ctx->deferedInitList);
free(ctx->argv);
/*box_free(ctx->argv);*/
for (int i=0; i<ctx->envc; ++i)
free(ctx->envv[i]);
free(ctx->envv);
/*for (int i=0; i<ctx->envc; ++i)
box_free(ctx->envv[i]);
box_free(ctx->envv);*/
if(ctx->atfork_sz) {
free(ctx->atforks);
box_free(ctx->atforks);
ctx->atforks = NULL;
ctx->atfork_sz = ctx->atfork_cap = 0;
}
@@ -273,16 +280,20 @@ void FreeBox86Context(box86context_t** context)
FreeDLPrivate(&ctx->dlprivate);
// free(ctx->stack); // don't free the stack, it's owned by main emu!
// box_free(ctx->stack); // don't free the stack, it's owned by main emu!
free(ctx->fullpath);
free(ctx->box86path);
box_free(ctx->fullpath);
box_free(ctx->box86path);
box_free(ctx->bashpath);
FreeBridge(&ctx->system);
freeGLProcWrapper(ctx);
freeALProcWrapper(ctx);
if(ctx->stack_clone)
box_free(ctx->stack_clone);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
free_tlsdatasize(ptr);
@@ -291,7 +302,7 @@ void FreeBox86Context(box86context_t** context)
pthread_key_delete(ctx->tlskey);
if(ctx->tlsdata)
free(ctx->tlsdata);
box_free(ctx->tlsdata);
for(int i=0; i<3; ++i) {
if(ctx->segtls[i].present) {
@@ -304,6 +315,8 @@ void FreeBox86Context(box86context_t** context)
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
finiAllHelpers(ctx);
@@ -319,7 +332,13 @@ void FreeBox86Context(box86context_t** context)
pthread_mutex_destroy(&ctx->mutex_thread);
pthread_mutex_destroy(&ctx->mutex_bridge);
free(ctx);
if(cycle_log)
for(int i=0; i<CYCLE_LOG; ++i) {
box_free(ctx->log_call[i]);
box_free(ctx->log_ret[i]);
}
box_free(ctx);
}
int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
@@ -327,7 +346,7 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
if(idx==ctx->elfcap) {
// resize...
ctx->elfcap += 16;
ctx->elfs = (elfheader_t**)realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
ctx->elfs = (elfheader_t**)box_realloc(ctx->elfs, sizeof(elfheader_t*) * ctx->elfcap);
}
ctx->elfs[idx] = head;
ctx->elfsize++;
@@ -338,7 +357,7 @@ int AddElfHeader(box86context_t* ctx, elfheader_t* head) {
int AddTLSPartition(box86context_t* context, int tlssize) {
int oldsize = context->tlssize;
context->tlssize += tlssize;
context->tlsdata = realloc(context->tlsdata, context->tlssize);
context->tlsdata = box_realloc(context->tlsdata, context->tlssize);
memmove(context->tlsdata+tlssize, context->tlsdata, oldsize); // move to the top, using memmove as regions will probably overlap
memset(context->tlsdata, 0, tlssize); // fill new space with 0 (not mandatory)
// clean GS segment for current emu
+1 -1
View File
@@ -3,6 +3,6 @@
#define BOX86_MAJOR 0
#define BOX86_MINOR 2
#define BOX86_REVISION 4
#define BOX86_REVISION 7
#endif //__BOX86_VERSION_H_
+489 -112
View File
@@ -25,36 +25,54 @@
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
#include "dynarec/dynarec_next.h"
#include "khash.h"
#define USE_MMAP
//#define USE_MMAP_MORE
// init inside dynablocks.c
KHASH_MAP_INIT_INT(dynablocks, dynablock_t*)
static dynablocklist_t* dynmap[DYNAMAP_SIZE]; // 4G of memory mapped by 4K block
static mmaplist_t *mmaplist = NULL;
static int mmapsize = 0;
static int mmapcap = 0;
static kh_dynablocks_t *dblist_oversized; // store the list of oversized dynablocks (normal sized are inside mmaplist)
static uintptr_t *box86_jumptable[JMPTABL_SIZE];
static uintptr_t box86_jmptbl_default[1<<JMPTABL_SHIFT];
// lock addresses
KHASH_SET_INIT_INT(lockaddress)
static kh_lockaddress_t *lockaddress = NULL;
#endif
#define MEMPROT_SHIFT 12
#define MEMPROT_SIZE (1<<(32-MEMPROT_SHIFT))
static uint8_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
typedef struct memprot_s
{
uint8_t prot;
uint8_t hot;
} memprot_t;
static memprot_t memprot[MEMPROT_SIZE] = {0}; // protection flags by 4K block
static int inited = 0;
typedef struct mapmem_s {
uintptr_t begin, end;
struct mapmem_s *next;
} mapmem_t;
static mapmem_t *mapmem = NULL;
typedef struct blocklist_s {
void* block;
int maxfree;
size_t size;
void* first;
} blocklist_t;
#define MMAPSIZE (256*1024) // allocate 256kb sized blocks
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
static int n_blocks = 0; // number of blocks for custom malloc
static int c_blocks = 0; // capacity of blocks for custom malloc
static blocklist_t* p_blocks = NULL; // actual blocks for custom malloc
typedef union mark_s {
struct {
@@ -98,6 +116,23 @@ static void* getFirstBlock(void* block, size_t maxsize, size_t* size, void* star
return NULL;
}
static void* getNextFreeBlock(void* block)
{
blockmark_t *m = (blockmark_t*)block;
while (m->next.fill) {
m = NEXT_BLOCK(m);
};
return m;
}
static void* getPrevFreeBlock(void* block)
{
blockmark_t *m = (blockmark_t*)block;
do {
m = PREV_BLOCK(m);
} while (m->next.fill);
return m;
}
static size_t getMaxFreeBlock(void* block, size_t block_size, void* start)
{
// get start of block
@@ -228,19 +263,37 @@ static size_t sizeBlock(void* sub)
return s->next.size;
}
#define THRESHOLD (128-2*sizeof(blockmark_t))
static size_t roundSize(size_t size)
{
if(!size)
return size;
size = (size+7)&~7LL; // 8 bytes align in size
if(size<THRESHOLD)
size = THRESHOLD;
return size;
}
void* customMalloc(size_t size)
{
size = roundSize(size);
// look for free space
void* sub = NULL;
size_t fullsize = size+2*sizeof(blockmark_t);
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
if(p_blocks[i].maxfree>=size) {
size_t rsize = 0;
sub = getFirstBlock(p_blocks[i].block, size, &rsize, NULL);
sub = getFirstBlock(p_blocks[i].block, size, &rsize, p_blocks[i].first);
if(sub) {
if(rsize-size<THRESHOLD)
size = rsize;
void* ret = allocBlock(p_blocks[i].block, sub, size, NULL);
if(rsize==p_blocks[i].maxfree)
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
pthread_mutex_unlock(&mutex_blocks);
return ret;
}
@@ -248,17 +301,20 @@ void* customMalloc(size_t size)
}
// add a new block
int i = n_blocks++;
p_blocks = (blocklist_t*)realloc(p_blocks, n_blocks*sizeof(blocklist_t));
size_t allocsize = MMAPSIZE;
if(size+2*sizeof(blockmark_t)>allocsize)
allocsize = size+2*sizeof(blockmark_t);
#ifdef USE_MMAP
if(n_blocks>c_blocks) {
c_blocks += 4;
p_blocks = (blocklist_t*)box_realloc(p_blocks, c_blocks*sizeof(blocklist_t));
}
size_t allocsize = (fullsize>MMAPSIZE)?fullsize:MMAPSIZE;
#ifdef USE_MMAP_MORE
void* p = mmap(NULL, allocsize, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
memset(p, 0, allocsize);
setProtection((uintptr_t)p, allocsize, PROT_READ|PROT_WRITE);
#else
void* p = calloc(1, allocsize);
void* p = box_calloc(1, allocsize);
#endif
p_blocks[i].block = p;
p_blocks[i].first = p;
p_blocks[i].size = allocsize;
// setup marks
blockmark_t* m = (blockmark_t*)p;
@@ -277,7 +333,7 @@ void* customMalloc(size_t size)
}
void* customCalloc(size_t n, size_t size)
{
size_t newsize = n*size;
size_t newsize = roundSize(n*size);
void* ret = customMalloc(newsize);
memset(ret, 0, newsize);
return ret;
@@ -286,6 +342,7 @@ void* customRealloc(void* p, size_t size)
{
if(!p)
return customMalloc(size);
size = roundSize(size);
uintptr_t addr = (uintptr_t)p;
pthread_mutex_lock(&mutex_blocks);
for(int i=0; i<n_blocks; ++i) {
@@ -293,7 +350,9 @@ void* customRealloc(void* p, size_t size)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
if(expandBlock(p_blocks[i].block, sub, size)) {
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL);
if(sub<p_blocks[i].first && p+size<p_blocks[i].first)
p_blocks[i].first = getNextFreeBlock(sub);
p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first);
pthread_mutex_unlock(&mutex_blocks);
return p;
}
@@ -319,7 +378,10 @@ void customFree(void* p)
if ((addr>(uintptr_t)p_blocks[i].block)
&& (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) {
void* sub = (void*)(addr-sizeof(blockmark_t));
void* n = NEXT_BLOCK((blockmark_t*)sub);
size_t newfree = freeBlock(p_blocks[i].block, sub, NULL);
if(sub<=p_blocks[i].first)
p_blocks[i].first = getPrevFreeBlock(n);
if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree;
pthread_mutex_unlock(&mutex_blocks);
return;
@@ -346,35 +408,40 @@ uintptr_t FindFreeDynarecMap(dynablock_t* db, int size)
// look for free space
void* sub = NULL;
for(int i=0; i<mmapsize; ++i) {
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t) && !mmaplist[i].locked) {
mmaplist[i].locked = 1;
int rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
if(rsize==mmaplist[i].maxfree) {
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
if(mmaplist[i].maxfree>=size+sizeof(blockmark_t)) {
if(!arm_lock_xchg(&mmaplist[i].locked, 1)) {
size_t rsize = 0;
sub = getFirstBlock(mmaplist[i].block, size, &rsize, mmaplist[i].first);
if(sub) {
uintptr_t ret = (uintptr_t)allocBlock(mmaplist[i].block, sub, size, &mmaplist[i].first);
if(rsize==mmaplist[i].maxfree) {
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, mmaplist[i].first);
}
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(!blocks) {
blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
int size255=(size<256)?size:255;
for(size_t j=0; j<size255; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
if(size!=size255)
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
arm_lock_store(&mmaplist[i].locked, 0);
return ret;
} else {
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted mmaplist[%d] info (requested size=%d)?\n", i, size);
if(box86_log >= LOG_DEBUG)
printBlock(mmaplist[i].block, mmaplist[i].first);
// reset block meta info
mmaplist[i].first = getFirstBlock(mmaplist[i].block, 1, &rsize, NULL);
mmaplist[i].maxfree = getMaxFreeBlock(mmaplist[i].block, mmaplist[i].size, NULL);
arm_lock_store(&mmaplist[i].locked, 0);
}
kh_dynablocks_t *blocks = mmaplist[i].dblist;
if(!blocks) {
blocks = mmaplist[i].dblist = kh_init(dynablocks);
kh_resize(dynablocks, blocks, 64);
}
khint_t k;
int r;
k = kh_put(dynablocks, blocks, (uintptr_t)ret, &r);
kh_value(blocks, k) = db;
int size255=(size<256)?size:255;
for(size_t j=0; j<size255; ++j)
mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+j] = j;
if(size!=size255)
memset(&mmaplist[i].helper[(uintptr_t)ret-(uintptr_t)mmaplist[i].block+256], -1, size-255);
mmaplist[i].locked = 0;
return ret;
} else {
printf_log(LOG_INFO, "BOX86: Warning, sub not found, corrupted mmaplist[%d] info?\n", i);
if(box86_log >= LOG_DEBUG)
printBlock(mmaplist[i].block, mmaplist[i].first);
}
}
}
@@ -387,7 +454,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
dynarec_log(LOG_DEBUG, "Ask for DynaRec Block Alloc #%zu/%zu\n", mmapsize, mmapcap);
if(mmapsize>mmapcap) {
mmapcap += 32;
mmaplist = (mmaplist_t*)realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
mmaplist = (mmaplist_t*)box_realloc(mmaplist, mmapcap*sizeof(mmaplist_t));
}
#ifndef USE_MMAP
void *p = NULL;
@@ -407,10 +474,10 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
#endif
setProtection((uintptr_t)p, MMAPSIZE, PROT_READ | PROT_WRITE | PROT_EXEC);
mmaplist[i].locked = 1;
arm_lock_store(&mmaplist[i].locked, 1);
mmaplist[i].block = p;
mmaplist[i].size = MMAPSIZE;
mmaplist[i].helper = (uint8_t*)calloc(1, MMAPSIZE);
mmaplist[i].helper = (uint8_t*)box_calloc(1, MMAPSIZE);
mmaplist[i].first = p;
// setup marks
blockmark_t* m = (blockmark_t*)p;
@@ -432,7 +499,7 @@ uintptr_t AddNewDynarecMap(dynablock_t* db, int size)
kh_value(blocks, k) = db;
for(int j=0; j<size; ++j)
mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block + j] = (j<256)?j:255;
mmaplist[i].locked = 0;
arm_lock_store(&mmaplist[i].locked, 0);
return sub;
}
@@ -443,6 +510,12 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
for(int i=0; i<mmapsize; ++i) {
if ((addr>(uintptr_t)mmaplist[i].block)
&& (addr<((uintptr_t)mmaplist[i].block+mmaplist[i].size))) {
// wait the map is free
int cnt = 100;
while(my_context && cnt && arm_lock_store_xchg(&mmaplist[i].locked, (void*)1)) {
--cnt;
sched_yield();
}
void* sub = (void*)(addr-sizeof(blockmark_t));
size_t newfree = freeBlock(mmaplist[i].block, sub, &mmaplist[i].first);
if(mmaplist[i].maxfree < newfree) mmaplist[i].maxfree = newfree;
@@ -453,10 +526,7 @@ void ActuallyFreeDynarecMap(dynablock_t* db, uintptr_t addr, int size)
kh_del(dynablocks, blocks, k);
memset(&mmaplist[i].helper[(uintptr_t)sub-(uintptr_t)mmaplist[i].block], 0, size);
}
if(mmaplist[i].locked) {
printf_log(LOG_INFO, "BOX86: Warning, Free a chunk in a locked mmaplist[%d]\n", i);
++mmaplist[i].locked;
}
arm_lock_store(&mmaplist[i].locked, 0);
return;
}
}
@@ -531,7 +601,7 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
return;
if(size>MMAPSIZE-2*sizeof(blockmark_t)) {
#ifndef USE_MMAP
free((void*)addr);
box_free((void*)addr);
#else
munmap((void*)addr, size);
#endif
@@ -546,9 +616,23 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size)
ActuallyFreeDynarecMap(db, addr, size);
}
dynablocklist_t* getDB(uintptr_t idx)
dynablock_t* getDB(uintptr_t addr)
{
return dynmap[idx];
if(isJumpTableDefault((void*)addr))
return NULL;
uintptr_t ret = getJumpAddress(addr);
return *(dynablock_t**)(ret-sizeof(void*));
}
uintptr_t getDefaultSize(uintptr_t addr)
{
uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default)
return (addr&~((1<<JMPTABL_SHIFT)-1)|0xffff)-addr + 1;
uintptr_t idx0 = addr&0xffff;
while(box86_jumptable[idx][idx0]==(uintptr_t)arm_next)
++idx0;
return idx0 - (addr&0xffff);
}
// each dynmap is 64k of size
@@ -556,49 +640,41 @@ dynablocklist_t* getDB(uintptr_t idx)
void addDBFromAddressRange(uintptr_t addr, uintptr_t size)
{
dynarec_log(LOG_DEBUG, "addDBFromAddressRange %p -> %p\n", (void*)addr, (void*)(addr+size-1));
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!dynmap[i]) {
dynablocklist_t* p = NewDynablockList(i<<DYNAMAP_SHIFT, 1<<DYNAMAP_SHIFT, 0);
if(arm_lock_storeifnull(&dynmap[i], p)!=p)
FreeDynablockList(&p);
}
}
// do nothing, dynablock are allowed based on memory protection flags
}
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy)
{
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p -> %p %s\n", (void*)addr, (void*)(addr+size-1), destroy?"destroy":"mark");
uintptr_t idx = (addr>>DYNAMAP_SHIFT);
uintptr_t end = ((addr+size-1)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
dynablocklist_t* dblist = dynmap[i];
if(dblist) {
uintptr_t start_addr = my_context?((addr<my_context->max_db_size)?0:(addr-my_context->max_db_size)):addr;
dynarec_log(LOG_DEBUG, "cleanDBFromAddressRange %p/%p -> %p %s\n", (void*)addr, (void*)start_addr, (void*)(addr+size-1), destroy?"destroy":"mark");
for (uintptr_t i=start_addr; i<addr+size; ++i) {
dynablock_t* db = getDB(i);
if(db) {
if(destroy)
FreeRangeDynablock(dblist, addr, size);
FreeRangeDynablock(db, addr, size);
else
MarkRangeDynablock(dblist, addr, size);
MarkRangeDynablock(db, addr, size);
} else {
uintptr_t next = getDefaultSize(i);
if(next)
i+=next-1;
}
}
}
#ifdef ARM
void arm_next(void);
#endif
void addJumpTableIfDefault(void* addr, void* jmp)
int addJumpTableIfDefault(void* addr, void* jmp)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default) {
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm_next;
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
free(tbl);
box_free(tbl);
}
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
arm_lock_storeifref(&box86_jumptable[idx][off], jmp, arm_next);
return (arm_lock_storeifref(&box86_jumptable[idx][off], jmp, arm_next)==jmp)?1:0;
}
void setJumpTableDefault(void* addr)
{
@@ -609,6 +685,28 @@ void setJumpTableDefault(void* addr)
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
box86_jumptable[idx][off] = (uintptr_t)arm_next;
}
void setJumpTableDefaultRef(void* addr, void* jmp)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default) {
return;
}
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
arm_lock_storeifref(&box86_jumptable[idx][off], arm_next, jmp);
}
void setJumpTableIfRef(void* addr, void* jmp, void* ref)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default) {
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm_next;
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
box_free(tbl);
}
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
arm_lock_storeifref(&box86_jumptable[idx][off], jmp, ref);
}
int isJumpTableDefault(void* addr)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
@@ -627,16 +725,30 @@ uintptr_t getJumpTableAddress(uintptr_t addr)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default) {
uintptr_t* tbl = (uintptr_t*)malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm_next;
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
free(tbl);
box_free(tbl);
}
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
return (uintptr_t)&box86_jumptable[idx][off];
}
uintptr_t getJumpAddress(uintptr_t addr)
{
const uintptr_t idx = ((uintptr_t)addr>>JMPTABL_SHIFT);
if(box86_jumptable[idx] == box86_jmptbl_default) {
uintptr_t* tbl = (uintptr_t*)box_malloc((1<<JMPTABL_SHIFT)*sizeof(uintptr_t));
for(int i=0; i<(1<<JMPTABL_SHIFT); ++i)
tbl[i] = (uintptr_t)arm_next;
if(arm_lock_storeifref(&box86_jumptable[idx], tbl, box86_jmptbl_default)!=tbl)
box_free(tbl);
}
const uintptr_t off = (uintptr_t)addr&((1<<JMPTABL_SHIFT)-1);
return (uintptr_t)box86_jumptable[idx][off];
}
// 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)
@@ -645,70 +757,311 @@ void protectDB(uintptr_t addr, uintptr_t size)
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
if(!(prot&PROT_DYNAREC)) {
if(!prot)
prot = PROT_READ | PROT_WRITE; // comes from malloc & co, so should not be able to execute
memprot[i] = prot|PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
}
uint32_t prot = memprot[i].prot;
uint32_t dyn = prot&PROT_CUSTOM;
prot&=~PROT_CUSTOM;
if(!prot)
prot = PROT_READ | PROT_WRITE | PROT_EXEC; // comes from malloc & co, so should not be able to execute
if(prot&PROT_WRITE) {
memprot[i].prot = prot|PROT_DYNAREC;
if(!dyn) mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
} else
memprot[i].prot = prot|PROT_DYNAREC_R;
}
}
// 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, uintptr_t size, int mark)
{
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p\n", (void*)addr, (void*)(addr+size-1));
dynarec_log(LOG_DEBUG, "unprotectDB %p -> %p (mark=%d)\n", (void*)addr, (void*)(addr+size-1), mark);
uintptr_t idx = (addr>>MEMPROT_SHIFT);
uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t prot = memprot[i];
uint32_t prot = memprot[i].prot;
if(prot&PROT_DYNAREC) {
memprot[i] = prot&~PROT_DYNAREC;
memprot[i].prot = prot&~PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
}
if(mark)
cleanDBFromAddressRange((i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, 0);
} else if(prot&PROT_DYNAREC_R)
memprot[i].prot = prot&~(PROT_CUSTOM);
}
}
#define HOTPAGE_STEP 16
int IsInHotPage(uintptr_t addr) {
uintptr_t idx = (addr>>MEMPROT_SHIFT);
if(!memprot[idx].hot)
return 0;
// decrement hot
arm_lock_dec_b(&memprot[idx].hot);
return 1;
}
int AreaInHotPage(uintptr_t start, uintptr_t end_) {
//dynarec_log(LOG_DEBUG, "AreaInHotPage %p -> %p => ", (void*)start, (void*)end_);
uintptr_t idx = (start>>MEMPROT_SHIFT);
uintptr_t end = (end_>>MEMPROT_SHIFT);
if(end<idx) { // memory addresses higher than 48bits are not tracked
//dynarec_log(LOG_DEBUG, "00\n");
return 0;
}
for (uintptr_t i=idx; i<=end; ++i) {
if(memprot[i].hot) {
// decrement hot
arm_lock_dec_b(&memprot[i].hot);
//dynarec_log(LOG_DEBUG, "1\n");
return 1;
}
}
//dynarec_log(LOG_DEBUG, "0\n");
return 0;
}
void AddHotPage(uintptr_t addr) {
int idx = (addr>>MEMPROT_SHIFT);
arm_lock_store_b(&memprot[idx].hot, HOTPAGE_STEP);
}
#endif
void printMapMem()
{
mapmem_t* m = mapmem;
while(m) {
printf_log(LOG_NONE, " %p-%p\n", (void*)m->begin, (void*)m->end);
m = m->next;
}
}
void addMapMem(uintptr_t begin, uintptr_t end)
{
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
// find attach point (cannot be the 1st one by construction)
mapmem_t* m = mapmem;
while(m->next && begin>m->next->begin) {
m = m->next;
}
// attach at the end of m
mapmem_t* newm;
if(m->end>=begin-1) {
if(end<=m->end)
return; // zone completly inside current block, nothing to do
m->end = end; // enlarge block
newm = m;
} else {
// create a new block
newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
newm->next = m->next;
newm->begin = begin;
newm->end = end;
m->next = newm;
}
while(newm && newm->next && (newm->next->begin-1)<=newm->end) {
// fuse with next
if(newm->next->end>newm->end)
newm->end = newm->next->end;
mapmem_t* tmp = newm->next;
newm->next = tmp->next;
box_free(tmp);
}
// all done!
}
void removeMapMem(uintptr_t begin, uintptr_t end)
{
begin &=~0xfff;
end = (end&~0xfff)+0xfff; // full page
// sanitize values
if(end<0x10000) return;
if(!begin) begin = 0x10000;
mapmem_t* m = mapmem, *prev = NULL;
while(m) {
// check if block is beyond the zone to free
if(m->begin > end)
return;
// check if the block is completly inside the zone to free
if(m->begin>=begin && m->end<=end) {
// just free the block
mapmem_t *tmp = m;
if(prev) {
prev->next = m->next;
m = prev;
} else {
mapmem = m->next; // change attach, but should never happens
m = mapmem;
prev = NULL;
}
box_free(tmp);
} else if(begin>m->begin && end<m->end) { // the zone is totaly inside the block => split it!
mapmem_t* newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t)); // create a new "next"
newm->end = m->end;
m->end = begin - 1;
newm->begin = end + 1;
newm->next = m->next;
m->next = newm;
// nothing more to free
return;
} else if(begin>m->begin && begin<m->end) { // free the tail of the block
m->end = begin - 1;
} else if(end>m->begin && end<m->end) { // free the head of the block
m->begin = end + 1;
}
prev = m;
m = m->next;
}
}
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "updateProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
uint32_t dyn=(memprot[i]&PROT_DYNAREC);
if(dyn && (prot&PROT_WRITE)) // need to remove the write protection from this block
uint32_t dyn=(memprot[i].prot&(PROT_DYNAREC|PROT_DYNAREC_R));
if(dyn && (prot&PROT_WRITE)) { // need to remove the write protection from this block
dyn = PROT_DYNAREC;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_WRITE);
memprot[i] = prot|dyn;
} else if(dyn && !(prot&PROT_WRITE)) {
dyn = PROT_DYNAREC_R;
}
#ifdef DYNAREC
arm_lock_store_b(&memprot[i].prot, prot|dyn);
#else
memprot[i].prot = prot|dyn;
#endif
}
}
void forceProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "forceProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_DYNAREC);
memprot[i] = prot;
mprotect((void*)(i<<MEMPROT_SHIFT), 1<<MEMPROT_SHIFT, prot&~PROT_CUSTOM);
#ifdef DYNAREC
arm_lock_store_b(&memprot[i].prot, prot);
#else
memprot[i].prot=prot;
#endif
}
}
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
//dynarec_log(LOG_DEBUG, "setProtection %p -> %p to 0x%02x\n", (void*)addr, (void*)(addr+size-1), prot);
if(!mapmem)
return;
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i] = prot;
#ifdef DYNAREC
arm_lock_store_b(&memprot[i].prot, prot);
#else
memprot[i].prot=prot;
#endif
}
}
void freeProtection(uintptr_t addr, uintptr_t size)
{
removeMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
memprot[i].prot = 0;
memprot[i].hot = 0;
}
}
uint32_t getProtection(uintptr_t addr)
{
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
uint32_t ret = memprot[idx];
uint32_t ret = memprot[idx].prot;
return ret;
}
void allocProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
{
addMapMem(addr, addr+size-1);
const uintptr_t idx = (addr>>MEMPROT_SHIFT);
const uintptr_t end = ((addr+size-1)>>MEMPROT_SHIFT);
for (uintptr_t i=idx; i<=end; ++i) {
if(!memprot[i].prot)
memprot[i].prot = prot;
}
}
void loadProtectionFromMap()
{
if(box86_mapclean)
return;
char buf[500];
FILE *f = fopen("/proc/self/maps", "r");
uintptr_t current = 0x0;
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "Refresh mmap allocated block start =============\n");}
if(!f)
return;
while(!feof(f)) {
char* ret = fgets(buf, sizeof(buf), f);
(void)ret;
char r, w, x;
uintptr_t s, e;
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {printf_log(LOG_NONE, "\t%s", buf);}
if(sscanf(buf, "%lx-%lx %c%c%c", &s, &e, &r, &w, &x)==5) {
if(current<s) {
removeMapMem(current, s-1);
current = e;
}
int prot = ((r=='r')?PROT_READ:0)|((w=='w')?PROT_WRITE:0)|((x=='x')?PROT_EXEC:0);
allocProtection(s, e-s, prot);
}
}
fclose(f);
if(box86_log>=LOG_DEBUG || box86_dynarec_log>=LOG_DEBUG) {
printf_log(LOG_NONE, "Refresh mmap allocated block done =============\n");
printMapMem();
}
box86_mapclean = 1;
}
#define LOWEST (void*)0x10000
#define MEDIAN (void*)0x40000000
static void* findBlockHinted(void* hint, size_t size)
{
mapmem_t* m = mapmem;
uintptr_t h = (uintptr_t)hint;
while(m) {
// granularity 0x10000
uintptr_t addr = (m->end+1+0xffff)&~0xffff;
uintptr_t end = (m->next)?(m->next->begin-1):0xffffffff;
// check hint and available size
if(addr<=h && end>=h && end-h+1>=size)
return hint;
if(addr>=h && end-addr+1>=size)
return (void*)addr;
if(end>=0xc0000000 & h<0xc0000000)
return NULL;
m = m->next;
}
return NULL;
}
void* findBlockNearHint(void* hint, size_t size)
{ void* ret = findBlockHinted(hint, size);
return ret?ret:hint;
}
void* find32bitBlock(size_t size)
{
void* ret = findBlockHinted(MEDIAN, size);
if(!ret) ret = findBlockHinted(LOWEST, size);
return ret;
}
@@ -767,8 +1120,14 @@ void init_custommem_helper(box86context_t* ctx)
#else
#error Unsupported architecture!
#endif
lockaddress = kh_init(lockaddress);
#endif
pthread_atfork(NULL, NULL, atfork_child_custommem);
// init mapmem list
mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mapmem->begin = 0x0;
mapmem->end = (uintptr_t)LOWEST - 1;
loadProtectionFromMap();
}
void fini_custommem_helper(box86context_t *ctx)
@@ -784,14 +1143,14 @@ void fini_custommem_helper(box86context_t *ctx)
#ifdef USE_MMAP
munmap(mmaplist[i].block, mmaplist[i].size);
#else
free(mmaplist[i].block);
box_free(mmaplist[i].block);
#endif
if(mmaplist[i].dblist) {
kh_destroy(dynablocks, mmaplist[i].dblist);
mmaplist[i].dblist = NULL;
}
if(mmaplist[i].helper) {
free(mmaplist[i].helper);
box_free(mmaplist[i].helper);
mmaplist[i].helper = NULL;
}
}
@@ -801,24 +1160,42 @@ void fini_custommem_helper(box86context_t *ctx)
}
mmapsize = 0;
mmapcap = 0;
dynarec_log(LOG_DEBUG, "Free dynamic Dynarecblocks\n");
uintptr_t idx = 0;
uintptr_t end = ((0xFFFFFFFF)>>DYNAMAP_SHIFT);
for (uintptr_t i=idx; i<=end; ++i)
if(dynmap[i])
FreeDynablockList(&dynmap[i]);
free(mmaplist);
box_free(mmaplist);
for (int i=0; i<DYNAMAP_SIZE; ++i)
if(box86_jumptable[i]!=box86_jmptbl_default)
free(box86_jumptable[i]);
box_free(box86_jumptable[i]);
}
kh_destroy(lockaddress, lockaddress);
lockaddress = NULL;
#endif
for(int i=0; i<n_blocks; ++i)
#ifdef USE_MMAP
#ifdef USE_MMAP_MORE
munmap(p_blocks[i].block, p_blocks[i].size);
#else
free(p_blocks[i].block);
box_free(p_blocks[i].block);
#endif
free(p_blocks);
box_free(p_blocks);
pthread_mutex_destroy(&mutex_blocks);
while(mapmem) {
mapmem_t *tmp = mapmem;
mapmem = mapmem->next;
box_free(tmp);
}
}
#ifdef DYNAREC
// add an address to the list of "LOCK"able
void addLockAddress(uintptr_t addr)
{
int ret;
kh_put(lockaddress, lockaddress, addr, &ret);
}
// return 1 is the address is used as a LOCK, 0 else
int isLockAddress(uintptr_t addr)
{
khint_t k = kh_get(lockaddress, lockaddress, addr);
return (k==kh_end(lockaddress))?0:1;
}
#endif
+101 -13
View File
@@ -66,7 +66,7 @@ Op is 20-27
#define c__ (0b1110<<28) // means all
// nop
#define NOP EMIT(0xe1a00000)
#define NOP EMIT(0xe320f000)
// mov dst, src
#define MOV_REG(dst, src) EMIT(0xe1a00000 | ((dst) << 12) | (src) )
@@ -213,6 +213,9 @@ Op is 20-27
// add dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.c dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT((cond) | 0x00800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// add.s dst, src1, src2, lsl #imm
#define ADDS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -242,9 +245,12 @@ Op is 20-27
// cmp.s dst, src, #imm
#define CMPS_IMM8(src, imm8) \
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmn.s dst, src, #imm
// cmn.s.cond dst, src, #imm
#define CMNS_IMM8_COND(cond, src, imm8) \
EMIT((cond) | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// cmn.s dst, src, #imm
#define CMNS_IMM8(src, imm8) \
EMIT(c__ | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
// tst.s dst, src1, src2, lsl #imm
#define TSTS_REG_LSL_IMM5(src1, src2, imm5) \
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -254,21 +260,33 @@ Op is 20-27
// tst.s dst, src1, #imm ror rot*2
#define TSTS_IMM8_ROR(src, imm8, rot) \
EMIT(0xe3100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// tst.s.cond dst, src1, #imm ror rot*2
#define TSTS_IMM8_ROR_COND(cond, src, imm8, rot) \
EMIT((cond) | 0x03100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
// orr dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr.cond dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT(cond | 0x01800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr.s dst, src1, src2, lsl #imm
#define ORRS_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
// orr dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.cond dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM5_COND(cond, dst, src1, src2, imm5) \
EMIT(cond | 0x01800000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.s dst, src1, src2, lsr #imm
#define ORRS_REG_LSR_IMM5(dst, src1, src2, imm5) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brLSR(imm5, src2) )
// orr.s dst, src1, src2, lsl rs
#define ORRS_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// orr.s dst, src1, src2, lsr rs
#define ORRS_REG_LSR_REG(dst, src1, src2, rs) \
EMIT(0xe1900000 | ((dst) << 12) | ((src1) << 16) | brRLSR(rs, src2) )
// orr dst, src1, #imm8
#define ORR_IMM8(dst, src, imm8, rot) \
EMIT(0xe3800000 | ((dst) << 12) | ((src) << 16) | ((rot)<<8) | imm8 )
@@ -281,6 +299,9 @@ Op is 20-27
// orr dst, src1, src2, lsl rs
#define ORR_REG_LSL_REG(dst, src1, src2, rs) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brRLSL(rs, src2) )
// orr dst, src1, src2, lsr rs
#define ORR_REG_LSR_REG(dst, src1, src2, rs) \
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brRLSR(rs, src2) )
// xor dst, src1, src2, lsl #imm
#define XOR_REG_LSL_IMM5(dst, src1, src2, imm5) \
EMIT(0xe0200000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
@@ -370,6 +391,8 @@ Op is 20-27
// ldrd reg, reg+1, [addr, +rm], reg must be even, reg+1 is implicit
#define LDRD_REG(reg, addr, rm) EMIT(c__ | 0b000<<25 | 1<<24 | 1<<23 | 0<<22 | 0<<21 | 0<<20 | ((reg) << 12) | ((addr) << 16) | 0b1101<<4 | (rm) )
#define LDR_litteral(reg, imm12) EMIT(c__ | 0b010<<25 | 0<<24 | ((imm12<0)?0:1)<<23 | 0<<22 | 0<<21 | 1<<20 | 0b1111<<16 | (reg)<<12 | (abs(imm12)))
// str reg, [addr, #+/-imm9]
#define STR_IMM9(reg, addr, imm9) EMIT(0xe5000000 | (((imm9)<0)?0:1)<<23 | ((reg) << 12) | ((addr) << 16) | brIMM(imm9) )
// str with cond reg, [addr, #+/-imm9]
@@ -443,7 +466,6 @@ Op is 20-27
#define LDRH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
#define LDRH_IMM8_COND(cond, reg, addr, imm8) EMIT(HWS_OFF(cond, 1, (((imm8)<0)?0:1), 0, 1, addr, reg, 0, 1, abs(imm8)))
#define STRH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 0, 1, abs(imm8)))
#define STRSH_IMM8(reg, addr, imm8) EMIT(HWS_OFF(c__, 1, (((imm8)<0)?0:1), 0, 0, addr, reg, 1, 1, abs(imm8)))
#define LDRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 1, addr, reg, 0, 1, rm))
#define STRH_REG(reg, addr, rm) EMIT(HWS_REG(c__, 1, 1, 0, 0, addr, reg, 0, 1, rm))
@@ -466,6 +488,7 @@ Op is 20-27
// Mul and MulA
#define MULMULA(Cond, A, S, Rd, Rn, Rs, Rm) (Cond | 0b000000<<22 | (A)<<21 | (S)<<20 | (Rd)<<16 | (Rn)<<12 | (Rs)<<8 | 0b1001<<4 | (Rm))
#define MUL(Rd, Rm, Rn) EMIT(MULMULA(c__, 0, 0, (Rd), 0, (Rm), (Rn)))
#define MLA(Rd, Rn, Rm, Ra) EMIT(MULMULA(c__, 1, 0, (Rd), (Ra), (Rm), (Rn)))
#define MLS_gen(Cond, Rd, Ra, Rm, Rn) (Cond | 0b00000110<<20 | (Rd)<<16 | (Ra)<<12 | (Rm)<<8 | 0b1001<<4 | (Rn))
//MLS : Rd = Ra - Rm*Rn
@@ -486,6 +509,8 @@ Op is 20-27
// UBFX: Unsigned Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define UBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111111<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
// UBFX: Unsigned Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define UBFX_COND(cond, rd, rn, lsb, width) EMIT(cond | (0b0111111<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
// SBFX: Signed Bit Field Extract: extract any number of bits from Rn, zero extend and put in Rd
#define SBFX(rd, rn, lsb, width) EMIT(c__ | (0b0111101<<21) | (((width)-1)<<16) | ((rd)<<12) | ((lsb)<<7) | (0b101<<4) | (rn))
@@ -554,6 +579,16 @@ Op is 20-27
#define STREXB(Rd, Rt, Rn) EMIT(STREXB_gen(c__, Rd, Rn, Rt))
#define STREXB_COND(cond, Rd, Rt, Rn) EMIT(STREXB_gen(cond, Rd, Rn, Rt))
#define LDREXH_gen(cond, Rn, Rt) (cond | 0b0001111<<21 | 1<<20 | (Rn)<<16 | (Rt)<<12 | 0b1111<<8 | 0b1001<<4 | 0b1111)
// Load Exclusive Half-Word Rt from Rn (tagging the memory)
#define LDREXH(Rt, Rn) EMIT(LDREXH_gen(c__, Rn, Rt))
#define LDREXH_COND(cond, Rt, Rn) EMIT(LDREXH_gen(cond, Rn, Rt))
#define STREXH_gen(cond, Rd, Rn, Rt) (cond | 0b0001111<<21 | 0<<20 | (Rn)<<16 | (Rd)<<12 | 0b1111<<8 | 0b1001<<4 | (Rt))
// Store Exclusive Half-Word Rt to Rn, with result in Rd=0 if tag is ok, Rd==1 if store failed (Rd!=Rn && Rd!=Rt)
#define STREXH(Rd, Rt, Rn) EMIT(STREXH_gen(c__, Rd, Rn, Rt))
#define STREXH_COND(cond, Rd, Rt, Rn) EMIT(STREXH_gen(cond, Rd, Rn, Rt))
// Count leading 0 bit of Rm, store result in Rd
#define CLZ(Rd, Rm) EMIT(c__ | 0b00010110<<20 | 0b1111<<16 | (Rd)<<12 | 0b1111<<8 | 0b0001<<4 | (Rm))
// Reverse bits of Rm, store result in Rd
@@ -654,6 +689,10 @@ Op is 20-27
// Store to memory to single VSTR Sd, [Rn, #+/-imm8], imm8&3 ignored!
#define VSTR_32(Sd, Rn, Imm8) EMIT(c__ | (0b1101<<24) | (((Imm8)<0)?0:1)<<23 | (((Sd)&1)<<22) | (0<<20) | ((Rn)<<16) | ((((Sd)>>1)&15)<<12) | (0b1010<<8) | ((abs(Imm8)>>2)&255))
#define VSTM_64_gen(cond, P, U, D, W, Rn, Vd, imm8) (cond | 0b110<<25 | (P)<<24 | (U)<<23 | (D)<<22 | (W)<<21 | (Rn)<<16 | (Vd)<<12 | 0b1011<<8 | (imm8))
// Store a sery of Dx, post imcrementing Rn
#define VSTM_64_W(Dd, Rn) EMIT(VSTM_64_gen(c__, 0, 1, ((Dd)>>4)&1, 1, Rn, (Dd)&15, 2))
// Convert from single Sm to double Dd
#define VCVT_F64_F32(Dd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0111<<16) | (((Dd)&15)<<12) | (0b101<<9) | (0<<8) | (0b11<<6) | (((Sm)&1)<<5) | (0<<4) | (((Sm)>>1)&15))
// Convert from double Dm to single Sd
@@ -680,6 +719,42 @@ Op is 20-27
// Inplace convert from F64 to S16. Rounding is not selectable
#define VCVT_S16_F64(Dd) EMIT(VCVT_FP_gen(c__, ((Dd)>>4)&1, 1, 0, (Dd)&15, 1, 0, 16&1, (16>>1)&15))
#define VRINT_FP_gen(D, RM, Vd, size, M, Vm) (0b111111101<<23 | (D)<<22 | 0b111<<19 | (RM)<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<4 | (Vm))
// Round floating-point to integer to Nearest with Ties to Away
#define VRINTA_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b00, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer to Nearest with Ties to Away
#define VRINTA_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b00, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer towards -Infinity
#define VRINTM_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b11, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards -Infinity
#define VRINTM_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b11, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer to Nearest
#define VRINTN_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b01, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer to Nearest
#define VRINTN_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b01, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Round floating-point to integer towards +Infinity
#define VRINTP_F32(Sd, Sm) EMIT(VRINT_FP_gen(((Sd)&1), 0b10, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards +Infinity
#define VRINTP_F64(Dd, Dm) EMIT(VRINT_FP_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTR_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b110<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR
#define VRINTR_F32(Sd, Sm) EMIT(VRINTR_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR
#define VRINTR_F64(Dd, Dm) EMIT(VRINTR_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTX_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b111<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR with eXecptions if inexact
#define VRINTX_F32(Sd, Sm) EMIT(VRINTX_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer rounds a floating-point value to an integral floating-point value of the same size using the rounding mode specified in the FPSCR with eXecptions if inexact
#define VRINTX_F64(Dd, Dm) EMIT(VRINTX_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
#define VRINTZ_gen(cond, D, Vd, size, M, Vm) (cond | 0b11101<<23 | (D)<<22 | 0b11<<20 | 0b110<<16 | (Vd)<<12 | 0b10<<10 | (size)<<8 | 1<<7 | 1<<6 | (M)<<5 | (Vm))
// Round floating-point to integer towards Zero
#define VRINTZ_F32(Sd, Sm) EMIT(VRINTZ_gen(c__, (Sd)&1, ((Sd)>>1)&15, 0b10, (Sm)&1, ((Sm)>>1)&15))
// Round floating-point to integer towards Zero
#define VRINTZ_F64(Dd, Dm) EMIT(VRINTZ_gen(c__, ((Dd)>>4)&1, (Dd)&15, 0b11, ((Dm)>>4)&1, (Dm)&15))
// Mutiply F64 Dd = Dn*Dm
#define VMUL_F64(Dd, Dn, Dm) EMIT(c__ | (0b1110<<24) | (0<<23) | ((((Dd)>>4)&1)<<22) | (0b10<<20) | (((Dn)&15)<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | ((((Dn)>>4)&1)<<7) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
@@ -719,6 +794,8 @@ Op is 20-27
#define VNEG_F64_cond(cond, Dd, Dm) EMIT((cond) | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b01<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
// Neg F32 Dd = - Dm
#define VNEG_F32(Sd, Sm) EMIT(c__ | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Neg F32 Dd = - Dm
#define VNEG_F32_cond(cond, Sd, Sm) EMIT((cond) | (0b1110<<24) | (1<<23) | (((Sd)&1)<<22) | (0b11<<20) | (0b0001<<16) | ((((Sd)>>1)&15)<<12) | (0b101<<9) | (0<<8) | (0b01<<6) | (((Sm)&1)<<5) | (((Sm)>>1)&15) )
// Sqrt F64 Dd = - Dm
#define VSQRT_F64(Dd, Dm) EMIT(c__ | (0b1110<<24) | (1<<23) | ((((Dd)>>4)&1)<<22) | (0b11<<20) | (0b0001<<16) | (((Dd)&15)<<12) | (0b101<<9) | (1<<8) | (0b11<<6) | ((((Dm)>>4)&1)<<5) | ((Dm)&15) )
@@ -814,19 +891,19 @@ Op is 20-27
#define VMOVQ_H16(Dd, imm8) EMIT(VMOV_igen(((imm8)>>7)&1, ((Dd)>>4)&1, ((imm8)>>4)&7, (Dd)&15, 0b1010, 1, 0, (imm8)&15))
#define VLD1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
#define VLD1LANE_16(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, (index)<<2, 15))
#define VLD1LANE_32(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, (index)<<3, 15))
#define VLD1LANE_8(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 0, (index)<<1, 15))
#define VLD1LANE_16(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, (index)<<2, 15))
#define VLD1LANE_32(Dd, Rn, index) EMIT(VLD1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, (index)<<3, 15))
#define VLD1ALL_gen(D, Rn, Vd, size, T, a, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b10<<20 | (Rn)<<16 | (Vd)<<12 | 0b11<<10| (size)<<6 | (T)<<5 | (a)<<4 | (Rm))
#define VLD1ALL_16(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, 0, 0, 15))
#define VLD1ALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, 0, 0, 15))
#define VLD1QALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, 1, 0, 15))
#define VLD1ALL_16(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, 0, 0, 15))
#define VLD1ALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, 0, 0, 15))
#define VLD1QALL_32(Dd, Rn) EMIT(VLD1ALL_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, 1, 0, 15))
#define VST1LANE_gen(D, Rn, Vd, size, index_align, Rm) (0b1111<<28 | 0b0100<<24 | 1<<23 | (D)<<22 | 0b00<<20 | (Rn)<<16 | (Vd)<<12 | (size)<<10 | (index_align)<<4 | (Rm))
#define VST1LANE_8(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 0, (index)<<1, 15))
#define VST1LANE_16(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 1, (index)<<2, 15))
#define VST1LANE_32(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, Rn, (Dd)&15, 2, (index)<<3, 15))
#define VST1LANE_8(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 0, (index)<<1, 15))
#define VST1LANE_16(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 1, (index)<<2, 15))
#define VST1LANE_32(Dd, Rn, index) EMIT(VST1LANE_gen(((Dd)>>4)&1, (Rn), (Dd)&15, 2, (index)<<3, 15))
#define VADD_gen(size, D, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1000<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#define VADD_8(Dd, Dn, Dm) EMIT(VADD_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -870,7 +947,7 @@ Op is 20-27
#define VCEQQ_16(Dd, Dn, Dm) EMIT(VCEQ_I_gen(1, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_32(Dd, Dn, Dm) EMIT(VCEQ_I_gen(2, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_32(Dd, Dn, Dm) EMIT(VCEQ_I_gen(2, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
//#define VCEQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15)) // doesn't exist
#define VCEQQ_64(Dd, Dn, Dm) EMIT(VCEQ_I_gen(3, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQ_F_gen(sz, D, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b0010<<24 | 0<<23 | (D)<<22 | (sz)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1110<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 0<<4 | (Vm))
#define VCEQ_F32(Dd, Dn, Dm) EMIT(VCEQ_F_gen(0, ((Dd)>>4)&1, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -883,6 +960,7 @@ Op is 20-27
#define VCEQQ_0_8(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_16(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 1, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCEQQ_0_F32(Dd, Dm) EMIT(VCEQ_0_gen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
#define VCGT_I_gen(U, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (U)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b0011<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VCGT_U8(Dd, Dn, Dm) EMIT(VCGT_I_gen(1, ((Dd)>>4)&1, 0, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 0, ((Dm)>>4)&1, (Dm)&15))
@@ -1288,7 +1366,17 @@ Op is 20-27
#define VDUP_sgen(D, imm4, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (imm4)<<16 | (Vd)<<12 | 0b1100<<8 | (Q)<<6 | (M)<<5 | (Vm))
// Dd <= Dup(Dm[x])
#define VDUP_8(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<1)|0b1), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_8(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<1)|0b1), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_16(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<2)|0b10), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_16(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<2)|0b10), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUP_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_32(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<3)|0b100), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VDUPQ_64(Dd, Dm, x) EMIT(VDUP_sgen(((Dd)>>4)&1, (((x)<<4)|0b1000), (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VREV64_gen(D, size, Vd, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | (Q)<<6 | (M)<<5 | (Vm))
#define VREV64_32(Dd, Dm) EMIT(VREV64_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 0, ((Dm)>>4)&1, (Dm)&15))
#define VREV64Q_32(Dd, Dm) EMIT(VREV64_gen(((Dd)>>4)&1, 0b10, (Dd)&15, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABS_vgen(D, size, Vd, F, Q, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | 0b01<<16 | (Vd)<<12 | (F)<<10 | 0b110<<7 | (Q)<<6 | (M)<<5 | (Vm))
#define VABS_S32(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 0, 0, ((Dm)>>4)&1, (Dm)&15))
+1 -1
View File
@@ -179,7 +179,7 @@ INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d64 &g&g param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
+12
View File
@@ -0,0 +1,12 @@
#include <stdint.h>
#include <stdlib.h>
#include "arm_emitter.h"
#define EMIT(A) *block = (A); ++block
void CreateJmpNextTo(void* addr, void* tonext)
{
uint32_t* block = (uint32_t*)addr;
MOV32(x3, (uintptr_t)tonext);
BX(x3);
}
+48
View File
@@ -16,6 +16,11 @@
.global arm_lock_xchg
.global arm_lock_storeifnull
.global arm_lock_storeifref
.global arm_lock_store_xchg
.global arm_lock_dec
.global arm_lock_dec_b
.global arm_lock_store
.global arm_lock_store_b
arm_lock_read_b:
@@ -113,3 +118,46 @@ arm_lock_storeifref_exit:
mov r0, r3
pop {r4}
bx lr
arm_lock_store_xchg:
// address is r0, value is r1, r1 store to r0 only if [r0] is 0. return new [r0] value (so r1 or old value)
// r0 needs to be aligned
ldrex r2, [r0]
cmp r2, #0
bne arm_lock_store_xchg_exit
mov r2, r1
strex r3, r2, [r0]
cmp r3, #1
beq arm_lock_store_xchg
mov r2, #0
arm_lock_store_xchg_exit:
mov r0, r2
bx lr
arm_lock_dec:
dmb ish
ldrex r1, [r0]
sub r1, r1, #1
strex r2, r1, [r0]
cmp r2, #1
beq arm_lock_dec
bx lr
arm_lock_dec_b:
dmb ish
ldrexb r1, [r0]
sub r1, r1, #1
strexb r2, r1, [r0]
cmp r2, #1
beq arm_lock_dec_b
bx lr
arm_lock_store:
str r1, [r0]
dmb ish
bx lr
arm_lock_store_b:
strb r1, [r0]
dmb ish
bx lr
+15
View File
@@ -31,4 +31,19 @@ extern void* arm_lock_storeifnull(void* p, void* val);
// Atomically store value to [p] only if [p] is ref. Return new [p] value (so val or old)
extern void* arm_lock_storeifref(void* p, void* val, void* ref);
// Atomically store value to [p] only if [p] is NULL. Return old [p] value
extern void* arm_lock_store_xchg(void* p, void* val);
// will decrease *p atomicaly
extern void arm_lock_dec_b(uint8_t* p);
// will decrease *p atomicaly
extern void arm_lock_dec(int* p);
// store value, with data memory barrier
extern void arm_lock_store_b(uint8_t* p, uint8_t val);
// store value, with data memory barrier
extern void arm_lock_store(int* p, int val);
#endif //__ARM_LOCK_HELPER__H__
+2 -2
View File
@@ -1,5 +1,5 @@
/******************************************************************
* File automatically generated by rebuild_printer.py (v1.2.0.05) *
* File automatically generated by rebuild_printer.py (v1.2.0.06) *
******************************************************************/
#include <stdint.h>
#include <stddef.h>
@@ -1164,7 +1164,7 @@ const char* arm_print(uint32_t opcode) {
int m = ((opcode >> 5) & 1) << 4 | ((opcode >> 0) & 0xF);
int param = (opcode >> 7) & 0x3;
sprintf(ret, "VREV%d.%d %s, %s", 16 << param, 8 << size, vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m]);
sprintf(ret, "VREV%d.%d %s, %s", 64 >> param, 8 << size, vecname[(q << 5) + 0x20 + d], vecname[(q << 5) + 0x20 + m]);
} else if ((opcode & 0xFFB30F10) == 0xF3B00200) {
int u = (opcode >> 7) & 1;
int size = (opcode >> 18) & 0x3;
+99 -282
View File
@@ -4,6 +4,7 @@
#include <errno.h>
#include <sys/mman.h>
#include <setjmp.h>
#include <sys/mman.h>
#include "debug.h"
#include "box86context.h"
@@ -20,6 +21,7 @@
#include "dynablock_private.h"
#include "dynarec_private.h"
#include "elfloader.h"
#include "bridge.h"
#ifdef ARM
#include "dynarec_arm.h"
#include "arm_lock_helper.h"
@@ -40,108 +42,36 @@ uint32_t X31_hash_code(void* addr, int len)
return (uint32_t)h;
}
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct)
{
if(!textsz) {
printf_log(LOG_NONE, "Error, creating a NULL sized Dynablock\n");
return NULL;
}
dynablocklist_t* ret = (dynablocklist_t*)calloc(1, sizeof(dynablocklist_t));
ret->text = text;
ret->textsz = textsz;
if(direct && textsz) {
ret->direct = (dynablock_t**)calloc(textsz, sizeof(dynablock_t*));
if(!ret->direct) {printf_log(LOG_NONE, "Warning, fail to create direct block for dynablock @%p\n", (void*)text);}
}
dynarec_log(LOG_DEBUG, "New Dynablocklist %p, from %p->%p\n", ret, (void*)text, (void*)(text+textsz));
return ret;
}
void FreeDynablock(dynablock_t* db, int need_lock)
{
if(db) {
if(db->gone)
return; // already in the process of deletion!
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->father, db->sons_size, db->gone);
dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x86=%p:%p already gone=%d\n", db, db->block, db->x86_addr, db->x86_addr+db->x86_size, db->gone);
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
db->done = 0;
db->gone = 1;
// remove from direct if there
uintptr_t startdb = db->parent->text;
uintptr_t enddb = db->parent->text + db->parent->textsz;
if(db->parent->direct) {
uintptr_t addr = (uintptr_t)db->x86_addr;
if(addr>=startdb && addr<enddb)
db->parent->direct[addr-startdb] = NULL;
}
// remove jumptable
setJumpTableDefault(db->x86_addr);
// remove and free the sons
for (int i=0; i<db->sons_size; ++i) {
dynablock_t *son = (dynablock_t*)arm_lock_xchg(&db->sons[i], 0);
FreeDynablock(son, 0);
}
// only the father free the DynarecMap
if(!db->father) {
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size);
FreeDynarecMap(db, (uintptr_t)db->block, db->size);
free(db->sons);
free(db->instsize);
}
free(db);
dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->actual_block, db->size);
db->done = 0;
db->gone = 1;
FreeDynarecMap(db, (uintptr_t)db->actual_block, db->size);
box_free(db);
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
}
void FreeDynablockList(dynablocklist_t** dynablocks)
{
if(!dynablocks)
return;
if(!*dynablocks)
return;
dynarec_log(LOG_DEBUG, "Free Dynablocklist %p, with Direct Blocks %p\n", *dynablocks, (*dynablocks)->direct);
if((*dynablocks)->direct) {
for (int i=0; i<(*dynablocks)->textsz; ++i) {
if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father)
FreeDynablock((*dynablocks)->direct[i], my_context?1:0);
}
free((*dynablocks)->direct);
}
(*dynablocks)->direct = NULL;
free(*dynablocks);
*dynablocks = NULL;
}
void MarkDynablock(dynablock_t* db)
{
if(db) {
if(db->father)
db = db->father; // mark only father
if(db->need_test)
return; // already done
db->need_test = 1;
setJumpTableDefault(db->x86_addr);
for(int i=0; i<db->sons_size; ++i)
setJumpTableDefault(db->sons[i]->x86_addr);
}
}
uintptr_t StartDynablockList(dynablocklist_t* db)
{
if(db)
return db->text;
return 0;
}
uintptr_t EndDynablockList(dynablocklist_t* db)
{
if(db)
return db->text+db->textsz-1;
return 0;
}
int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintptr_t end2)
{
if(start1 > end2 || start2 > end1)
@@ -149,80 +79,27 @@ int IntervalIntersects(uintptr_t start1, uintptr_t end1, uintptr_t start2, uintp
return 1;
}
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
if(!db)
return;
if(!dynablocks->direct)
return;
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz -1;
uintptr_t start = addr;
uintptr_t end = addr+size-1;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
dynablock_t *db;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i)
if((db=dynablocks->direct[i-startdb]))
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
MarkDynablock(db);
dynarec_log(LOG_DEBUG, "MarkRangeDynablock %p-%p .. startdb=%p, sizedb=%p\n", (void*)addr, (void*)addr+size-1, (void*)db->x86_addr, (void*)db->x86_size);
if(!db->need_test)
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1))
MarkDynablock(db);
}
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(!db)
return 1;
if(dynablocks->direct) {
dynablock_t* db;
int ret;
khint_t k;
kh_dynablocks_t *blocks = kh_init(dynablocks);
// copy in a temporary list
if(dynablocks->direct) {
uintptr_t startdb = dynablocks->text;
uintptr_t enddb = startdb + dynablocks->textsz;
uintptr_t start = addr;
uintptr_t end = addr+size;
if(start<startdb)
start = startdb;
if(end>enddb)
end = enddb;
if(end>startdb && start<enddb)
for(uintptr_t i = start; i<end; ++i) {
db = (dynablock_t*)arm_lock_xchg(&dynablocks->direct[i-startdb], 0);
if(db) {
if(db->father)
db = db->father;
if(db->parent==dynablocks) {
k = kh_put(dynablocks, blocks, (uintptr_t)db, &ret);
kh_value(blocks, k) = db;
}
}
}
}
// purge the list
kh_foreach_value(blocks, db,
FreeDynablock(db, 1);
);
kh_destroy(dynablocks, blocks);
}
}
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size)
{
if(!dynablocks)
return;
if(dynablocks->direct) {
uintptr_t new_addr = addr - dynablocks->maxsz;
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)
MarkDirectDynablock(getDB(idx), new_addr, new_size);
int need_lock = my_context?1:0;
if(IntervalIntersects((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr+db->x86_size-1, addr, addr+size+1)) {
FreeDynablock(db, need_lock);
return 0;
}
return 1;
}
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
@@ -234,66 +111,27 @@ dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks)
const uintptr_t s = (uintptr_t)db->block;
const uintptr_t e = (uintptr_t)db->block+db->size;
if((uintptr_t)addr>=s && (uintptr_t)addr<e)
return db->father?db->father:db;
return db;
)
return NULL;
}
static dynablocklist_t* getDBFromAddress(uintptr_t addr)
dynablock_t *AddNewDynablock(uintptr_t addr)
{
const int idx = (addr>>DYNAMAP_SHIFT);
return getDB(idx);
}
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created)
{
if(!dynablocks) {
dynarec_log(LOG_INFO, "Warning: Ask to create a dynablock with a NULL dynablocklist (addr=%p)\n", (void*)addr);
*created = 0;
dynablock_t* block;
#if 0
// check if memory as the correct flags
int prot = getProtection(addr);
if(!(prot&(PROT_EXEC|PROT_DYNAREC|PROT_DYNAREC_R))) {
dynarec_log(LOG_VERBOSE, "Block asked on a memory with no execution flags 0x%02X\n", prot);
return NULL;
}
if((addr<dynablocks->text) || (addr>=(dynablocks->text+dynablocks->textsz))) {
// this should be useless
//dynarec_log(LOG_INFO, "Warning: Refused to create a Direct Block that is out-of-bound: dynablocks=%p (%p:%p), addr=%p\n", dynablocks, (void*)(dynablocks->text), (void*)(dynablocks->text+dynablocks->textsz), (void*)addr);
//*created = 0;
//return NULL;
return AddNewDynablock(getDBFromAddress(addr), addr, created);
}
dynablock_t* block = NULL;
// first, check if it exist in direct access mode
if(dynablocks->direct) {
block = dynablocks->direct[addr-dynablocks->text];
if(block) {
dynarec_log(LOG_VERBOSE, "Block already exist in Direct Map\n");
*created = 0;
return block;
}
}
if (!*created)
return block;
#endif
pthread_mutex_lock(&my_context->mutex_dyndump);
if(!dynablocks->direct) {
dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*));
if(arm_lock_storeifnull(&dynablocks->direct, p)!=p)
free(p); // someone already create the direct array, too late...
}
// create and add new block
dynarec_log(LOG_VERBOSE, "Ask for DynaRec Block creation @%p\n", (void*)addr);
block = (dynablock_t*)calloc(1, sizeof(dynablock_t));
block->parent = dynablocks;
dynablock_t* tmp = (dynablock_t*)arm_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block);
block = (dynablock_t*)box_calloc(1, sizeof(dynablock_t));
pthread_mutex_unlock(&my_context->mutex_dyndump);
if(tmp != block) {
// a block appeard!
free(block);
*created = 0;
return tmp;
}
*created = 1;
return block;
}
@@ -309,39 +147,28 @@ void cancelFillBlock()
return NULL if block is not found / cannot be created.
Don't create if create==0
*/
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock)
static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, int need_lock)
{
// try the quickest way first: get parent of current and check if ok!
dynablocklist_t *dynablocks = NULL;
dynablock_t* block = NULL;
if(current) {
dynablocks = current->parent;
if(dynablocks && !(addr>=dynablocks->text && addr<(dynablocks->text+dynablocks->textsz)))
dynablocks = NULL;
}
// nope, lets do the long way
if(!dynablocks) {
dynablocks = getDBFromAddress(addr);
if(!dynablocks) {
dynablocks = GetDynablocksFromAddress(emu->context, addr);
if(!dynablocks)
return NULL;
}
}
// check direct first, without lock
if(dynablocks->direct/* && (addr>=dynablocks->text) && (addr<(dynablocks->text+dynablocks->textsz))*/)
if((block = dynablocks->direct[addr-dynablocks->text]))
return block;
if(hasAlternate((void*)addr))
return NULL;
dynablock_t* block = getDB(addr);
if(block || !create)
return block;
int created = create;
block = AddNewDynablock(dynablocks, addr, &created);
if(!created)
return block; // existing block...
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
block = getDB(addr); // just in case
if(block) {
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
return block;
}
block = AddNewDynablock(addr);
// fill the block
block->x86_addr = (void*)addr;
if(need_lock)
pthread_mutex_lock(&my_context->mutex_dyndump);
if(sigsetjmp(&dynarec_jmpbuf, 1)) {
printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr);
if(need_lock)
@@ -353,68 +180,60 @@ static dynablock_t* internalDBGetBlock(x86emu_t* emu, uintptr_t addr, uintptr_t
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*)arm_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);
// Doing nothing else, the block has not been written
}
free(block);
box_free(block);
block = NULL;
}
// check size
if(block && block->x86_size) {
if(block && (block->x86_size || (!block->x86_size && !block->done))) {
int blocksz = block->x86_size;
if(dynablocks->maxsz<blocksz) {
dynablocks->maxsz = blocksz;
for(int idx=(addr>>DYNAMAP_SHIFT)+1; idx<=((addr+blocksz)>>DYNAMAP_SHIFT); ++idx) {
dynablocklist_t* dblist;
if((dblist = getDB(idx)))
if(dblist->maxsz<blocksz)
dblist->maxsz = blocksz;
}
}
//protectDB((uintptr_t)block->x86_addr, block->x86_size); // already protected in FillBlock
// but check if it already need test
if(block->need_test || (block->father && block->father->need_test))
return NULL;
if(blocksz>my_context->max_db_size)
my_context->max_db_size = blocksz;
// fill-in jumptable
addJumpTableIfDefault(block->x86_addr, block->block);
for(int i=0; i<block->sons_size; ++i)
addJumpTableIfDefault(block->sons[i]->x86_addr, block->sons[i]->block);
if(!addJumpTableIfDefault(block->x86_addr, block->block)) {
FreeDynablock(block, 1);
block = getDB(addr);
} else {
if(block->x86_size)
block->done = 1; // don't validate the block if the size is null, but keep the block
}
}
if(need_lock)
pthread_mutex_unlock(&my_context->mutex_dyndump);
dynarec_log(LOG_DEBUG, " --- DynaRec Block %s @%p:%p (%p, 0x%x bytes, with %d son(s))\n", created?"created":"recycled", (void*)addr, (void*)(addr+((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0, (block)?block->sons_size:0);
dynarec_log(LOG_DEBUG, " --- DynaRec Block created @%p:%p (%p, 0x%x bytes)\n", (void*)addr, (void*)(addr+((block)?block->x86_size:0)), (block)?block->block:0, (block)?block->size:0);
return block;
}
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current)
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create)
{
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(AreaInHotPage((uintptr_t)db->x86_addr, (uintptr_t)db->x86_addr + db->x86_size - 1)) {
dynarec_log(LOG_DEBUG, "Not running block %p from %p:%p with for %p because it's in a hotpage\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, (void*)addr);
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// no more current if it gets invalidated too
if(*current && father->x86_addr>=(*current)->x86_addr && (father->x86_addr+father->x86_size)<(*current)->x86_addr)
*current = NULL;
// Free father, it's now invalid!
FreeDynablock(father, 0);
}
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
if(pthread_mutex_trylock(&my_context->mutex_dyndump)) {
dynarec_log(LOG_DEBUG, "mutex_dyndump not available when trying to validate block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
return NULL;
}
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, addr, create, *current, 0);
db = internalDBGetBlock(emu, addr, addr, create, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
// fill back jumptable
addJumpTableIfDefault(father->x86_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
db->need_test = 0;
dynarec_log(LOG_DEBUG, "Validating block %p from %p:%p (hash:%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size-1, db->hash, (void*)addr);
protectDB((uintptr_t)db->x86_addr, db->x86_size);
// fill back jumptable
setJumpTableIfRef(db->x86_addr, db->block, db->jmpnext);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
}
return db;
}
@@ -422,27 +241,25 @@ dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr)
{
dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr);
int create = 1;
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1);
if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) {
dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, 1);
if(db && db->done && db->block && db->need_test) {
if(pthread_mutex_trylock(&my_context->mutex_dyndump))
return NULL;
dynablock_t *father = db->father?db->father:db;
uint32_t hash = (getProtection((uintptr_t)father->x86_addr)&PROT_READ)?X31_hash_code(father->x86_addr, father->x86_size):0;
if(hash!=father->hash) {
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x86_addr, father->x86_addr+father->x86_size, hash, father->hash, father->sons_size, (void*)addr);
// Free father, it's now invalid!
FreeDynablock(father, 0);
uint32_t hash = X31_hash_code(db->x86_addr, db->x86_size);
if(hash!=db->hash) {
db->done = 0; // invalidating the block
dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) for %p\n", db, db->x86_addr, db->x86_addr+db->x86_size, hash, db->hash, (void*)addr);
// Free db, it's now invalid!
FreeDynablock(db, 0);
// start again... (will create a new block)
db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0);
db = internalDBGetBlock(emu, addr, filladdr, create, 0);
} else {
father->need_test = 0;
protectDB((uintptr_t)father->x86_addr, father->x86_size);
db->need_test = 0;
protectDB((uintptr_t)db->x86_addr, db->x86_size);
// fill back jumptable
addJumpTableIfDefault(father->x86_addr, father->block);
for(int i=0; i<father->sons_size; ++i)
addJumpTableIfDefault(father->sons[i]->x86_addr, father->sons[i]->block);
addJumpTableIfDefault(db->x86_addr, db->block);
}
pthread_mutex_unlock(&my_context->mutex_dyndump);
}
return db;
}
}
+5 -15
View File
@@ -1,16 +1,15 @@
#ifndef __DYNABLOCK_PRIVATE_H_
#define __DYNABLOCK_PRIVATE_H_
typedef struct dynablocklist_s dynablocklist_t;
typedef struct instsize_s {
unsigned int x86:4;
unsigned int nat:4;
unsigned char x86:4;
unsigned char nat:4;
} instsize_t;
typedef struct dynablock_s {
dynablocklist_t* parent;
void* block;
void* block; // block-sizeof(void*) == self
void* actual_block; // the actual start of the block (so block-sizeof(void*))
int size;
void* x86_addr;
uintptr_t x86_size;
@@ -20,17 +19,8 @@ typedef struct dynablock_s {
uint8_t gone;
uint8_t dummy;
int isize;
dynablock_t** sons; // sons (kind-of dummy dynablock...)
int sons_size;
dynablock_t* father; // set only in the case of a son
instsize_t* instsize;
void* jmpnext; // a branch jmpnext code when block is marked
} dynablock_t;
typedef struct dynablocklist_s {
uintptr_t text;
int textsz;
int maxsz; // maxblock size (for this block or previous block)
dynablock_t** direct; // direct mapping (waste of space, so the array is created at first write)
} dynablocklist_t;
#endif //__DYNABLOCK_PRIVATE_H_
+16 -19
View File
@@ -20,16 +20,12 @@
#include "dynablock.h"
#include "dynablock_private.h"
#include "bridge.h"
#endif
#ifdef ARM
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
void arm_epilog() EXPORTDYN;
void arm_epilog_fast() EXPORTDYN;
#include "dynarec_next.h"
#endif
#ifdef DYNAREC
#ifdef HAVE_TRACE
#include "elfloader.h"
uintptr_t getX86Address(dynablock_t* db, uintptr_t arm_addr);
#endif
void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
@@ -38,12 +34,13 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
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, x86addr=%p)\n", x2, db, db?(void*)getX86Address(db, (uintptr_t)x2):NULL);
void* x86addr = db?(void*)getX86Address(db, (uintptr_t)x2):NULL;
const char* pcname = getAddrFunctionName((uintptr_t)x86addr);
printf_log(LOG_NONE, "Warning, jumping to NULL address from %p (db=%p, x86addr=%p/%s)\n", x2, db, x86addr, pcname);
}
#endif
dynablock_t* current = NULL;
void * jblock;
dynablock_t* block = DBGetBlock(emu, addr, 1, &current);
dynablock_t* block = DBGetBlock(emu, addr, 1);
if(!block) {
// no block, let link table as is...
if(hasAlternate((void*)addr)) {
@@ -51,7 +48,7 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
addr = (uintptr_t)getAlternate((void*)addr);
R_EIP = addr;
printf_log(LOG_INFO, " -> %p\n", (void*)addr);
block = DBGetBlock(emu, addr, 1, &current);
block = DBGetBlock(emu, addr, 1);
}
if(!block) {
#ifdef HAVE_TRACE
@@ -111,18 +108,15 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
PushExit(emu);
R_EIP = addr;
emu->df = d_none;
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = block;
dynablock_t* block = DBGetBlock(emu, R_EIP, 1);
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Calling Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Calling DynaRec Block @%p (%p) of %d x86 instructions emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize ,emu);
CHECK_FLAGS(emu);
// block is here, let's run it!
#ifdef ARM
@@ -165,6 +159,7 @@ void DynaCall(x86emu_t* emu, uintptr_t addr)
ejb->jmpbuf_ok = 0;
}
int my_setcontext(x86emu_t* emu, void* ucp);
int DynaRun(x86emu_t* emu)
{
// prepare setjump for signal handling
@@ -196,17 +191,15 @@ int DynaRun(x86emu_t* emu)
#ifdef DYNAREC
else {
dynablock_t* block = NULL;
dynablock_t* current = NULL;
while(!emu->quit) {
block = DBGetBlock(emu, R_EIP, 1, &current);
current = block;
block = DBGetBlock(emu, R_EIP, 1);
if(!block || !block->block || !block->done) {
// no block, of block doesn't have DynaRec content (yet, temp is not null)
// Use interpreter (should use single instruction step...)
dynarec_log(LOG_DEBUG, "%04d|Running Interpretor @%p, emu=%p\n", GetTID(), (void*)R_EIP, emu);
Run(emu, 1);
} else {
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts (father=%p) emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, block->father, emu);
dynarec_log(LOG_DEBUG, "%04d|Running DynaRec Block @%p (%p) of %d x86 insts emu=%p\n", GetTID(), (void*)R_EIP, block->block, block->isize, emu);
// block is here, let's run it!
#ifdef ARM
arm_prolog(emu, block->block);
@@ -226,6 +219,10 @@ int DynaRun(x86emu_t* emu)
printf_log(LOG_DEBUG, "Setjmp inner DynaRun, fs=0x%x\n", ejb->emu->segs[_FS]);
}
}
else if(emu->quit && emu->uc_link) {
emu->quit = 0;
my_setcontext(emu, emu->uc_link);
}
}
}
// clear the setjmp
+196 -160
View File
@@ -3,6 +3,7 @@
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include "debug.h"
#include "box86context.h"
@@ -22,21 +23,22 @@
#include "dynarec_arm_private.h"
#include "dynarec_arm_functions.h"
#include "elfloader.h"
#include "dynarec_next.h"
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name) {
uint8_t *ip = (uint8_t*)inst->addr;
if(ip[0]==0xcc && ip[1]=='S' && ip[2]=='C') {
uint32_t a = *(uint32_t*)(ip+3);
if(a==0) {
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Exit x86emu%s\n", (box86_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (box86_dynarec_dump>1)?"\e[m":"");
} else {
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[1m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
dynarec_log(LOG_NONE, "%s%p: Native call to %p%s\n", (box86_dynarec_dump>1)?"\e[01;33m":"", (void*)ip, (void*)a, (box86_dynarec_dump>1)?"\e[m":"");
}
} else {
if(dec) {
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[1m":"", ip, DecodeX86Trace(dec, inst->addr));
dynarec_log(LOG_NONE, "%s%p: %s", (box86_dynarec_dump>1)?"\e[01;33m":"", ip, DecodeX86Trace(dec, inst->addr));
} else {
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[1m":"", ip);
dynarec_log(LOG_NONE, "%s%p: ", (box86_dynarec_dump>1)?"\e[01;33m":"", ip);
for(int i=0; i<inst->size; ++i) {
dynarec_log(LOG_NONE, "%02X ", ip[i]);
}
@@ -60,12 +62,20 @@ void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const cha
void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
if(!box86_dynarec_bigblock)
return;
// exist?
for(int i=0; i<dyn->next_sz; ++i)
if(dyn->next[i]==addr)
return;
// put in a free slot
for(int i=0; i<dyn->next_sz; ++i)
if(!dyn->next[i]) {
dyn->next[i] = addr;
return;
}
// add slots
if(dyn->next_sz == dyn->next_cap) {
dyn->next_cap += 16;
dyn->next = (uintptr_t*)realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
dyn->next = (uintptr_t*)box_realloc(dyn->next, dyn->next_cap*sizeof(uintptr_t));
}
dyn->next[dyn->next_sz++] = addr;
}
@@ -75,13 +85,12 @@ uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr) {
int i = 0;
while((i<dyn->next_sz) && (best!=addr)) {
if(dyn->next[i]<addr) { // remove the address, it's before current address
memmove(dyn->next+i, dyn->next+i+1, (dyn->next_sz-i-1)*sizeof(uintptr_t));
--dyn->next_sz;
dyn->next[i] = 0;
} else {
if((dyn->next[i]<best) || !best)
best = dyn->next[i];
++i;
}
++i;
}
return best;
}
@@ -92,7 +101,9 @@ int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n)
return 1;
if(PK(0)==0x90)
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than is *can* be a NOP
if(n>1 && PK(0)==0x2E) // if opcode start with 0x2E, and there is more after, than this *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>1 && PK(0)==0x66) // if opcode start with 0x66, and there is more after, than this *can* be a NOP
return is_nops(dyn, addr+1, n-1);
if(n>2 && PK(0)==0x0f && PK(1)==0x1f && PK(2)==0x00)
return is_nops(dyn, addr+3, n-3);
@@ -206,7 +217,7 @@ int next_instruction(dynarec_arm_t *dyn, uintptr_t addr)
nextop = PK(1);
switch((nextop>>3)&7) {
case 0: // INC Ed
case 1: //DEC Ed
case 1: // DEC Ed
case 2: // CALL Ed
case 4: // JMP Ed
case 6: // Push Ed
@@ -231,7 +242,7 @@ int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n)
return (i==n)?1:0;
}
instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size, int arm_size)
{
// x86 instruction is <16 bytes
int toadd;
@@ -241,7 +252,7 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size,
toadd = 1 + arm_size/15;
if((*size)+toadd>(*cap)) {
*cap = (*size)+toadd;
insts = (instsize_t*)realloc(insts, (*cap)*sizeof(instsize_t));
insts = (instsize_t*)box_realloc(insts, (*cap)*sizeof(instsize_t));
}
while(toadd) {
if(x86_size>15)
@@ -260,6 +271,89 @@ instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86_size,
return insts;
}
static void fillPredecessors(dynarec_arm_t* dyn)
{
int pred_sz = 1; // to be safe
// compute total size of predecessor to alocate the array
// first compute the jumps
for(int i=0; i<dyn->size; ++i) {
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1) {
++pred_sz;
++dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz;
}
}
// second the "has_next"
for(int i=0; i<dyn->size-1; ++i) {
if(dyn->insts[i].x86.has_next) {
++pred_sz;
++dyn->insts[i+1].pred_sz;
}
}
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
dyn->insts[i].pred = p;
p += dyn->insts[i].pred_sz;
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
// fill pred
for(int i=0; i<dyn->size; ++i) {
if(i!=dyn->size-1 && dyn->insts[i].x86.has_next && (!i || dyn->insts[i].pred_sz))
dyn->insts[i+1].pred[dyn->insts[i+1].pred_sz++] = i;
if(dyn->insts[i].x86.jmp && dyn->insts[i].x86.jmp_insts!=-1)
dyn->insts[dyn->insts[i].x86.jmp_insts].pred[dyn->insts[dyn->insts[i].x86.jmp_insts].pred_sz++] = i;
}
}
// updateNeed goes backward, from last intruction to top
static int updateNeed(dynarec_arm_t* dyn, int ninst, uint8_t need) {
while (ninst>=0) {
// need pending but instruction is only a subset: remove pend and use an X_ALL instead
need |= dyn->insts[ninst].x86.need_after;
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
need &=~X_PEND;
need |= X_ALL;
}
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags==SF_SET)) {
need &=~X_PEND;
need |= dyn->insts[ninst].x86.set_flags; // SF_SET will compute all flags, it's not SUBSET!
}
if((need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET_PENDING) {
need |= X_ALL&~(dyn->insts[ninst].x86.set_flags);
}
dyn->insts[ninst].x86.gen_flags = need&dyn->insts[ninst].x86.set_flags;
if((need&X_PEND) && (dyn->insts[ninst].x86.state_flags&SF_PENDING))
dyn->insts[ninst].x86.gen_flags |= X_PEND;
dyn->insts[ninst].x86.need_after = need;
need = dyn->insts[ninst].x86.need_after&~dyn->insts[ninst].x86.gen_flags;
if(dyn->insts[ninst].x86.may_set)
need |= dyn->insts[ninst].x86.gen_flags; // forward the flags
// Consume X_PEND if relevant
if((need&X_PEND) && (dyn->insts[ninst].x86.set_flags&SF_PENDING))
need &=~X_PEND;
need |= dyn->insts[ninst].x86.use_flags;
if(dyn->insts[ninst].x86.need_before == need)
return ninst - 1;
dyn->insts[ninst].x86.need_before = need;
if(dyn->insts[ninst].x86.barrier&BARRIER_FLAGS) {
need = need?X_PEND:0;
}
int ok = 0;
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i) {
if(dyn->insts[ninst].pred[i] == ninst-1)
ok = 1;
else
updateNeed(dyn, dyn->insts[ninst].pred[i], need);
}
if(!ok)
return ninst - 1;
--ninst;
}
return ninst;
}
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);
@@ -273,20 +367,49 @@ void CancelBlock()
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->sons_x86);
free(helper->sons_arm);
if(helper->dynablock && helper->dynablock->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->block, helper->dynablock->size);
box_free(helper->next);
box_free(helper->insts);
box_free(helper->instsize);
box_free(helper->predecessor);
if(helper->dynablock && helper->dynablock->actual_block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->dynablock->actual_block, helper->dynablock->size);
else if(helper->dynablock && helper->block)
FreeDynarecMap(helper->dynablock, (uintptr_t)helper->block-sizeof(void*), helper->dynablock->size);
}
void* CreateEmptyBlock(dynablock_t* block, uintptr_t addr) {
block->isize = 0;
block->done = 0;
size_t sz = 4*sizeof(void*);
void* actual_p = (void*)AllocDynarecMap(block, sz);
void* p = actual_p + sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_INFO, "AllocDynarecMap(%p, %zu) failed, cancelling block\n", block, sz);
CancelBlock();
return NULL;
}
block->size = sz;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = p;
*(dynablock_t**)actual_p = block;
CreateJmpNextTo(block->jmpnext, arm_epilog);
block->need_test = 0;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
return block;
}
void* FillBlock(dynablock_t* block, uintptr_t addr) {
dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
dynarec_log(LOG_DEBUG, "Asked to fill a block in fobidden zone\n");
if(IsInHotPage(addr)) {
dynarec_log(LOG_DEBUG, "Cancelling dynarec FillBlock on hotpage for %p\n", (void*)addr);
return NULL;
}
if(addr>=box86_nodynarec_start && addr<box86_nodynarec_end) {
dynarec_log(LOG_INFO, "Create empty block in no-dynarec zone\n");
return CreateEmptyBlock(block, addr);
}
if(!isJumpTableDefault((void*)addr)) {
dynarec_log(LOG_DEBUG, "Asked to fill a block at %p, but JumpTable is not default\n", (void*)addr);
return NULL;
@@ -298,46 +421,29 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
helper.start = addr;
uintptr_t start = addr;
helper.cap = 64; // needs epilog handling
helper.insts = (instruction_arm_t*)calloc(helper.cap, sizeof(instruction_arm_t));
helper.insts = (instruction_arm_t*)box_calloc(helper.cap, sizeof(instruction_arm_t));
// pass 0, addresses, x86 jump addresses, overall size of the block
uintptr_t end = arm_pass0(&helper, addr);
// no need for next anymore
free(helper.next);
box_free(helper.next);
helper.next_sz = helper.next_cap = 0;
helper.next = NULL;
// basic checks
if(!helper.size) {
dynarec_log(LOG_DEBUG, "Warning, null-sized dynarec block (%p)\n", (void*)addr);
CancelBlock();
return (void*)block;
return CreateEmptyBlock(block, addr);
}
// 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);
// Compute flag_need, without taking into account any barriers
uint32_t last_need = X_PEND;
for(int i = helper.size; i-- > 0;) {
last_need |= helper.insts[i].x86.use_flags;
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
if (last_need == (X_PEND | X_ALL)) {
last_need = X_ALL;
}
helper.insts[i].x86.need_flags = last_need;
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
if (last_need & X_PEND) {
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
} else {
last_need &= ~helper.insts[i].x86.set_flags;
}
}
}
// calculate barriers
for(int i=0; i<helper.size; ++i)
if(helper.insts[i].x86.jmp) {
uintptr_t j = helper.insts[i].x86.jmp;
if(j<start || j>=end) {
helper.insts[i].x86.jmp_insts = -1;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
@@ -345,101 +451,61 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
if(helper.insts[i2].x86.addr==j)
k=i2;
}
if(k!=-1) // -1 if not found, mmm, probably wrong, exit anyway
helper.insts[k].x86.barrier = 1;
if(k!=-1 && !helper.insts[i].barrier_maybe)
helper.insts[k].x86.barrier |= BARRIER_FULL;
helper.insts[i].x86.jmp_insts = k;
}
}
// check for the optionnal barriers now
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].x86.barrier==3)
if(helper.insts[i].x86.jmp_insts == -1) {
if(i==helper.size-1 || helper.insts[i+1].x86.barrier)
helper.insts[i].x86.barrier=2; // nope, end of block or barrier just after
else
helper.insts[i].x86.barrier=0; // ok, no need for a barrier here after all
} else
helper.insts[i].x86.barrier=2;
}
// check to remove useless barrier, in case of jump when destination doesn't needs flags
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].x86.jmp
&& helper.insts[i].x86.jmp_insts>=0
&& helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1) {
int k = helper.insts[i].x86.jmp_insts;
//TODO: optimize FPU barrier too
if((!helper.insts[k].x86.need_flags)
||(helper.insts[k].x86.set_flags==X_ALL
&& helper.insts[k].x86.state_flags==SF_SET)
||(helper.insts[k].x86.state_flags==SF_SET_PENDING)) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Removed barrier for inst %d\n", k);
helper.insts[k].x86.barrier = 4; // remove barrier (keep FPU barrier, and still reset state flag)
}
}
}
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
for(int i = helper.size; i-- > 0;) {
if(helper.insts[i].x86.barrier==1)
// immediate barrier
helper.insts[i].x86.use_flags |= X_PEND;
else if(helper.insts[i].x86.jmp
&& helper.insts[i].x86.jmp_insts>=0
) {
if(helper.insts[helper.insts[i].x86.jmp_insts].x86.barrier==1)
// jumpto barrier
helper.insts[i].x86.use_flags |= X_PEND;
else
helper.insts[i].x86.use_flags |= helper.insts[helper.insts[i].x86.jmp_insts].x86.need_flags;
}
}
for(int i = helper.size; i-- > 0;)
helper.insts[i].x86.need_flags = 0;
last_need = X_PEND;
for(int i = helper.size; i-- > 0;) {
helper.insts[i].x86.need_flags = last_need;
if((helper.insts[i].x86.state_flags == SF_SUBSET) && (last_need&X_PEND))
last_need = (X_ALL & (~helper.insts[i].x86.set_flags) ) | helper.insts[i].x86.use_flags;
if ((helper.insts[i].x86.set_flags) && !(helper.insts[i].x86.state_flags & SF_MAYSET)) {
if (last_need & X_PEND) {
last_need = (~helper.insts[i].x86.set_flags) & X_ALL;
} else {
last_need &= ~helper.insts[i].x86.set_flags;
}
}
last_need |= helper.insts[i].x86.use_flags;
if (last_need == (X_PEND | X_ALL)) {
last_need = X_ALL;
}
}
// fill predecessors with the jump address
fillPredecessors(&helper);
// pass 1, float optimisations
int pos = helper.size;
while (pos>=0)
pos = updateNeed(&helper, pos, 0);
// pass 1, float optimisations, first pass for flags
arm_pass1(&helper, addr);
// pass 2, instruction size
arm_pass2(&helper, addr);
// ok, now allocate mapped memory, with executable flag on
int sz = helper.arm_size;
void* p = (void*)AllocDynarecMap(block, sz);
if(p==NULL) {
// keep size of instructions for signal handling
size_t insts_ursize = 0;
{
size_t insts_size = 0;
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
helper.instsize = (instsize_t*)box_calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
helper.instsize = addInst(helper.instsize, &insts_size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
helper.instsize = addInst(helper.instsize, &insts_size, &cap, 0, 0); // add a "end of block" mark, just in case
insts_ursize = insts_size*sizeof(instsize_t);
}
size_t insts_rsize = (insts_ursize+7)&~7; // round the size...
size_t sz = sizeof(void*) + helper.arm_size + 4*sizeof(void*) + insts_rsize;
// dynablock_t* block (arm insts) jmpnext code instsize
void* actual_p = (void*)AllocDynarecMap(block, sz);
void* p = actual_p + sizeof(void*);
void* next = p + helper.arm_size;
void* instsize = next + 4*sizeof(void*);
if(actual_p==NULL) {
dynarec_log(LOG_DEBUG, "AllocDynarecMap(%p, %d) failed, cancelling block\n", block, sz);
CancelBlock();
return NULL;
}
helper.block = p;
helper.arm_start = (uintptr_t)p;
if(helper.sons_size) {
helper.sons_x86 = (uintptr_t*)calloc(helper.sons_size, sizeof(uintptr_t));
helper.sons_arm = (void**)calloc(helper.sons_size, sizeof(void*));
}
*(dynablock_t**)actual_p = block;
// pass 3, emit (log emit arm opcode)
if(box86_dynarec_dump) {
dynarec_log(LOG_NONE, "%s%04d|Emitting %d bytes for %d x86 bytes", (box86_dynarec_dump>1)?"\e[01;36m":"", GetTID(), helper.arm_size, helper.isize);
printFunctionAddr(helper.start, " => ");
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":"");
}
size_t oldarmsize = helper.arm_size;
helper.arm_size = 0;
arm_pass3(&helper, addr);
if(sz!=helper.arm_size) {
if(oldarmsize!=helper.arm_size) {
printf_log(LOG_NONE, "BOX86: Warning, size difference in block between pass2 (%d) & pass3 (%d)!\n", sz, helper.arm_size);
uint8_t *dump = (uint8_t*)helper.start;
printf_log(LOG_NONE, "Dump of %d x86 opcodes:\n", helper.size);
@@ -451,32 +517,32 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
printf_log(LOG_NONE, " ------------\n");
}
// all done...
__clear_cache(p, p+sz); // need to clear the cache before execution...
// keep size of instructions for signal handling
{
size_t cap = 1;
for(int i=0; i<helper.size; ++i)
cap += 1 + ((helper.insts[i].x86.size>helper.insts[i].size)?helper.insts[i].x86.size:helper.insts[i].size)/15;
size_t size = 0;
block->instsize = (instsize_t*)calloc(cap, sizeof(instsize_t));
for(int i=0; i<helper.size; ++i)
block->instsize = addInst(block->instsize, &size, &cap, helper.insts[i].x86.size, helper.insts[i].size/4);
block->instsize = addInst(block->instsize, &size, &cap, 0, 0); // add a "end of block" mark, just in case
}
memcpy(instsize, helper.instsize, insts_ursize);
block->instsize = instsize;
// ok, free the helper now
free(helper.insts);
box_free(helper.insts);
helper.insts = NULL;
free(helper.next);
box_free(helper.next);
helper.next = NULL;
box_free(helper.instsize);
helper.instsize = NULL;
box_free(helper.predecessor);
helper.predecessor = NULL;
block->size = sz;
block->isize = helper.size;
block->actual_block = actual_p;
block->block = p;
block->jmpnext = next+sizeof(void*);
*(dynablock_t**)next = block;
CreateJmpNextTo(block->jmpnext, arm_next);
block->need_test = 0;
//block->x86_addr = (void*)start;
block->x86_size = end-start;
if(box86_dynarec_largest<block->x86_size)
box86_dynarec_largest = block->x86_size;
// all done...
__clear_cache(actual_p, actual_p+sz); // need to clear the cache before execution...
block->hash = X31_hash_code(block->x86_addr, block->x86_size);
// Check if something changed, to abbort if it as
if(block->hash != hash) {
@@ -484,37 +550,7 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
CancelBlock();
return NULL;
}
// fill sons if any
dynablock_t** sons = NULL;
int sons_size = 0;
if(helper.sons_size) {
sons = (dynablock_t**)calloc(helper.sons_size, sizeof(dynablock_t*));
for (int i=0; i<helper.sons_size; ++i) {
int created = 1;
dynablock_t *son = AddNewDynablock(block->parent, helper.sons_x86[i], &created);
if(created) { // avoid breaking a working block!
son->block = helper.sons_arm[i];
son->x86_addr = (void*)helper.sons_x86[i];
son->x86_size = end-helper.sons_x86[i];
if(!son->x86_size) {printf_log(LOG_NONE, "Warning, son with null x86 size! (@%p / ARM=%p)", son->x86_addr, son->block);}
son->father = block;
son->done = 1;
sons[sons_size++] = son;
if(!son->parent)
son->parent = block->parent;
}
}
if(sons_size) {
block->sons = sons;
block->sons_size = sons_size;
} else
free(sons);
}
free(helper.sons_x86);
helper.sons_x86 = NULL;
free(helper.sons_arm);
helper.sons_arm = NULL;
current_helper = NULL;
block->done = 1;
return (void*)block;
}
}
+208 -132
View File
@@ -5,6 +5,7 @@
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#include "debug.h"
#include "box86context.h"
@@ -21,6 +22,7 @@
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "custommem.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
@@ -36,12 +38,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uint32_t u32;
uint8_t wback, wb1, wb2;
int fixedaddress;
int lock;
int cacheupd;
opcode = F8;
MAYUSE(eb1);
MAYUSE(eb2);
MAYUSE(tmp);
MAYUSE(j32);
MAYUSE(lock);
MAYUSE(cacheupd);
switch(opcode) {
case 0x00:
@@ -340,7 +346,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x27:
INST_NAME("DAA");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DAA\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTB(x1, xEAX, 0);
@@ -402,7 +408,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x2F:
INST_NAME("DAS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DAS\n");
READFLAGS(X_AF|X_CF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTB(x1, xEAX, 0);
@@ -464,7 +470,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x37:
INST_NAME("AAA");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization AAA\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTH(x1, xEAX, 0);
@@ -532,7 +538,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0x3F:
INST_NAME("AAS");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization AAS\n");
READFLAGS(X_AF);
SETFLAGS(X_AF|X_CF|X_PF|X_SF|X_ZF, SF_SET);
UXTH(x1, xEAX, 0);
@@ -548,7 +554,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x46:
case 0x47:
INST_NAME("INC reg");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&0x07);
emit_inc32(dyn, ninst, gd, x3, x14);
break;
@@ -561,7 +567,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x4E:
case 0x4F:
INST_NAME("DEC reg");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&0x07);
emit_dec32(dyn, ninst, gd, x3, x14);
break;
@@ -575,7 +581,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x57:
INST_NAME("PUSH reg");
gd = xEAX+(opcode&0x07);
#ifdef RPI2
if(gd==xESP) {
MOV_REG(x1, gd);
PUSH1(x1);
} else {
PUSH1(gd);
}
#else
PUSH1(gd);
#endif
break;
case 0x58:
case 0x59:
@@ -587,7 +602,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x5F:
INST_NAME("POP reg");
gd = xEAX+(opcode&0x07);
#ifdef RPI2
if(gd==xESP) {
POP1(x1);
MOV_REG(gd, x1);
} else {
POP1(gd);
}
#else
POP1(gd);
#endif
break;
case 0x60:
INST_NAME("PUSHAD");
@@ -691,24 +715,29 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F|(dyn->insts[ninst].x86.barrier?0:X_PEND)); \
READFLAGS(F); \
i8 = F8S; \
BARRIER(3); \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8);\
Bcond(NO, i32); \
if(!dyn->insts[ninst].x86.barrier) \
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0x70:
@@ -987,7 +1016,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETGB(x14);
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
// do the swap with exclusive locking
LDREXB(x1, ed);
@@ -1013,7 +1042,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETGD;
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(ed, 3);
B_MARK(cNE);
@@ -1058,8 +1087,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = ((ed&4)>>2); // L or H
BFI(eb1, gd, eb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STRB_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
case 0x89:
@@ -1069,8 +1099,9 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
STR_IMM9(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
case 0x8A:
@@ -1094,7 +1125,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, &lock);
if(lock) {DMB_ISH();}
LDRB_IMM9(x14, wback, fixedaddress);
ed = x14;
}
@@ -1107,11 +1139,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
if(box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier))) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
if(lock || (box86_dynarec_strongmem &&
(dyn->insts[ninst].x86.barrier || !ninst || (box86_dynarec_strongmem>1) || (ninst && dyn->insts[ninst-1].x86.barrier)))) {
DMB_ISH();
}
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
LDR_IMM9(gd, ed, fixedaddress);
}
break;
@@ -1122,7 +1154,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= seg
LDRH_REG(xEAX+(nextop&7), xEmu, x3);
} else { // mem <= seg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDRH_REG(x3, xEmu, x3);
STRH_IMM8(x3, ed, fixedaddress);
}
@@ -1134,7 +1166,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg? that's an invalid operation
DEFAULT;
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, gd, &fixedaddress, 0, 0, 0, NULL);
if(gd!=ed) { // it's sometimes used as a 3 bytes NOP
MOV_REG(gd, ed);
}
@@ -1146,7 +1178,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
ed = x1;
}
@@ -1167,7 +1199,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
POP1(xEAX+(nextop&7));
} else {
POP1(x2); // so this can handle POP [ESP] and maybe some variant too
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
if(ed==xESP) {
STR_IMM9(x2, ed, fixedaddress);
} else {
@@ -1377,7 +1409,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Eb, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
u8 = F8;
emit_rol8c(dyn, ninst, x1, u8&0x1f, x2, x14);
@@ -1385,7 +1417,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("ROR Eb, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
u8 = F8;
emit_ror8c(dyn, ninst, x1, u8&0x1f, x2, x14);
@@ -1393,7 +1425,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
@@ -1404,7 +1436,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
INST_NAME("RCR Eb, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
@@ -1467,7 +1499,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
u8 = (F8)&0x1f;
emit_rol32c(dyn, ninst, ed, u8, x3, x14);
@@ -1475,7 +1507,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1:
INST_NAME("ROR Ed, Ib");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
u8 = (F8)&0x1f;
emit_ror32c(dyn, ninst, ed, u8, x3, x14);
@@ -1483,14 +1515,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Ed, Ib");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
GETEDW(x14, x1);
u8 = F8;
MOVW(x2, u8);
CALL_(rcl32, ed, (1<<x14));
WBACK;
WBACK; // no SBACK here because ret value is ed directly
break;
case 3:
INST_NAME("RCR Ed, Ib");
@@ -1498,7 +1530,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEDW(x14, x1);
u8 = F8&0x1f;
if(u8==1) {
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
MOVW(x3, u8);
@@ -1521,13 +1553,13 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFC_COND(cCC, xFlags, F_CF, 1);
}
WBACK;
WBACK; // no SBACK here because ed has been used all along and not x1
} else if(u8>1) {
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, u8);
CALL_(rcr32, ed, (1<<x14));
WBACK;
WBACK; // no SBACK here because ret value is ed directly
}
break;
case 4:
@@ -1564,8 +1596,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xC2:
INST_NAME("RETN");
//SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
READFLAGS(X_PEND); // lets play safe here too
BARRIER(2);
if(box86_dynarec_safeflags) {
READFLAGS(X_PEND); // lets play safe here too
}
BARRIER(BARRIER_FLOAT);
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
*need_epilog = 0;
@@ -1575,8 +1609,10 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("RET");
// SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
// ^^^ that hack break PlantsVsZombies and GOG Setup under wine....
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
BARRIER(2);
if(box86_dynarec_safeflags) {
READFLAGS(X_PEND); // so instead, force the defered flags, so it's not too slow, and flags are not lost
}
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -1593,10 +1629,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x3, u8);
BFI(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, &lock);
u8 = F8;
MOVW(x3, u8);
STRB_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
case 0xC7:
@@ -1607,10 +1644,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, &lock);
i32 = F32S;
MOV32(x3, i32);
STR_IMM9(x3, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
@@ -1624,7 +1662,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET); // Hack, set all flags (to an unknown state...)
if(PK(0)=='S' && PK(1)=='C') {
addr+=2;
BARRIER(2);
BARRIER(BARRIER_FLOAT);
INST_NAME("Special Box86 instruction");
if((PK(0)==0) && (PK(1)==0) && (PK(2)==0) && (PK(3)==0))
{
@@ -1639,7 +1677,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
x87_forget(dyn, ninst, x3, x14, 0);
if(box86_log<2) { // call the wrapper directly
if((box86_log<2) && !cycle_log) { // call the wrapper directly
uintptr_t ncall[2]; // to avoid BUSERROR!!!
memcpy(ncall, (void*)addr, 2*sizeof(void*)); // the wrapper + function
addr+=8;
@@ -1684,7 +1722,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(PK(0)==0x80) {
INST_NAME("Syscall");
u8 = F8;
BARRIER(2);
BARRIER(BARRIER_FLOAT);
MOV32(xEIP, ip+2);
STM(xEmu, (1<<xEAX)|(1<<xEBX)|(1<<xECX)|(1<<xEDX)|(1<<xESI)|(1<<xEDI)|(1<<xESP)|(1<<xEBP)|(1<<xEIP)|(1<<xFlags));
CALL_S(x86Syscall, -1, 0);
@@ -1706,7 +1744,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("IRET");
SETFLAGS(X_ALL, SF_SET); // Not a hack, EFLAGS are restored
BARRIER(2);
BARRIER(BARRIER_FLOAT);
iret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -1718,14 +1756,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
if(opcode==0xD0) {
INST_NAME("ROL Eb, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_rol8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
} else {
INST_NAME("ROL Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization ROL 8b\n");
SETFLAGS(X_OF|X_CF, SF_SET);
GETEB(x1);
CALL_(rol8, x1, (1<<x3));
@@ -1736,7 +1774,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if(opcode==0xD0) {
INST_NAME("ROR Eb, 1");
MOVW(x2, 1);
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_ror8c(dyn, ninst, ed, 1, x2, x14);
EBBACK;
@@ -1744,7 +1782,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("ROR Eb, CL");
AND_IMM8(x2, xECX, 0x1f);
SETFLAGS(X_OF|X_CF, SF_SET);
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization ROR 8b\n");
GETEB(x1);
CALL_(ror8, x1, (1<<x3));
EBBACK;
@@ -1752,7 +1790,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
if(opcode==0xD0) {INST_NAME("RCL Eb, 1");} else {INST_NAME("RCL Eb, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
@@ -1762,7 +1800,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 3:
if(opcode==0xD0) {INST_NAME("RCR Eb, 1");} else {INST_NAME("RCR Eb, CL");}
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR 8b\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
if(opcode==0xD0) {MOVW(x2, 1);} else {AND_IMM8(x2, xECX, 0x1f);}
@@ -1826,36 +1864,55 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 2:
INST_NAME("RCL Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
WBACK;
WBACK; // no SBACK here because ret value is ed directly
break;
case 3:
INST_NAME("RCR Ed, 1");
MESSAGE(LOG_DUMP, "Need Optimization\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
MOVW(x2, 1);
GETEDW(x14, x1);
CALL_(rcr32, ed, (1<<x14));
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETED;
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, op1));
MOVW(x3, 1);
STR_IMM9(x3, xEmu, offsetof(x86emu_t, op2));
SET_DF(x3, d_rcr32);
} else IFX(X_ALL) {
SET_DFNONE(x3);
}
IFX(X_OF) {
XOR_REG_LSR_IMM8(x3, xFlags, ed, 31);
BFI(xFlags, x3, F_OF, 1);
}
MOVS_REG_LSR_IMM5(x3, xFlags, 1); // load CC (F_CF==0) into ARM CF
MOVS_REG_RRX(ed, ed);
IFX(X_PEND) {
STR_IMM9(ed, xEmu, offsetof(x86emu_t, res));
}
IFX(X_CF) {
ORR_IMM8_COND(cCS, xFlags, xFlags, 1, 0);
BFC_COND(cCC, xFlags, F_CF, 1);
}
WBACK;
break;
case 4:
@@ -1931,23 +1988,23 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2:
INST_NAME("RCL Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCL\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcl32, ed, (1<<x14));
WBACK;
WBACK; // no SBACK here because ret value is ed directly
break;
case 3:
INST_NAME("RCR Ed, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization RCR\n");
READFLAGS(X_CF);
SETFLAGS(X_OF|X_CF, SF_SET);
AND_IMM8(x2, xECX, 0x1f);
GETEDW(x14, x1);
CALL_(rcr32, ed, (1<<x14));
WBACK;
WBACK; // no SBACK here because ret value is ed directly
break;
case 4:
case 6:
@@ -2035,20 +2092,27 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
addr = dynarecDF(dyn, addr, ip, ninst, ok, need_epilog);
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8, 1); \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ");
@@ -2094,7 +2158,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#if STEP < 2
if (i32==0)
tmp = dyn->insts[ninst].pass2choice = 1;
else if (((u32)>0x10000) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
else if ((getProtection(u32)&PROT_READ) && (PKa(u32+0)==0x8B) && (((PKa(u32+1))&0xC7)==0x04) && (PKa(u32+2)==0x24) && (PKa(u32+3)==0xC3))
tmp = dyn->insts[ninst].pass2choice = 2;
/*else if(isNativeCall(dyn, u32, &dyn->insts[ninst].natcall, &dyn->insts[ninst].retn))
tmp = dyn->insts[ninst].pass2choice = 3;*/
@@ -2120,14 +2184,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// disabling this to avoid fetching data outside current block (in case this part changed, this block will not been marck as dirty)
/*case 3:
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(1);
BARRIER_NEXT(1);
BARRIER(BARRIER_FULL);
BARRIER_NEXT(BARRIER_FULL);
MOV32(x2, addr);
PUSH1(x2);
MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
// calling a native function
x87_forget(dyn, ninst, x3, x14, 0);
if(box86_log<2 && dyn->insts[ninst].natcall) { // call the wrapper directly
if((box86_log<2) && !cycle_log && dyn->insts[ninst].natcall) { // call the wrapper directly
uintptr_t ncall[2];
memcpy(ncall, (void*)(dyn->insts[ninst].natcall+2), 2*sizeof(void*)); // the wrapper + function
MOV32(xEIP, dyn->insts[ninst].natcall+2+4+4);
@@ -2159,18 +2223,16 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
jump_to_epilog(dyn, 0, xEIP, ninst);
break;*/
default:
if(ninst && dyn->insts[ninst-1].x86.set_flags) {
if((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags)) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
//SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
// regular call
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst==dyn->size-1) {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
if(u32==0) { // self modifying code maybe? so use indirect address fetching
@@ -2184,7 +2246,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xE9:
case 0xEB:
BARRIER(1);
BARRIER(BARRIER_MAYBE);
if(opcode==0xE9) {
INST_NAME("JMP Id");
i32 = F32S;
@@ -2193,18 +2255,18 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
i32 = F8S;
}
JUMP(addr+i32, 0);
if(dyn->insts) {
PASS2IF(dyn->insts[ninst].x86.jmp_insts==-1, 1) {
// out of the block
jump_to_next(dyn, addr+i32, 0, ninst);
if(dyn->insts[ninst].x86.jmp_insts==-1) {
// out of the block
fpu_purgecache(dyn, ninst, 1, x1, x2, x3);
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
CacheTransform(dyn, ninst, CHECK_CACHE(), x1, x2, x3);
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
if(tmp==-4) {
NOP;
} else {
// inside the block
tmp = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);
if(tmp==-4) {
NOP;
} else {
Bcond(c__, tmp);
}
Bcond(c__, tmp);
}
}
*need_epilog = 0;
@@ -2255,7 +2317,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xAF:
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3, 2);
@@ -2314,8 +2377,12 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC3:
INST_NAME("(REPZ) RET");
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
BARRIER(2);
if(box86_dynarec_safeflags>1) {
READFLAGS(X_PEND);
} else {
SETFLAGS(X_ALL, SF_SET); // Hack to set flags to "dont'care" state
}
BARRIER(BARRIER_FLOAT);
ret_to_epilog(dyn, ninst);
*need_epilog = 0;
*ok = 0;
@@ -2346,7 +2413,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xA6:
if(opcode==0xF2) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,1);
@@ -2370,7 +2438,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xA7:
if(opcode==0xF2) {INST_NAME("REPNZ CMPSD");} else {INST_NAME("REPZ CMPSD");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,4);
@@ -2435,7 +2504,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xAE:
if(opcode==0xF2) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,1);
@@ -2459,7 +2529,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xAF:
if(opcode==0xF2) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3,4);
@@ -2537,7 +2608,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("IMUL AL, Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization IMUL 8b\n");
SETFLAGS(X_ALL, SF_PENDING);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2546,7 +2617,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 6:
INST_NAME("DIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization DIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2555,7 +2626,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("IDIV Eb");
MESSAGE(LOG_DUMP, "Need Optimization\n");
MESSAGE(LOG_DUMP, "Need Optimization IDIV 8b\n");
SETFLAGS(X_ALL, SF_SET);
GETEB(x1);
STM(xEmu, (1<<xEAX));
@@ -2612,7 +2683,8 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SETFLAGS(X_ALL, SF_SET);
if(arm_div && ninst && dyn->insts
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
&& (*(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x31
|| *(uint8_t*)(dyn->insts[ninst-1].x86.addr)==0x33)
&& *(uint8_t*)(dyn->insts[ninst-1].x86.addr+1)==0xD2) {
// previous instruction is XOR EDX, EDX, so its 32bits / 32bits
SET_DFNONE(x2); // flags are undefined
@@ -2655,9 +2727,15 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETEDH(x1);
if(arm_div) {
// check if a 32bits division is enough
CMPS_IMM8(xEDX, 0); // compare to 0
CMNS_IMM8_COND(cNE, xEDX, 1); // compare to FFFFFFFF if not 0
TSTS_IMM8_ROR_COND(cEQ, xEAX, 0b10, 1); // also test that xEAX is not signed!
B_MARK(cEQ);
CMNS_IMM8(xEDX, 1); // compare to FFFFFFFF if not 0
B_MARK2(cNE);
TSTS_IMM8_ROR(xEAX, 0b10, 1); // also test that xEAX is signed!
B_MARK(cNE);
MARK2;
}
if(ed!=x1) {MOV_REG(x1, ed);}
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
@@ -2711,14 +2789,14 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_inc8(dyn, ninst, x1, x2, x14);
EBBACK;
break;
case 1:
INST_NAME("DEC Eb");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEB(x1);
emit_dec8(dyn, ninst, x1, x2, x14);
EBBACK;
@@ -2733,39 +2811,37 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETED;
emit_inc32(dyn, ninst, ed, x3, x14);
WBACK;
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETED;
emit_dec32(dyn, ninst, ed, x3, x14);
WBACK;
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(ninst && dyn->insts[ninst-1].x86.set_flags, 1) {
PASS2IF((box86_dynarec_safeflags>1) || (ninst && dyn->insts[ninst-1].x86.set_flags), 1) {
READFLAGS(X_PEND); // that's suspicious
} else {
SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
//SETFLAGS(X_ALL, SF_SET); //Hack to put flag in "don't care" state
}
GETEDH(xEIP);
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst==dyn->size-1) {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FLOAT);
//BARRIER_NEXT(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
jump_to_next(dyn, 0, ed, ninst);
break;
case 4: // JMP Ed
INST_NAME("JMP Ed");
BARRIER(1);
BARRIER(BARRIER_FULL);
GETEDH(xEIP);
jump_to_next(dyn, 0, ed, ninst);
*need_epilog = 0;
+355 -173
View File
@@ -31,7 +31,7 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_64(a, ed); \
}
@@ -42,7 +42,7 @@
if((nextop&0xC0)==0xC0) { \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_double(dyn); \
VLD1_64(a, ed); \
}
@@ -66,6 +66,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int s0;
int fixedaddress;
int parity;
int cacheupd;
MAYUSE(s0);
MAYUSE(q1);
MAYUSE(v2);
@@ -75,6 +76,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(eb1);
MAYUSE(wb2);
MAYUSE(j32);
MAYUSE(cacheupd);
#if STEP == 3
static const int8_t mask_shift8[] = { -7, -6, -5, -4, -3, -2, -1, 0 };
#endif
@@ -87,6 +89,20 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
//CALL(arm_ud, -1, 0);
UDF(0);
break;
case 0x0D:
nextop = F8;
switch((nextop>>3)&7) {
case 1:
INST_NAME("PREFETCHW");
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
addr = fakeed(dyn,addr, ninst, nextop);
// should use PLDW, but it's not available on cortex-a8 for example
break;
default:
DEFAULT;
}
break;
case 0x10:
INST_NAME("MOVUPS Gx,Ex");
nextop = F8;
@@ -97,7 +113,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
//LDRD also have alignment requirements
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
@@ -116,7 +132,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-16, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-16, 0, 0, NULL);
VMOVfrV_D(x2, x3, v0);
// cannot use STRD, this needs alignement too
STR_IMM9(x2, ed, fixedaddress+0);
@@ -136,7 +152,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("MOVLPS Gx,Ex");
GETGX(v0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -152,12 +168,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1_32(v0, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -196,7 +212,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
INST_NAME("MOVHPS Gx,Ex");
GETGX(v0, 1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0+1, ed);
}
break;
@@ -210,12 +226,12 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1_64(v0+1, ed); // better to use VST1 than VSTR_64, to avoid NEON->VFPU transfert I assume
} else {
VMOVfrV_D(x2, x3, v0+1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -232,7 +248,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 2:
case 3:
INST_NAME("PREFETCHh Ed");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xffff, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xffff, 0, 0, NULL);
MOVW(x3, fixedaddress);
if(fixedaddress<0) {
PLDn(ed, x3);
@@ -262,7 +278,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
}
break;
@@ -275,7 +291,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
}
break;
@@ -287,7 +303,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
}
@@ -302,7 +318,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
}
break;
@@ -314,7 +330,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
}
@@ -328,7 +344,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_double(dyn);
VLD1_32(v1, ed);
}
@@ -370,7 +386,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
parity = getedparity(dyn, ninst, addr, nextop, 2);
s0 = fpu_get_scratch_single(dyn);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -428,11 +444,60 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEM(d1);
VQRDMULH_S16(d0, d0, d1);
break;
case 0xF0:
INST_NAME("MOVBE Gd, Ed");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
REV(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(gd, ed, fixedaddress);
REV(gd, gd);
}
break;
case 0xF1:
INST_NAME("MOVBE Ed, Gd");
nextop=F8;
GETGD;
if((nextop&0xC0)==0xC0) { // reg <= reg
REV(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
REV(x1, gd);
STR_IMM9(gd, ed, fixedaddress);
}
break;
default:
DEFAULT;
}
break;
case 0x3A: // these are some more SSSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x0F:
INST_NAME("PALIGNR Gm, Em, Ib");
nextop = F8;
GETGM(q0);
GETEM(q1);
u8 = F8;
if(u8>15) {
VEOR(q0, q0, q0);
} else if(u8>7) {
d0 = fpu_get_scratch_quad(dyn);
VEOR(d0, d0, d0);
VEXT_8(q0, q0, d0, u8-8);
} else {
VEXT_8(q0, q1, q0, u8);
}
break;
default:
DEFAULT;
}
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F); \
@@ -443,7 +508,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7); \
MOV_REG_COND(YES, gd, ed); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9_COND(YES, gd, ed, fixedaddress); \
}
@@ -555,7 +620,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gd, x3, 3, 1);
} else {
// EX is memory
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4096-16, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4096-16, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
UBFX(x3, x2, 31, 1);
BFI(gd, x3, 0, 1);
@@ -577,23 +642,37 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
v2 = fpu_get_scratch_quad(dyn);
#if 0
VRSQRTEQ_F32(v2, q0);
//step?
VRECPEQ_F32(v0, v2);
//step?
#else
// more precise
if(v0==q0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
VRSQRTEQ_F32(v2, q0);
VMULQ_F32(v1, v2, q0);
VRSQRTSQ_F32(v1, v1, v2);
VMULQ_F32(v1, v1, v2);
VMULQ_F32(v0, v1, q0);
#endif
v1 = fpu_get_scratch_quad(dyn);
// Newton-Raphson: Xn+1 = Xn*(3-d*Xn²)/2 converge to 1/sqrt(d) with X0 = result of VSQRTE
// and VSQRTS is (3-A*B)/2
// so VSQRTE(d) -> X is initial step
// VSQRTS(d,X*X)*X -> X loop
// than d*X -> SQRT(d) (because X ~ 1/sqrt(d))
VRSQRTEQ_F32(v2, q0); // v2 = X0 (=X), q0 = d
VMULQ_F32(v1, v2, v2); // v1 = X0²
VRSQRTSQ_F32(v1, v1, q0); // v1 = (3-d*X0²)/2
VMULQ_F32(v2, v2, v1); // v2 = X0*(3-d*X0²)/2 = X1
VMULQ_F32(v1, v2, v2); // v1 = x1²
VRSQRTSQ_F32(v1, v1, q0); // v1 = (3-d*X1²)/2
VMULQ_F32(v2, v2, v1); // v2 = X1*(3-d*X1²)/2 = X2
if(!box86_dynarec_fastnan) {
// need to preserve v0, in case it's == q0
VMULQ_F32(v1, v2, q0); // v1 = X2*d ~ SQRT(d)
if(v0<dyn->n.fpu_scratch || v0!=q0)
q1 = v0; // v0 is a scratch register
else
q1 = fpu_get_scratch_quad(dyn); // need a new scratch
VCEQQ_0_F32(q1, q0); // prepare mask, 111 when == 0.0
VMOVQ_H32(v2, 0xff); // prepare +inf
VSHRQ_U32(v2, v2, 1); // 0xff000000 -> 0x7f800000 == +inf
VCEQQ_32(v2, v2, q0); // v2 mask: 111 when == +inf
VORRQ(q1, q1, v2); // q1 mask: 111 when ==0 || == +inf
VBICQ(v1, v1, q1); // mask value in result
VANDQ(q1, q0, q1); // keep original value that are 0 or +inf
VORRQ(v0, v1, q1); // copy over
} else {
VMULQ_F32(v0, v2, q0); // v0 = X2*d ~ SQRT(d)
}
break;
case 0x52:
INST_NAME("RSQRTPS Gx, Ex");
@@ -601,21 +680,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
#if 0
VRSQRTEQ_F32(v0, q0);
//step?
#else
v2 = fpu_get_scratch_quad(dyn);
// more precise
if(v0==q0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
VRSQRTEQ_F32(v2, q0);
VMULQ_F32(v1, v2, q0);
VRSQRTSQ_F32(v1, v1, v2);
VMULQ_F32(v0, v1, v2);
#endif
break;
case 0x53:
INST_NAME("RCPPS Gx, Ex");
@@ -623,14 +688,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
GETEX(q0, 0);
gd = (nextop&0x38)>>3;
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(q0 == v0)
v1 = fpu_get_scratch_quad(dyn);
else
v1 = v0;
v2 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v2, q0);
VRECPSQ_F32(v1, v2, q0);
VMULQ_F32(v0, v2, v1);
VRECPEQ_F32(v0, q0);
break;
case 0x54:
INST_NAME("ANDPS Gx, Ex");
@@ -719,16 +777,19 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x5E:
INST_NAME("DIVPS Gx, Ex");
nextop = F8;
GETEX(v1, 0);
GETGX(v0, 1);
q0 = fpu_get_scratch_quad(dyn);
q1 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(q0, v1);
VRECPSQ_F32(q1, q0, v1);
VMULQ_F32(q0, q0, q1);
VRECPSQ_F32(q1, q0, v1);
VMULQ_F32(q0, q0, q1);
VMULQ_F32(v0, v0, q0);
GETEX(q0, 0);
GETGX(q1, 1);
// use Gx * 1/Ex, using RECP
// Newton-Raphson: Xn+1 = Xn*(2-d*Xn) converge to 1/d if X0 if result of VRECPE(d)
// VRECPE is 2-A*B
v1 = fpu_get_scratch_quad(dyn);
v2 = fpu_get_scratch_quad(dyn);
VRECPEQ_F32(v2, q0); // v2 = X0, q0 = d
VRECPSQ_F32(v1, q0, v2); // v1 = 2-d*X0
VMULQ_F32(v2, v2, v1); // v2 = X0*(2-d*X0) = X1
VRECPSQ_F32(v1, q0, v2); // v1 = 2-d*X1
VMULQ_F32(v2, v2, v1); // v2 = X1*(2-d*X1) = X2 ~ 1/d
VMULQ_F32(q1, q1, v2);
break;
case 0x5F:
INST_NAME("MAXPS Gx, Ex");
@@ -810,7 +871,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
VMOVD(q0+1, d1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(q0+1, ed);
}
VMOVD(q0, d0);
@@ -857,9 +918,13 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
nextop = F8;
GETGM(v0);
GETEM(v1);
q0 = fpu_get_scratch_quad(dyn);
VMOVD(q0+0, v0);
VMOVD(q0+1, v1);
if(!(v0&1) && (v1==(v0+1))) {
q0 = v0; // no need to move the regs...
} else {
q0 = fpu_get_scratch_quad(dyn);
VMOVD(q0+0, v0);
VMOVD(q0+1, v1);
}
VQMOVN_S32(v0, q0);
break;
@@ -882,7 +947,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVD(v0, v1);
} else {
v0 = mmx_get_reg_empty(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0, ed);
}
break;
@@ -916,7 +981,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
ADD_IMM8(xSP, xSP, 4);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
if (u8) {
for (int i=0; i<4; ++i) {
@@ -940,7 +1005,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
}
@@ -961,7 +1026,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
}
@@ -978,7 +1043,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
d0 = mmx_get_reg(dyn, ninst, x1, x2, x3, nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
d0 = fpu_get_scratch_quad(dyn);
VLD1_16(d0, ed);
}
@@ -1104,7 +1169,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOVfrDx_32(ed, v0, 0);
} else {
VMOVfrDx_32(x2, v0, 0); // there can be some bus error is storing the VFPU reg directly
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
}
break;
@@ -1118,11 +1183,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v0, ed, fixedaddress);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -1130,24 +1195,29 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
#define GO(GETFLAGS, NO, YES, F) \
READFLAGS(F|(dyn->insts[ninst].x86.barrier?0:X_PEND)); \
i32_ = F32S; \
BARRIER(3); \
JUMP(addr+i32_, 1); \
GETFLAGS; \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8);\
Bcond(NO, i32); \
if(!dyn->insts[ninst].x86.barrier) \
READFLAGS(F); \
i32_ = F32S; \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i32_, 1); \
GETFLAGS; \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i32_, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0x80:
@@ -1249,7 +1319,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = ((ed&4)>>2); \
BFI(eb1, x3, eb2*8, 8); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);\
STRB_IMM9(x3, ed, fixedaddress); \
}
@@ -1373,7 +1443,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x1, ed, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x1, fixedaddress);
@@ -1396,13 +1466,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xA5:
nextop = F8;
INST_NAME("SHLD Ed, Gd, CL");
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET_PENDING);
UXTB(x3, xECX, 0);
GETEDW(x14, x1);
SETFLAGS(X_ALL, SF_SET);
AND_IMM8(x3, xECX, 0x1f);
GETED;
GETGD;
MOV_REG(x2, gd);
CALL(shld32, ed, (wback?(1<<wback):0));
emit_shld32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
@@ -1431,7 +1499,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
@@ -1495,7 +1563,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fxsave, -1, 0);
}
@@ -1507,7 +1575,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
DEFAULT;
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fxrstor, -1, 0);
}
@@ -1523,7 +1591,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
LDR_IMM9(ed, xEmu, offsetof(x86emu_t, mxcsr));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, mxcsr));
STR_IMM9(x14, ed, fixedaddress);
}
@@ -1606,7 +1674,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
wback = x3;
@@ -1638,7 +1706,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = (ed&4)>>2; // L or H
UXTB(gd, eb1, eb2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(gd, ed, fixedaddress);
}
break;
@@ -1650,7 +1718,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
UXTH(gd, ed, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(gd, ed, fixedaddress);
}
break;
@@ -1666,7 +1734,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
}
@@ -1686,7 +1754,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
}
@@ -1716,7 +1784,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
}
@@ -1746,7 +1814,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress);
ed = x1;
}
@@ -1784,7 +1852,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
LDR_IMM9(x1, x3, fixedaddress);
@@ -1856,7 +1924,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
eb2 = (ed&4)>>2; // L or H
SXTB(gd, eb1, eb2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(gd, ed, fixedaddress);
}
break;
@@ -1868,7 +1936,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
SXTH(gd, ed, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSH_IMM8(gd, ed, fixedaddress);
}
break;
@@ -1935,7 +2003,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd); // doesn't exist
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(gd, ed, fixedaddress);
}
break;
@@ -1948,7 +2016,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
VMOVtoDx_16(d0, u8, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&3;
VLD1LANE_16(d0, wback, u8);
}
@@ -1962,7 +2030,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
u8 = (F8)&3;
VMOVfrDx_U16(gd, d0, u8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-8, 0, 0, NULL);
u8 = (F8)&3;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
}
@@ -1971,68 +2039,182 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("SHUFPS Gx, Ex, Ib");
nextop = F8;
i32 = -1;
j32 = 0;
GETGX(v0, 1);
q0 = fpu_get_scratch_quad(dyn); // temporary storage
// use stack as temporary storage
SUB_IMM8(xSP, xSP, 4);
if((nextop&0xC0)!=0xC0)
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
u8 = F8;
// first two elements from Gx
for (int i=0; i<2; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
VST1LANE_32(v0+(idx/2), xSP, idx&1);
i32 = idx;
v2 = fpu_get_scratch_double(dyn);
if((nextop&0xC0)!=0xC0) {
// from memory
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
q0 = v0;
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v0, 0); break;
case 0b0001: VREV64_32(q0, v0); break; // reverse low part
case 0b0010: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0011: VEXT_8(q0, v0+1, v0, 4); break;
case 0b0100: break; // same
case 0b0101: VDUP_32(q0, v0, 1); break;
case 0b0110: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0111: VREV64_32(v2, v0);
VEXT_8(q0, v0+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v0);
VEXT_8(q0, v2, v0+1, 4); break;
case 0b1001: VEXT_8(q0, v0, v0+1, 4); break;
case 0b1010: VDUP_32(q0, v0+1, 0); break;
case 0b1011: VREV64_32(q0, v0+1); break;
case 0b1100: VEXT_8(q0, v0+1, v0, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(v2, v0+1);
VEXT_8(q0, v0, v2, 4); break;
case 0b1110: VMOVD(q0, v0+1); break;
case 0b1111: VDUP_32(q0, v0+1, 1); break;
}
VLD1LANE_32(q0+(i/2), xSP, i&1);
}
i32 = -1;
// next two from Ex
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
for (int i=2; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
VST1LANE_32(v1+(idx/2), xSP, idx&1);
i32 = idx;
// High part
if(((u8>>4)&3) == ((u8>>6)&3)) {
if((u8>>4)&3) {
ADD_IMM8(x3, wback, ((u8>>4)&3)*4);
}
VLD1LANE_32(q0+(i/2), xSP, i&1);
VLD1ALL_32(q0+1, ((u8>>4)&3)?x3:wback);
} else {
if((u8>>4)&3) {
ADD_IMM8(x3, wback, ((u8>>4)&3)*4);
}
VLD1LANE_32(q0+1, ((u8>>4)&3)?x3:wback, 0);
if((u8>>6)&3) {
ADD_IMM8(x3, wback, ((u8>>6)&3)*4);
}
VLD1LANE_32(q0+1, ((u8>>6)&3)?x3:wback, 1);
}
} else {
for (int i=2; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
ADD_IMM8(x2, ed, idx*4);
i32 = idx;
// from register
wback = 0; ed = nextop&7;
v1 = sse_get_reg(dyn, ninst, x1, ed, 0);
u8 = F8;
if((v0==v1) && ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111))) {
// same value duplicated all along
q0 = v0;
VDUPQ_32(v0, v0+((u8>>1)&1), u8&1);
} else if ((v0==v1) && (u8==0b01000100)) {
q0 = v0;
VMOVD(v0+1, v0);
} else if ((v0==v1) && (u8==0b11101110)) {
q0 = v0;
VMOVD(v0, v0+1);
} else if ((v0==v1) && (u8==0b10110001)) {
q0 = v0;
VREV64Q_32(v0, v0);
} else if ((v0==v1) && (u8==0b01001110)) {
q0 = v0;
VSWP(v0, v0+1);
} else if ((v0==v1) && (u8==0b11011000)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0, v0+1);
} else if ((v0==v1) && (u8==0b00100111)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0+1, v0);
} else if ((v0==v1) && (u8==0b01110010)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0, v0+1);
VREV64Q_32(v0, v0);
} else if ((v0==v1) && (u8==0b10001101)) {
q0 = v0;
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VTRN_32(v0+1, v0);
VREV64Q_32(v0, v0);
} else {
if(v1!=v0)
q0 = v0; // no need for temp storage
else if((u8&0b10100000)==0b10100000)
q0 = v0; // no need for temp if only low/low and high/high are shuffled
else
q0 = fpu_get_scratch_quad(dyn); // temporary storage
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v0, 0); break;
case 0b0001: VREV64_32(q0, v0); break; // reverse low part
case 0b0010: VREV64_32(v2, v0+1);
VEXT_8(q0, v2, v0, 4); break;
case 0b0011: VEXT_8(q0, v0+1, v0, 4); break;
case 0b0100: VMOVD(q0, v0); break; // same
case 0b0101: VDUP_32(q0, v0, 1); break;
case 0b0110: VEXT_8(q0, v0, v0+1, 4);
VREV64_32(q0, q0); break;
case 0b0111: VREV64_32(v2, v0);
VEXT_8(q0, v0+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v0);
VEXT_8(q0, v2, v0+1, 4); break;
case 0b1001: VEXT_8(q0, v0, v0+1, 4); break;
case 0b1010: VDUP_32(q0, v0+1, 0); break;
case 0b1011: VREV64_32(q0, v0+1); break;
case 0b1100: VEXT_8(q0, v0+1, v0, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(v2, v0+1);
VEXT_8(q0, v0, v2, 4); break;
case 0b1110: VMOVD(q0, v0+1); break;
case 0b1111: VDUP_32(q0, v0+1, 1); break;
}
// High part
switch ((u8>>4)&0xf) {
case 0b0000: VDUP_32(q0+1, v1, 0); break;
case 0b0001: VREV64_32(q0+1, v1); break; // reverse low part
case 0b0010: VREV64_32(v2, v1+1);
VEXT_8(q0+1, v2, v1, 4); break;
case 0b0011: VEXT_8(q0+1, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0+1, v1); break; // same
case 0b0101: VDUP_32(q0+1, v1, 1); break;
case 0b0110: VEXT_8(q0+1, v1, v1+1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b0111: VREV64_32(v2, v1);
VEXT_8(q0+1, v1+1, v2, 4); break;
case 0b1000: VREV64_32(v2, v1);
VEXT_8(q0+1, v2, v1+1, 4); break;
case 0b1001: VEXT_8(q0+1, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0+1, v1+1, 0); break;
case 0b1011: VREV64_32(q0+1, v1+1); break;
case 0b1100: VEXT_8(q0+1, v1+1, v1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b1101: VREV64_32(v2, v1+1);
VEXT_8(q0+1, v1, v2, 4); break;
case 0b1110: VMOVD(q0+1, v1+1); break;
case 0b1111: VDUP_32(q0+1, v1+1, 1); break;
}
VLD1LANE_32(q0+(i/2), x2, i&1);
}
}
ADD_IMM8(xSP, xSP, 4);
VMOVQ(v0, q0);
break;
case 0xC7:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0);
LDR_IMM9(x1, wback, fixedaddress+0);
LDR_IMM9(x2, wback, fixedaddress+4);
CMPS_REG_LSL_IMM5(xEAX, x1, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x2, 0);
B_MARK(cNE); // EDX != Ed[1]
STR_IMM9(xEBX, wback, fixedaddress+0);
STR_IMM9(xECX, wback, fixedaddress+4);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x1);
MOV_REG(xEDX, x2);
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
switch((nextop>>3)&7) {
case 1:
INST_NAME("CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x1, wback, fixedaddress+0);
LDR_IMM9(x2, wback, fixedaddress+4);
CMPS_REG_LSL_IMM5(xEAX, x1, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x2, 0);
B_MARK(cNE); // EDX != Ed[1]
STR_IMM9(xEBX, wback, fixedaddress+0);
STR_IMM9(xECX, wback, fixedaddress+4);
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x1);
MOV_REG(xEDX, x2);
MOVW(x1, 0);
MARK3;
BFI(xFlags, x1, F_ZF, 1);
break;
default:
DEFAULT;
}
break;
case 0xC8:
case 0xC9:
@@ -2250,7 +2432,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DEFAULT;
} else {
v0 = mmx_get_reg(dyn, ninst, x1, x2, x3, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1_64(v0, ed);
}
break;
+20 -14
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -28,7 +29,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback;
uint8_t wback, u8;
int fixedaddress;
MAYUSE(j32);
@@ -184,7 +185,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -197,7 +198,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -209,7 +210,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
POP1(xEAX+(nextop&7));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
@@ -260,6 +261,15 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xA8:
INST_NAME("TEST AL, Ib");
SETFLAGS(X_ALL, SF_SET_PENDING);
UXTB(x1, xEAX, 0);
u8 = F8;
MOVW(x2, u8);
emit_test8(dyn, ninst, x1, x2, x3, x14);
break;
case 0xC7:
INST_NAME("MOV FS:Ed, Id");
grab_fsdata(dyn, addr, ninst, x14);
@@ -269,7 +279,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
@@ -296,16 +306,12 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
MOV_REG(xEIP, xEAX+(nextop&7));
} else { // mem
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(xEIP, ed, x14, 0);
}
BARRIER(1);
BARRIER_NEXT(1);
if(!dyn->insts || ninst!=dyn->size-1) {
} else {
*need_epilog = 0;
*ok = 0;
}
BARRIER(BARRIER_FULL);
*need_epilog = 0;
*ok = 0;
MOV32(x2, addr);
PUSH1(x2);
jump_to_next(dyn, 0, xEIP, ninst);
@@ -315,7 +321,7 @@ uintptr_t dynarecFS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
+51 -8
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -28,16 +29,30 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t i32, j32;
uint32_t u32;
uint8_t gd, ed;
uint8_t wback, wb1, wb2, wb;
uint8_t wback, wb1, wb2, wb, eb1, eb2;
uint8_t u8;
int fixedaddress;
MAYUSE(j32);
MAYUSE(wback);
MAYUSE(wb2);
MAYUSE(wb);
MAYUSE(eb1);
MAYUSE(eb2);
switch(opcode) {
case 0x01:
INST_NAME("ADD GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO2(x14);
emit_add32(dyn, ninst, ed, gd, x3, x14);
WBACK;
break;
case 0x03:
INST_NAME("ADD Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -137,6 +152,16 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_xor32(dyn, ninst, gd, ed, x3, x14);
break;
case 0x39:
INST_NAME("CMP GS:Ed, Gd");
SETFLAGS(X_ALL, SF_SET_PENDING);
grab_tlsdata(dyn, addr, ninst, x14);
nextop = F8;
GETGD;
GETEDO(x14);
emit_cmp32(dyn, ninst, ed, gd, x3, x14);
break;
case 0x3B:
INST_NAME("CMP Gd, GS:Ed");
SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -347,7 +372,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(xEAX+(nextop&7), gd);
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
STR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -360,7 +385,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg <= reg
MOV_REG(gd, xEAX+(nextop&7));
} else { // mem <= reg
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(gd, ed, x14, 0);
}
break;
@@ -372,7 +397,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
POP1((xEAX+(nextop&7)));
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
POP1(x2);
STR_REG_LSL_IMM5(x2, ed, x14, 0);
}
@@ -400,6 +425,24 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(xEAX, x2, 0);
break;
case 0xC6:
INST_NAME("MOV GS:Eb, Ib");
grab_tlsdata(dyn, addr, ninst, x14);
nextop=F8;
if((nextop&0xC0)==0xC0) { // reg <= u8
u8 = F8;
ed = (nextop&7);
eb1 = xEAX+(ed&3); // Ax, Cx, Dx or Bx
eb2 = (ed&4)>>2; // L or H
MOVW(x3, u8);
BFI(eb1, x3, eb2*8, 8);
} else { // mem <= u8
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
MOVW(x3, u8);
STRB_REG_LSL_IMM5(x3, ed, x14, 0);
}
break;
case 0xC7:
INST_NAME("MOV GS:Ed, Id");
grab_tlsdata(dyn, addr, ninst, x14);
@@ -409,7 +452,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
MOV32(ed, i32);
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
i32 = F32S;
MOV32(x3, i32);
STR_REG_LSL_IMM5(x3, ed, x14, 0);
@@ -422,14 +465,14 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("ROL Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_rol32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
break;
case 1:
INST_NAME("ROR Ed, 1");
SETFLAGS(X_OF|X_CF, SF_SUBSET);
SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING);
GETEDO2(x14);
emit_ror32c(dyn, ninst, ed, 1, x3, x14);
WBACK;
@@ -597,7 +640,7 @@ uintptr_t dynarecGS(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) { // reg
DEFAULT;
} else { // mem <= i32
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, NULL);
LDR_REG_LSL_IMM5(x3, ed, x14, 0);
PUSH1(x3);
}
+39 -15
View File
@@ -33,12 +33,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uint16_t u16;
uint8_t gd, ed;
uint8_t wback, wb1;
int lock;
int fixedaddress;
MAYUSE(u16);
MAYUSE(u8);
MAYUSE(j32);
MAYUSE(lock);
while(opcode==0x66) opcode = F8; // "unlimited" 0x66 as prefix for variable sized NOP
if(opcode==0x2E) opcode = F8; // cs: is ignored
if((opcode==0x26) || (opcode==0x2E) || (opcode==0x36) || (opcode==0x3E)) opcode = F8; // segment prefix are ignored
switch(opcode) {
case 0x01:
@@ -175,6 +177,12 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sbb16c(dyn, ninst, x1, i16, x3, x14);
BFI(xEAX, x1, 0, 16);
break;
case 0x1E:
INST_NAME("PUSH DS");
MOVW(x1, offsetof(x86emu_t, segs[_DS]));
LDRH_REG(x2, xEmu, x1);
PUSH16(x2, xESP);
break;
case 0x21:
INST_NAME("AND Ew, Gw");
@@ -295,7 +303,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x46:
case 0x47:
INST_NAME("INC Reg16");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_inc16(dyn, ninst, x1, x3, x14);
@@ -310,7 +318,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0x4E:
case 0x4F:
INST_NAME("DEC Reg16");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
gd = xEAX+(opcode&7);
UXTH(x1, gd, 0);
emit_dec16(dyn, ninst, x1, x3, x14);
@@ -510,7 +518,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
GETGD;
UXTH(x14, gd, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
#if 0
MARKLOCK;
// do the swap with exclusive locking
@@ -537,8 +545,9 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(ed, gd, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
STRH_IMM8(gd, ed, fixedaddress);
if(lock) {DMB_ISH();}
}
break;
case 0x8B:
@@ -551,7 +560,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
BFI(gd, ed, 0, 16);
}
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, &lock);
if(lock) {DMB_ISH();}
LDRH_IMM8(x1, ed, fixedaddress);
BFI(gd, x1, 0, 16);
}
@@ -565,7 +575,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
BFI(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
STRH_IMM8(x1, ed, fixedaddress);
}
break;
@@ -578,7 +588,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(ed, xEmu, x2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
MOV32(x2, offsetof(x86emu_t, segs[(nextop&0x38)>>3]));
STRH_REG(x1, xEmu, x2);
@@ -681,6 +691,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xAF:
INST_NAME("SCASW");
SETFLAGS(X_ALL, SF_SET_PENDING);
GETDIR(x3, 2);
UXTH(x1, xEAX, 0);
LDRHAI_REG_LSL_IMM5(x2, xEDI, x3);
@@ -791,7 +802,7 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(x1, u16);
BFI(ed, x1, 0, 16);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
u16 = F16;
MOVW(x1, u16);
STRH_IMM8(x1, ed, fixedaddress);
@@ -898,6 +909,10 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xF0:
return dynarec66F0(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0xF2:
case 0xF3:
nextop = F8;
@@ -928,7 +943,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xA7:
if(opcode==0xF2) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3, 2);
@@ -964,7 +980,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xAF:
if(opcode==0xF2) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
SETFLAGS(X_ALL, SF_MAYSET);
MAYSETFLAGS();
SETFLAGS(X_ALL, SF_SET_PENDING);
TSTS_REG_LSL_IMM5(xECX, xECX, 0);
B_NEXT(cEQ); // end of loop
GETDIR(x3, 2);
@@ -991,6 +1008,13 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
case 0xF5:
INST_NAME("CMC");
READFLAGS(X_CF);
SETFLAGS(X_CF, SF_SUBSET);
XOR_IMM8(xFlags, xFlags, 1<<F_CF);
break;
case 0xF7:
nextop = F8;
switch((nextop>>3)&7) {
@@ -1045,8 +1069,8 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ORR_REG_LSL_IMM5(x2, x2, xEDX, 16);
UDIV(x3, x2, ed);
MLS(x14, x3, ed, x2); // x14 = x2 mod ed (i.e. x2 - x3*ed)
BFI(xEAX, x3, 1, 16);
BFI(xEDX, x14, 1, 16);
BFI(xEAX, x3, 0, 16);
BFI(xEDX, x14, 0, 16);
} else {
MESSAGE(LOG_DUMP, "Need Optimization\n");
SETFLAGS(X_ALL, SF_SET);
@@ -1086,14 +1110,14 @@ uintptr_t dynarec66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1);
emit_inc16(dyn, ninst, x1, x2, x14);
EWBACK;
break;
case 1:
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
GETEW(x1);
emit_dec16(dyn, ninst, x1, x2, x14);
EWBACK;
+269 -132
View File
@@ -27,7 +27,7 @@
if((nextop&0xC0)==0xC0) { \
a = sse_get_reg(dyn, ninst, x1, nextop&7, w); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL); \
a = fpu_get_scratch_quad(dyn); \
VLD1Q_8(a, ed); \
}
@@ -71,7 +71,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -89,7 +89,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 255-16, 0, 0, NULL);
VMOVfrV_D(x2, x3, v0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -109,10 +109,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -129,11 +129,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v0, ed, fixedaddress);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -146,7 +146,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
break;
@@ -159,7 +159,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1+1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-4, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress+4);
}
break;
@@ -174,10 +174,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0+1,x2, x3);
@@ -194,11 +194,11 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v0+1, ed, fixedaddress);
} else {
VMOVfrV_D(x2, x3, v0+1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -220,7 +220,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_32(v0, ed);
}
break;
@@ -233,7 +233,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
}
break;
@@ -262,7 +262,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_64(q1, ed);
v0 = q1;
}
@@ -469,7 +469,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) { \
ed = xEAX+(nextop&7); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);\
LDRH_IMM8_COND(YES, x1, ed, fixedaddress); \
ed = x1; \
} \
@@ -619,17 +619,55 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("ADDPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VADD_F64(v0, v0, q0);
VADD_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
VMSR(x14); // restore fpscr
}
break;
case 0x59:
INST_NAME("MULPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VMUL_F64(v0, v0, q0);
VMUL_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
VMSR(x14); // restore fpscr
}
break;
case 0x5A:
INST_NAME("CVTPD2PS Gx, Ex");
@@ -656,9 +694,28 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("SUBPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VSUB_F64(v0, v0, q0);
VSUB_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
VMSR(x14); // restore fpscr
}
break;
case 0x5D:
INST_NAME("MINPD Gx, Ex");
@@ -677,9 +734,28 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
INST_NAME("DIVPD Gx, Ex");
nextop = F8;
GETEX(q0, 0);
GETGX(v0, 1);
VDIV_F64(v0, v0, q0);
VDIV_F64(v0+1, v0+1, q0+1);
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(q1, q1, q0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1, q1);
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPSCR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, q1+1, q1+1);
VMSR(x14); // restore fpscr
}
break;
case 0x5F:
INST_NAME("MAXPD Gx, Ex");
@@ -817,7 +893,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(v0+1, v1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0+1, ed, fixedaddress);
}
break;
@@ -830,7 +906,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
VMOVD(q0+1, q1+1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023-8, 3, 0, NULL);
VLDR_64(q0+1, ed, fixedaddress+8);
}
break;
@@ -853,7 +929,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1Q_64(v0, ed);
}
break;
@@ -866,51 +942,116 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
u8 = F8;
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
if(u8==0x4E) {
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
VDUPQ_32(v0, v1+((u8>>1)&1), u8&1);
} else if (u8==0b01000100) {
VMOVD(v0+1, v1);
VMOVD(v0, v1);
} else if (u8==0b11101110) {
VMOVD(v0, v1+1);
VMOVD(v0+1, v1+1);
} else if (u8==0b10110001) {
VREV64Q_32(v0, v1);
} else if (u8==0b01010001) {
VDUP_32(v0+1, v1, 1);
VREV64Q_32(v0, v1);
} else if (u8==0b00011011) {
VREV64Q_32(v0, v1);
VSWP(v0, v0+1);
} else if (u8==0b01001110) {
if(v0==v1) {
VSWP(v0, v0+1);
} else {
VMOVD(v0, v1+1);
VMOVD(v0+1, v1);
}
} else if (u8==0b11011000) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VMOVQ(v0, v1);
VTRN_32(v0, v0+1);
} else if (u8==0b00100111) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VMOVQ(v0, v1);
VTRN_32(v0+1, v0);
} else if (u8==0b10001101) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VREV64Q_32(v0, v1); // 10 11 00 01
VTRN_32(v0, v0+1); // 10 00 11 01
} else if (u8==0b01110010) {
//VTRN_32(Dd, Dm) swap Dd[1] with Dm[0]
VREV64Q_32(v0, v1); // 10 11 00 01
VTRN_32(v0+1, v0); // 01 11 00 10
} else {
uint32_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)
};
q0 = fpu_get_scratch_quad(dyn); // temporary storage
d0 = fpu_get_scratch_double(dyn);
if(v0==v1) {
q1 = fpu_get_scratch_quad(dyn);
VMOVQ(q1, v1);
} else
q1 = v1;
uint32_t a1, a2, a3, a4;
a1 = swp[(u8>>(0*2))&3];
a2 = swp[(u8>>(1*2))&3];
MOV32(x2, a1);
if(a1==a2) {MOV_REG(x3, x2);} else {MOV32(x3, a2);}
VMOVtoV_D(d0, x2, x3);
VTBL2_8(v0+0, q1, d0);
a3 = swp[(u8>>(2*2))&3];
a4 = swp[(u8>>(3*2))&3];
if(a3!=a1 || a4!=a2) {
if(a3!=a1) {
if(a3==a2) {MOV_REG(x2, x3);} else {MOV32(x2, a3);}
}
if(a4!=a2) {
if(a4==a3) {MOV_REG(x3, x2);} else {MOV32(x3, a4);}
}
VMOVtoV_D(d0, x2, x3);
if(v1!=v0)
q0 = v0; // no need for temp storage
else if((u8&0xf)==((u8>>4)&0xf))
q0 = v0;
// Low part
switch (u8&0xf) {
case 0b0000: VDUP_32(q0, v1, 0); break;
case 0b0001: VREV64_32(q0, v1); break; // reverse low part
case 0b0010: VREV64_32(d0, v1+1);
VEXT_8(q0, d0, v1, 4); break;
case 0b0011: VEXT_8(q0, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0, v1); break; // same
case 0b0101: VDUP_32(q0, v1, 1); break;
case 0b0110: VEXT_8(q0, v1, v1+1, 4);
VREV64_32(q0, q0); break;
case 0b0111: VREV64_32(d0, v1);
VEXT_8(q0, v1+1, d0, 4); break;
case 0b1000: VREV64_32(d0, v1);
VEXT_8(q0, d0, v1+1, 4); break;
case 0b1001: VEXT_8(q0, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0, v1+1, 0); break;
case 0b1011: VREV64_32(q0, v1+1); break;
case 0b1100: VEXT_8(q0, v1+1, v1, 4);
VREV64_32(q0, q0); break;
case 0b1101: VREV64_32(d0, v1+1);
VEXT_8(q0, v1, d0, 4); break;
case 0b1110: VMOVD(q0, v1+1); break;
case 0b1111: VDUP_32(q0, v1+1, 1); break;
}
VTBL2_8(v0+1, q1, d0);
// High part
if((u8&0xf)==((u8>>4)&0xf)) {
VMOVD(q0+1, q0);
} else switch ((u8>>4)&0xf) {
case 0b0000: VDUP_32(q0+1, v1, 0); break;
case 0b0001: VREV64_32(q0+1, v1); break; // reverse low part
case 0b0010: VREV64_32(d0, v1+1);
VEXT_8(q0+1, d0, v1, 4); break;
case 0b0011: VEXT_8(q0+1, v1+1, v1, 4); break;
case 0b0100: VMOVD(q0+1, v1); break; // same
case 0b0101: VDUP_32(q0+1, v1, 1); break;
case 0b0110: VEXT_8(q0+1, v1, v1+1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b0111: VREV64_32(d0, v1);
VEXT_8(q0+1, v1+1, d0, 4); break;
case 0b1000: VREV64_32(d0, v1);
VEXT_8(q0+1, d0, v1+1, 4); break;
case 0b1001: VEXT_8(q0+1, v1, v1+1, 4); break;
case 0b1010: VDUP_32(q0+1, v1+1, 0); break;
case 0b1011: VREV64_32(q0+1, v1+1); break;
case 0b1100: VEXT_8(q0+1, v1+1, v1, 4);
VREV64_32(q0+1, q0+1); break;
case 0b1101: VREV64_32(d0, v1+1);
VEXT_8(q0+1, v1, d0, 4); break;
case 0b1110: VMOVD(q0+1, v1+1); break;
case 0b1111: VDUP_32(q0+1, v1+1, 1); break;
}
VMOVQ(v0, q0);
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
if (u8) {
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
if(u8&3) {
ADD_IMM8(x3, ed, (u8&3)*4);
}
VLD1QALL_32(v0, (u8&3)?x3:ed);
} else {
for (int i=0; i<4; ++i) {
int32_t idx = (u8>>(i*2))&3;
if(idx!=i32) {
@@ -919,8 +1060,6 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
VLD1LANE_32(v0+(i/2), x2, i&1);
}
} else {
VLD1QALL_32(v0, ed);
}
}
break;
@@ -932,7 +1071,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
}
@@ -953,7 +1092,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
}
@@ -970,7 +1109,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_16(q0, ed);
}
@@ -999,7 +1138,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
}
@@ -1020,7 +1159,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
}
@@ -1037,7 +1176,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_32(q0, ed);
}
@@ -1065,7 +1204,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
}
@@ -1086,7 +1225,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
}
@@ -1109,7 +1248,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
}
@@ -1130,7 +1269,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q0 = sse_get_reg(dyn, ninst, x1, nextop&7, 1);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q0 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q0, ed);
}
@@ -1184,7 +1323,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVfrDx_32(ed, v0, 0);
} else {
VMOVfrDx_32(x2, v0, 0); // to avoid Bus Error, using regular store
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
}
break;
@@ -1196,7 +1335,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_32(v0, ed);
}
break;
@@ -1210,7 +1349,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7); // no need for extract
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x1, gd, 4, 12); // r1 = (gw>>4);
ADD_REG_LSL_IMM5(x1, ed, x1, 1); //(&ed)+=r1*2;
LDRH_IMM8(x1, x1, fixedaddress);
@@ -1252,7 +1391,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
LDRH_IMM8(x14, x3, fixedaddress);
@@ -1300,7 +1439,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
}
@@ -1320,7 +1459,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
LDRH_IMM8(x14, x3, fixedaddress);
@@ -1349,7 +1488,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
eb2 = (ed&4)>>2; // L or H
UXTB(x1, eb1, eb2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 4095, 0, 0, NULL);
LDRB_IMM9(x1, ed, fixedaddress);
}
BFI(gd, x1, 0, 16);
@@ -1362,7 +1501,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX + (nextop&7);
UXTH(x1, ed, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, ed, fixedaddress);
}
BFI(gd, x1, 0, 16);
@@ -1378,7 +1517,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
}
@@ -1398,7 +1537,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
}
@@ -1427,7 +1566,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
}
@@ -1456,7 +1595,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRH_IMM8(x1, wback, fixedaddress);
ed = x1;
}
@@ -1490,7 +1629,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
wback = 0; // no need for extract
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
SBFX(x14, gd, 4, 12); // r14 = (gw>>4);
ADD_REG_LSL_IMM5(x3, wback, x14, 1); //(&ew)+=r14*2;
LDRH_IMM8(x14, x3, fixedaddress);
@@ -1549,11 +1688,18 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
eb2 = (ed&4)>>2; // L or H
SXTB(x1, eb1, eb2);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 255, 0, 0, NULL);
LDRSB_IMM8(x1, ed, fixedaddress);
}
BFI(gd, x1, 0, 16);
break;
case 0xBF:
INST_NAME("MOVSX Gw, Ew");
nextop = F8;
GETGD;
GETEW(x1);
BFI(gd, x1, 0, 16);
break;
case 0xC1:
INST_NAME("XADD Gw, Ew");
@@ -1562,7 +1708,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGW(x1);
GETEW(x2);
BFI((xEAX+((nextop&0x38)>>3)), x2, 0, 16); // GW <- EW
emit_add16(dyn, ninst, x1, x2, x14, x3, 1);
emit_add16(dyn, ninst, x2, x1, x14, x3, 1);
EWBACK;
break;
case 0xC2:
@@ -1571,42 +1717,34 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
u8 = F8;
u8 = F8&7;
// 0
if((u8&7)==6){
VCMP_F64(d0, v0);
} else {
VCMP_F64(v0, d0);
}
VCMP_F64(v0, d0);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0, x2, x2);
// 1
if((u8&7)==6){
VCMP_F64(d0+1, v0+1);
} else {
VCMP_F64(v0+1, d0+1);
}
VCMP_F64(v0+1, d0+1);
VMRS_APSR();
MOVW(x2, 0);
switch(u8&7) {
case 0: MVN_COND_REG_LSL_IMM5(cEQ, x2, x2, 0); break; // Equal
case 1: MVN_COND_REG_LSL_IMM5(cMI, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLE, x2, x2, 0); break; // Less or equal
case 1: MVN_COND_REG_LSL_IMM5(cCC, x2, x2, 0); break; // Less than
case 2: MVN_COND_REG_LSL_IMM5(cLS, x2, x2, 0); break; // Less or equal
case 3: MVN_COND_REG_LSL_IMM5(cVS, x2, x2, 0); break; // NaN
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal (or unordered on ARM, not on X86...)
case 4: MVN_COND_REG_LSL_IMM5(cNE, x2, x2, 0); break; // Not Equal or unordered
case 5: MVN_COND_REG_LSL_IMM5(cCS, x2, x2, 0); break; // Greater or equal or unordered
case 6: MVN_COND_REG_LSL_IMM5(cLT, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 6: MVN_COND_REG_LSL_IMM5(cHI, x2, x2, 0); break; // Greater or unordered, test inverted, N!=V so unordereded or less than (inverted)
case 7: MVN_COND_REG_LSL_IMM5(cVC, x2, x2, 0); break; // not NaN
}
VMOVtoV_D(v0+1, x2, x2);
@@ -1621,7 +1759,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
ed = xEAX+(nextop&7);
VMOVtoDx_16(v0+(u8/4), u8&3, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL);
u8 = (F8)&7;
VLD1LANE_16(v0+(u8/4), wback, u8&3);
}
@@ -1635,7 +1773,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
u8 = (F8)&7;
VMOVfrDx_U16(gd, v0+(u8/4), (u8&3));
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255-14, 0, 0, NULL);
u8 = (F8)&7;
LDRH_IMM8(gd, wback, fixedaddress+u8*2);
}
@@ -1646,17 +1784,21 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(v0, 1);
GETEX(v1, 0);
u8 = F8;
if(v0==v1 && u8==0) {
VMOVD(v0+1, v0);
if(v0==v1) {
switch (u8&3) {
case 0b00: VMOVD(v0+1, v0); break;
case 0b01: VSWP(v0, v0+1); break;
case 0b10: break;
case 0b11: VMOVD(v0, v0+1); break;
}
} else {
if(v0==v1)
q0 = fpu_get_scratch_quad(dyn);
else
q0 = v0;
VMOVD(q0, v0+(u8&1));
VMOVD(q0+1, v1+((u8>>1)&1));
if(v0==v1) {
VMOVQ(v0, q0);
switch(u8&1) {
case 0: break;
case 1: VMOVD(v0, v0+1); break;
}
switch((u8>>1)&1) {
case 0: VMOVD(v0+1, v1); break;
case 1: VMOVD(v0+1, v1+1); break;
}
}
break;
@@ -1688,13 +1830,8 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q0, 1);
GETEX(q1, 0);
v0 = fpu_get_scratch_quad(dyn);
VMOVD(v0, q1);
VMOVD(v0+1, q1);
VQMOVN_S64(v0, v0); // 2*q1 in 32bits now
VMOVD(v0+1, v0);
VQMOVN_S32(v0, v0); // 4*q1 in 16bits now
VNEGN_16(v0, v0); // because we want SHR and not SHL
VMOVD(v0+1, v0);
VDUPQ_16(v0, q1, 0);
VNEGNQ_16(v0, v0); // because we want SHR and not SHL
VSHLQ_U16(q0, q0, v0);
break;
case 0xD2:
@@ -1749,10 +1886,10 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
parity = getedparity(dyn, ninst, addr, nextop, 3);
// can be unaligned sometimes
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(q0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
VMOVfrV_D(x2, x3, q0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -1938,7 +2075,7 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VST1Q_64(v0, ed);
}
break;
+188
View File
@@ -0,0 +1,188 @@
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <pthread.h>
#include <errno.h>
#include "debug.h"
#include "box86context.h"
#include "dynarec.h"
#include "emu/x86emu_private.h"
#include "emu/x86run_private.h"
#include "x86run.h"
#include "x86emu.h"
#include "box86stack.h"
#include "callback.h"
#include "emu/x86run_private.h"
#include "x86trace.h"
#include "dynarec_arm.h"
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop, opcode = F8;
uint8_t wback, wb1, wb2, gb1, gb2;
uint8_t ed, gd, u8;
int fixedaddress;
int32_t i32, j32;
int16_t i16;
MAYUSE(i32);
MAYUSE(j32);
MAYUSE(gb1);
MAYUSE(gb2);
MAYUSE(wb1);
MAYUSE(wb2);
switch(opcode) {
case 0x81:
case 0x83:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7) {
case 0: //ADD
if(opcode==0x81) {
INST_NAME("LOCK ADD Ew, Iw");
} else {
INST_NAME("LOCK ADD Ew, Ib");
}
SETFLAGS(X_ALL, SF_SET_PENDING);
DMB_ISH();
if((nextop&0xC0)==0xC0) {
if(opcode==0x81) i16 = F16S; else i16 = F8S;
ed = xEAX+(nextop&7);
emit_add16c(dyn, ninst, ed, i16, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i16 = F16S; else i16 = F8S;
if(!fixedaddress) {
TSTS_IMM8(wback, 0x1);
B_MARK(cNE);
}
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
MARKLOCK;
LDREXH(x1, wback);
emit_add16c(dyn, ninst, x1, i16, x3, x14);
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
MARK; // unaligned! also, not enough
LDRH_IMM8(x1, wback, 0);
LDREXB(x14, wback);
BFI(x1, x14, 0, 8); // re-inject
emit_add16c(dyn, ninst, x1, i16, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0); // put the whole value
}
DMB_ISH();
}
break;
default:
DEFAULT;
}
DMB_ISH();
break;
case 0xFF:
nextop = F8;
DMB_ISH();
switch((nextop>>3)&7)
{
case 0: // INC Ew
INST_NAME("INC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
GETEW(x1);
emit_inc16(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(wback, 1);
B_MARK(cNE); // unaligned
}
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
MARKLOCK;
LDREXH(x1, wback);
emit_inc16(dyn, ninst, x1, x3, x14);
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&1))) {
MARK;
LDRH_IMM8(x1, wback, 0);
LDREXB(x3, wback);
BFI(x1, x3, 0, 8);
emit_inc16(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
}
}
break;
case 1: //DEC Ew
INST_NAME("DEC Ew");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
GETEW(x1);
emit_dec32(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(wback, 1);
B_MARK(cNE); // unaligned
}
if(!fixedaddress || (fixedaddress && !(fixedaddress&1))) {
MARKLOCK;
LDREXH(x1, wback);
emit_dec16(dyn, ninst, x1, x3, x14);
STREXH(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARKLOCK(cNE);
}
if(!fixedaddress) {
DMB_ISH();
B_NEXT(c__);
}
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
MARK;
LDRH_IMM8(x1, wback, 0);
LDREXB(x3, wback);
BFI(x1, x3, 0, 8);
emit_dec16(dyn, ninst, x1, x3, x14);
STREXB(x3, x1, wback);
CMPS_IMM8(x3, 0);
B_MARK(cNE);
STRH_IMM8(x1, wback, 0);
}
}
break;
default:
// default to NO LOCK
addr-=2;
}
DMB_ISH();
break;
default:
DEFAULT;
}
return addr;
}
+24 -14
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
@@ -29,9 +30,11 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uint32_t u32;
uint8_t gd, ed;
int fixedaddress;
int cacheupd;
MAYUSE(i32);
MAYUSE(j32);
MAYUSE(cacheupd);
nextop = F8;
@@ -132,20 +135,27 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
break;
#define GO(NO, YES) \
BARRIER(2); \
JUMP(addr+i8, 1); \
if(dyn->insts) { \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
/* out of the block */ \
i32 = dyn->insts[ninst+1].address-(dyn->arm_size+8); \
Bcond(NO, i32); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
} \
#define GO(NO, YES) \
BARRIER(BARRIER_MAYBE); \
JUMP(addr+i8, 1); \
if(dyn->insts[ninst].x86.jmp_insts==-1 || \
CHECK_CACHE()) { \
/* out of the block */ \
i32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(NO, i32); \
if(dyn->insts[ninst].x86.jmp_insts==-1) { \
if(!(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT)) \
fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \
jump_to_next(dyn, addr+i8, 0, ninst); \
} else { \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
} else { \
/* inside the block */ \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8); \
Bcond(YES, i32); \
}
case 0xE0:
INST_NAME("LOOPNZ (16bits)");
+8 -8
View File
@@ -190,7 +190,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -210,7 +210,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -230,7 +230,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -251,7 +251,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -273,7 +273,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -293,7 +293,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -313,7 +313,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -333,7 +333,7 @@ uintptr_t dynarecD8(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
+177 -69
View File
@@ -34,11 +34,15 @@ static const float f_pi = PI;
static const float f_lg2 = LG2;
static const float f_ln2 = LN2;
extern int arm_v8;
static const void* round_map[4] = {nearbyint, floor, ceil, trunc};
uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
uint8_t ed;
uint8_t wback, wb1;
uint8_t u8;
int fixedaddress;
int v1, v2;
int s0;
@@ -50,6 +54,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(j32);
(void)u8;
switch(nextop) {
@@ -69,9 +74,12 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_64(v2, v1);
}
// should set C1 to 0
break;
case 0xC8:
INST_NAME("FXCH ST0");
break;
case 0xC9:
case 0xCA:
case 0xCB:
@@ -81,17 +89,8 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xCF:
INST_NAME("FXCH STx");
// swap the cache value, not the double value itself :p
i1 = x87_get_cache(dyn, ninst, 1, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
// swap those too
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
i3 = dyn->n.neoncache[i1].v;
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
dyn->n.neoncache[i2].v = i3;
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
// should set C1 to 0
break;
case 0xD0:
@@ -106,6 +105,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VNEG_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE1:
INST_NAME("FABS");
@@ -115,6 +115,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VABS_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xE4:
@@ -136,7 +137,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
// not in cache, so check Empty status and load it
// x14 will be the actual top
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
i2 = -dyn->x87stack;
i2 = -dyn->n.x87stack;
if(i2) {
if(i2<0) {
SUB_IMM8(x14, x14, -i2);
@@ -154,7 +155,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
B_MARK3(cEQ);
} else {
// simply move from cache reg to r2/r3
v1 = dyn->x87reg[i1];
v1 = dyn->n.x87reg[i1];
VMOVfrV_D(x2, x3, v1);
}
// get exponant in r1
@@ -199,6 +200,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_i_64(v1, 0b01110000);
}
// should set C1 to 0
break;
case 0xE9:
INST_NAME("FLDL2T");
@@ -210,6 +212,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_l2t));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEA:
INST_NAME("FLDL2E");
@@ -221,6 +224,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_l2e));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEB:
INST_NAME("FLDPI");
@@ -232,6 +236,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_pi));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEC:
INST_NAME("FLDLG2");
@@ -243,6 +248,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_lg2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xED:
INST_NAME("FLDLN2");
@@ -254,6 +260,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOV32(x2, (&d_ln2));
VLDR_64(v1, x2, 0);
}
// should set C1 to 0
break;
case 0xEE:
INST_NAME("FLDZ");
@@ -263,41 +270,32 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
VMOV_8(v1, 0); // cannot use VMOV_i_F64
}
// should set C1 to 0
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VSQRT_F32(v1, v1);
} else {
VSQRT_F64(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, 0);
/*
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");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
CALL(arm_f2xm1, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
//if(ST0.d!=0.0)
// ST0.d = exp2(ST0.d)-1.0;
VMOV_64(0, v1);
CALL_1D(exp2, 0); // return is d0
if((PK(0)==0xD9 && PK(1)==0xE8) && // next inst is FLD1
(PK(2)==0xDE && PK(3)==0xC1)) {
MESSAGE(LOG_DUMP, "Hack for fld1 / faddp st1, st0\n");
VMOV_64(v1, 0);
addr+=4;
} else {
VMOV_i_64(v1, 0b01110000); // 1.0
VSUB_F64(v1, 0, v1);
}
#endif
// should set C1 to 0
break;
case 0xF1:
INST_NAME("FYL2X");
@@ -307,24 +305,30 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d)*ST(1).d
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF2:
INST_NAME("FTAN");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
INST_NAME("FPTAN");
v2 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_64(0, v1); // prepare call to tan
CALL_1D(tan, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C1 = 0;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C1 C2 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
// so here: F64: Imm8 = abcd efgh that gives => aBbbbbbb bbcdefgh 0000000 00000000 00000000...
// and want 1.0 = 0x3ff0000000000000
// so 00111111 11110000 00000000 00000000....
// a = 0, b = 1, c = 1, d = 1, efgh=0
// 0b01110000
VMOV_i_64(v2, 0b01110000);
if(ST_IS_F(0)) {
VMOV_i_32(v2, 0b01110000);
} else {
VMOV_i_64(v2, 0b01110000);
}
break;
case 0xF3:
INST_NAME("FPATAN");
@@ -335,6 +339,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_2D(atan2, 0);
VMOV_64(v2, 0); //ST(1).d = atan2(ST1.d, ST0.d);
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xF4:
INST_NAME("FXTRACT");
@@ -342,13 +347,48 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
x87_do_push_empty(dyn, ninst, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fxtract, -1, 0);
// C1 set only if stack under/overflow occurs
break;
case 0xF5:
INST_NAME("FPREM1");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem1, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_double(dyn);
VDIV_F64(s0, v1, v2);
// set rounding to Nearest
MOVW(x2, 1); // Nearest
VMRS(x1); // get fpscr
MOV_REG(x14, x1);
BFI(x1, x2, 22, 2); // inject new round
VMSR(x1); // put new fpscr
VCVTR_S32_F64(s0*2, s0); // => Q
// set back rounding
VMSR(x14);
// get Q
VMOVfrV(x14, s0*2);
// Put back Q in a double
VCVT_F64_S32(s0, s0*2);
VMUL_F64(s0, s0, v2);
VSUB_F64(v1, v1, s0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
// set C2 = 0
BFC(x1, 10, 1);
// set C1 = Q0
BFI(x1, x14, 9, 1);
// set C3 = Q1
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 14, 1);
// Set C0 = Q2
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 8, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
#endif
break;
case 0xF6:
INST_NAME("FDECSTP");
@@ -357,6 +397,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
SUB_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// should set C1 to 0
break;
case 0xF7:
INST_NAME("FINCSTP");
@@ -365,13 +406,40 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ADD_IMM8(x2, x2, 1);
AND_IMM8(x2, x2, 7);
STR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
// should set C1 to 0
break;
case 0xF8:
INST_NAME("FPREM");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
x87_forget(dyn, ninst, x1, x2, 1);
CALL(arm_fprem, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
s0 = fpu_get_scratch_double(dyn);
VDIV_F64(s0, v1, v2);
VCVT_S32_F64(s0*2, s0); // => Q
// get Q
VMOVfrV(x14, s0*2);
// Put back Q in a double
VCVT_F64_S32(s0, s0*2);
VMUL_F64(s0, s0, v2);
VSUB_F64(v1, v1, s0);
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
// set C2 = 0
BFC(x1, 10, 1);
// set C1 = Q0
BFI(x1, x14, 9, 1);
// set C3 = Q1
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 14, 1);
// Set C0 = Q2
MOV_REG_LSR_IMM5(x14, x14, 1);
BFI(x1, x14, 8, 1);
STR_IMM9(x1, xEmu, offsetof(x86emu_t, sw));
#endif
break;
case 0xF9:
INST_NAME("FYL2XP1");
@@ -382,21 +450,56 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
CALL_1D(log2, 0);
VMUL_F64(v2, v2, 0); //ST(1).d = log2(ST0.d + 1.0)*ST(1).d;
x87_do_pop(dyn, ninst, x3);
// should set C1 to 0
break;
case 0xFA:
INST_NAME("FSQRT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_ST0);
if(ST_IS_F(0)) {
VSQRT_F32(v1, v1);
} else {
VSQRT_F64(v1, v1);
}
// should set C1 to 0
break;
case 0xFB:
INST_NAME("FSINCOS");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = x87_do_push(dyn, ninst, x3, NEON_CACHE_ST_D);
v1 = x87_get_st(dyn, ninst, x1, x2, 1, NEON_CACHE_ST_D);
VMOV_64(0, v1);
CALL_1D(sin, 0);
VSWP(v1, 0);
CALL_1D(cos, 0);
CALL_1D(cos, 0); // would it be faster to do sqrt(1-sin()²) ???
VMOV_64(v2, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
case 0xFC:
INST_NAME("FRNDINT");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
if(!arm_v8) {
// check if finite first
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cVS); // Unordered, skip
B_NEXT(cEQ); // Zero, skip
// load round mode
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x2, x1, 10, 2); // extract round...
MOV32(x1, round_map);
LDR_REG_LSL_IMM5(x2, x1, x2, 2);
VMOV_64(0, v1); // prepare call to fpu_round
CALL_1DR(x2, x3, 0);
VMOV_64(v1, 0);
} else {
u8 = x87_setround(dyn, ninst, x1, x2, x14);
VRINTR_F64(v1, v1);
x87_restoreround(dyn, ninst, u8);
}
// should set C1 to 0
break;
case 0xFD:
INST_NAME("FSCALE");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
@@ -406,9 +509,15 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VCMP_F64_0(v1);
VMRS_APSR();
B_NEXT(cEQ);
VMOV_64(0, v2);
CALL_1DD(trunc, exp2, 0);
if(!arm_v8) {
VMOV_64(0, v2);
CALL_1DD(trunc, exp2, 0);
} else {
VRINTZ_F64(0, v2);
CALL_1D(exp2, 0);
}
VMUL_F64(v1, v1, 0);
// should set C1 to 0
break;
case 0xFE:
INST_NAME("FSIN");
@@ -416,9 +525,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOV_64(0, v1); // prepare call to sin
CALL_1D(sin, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
case 0xFF:
@@ -427,9 +536,9 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VMOV_64(0, v1); // prepare call to cos
CALL_1D(cos, 0);
VMOV_64(v1, 0);
//emu->sw.f.F87_C2 = 0;
//emu->sw.f.F87_C2 = 0; C1 too
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
BFC(x1, 10, 1); //C2 = 0
BFC(x1, 9, 2); //C2 C1 = 0 0
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
break;
@@ -459,23 +568,24 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 0:
INST_NAME("FLD ST0, float[ED]");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
v1 = x87_do_push(dyn, ninst, x1, box86_dynarec_x87double?NEON_CACHE_ST_D:NEON_CACHE_ST_F);
if(ST_IS_F(0))
s0 = v1;
else
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
if(!ST_IS_F(0)) {
VCVT_F64_F32(v1, s0);
}
// should set C1 to 0
break;
case 2:
INST_NAME("FST float[ED], ST0");
@@ -488,10 +598,10 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
@@ -507,10 +617,10 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VSTR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
VMOVfrV(x2, s0);
STR_IMM9(x2, ed, fixedaddress);
}
@@ -520,7 +630,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FLDENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
@@ -531,14 +641,12 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FLDCW Ew");
GETEW(x1);
STRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x1, x1, 10, 2); // extract round
STR_IMM9(x1, xEmu, offsetof(x86emu_t, round));
break;
case 6:
INST_NAME("FNSTENV Ed");
MESSAGE(LOG_DUMP, "Need Optimization\n");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3); // maybe only x87, not SSE?
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
@@ -547,7 +655,7 @@ uintptr_t dynarecD9(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 7:
INST_NAME("FNSTCW Ew");
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
wb1 = 1;
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, cw));
+95 -14
View File
@@ -122,9 +122,8 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xE2:
INST_NAME("FNCLEX");
LDRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
MOVW(x1, 0);
BFI(x2, x1, 0, 8); // IE .. PE, SF, ES
BFI(x2, x1, 15, 1); // B
BFC(x2, 0, 8); // IE .. PE, SF, ES
BFC(x2, 15, 1); // B
STRH_IMM8(x2, xEmu, offsetof(x86emu_t, sw));
break;
case 0xE3:
@@ -188,7 +187,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
GETED;
@@ -203,13 +202,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
VMRS(x14); // Get FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_S32_F64(s0, v1);
@@ -229,13 +228,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
ed = x1;
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
ed = x1; // will not be writen immediatly, so x1 is safe for now
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
@@ -254,13 +253,13 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL);
ed = x1;
}
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// The FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVTR_S32_F64(s0, v1);
@@ -274,7 +273,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 5:
INST_NAME("FLD tbyte");
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(PK(0)==0xDB && ((PK(1)>>3)&7)==7) {
// the FLD is immediatly followed by an FSTP
LDR_IMM9(x2, ed, 0);
@@ -284,28 +283,110 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MESSAGE(LOG_DUMP, "\tHack: FSTP tbyte\n");
nextop = F8; //0xDB
nextop = F8; //modrm
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
STRH_IMM8(x14, ed, 8);
} else {
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
if(ed!=x1) {
MOV_REG(x1, ed);
}
x87_do_push_empty(dyn, ninst, x3);
CALL(arm_fld, -1, 0);
#else
v1 = x87_do_push(dyn, ninst, x2, NEON_CACHE_ST_D);
// copy 10bytes of *ED to STld(0)
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
LDR_IMM9(x14, ed, 0);
STR_IMM9(x14, x2, 0);
LDR_IMM9(x14, ed, 4);
STR_IMM9(x14, x2, 4);
LDRH_IMM8(x14, ed, 8);
STRH_IMM8(x14, x2, 8);
// convert 10bytes -> double
CALL_1RD(FromLD, ed, x2, (1<<x3)|(1<<xFlags)|(1<<x2));
// store ref to STld(0).uref, but can be unaligned...
VMOVfrV_D(x3, x14, 0);
// also, store result to ST0
VMOVD(v1, 0);
STR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
STR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
#endif
}
break;
case 7:
INST_NAME("FSTP tbyte");
#if 0
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {
MOV_REG(x1, ed);
}
CALL(arm_fstp, -1, 0);
#else
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
v2 = fpu_get_scratch_double(dyn);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
// get top in x3
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, top));
int a = -dyn->n.x87stack;
if(a) {
if(a<0) {
SUB_IMM8(x3, x3, -a);
} else {
ADD_IMM8(x3, x3, a);
}
AND_IMM8(x3, x3, 7);
}
// get STld(0)
ADD_IMM8(x2, xEmu, offsetof(x86emu_t, fpu_ld)+offsetof(fpu_ld_t, ld));
MOVW(x14, sizeof(fpu_ld_t));
MLA(x2, x3, x14, x2);
// compare uref with actual value, top is not used anymore, so x3 is free
LDR_IMM9(x14, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld));
LDR_IMM9(x3, x2, offsetof(fpu_ld_t, uref)-offsetof(fpu_ld_t, ld)+4);
VMOVtoV_D(v2, x14, x3);
VCEQ_32(v2, v2, v1); // same?
VMOVfrV_D(x14, x3, v2);
TSTS_REG_LSL_IMM5(x14, x3, 0);
B_MARK(cEQ); // different, do the conversion
// same... copy STld(0).ld
LDR_IMM9(x14, x2, 0);
LDR_IMM9(x3, x2, 4);
STR_IMM9(x14, ed, 0);
STR_IMM9(x3, ed, 4);
LDRH_IMM8(x14, x2, 8);
STRH_IMM8(x14, ed, 8);
B_MARK2(c__);
MARK;
// different, call D2LD
SUB_IMM8(xSP, xSP, 8);
VSTR_64(v1, xSP, 0);
PUSH(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(0, xSP, 8); //1st arg is &d
if(ed!=x1) {
MOV_REG_LSL_IMM5(x1, ed, 0); //2nd arg is ed
}
CALL_S(D2LD, -2, 0);
POP(xSP, (1<<xEmu)|(1<<xFlags));
ADD_IMM8(xSP, xSP, 8);
MARK2;
#endif
x87_do_pop(dyn, ninst, x3);
break;
default:
+16 -16
View File
@@ -184,10 +184,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -200,10 +200,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -216,10 +216,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -233,10 +233,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -251,10 +251,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -267,10 +267,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -283,10 +283,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
@@ -299,10 +299,10 @@ uintptr_t dynarecDC(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
d1 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(d1, wback, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, wback, fixedaddress);
LDR_IMM9(x3, wback, fixedaddress+4);
VMOVtoV_D(d1, x2, x3);
+15 -25
View File
@@ -80,17 +80,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0xDF:
INST_NAME("FSTP ST0, STx");
// copy the cache value for st0 to stx
i1 = x87_get_cache(dyn, ninst, 0, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
i2 = x87_get_cache(dyn, ninst, 1, x1, x2, 0, X87_COMBINE(0, nextop&7));
i3 = dyn->x87cache[i1];
dyn->x87cache[i1] = dyn->x87cache[i2];
dyn->x87cache[i2] = i3;
// swap those too
i1 = x87_get_neoncache(dyn, ninst, x1, x2, nextop&7);
i2 = x87_get_neoncache(dyn, ninst, x1, x2, 0);
i3 = dyn->n.neoncache[i1].v;
dyn->n.neoncache[i1].v = dyn->n.neoncache[i2].v;
dyn->n.neoncache[i2].v = i3;
x87_swapreg(dyn, ninst, x1, x2, 0, nextop&7);
x87_do_pop(dyn, ninst, x3);
break;
@@ -166,10 +156,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if (parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress + 4);
VMOVtoV_D(v1, x2, x3);
@@ -178,7 +168,7 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("FISTTP i64, ST0");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fistt64, -1, 0);
x87_do_pop(dyn, ninst, x3);
@@ -188,10 +178,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -202,10 +192,10 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_D);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VSTR_64(v1, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
VMOVfrV_D(x2, x3, v1);
STR_IMM9(x2, ed, fixedaddress);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -215,28 +205,28 @@ uintptr_t dynarecDD(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 4:
INST_NAME("FRSTOR m108byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_frstor, -1, 0);
break;
case 6:
INST_NAME("FSAVE m108byte");
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(arm_fsave, -1, 0);
break;
case 7:
INST_NAME("FNSTSW m2byte");
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x14, &fixedaddress, 0, 0, 0, NULL);
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
if(dyn->x87stack) {
if(dyn->n.x87stack) {
// update top
if(dyn->x87stack>0) {
SUB_IMM8(x2, x2, dyn->x87stack);
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->x87stack);
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
+16
View File
@@ -166,11 +166,27 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FDIVP STx, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7));
v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7));
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
if(ST_IS_F(0)) {
VDIV_F32(v2, v2, v1);
} else {
VDIV_F64(v2, v2, v1);
}
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
if(ST_IS_F(0)) {
VNEG_F32_cond(cNE, v2, v2);
} else {
VNEG_F64_cond(cNE, v2, v2);
}
VMSR(x14); // restore fpscr
}
x87_do_pop(dyn, ninst, x3);
break;
+73 -39
View File
@@ -23,7 +23,7 @@
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
static const void* round_map[4] = {arm_fist64_0, arm_fist64_1, arm_fist64_2, arm_fist64_3};
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
@@ -31,7 +31,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
int32_t j32;
uint8_t wback;
uint8_t ed;
int v0, v1, v2;
int /*v0, */v1, v2;
int s0;
int fixedaddress;
int parity;
@@ -39,7 +39,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MAYUSE(s0);
MAYUSE(v2);
MAYUSE(v1);
MAYUSE(v0);
//MAYUSE(v0);
MAYUSE(j32);
switch(nextop) {
@@ -60,12 +60,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FNSTSW AX");
LDR_IMM9(x2, xEmu, offsetof(x86emu_t, top));
LDRH_IMM8(x1, xEmu, offsetof(x86emu_t, sw));
if(dyn->x87stack) {
if(dyn->n.x87stack) {
// update top
if(dyn->x87stack>0) {
SUB_IMM8(x2, x2, dyn->x87stack);
if(dyn->n.x87stack>0) {
SUB_IMM8(x2, x2, dyn->n.x87stack);
} else {
ADD_IMM8(x2, x2, -dyn->x87stack);
ADD_IMM8(x2, x2, -dyn->n.x87stack);
}
AND_IMM8(x2, x2, 7);
}
@@ -162,7 +162,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 0:
INST_NAME("FILD ST0, Ew");
v1 = x87_do_push(dyn, ninst, x1, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL);
LDRSH_IMM8(x1, wback, fixedaddress);
if(ST_IS_F(0)) {
VMOVtoV(v1, x1);
@@ -176,13 +176,13 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 1:
INST_NAME("FISTTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
VMRS(x14); // get fpscr
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
@@ -204,12 +204,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FIST Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
@@ -230,12 +230,12 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FISTP Ew, ST0");
v1 = x87_get_st(dyn, ninst, x1, x2, 0, NEON_CACHE_ST_F);
u8 = x87_setround(dyn, ninst, x1, x2, x14);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 255, 0, 0, NULL);
ed = x1;
s0 = fpu_get_scratch_single(dyn);
MSR_nzcvq_0();
// x1 already have FPCSR reg to clear exceptions flags
ORR_IMM8(x3, x1, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x1, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
if(ST_IS_F(0)) {
@@ -257,7 +257,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
INST_NAME("FBLD ST0, tbytes");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_do_push_empty(dyn, ninst, x1);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbld, -1, 0);
break;
@@ -267,7 +267,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v2 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 0, NULL);
if(parity) {
LDRD_IMM8(x2, wback, 0); // x2/x3 is 64bits
} else {
@@ -281,48 +281,46 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
MESSAGE(LOG_DUMP, "Hack for FILD/FISTP i64");
} else {
// Save xFlags to use it as scratch...
STR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
// set STll(0).ll=i64 and ref=ST(0).q later (emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top])
// get TOP
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->x87stack;
LDR_IMM9(x1, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(xFlags, xFlags, -a);
AND_IMM8(xFlags, xFlags, 7);
SUB_IMM8(x1, x1, -a);
AND_IMM8(x1, x1, 7);
} else if(a>0) {
ADD_IMM8(xFlags, xFlags, a);
AND_IMM8(xFlags, xFlags, 7);
ADD_IMM8(x1, x1, a);
AND_IMM8(x1, x1, 7);
}
ADD_REG_LSL_IMM5(xFlags, xEmu, xFlags, 4); // each fpu_ll is 2 int64: ref than ll
ADD_IMM8_ROR(xFlags, xFlags, offsetof(x86emu_t, fpu_ll)>>2, 15);
STRD_IMM8(x2, xFlags, 8); // save ll
// ed (and so x1) is not use anymore.
ADD_REG_LSL_IMM5(x1, xEmu, x1, 4); // each fpu_ll is 2 int64: ref than ll
ADD_IMM8_ROR(x1, x1, offsetof(x86emu_t, fpu_ll)>>2, 15);
STRD_IMM8(x2, x1, 8); // save ll
// continue with conversion
MOVS_REG_LSR_IMM5(x14, x3, 31); // x14 is sign bit
B_MARK(cEQ); // no NEG is no sign bit
RSBS_IMM8(x2, x2, 0);
RSC_IMM8(x3, x3, 0);
MARK;
VMOVtoV(s0, x3);
VMOVtoV(s0, x3); // last time x3 is used
VCVT_F64_U32(v1, s0);
VEOR(v2, v2, v2);
MOVW(x1, 0x41F0);
VMOVtoDx_16(v2, 3, x1);
MOVW(x3, 0x41F0);
VMOVtoDx_16(v2, 3, x3);
VMUL_F64(v1, v1, v2); // v1 = double high part of i64
VMOVtoV(s0, x2);
VCVT_F64_U32(v2, s0);
VADD_F64(v1, v1, v2);
TSTS_IMM8(x14, 1);
VNEG_F64_cond(cNE, v1, v1);
VST1_64(v1, xFlags); // Store STll(0).ref
LDR_IMM9(xFlags, xEmu, offsetof(x86emu_t, eflags));
VST1_64(v1, x1); // Store STll(0).ref
}
break;
case 6:
INST_NAME("FBSTP tbytes, ST0");
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x1, x2, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ed!=x1) {MOV_REG(x1, ed);}
CALL(fpu_fbst, -1, 0);
x87_do_pop(dyn, ninst, x3);
@@ -330,7 +328,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
case 7: // could be inlined for most thing, but is it usefull?
INST_NAME("FISTP i64, ST0");
parity = getedparity(dyn, ninst, addr, nextop, 3);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
if(ninst
&& dyn->insts[ninst-1].x86.addr
&& *(uint8_t*)dyn->insts[ninst-1].x86.addr==0xDF
@@ -343,16 +341,51 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
STR_IMM9(x3, ed, 4);
}
} else {
#if 0
v1 = x87_get_st(dyn, ninst, x2, x3, 0);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
#if 1
v1 = x87_get_st(dyn, ninst, x2, x3, 0, NEON_CACHE_ST_D);
//addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
fpu_get_scratch_double(dyn); // to alocate v0
v2 = fpu_get_scratch_double(dyn);
#if 1
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
} else if(a>0) {
ADD_IMM8(x14, x14, a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
}
ADD_REG_LSL_IMM5(x14, xEmu, x14, 4); // each fpu_ll is 2 int64: ref than ll
MOVW(x2, offsetof(x86emu_t, fpu_ll)); //can be optimized?
ADD_REG_LSL_IMM5(x14, x14, x2, offsetof(fpu_ll_t, sref));
VLDR_64(v2, x14, 0);
VCEQ_32(v2, v2, v1); // compare
VMOVfrV_D(x2, x3, v2);
ANDS_REG_LSL_IMM5(x2, x2, x3, 0); // if NE then values are the same!
B_MARK(cEQ); // do the i64 conversion
// memcpy(ed, &STll(0).ll, sizeof(int64_t));
LDRD_IMM8(x2, x14, offsetof(fpu_ll_t, sq)); // load ll
B_MARK3(c__);
MARK;
// load round mode
LDRH_IMM8(x14, xEmu, offsetof(x86emu_t, cw)); // hopefully cw is not too far for an imm8
UBFX(x2, x14, 10, 2); // extract round...
MOV32(x14, round_map);
LDR_REG_LSL_IMM5(x2, x14, x2, 2);
VMOV_64(0, v1); // prepare call to log2
CALL_1DR_U64(x2, x2, x3, x14, (1<<x1));
MARK3;
STR_IMM9(x2, ed, 0);
STR_IMM9(x3, ed, 4);
#else
v0 = fpu_get_scratch_double(dyn);
s0 = fpu_get_scratch_single(dyn);
// check STll(0).ref==ST(0).q so emu->fpu_ll[emu->top].ref == emu->mmx87[emu->top]
// get TOP
LDR_IMM9(x14, xEmu, offsetof(x86emu_t, top));
int a = 0 - dyn->x87stack;
int a = 0 - dyn->n.x87stack;
if(a<0) {
SUB_IMM8(x14, x14, -a);
AND_IMM8(x14, x14, 7); // (emu->top + i)&7
@@ -380,7 +413,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
VDIV_F64(v2, v1, v0); // v2 = abs(ST0)/(1<<32) : so 32 bits high part
MSR_nzcvq_0();
VMRS(x2); // get fpscr
ORR_IMM8(x3, x2, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x2, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
VCVT_U32_F64(s0, v2); // convert high part to U32
@@ -407,6 +440,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK3;
STR_IMM9(x2, x1, 0);
STR_IMM9(x3, x1, 4);
#endif
#else
MESSAGE(LOG_DUMP, "Need Optimization\n");
x87_forget(dyn, ninst, x2, x3, 0);
+6 -51
View File
@@ -27,8 +27,6 @@
void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -63,9 +61,6 @@ void emit_or32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -77,7 +72,7 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
ORR_IMM8(s1, s1, c, 0);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
MOV32(s3, c);
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -109,8 +104,6 @@ void emit_or32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -145,9 +138,6 @@ void emit_xor32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -159,7 +149,7 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
XOR_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
MOV32(s3, c);
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -191,8 +181,6 @@ void emit_xor32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -227,9 +215,6 @@ void emit_and32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -248,7 +233,7 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
BIC_IMM8(s1, s1, ~c, 0);
}
} else {
IFX(X_PEND) {} else {MOV32(s3, c);}
MOV32(s3, c);
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -281,8 +266,6 @@ void emit_and32c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -317,9 +300,6 @@ void emit_or8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -354,8 +334,6 @@ void emit_or8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -390,9 +368,6 @@ void emit_xor8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -427,8 +402,6 @@ void emit_xor8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -463,9 +436,6 @@ void emit_and8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOV32(s3, c&0xff);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and8);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -501,8 +471,6 @@ void emit_and8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -537,9 +505,6 @@ void emit_or16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_or16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -551,7 +516,7 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
ORR_IMM8(s1, s1, c, 0);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
MOVW(s3, c);
IFX(X_ALL) {
ORRS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -583,8 +548,6 @@ void emit_or16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -619,9 +582,6 @@ void emit_xor16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_xor16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -633,7 +593,7 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
XOR_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
MOVW(s3, c);
IFX(X_ALL) {
XORS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
@@ -665,8 +625,6 @@ void emit_xor16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s2, xEmu, offsetof(x86emu_t, op2));
SET_DF(s3, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s3);
@@ -701,9 +659,6 @@ void emit_and16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
IFX(X_PEND) {
MOVW(s3, c);
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
SET_DF(s4, d_and16);
} else IFX(X_ALL) {
SET_DFNONE(s4);
@@ -715,7 +670,7 @@ void emit_and16c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s
AND_IMM8(s1, s1, c);
}
} else {
IFX(X_PEND) {} else {MOVW(s3, c);}
MOVW(s3, c);
IFX(X_ALL) {
ANDS_REG_LSL_IMM5(s1, s1, s3, 0);
} else {
+2 -2
View File
@@ -76,7 +76,7 @@ void emit_add32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// 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, int s1, int32_t c, int s3, int s4)
{
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.gen_flags==X_PEND || dyn->insts[ninst].x86.gen_flags==X_ALL)))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<256) {
@@ -210,7 +210,7 @@ void emit_sub32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
// 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, int s1, int32_t c, int s3, int s4)
{
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.need_flags==X_PEND || dyn->insts[ninst].x86.need_flags==X_ALL)))
if(s1==xESP && (!dyn->insts || (dyn->insts[ninst].x86.gen_flags==X_PEND || dyn->insts[ninst].x86.gen_flags==X_ALL)))
{
// special case when doing math on ESP and only PEND is needed: ignoring it!
if(c>=0 && c<256) {
+64
View File
@@ -469,6 +469,7 @@ void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
int j32;
MAYUSE(j32);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
@@ -521,6 +522,69 @@ void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit SHLD32 instruction, from s1, fill s2 , shift s3, store result in s1 using s4 and s3 as scratch
void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
int j32;
MAYUSE(j32);
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, op1));
STR_IMM9(s3, xEmu, offsetof(x86emu_t, op2));
// same flags calc as shl32
SET_DF(s4, d_shl32);
} else IFX(X_ALL) {
SET_DFNONE(s4);
}
CMPS_IMM8(s3, 0);
IFX(F_OF) {
BFC_COND(cEQ, xFlags, F_OF, 1);
}
IFX(X_PEND) {
STR_IMM9_COND(cEQ, s1, xEmu, offsetof(x86emu_t, res));
}
B_NEXT(cEQ);
IFX(X_CF) {
RSB_IMM8(s4, s3, 32);
MOV_REG_LSR_REG(s4, s1, s4);
BFI(xFlags, s4, F_CF, 1);
}
IFX(X_OF) {
MOVS_REG_LSL_REG(s1, s1, s3);
} else {
MOV_REG_LSL_REG(s1, s1, s3);
}
IFX(X_OF) {
MOVW_COND(cCS, s4, 1);
MOVW_COND(cCC, s4, 0);
CMPS_IMM8(s3, 1);
ORR_REG_LSR_IMM5_COND(cEQ, s4, s4, s1, 30);
BFI_COND(cEQ, xFlags, s4, F_OF, 1);
//else
BFC_COND(cNE, xFlags, F_OF, 1);
}
RSB_IMM8(s3, s3, 32);
IFX(X_ZF) {
ORRS_REG_LSR_REG(s1, s1, s2, s3);
} else {
ORR_REG_LSR_REG(s1, s1, s2, s3);
}
IFX(X_PEND) {
STR_IMM9(s1, xEmu, offsetof(x86emu_t, res));
}
IFX(X_ZF) {
ORR_IMM8_COND(cEQ, xFlags, xFlags, 1<<F_ZF, 0);
BIC_IMM8_COND(cNE, xFlags, xFlags, 1<<F_ZF, 0);
}
IFX(X_SF) {
MOV_REG_LSR_IMM5(s4, s1, 31);
BFI(xFlags, s4, F_SF, 1);
}
IFX(X_PF) {
emit_pf(dyn, ninst, s1, s3, s4);
}
}
// emit ROL8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
{
+3 -4
View File
@@ -374,7 +374,7 @@ void emit_test16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
}
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch
// emit TEST8 instruction, from test s1 , s2, using s3 and s4 as scratch. May destroy s2 also
void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
{
IFX_PENDOR0 {
@@ -401,10 +401,9 @@ void emit_test8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4)
}
// PF: (((emu->x86emu_parity_tab[(res) / 32] >> ((res) % 32)) & 1) == 0)
IFX(X_PF) {
AND_IMM8(s3, s3, 0xE0); // lsr 5 masking pre-applied
AND_IMM8(s2, s3, 0xE0); // lsr 5 masking pre-applied
MOV32(s4, GetParityTab());
LDR_REG_LSR_IMM5(s4, s4, s3, 5-2); // x/32 and then *4 because array is integer
AND_REG_LSL_IMM5(s3, s1, s2, 0);
LDR_REG_LSR_IMM5(s4, s4, s2, 5-2); // x/32 and then *4 because array is integer
AND_IMM8(s3, s3, 31);
MVN_REG_LSR_REG(s4, s4, s3);
BFI(xFlags, s4, F_PF, 1);
+145 -116
View File
@@ -19,6 +19,7 @@
#include "dynarec_arm_private.h"
#include "arm_printer.h"
#include "dynarec_arm_functions.h"
#include "dynarec_arm_helper.h"
@@ -50,7 +51,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_add8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_add8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
@@ -70,7 +71,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_add32(dyn, ninst, x1, gd, x3, x14);
@@ -94,7 +95,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_or8(dyn, ninst, x1, x2, x14, x3);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
GETGB(x2);
LDREXB(x1, wback);
@@ -115,7 +116,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_or32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_or32(dyn, ninst, x1, gd, x3, x14);
@@ -140,7 +141,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_adc8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_adc8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
@@ -161,7 +162,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_adc32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_adc32(dyn, ninst, x1, gd, x3, x14);
@@ -186,7 +187,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sbb8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_sbb8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
@@ -207,7 +208,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_sbb32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_sbb32(dyn, ninst, x1, gd, x3, x14);
@@ -231,7 +232,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_and8(dyn, ninst, x1, x2, x14, x3);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
GETGB(x2);
LDREXB(x1, wback);
@@ -252,7 +253,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_and32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_and32(dyn, ninst, x1, gd, x3, x14);
@@ -276,7 +277,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sub8(dyn, ninst, x1, x2, x14, x3, 0);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x1, wback);
emit_sub8(dyn, ninst, x1, x2, x14, x3, (wback==x3)?1:0);
@@ -296,7 +297,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_sub32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_sub32(dyn, ninst, x1, gd, x3, x14);
@@ -320,7 +321,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_xor8(dyn, ninst, x1, x2, x14, x3);
BFI(wback, ed, wb2*8, 8);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
GETGB(x2);
LDREXB(x1, wback);
@@ -341,7 +342,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_xor32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREX(x1, wback);
emit_xor32(dyn, ninst, x1, gd, x3, x14);
@@ -351,6 +352,10 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
DMB_ISH();
break;
case 0x66:
return dynarec66F0(dyn, addr, ip, ninst, ok, need_epilog);
break;
case 0x81:
case 0x83:
@@ -369,7 +374,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_add32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(!fixedaddress) {
TSTS_IMM8(wback, 0x3);
@@ -410,7 +415,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_or32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
@@ -431,7 +436,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_adc32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
@@ -452,7 +457,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_sbb32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
@@ -472,7 +477,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
emit_and32c(dyn, ninst, ed, i32, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
@@ -492,7 +497,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_sub32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
if(!fixedaddress) {
TSTS_IMM8(wback, 0x3);
@@ -533,7 +538,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
emit_xor32c(dyn, ninst, ed, i32, x3, x14);
} else {
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, LOCK_LOCK);
if(opcode==0x81) i32 = F32S; else i32 = F8S;
MARKLOCK;
LDREX(x1, wback);
@@ -608,7 +613,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = x2;
wb1 = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x2, wback);
ed = x2;
@@ -637,7 +642,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MARK3;
DMB_ISH();
// done, do the cmp now
emit_cmp8(dyn, ninst, x1, x2, x3, x14);
UFLAG_IF {emit_cmp8(dyn, ninst, x1, x2, x3, x14);}
break;
case 0xB1:
INST_NAME("LOCK CMPXCHG Ed, Gd");
@@ -647,50 +652,68 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
DMB_ISH();
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
TSTS_IMM8(wback, 3); // can be unaligned it seems
LDREX_COND(cEQ, x1, wback);
LDR_IMM9_COND(cNE, x1, wback, 0);
LDREXB_COND(cNE, x3, wback); // dummy read, to arm the write...
} else {
LDREX(x1, wback);
}
ed = x1;
}
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
if(wback) {
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
TSTS_IMM8(wback, 3);
STREX_COND(cEQ, x14, gd, wback);
STREXB_COND(cNE, x14, gd, wback);
} else {
STREX(x14, gd, wback);
}
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
TSTS_IMM8(wback, 3); // anoying, all those test
STR_IMM9_COND(cNE, gd, wback, 0);
}
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
} else {
emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);
// same as no lock, all in regs...
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
MOV_REG(x3, ed);
MOV_REG(ed, gd);
emit_cmp32(dyn, ninst, xEAX, x3, x1, x14);
B_NEXT(c__);
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);
MOV_REG(xEAX, ed);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
ed = x1;
if(!fixedaddress || (fixedaddress && (fixedaddress&3))) {
if(!fixedaddress) {
// alignment is undetermined
TSTS_IMM8(wback, 3);
B_MARK2(cNE);
MARKLOCK;
// aligned
LDREX(ed, wback);
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
STREX(x14, gd, wback);
DMB_ISH();
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
B_MARK(c__);
}
// unaligned
MARK2;
LDR_IMM9(x1, wback, 0);
LDREXB( x3, wback); // dummy read, to arm the write...
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
STREXB(x14, gd, wback);
CMPS_IMM8(x14, 0);
B_MARK2(cNE);
STR_IMM9(gd, wback, 0);
DMB_ISH();
} else {
MARKLOCK;
// alignment is good
LDREX(ed, wback);
CMPS_REG_LSL_IMM5(xEAX, ed, 0);
B_MARK(cNE);
// EAX == Ed
STREX(x14, gd, wback);
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
DMB_ISH();
}
// end of EAX == Ed or EAX != Ed
MARK;
UFLAG_IF { MOV_REG(x2, xEAX); }
MOV_REG(xEAX, ed);
UFLAG_IF { emit_cmp32(dyn, ninst, x2, ed, x3, x14); }
}
// done
B_MARK3(c__); // not next, in case its called with a LOCK prefix
MARK;
// EAX != Ed
emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);
MOV_REG(xEAX, ed);
MARK3
DMB_ISH();
break;
case 0xB3:
INST_NAME("LOCK BTR Ed, Gd");
@@ -703,7 +726,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
wback = x3;
@@ -739,7 +762,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x3, &fixedaddress, 4095-32, 0, 0, LOCK_LOCK);
LDR_IMM9(x1, ed, fixedaddress);
ed = x1;
}
@@ -762,7 +785,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(gd, u8&0x1f);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
ed = x1;
MOVW(gd, u8&0x1f);
@@ -793,7 +816,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
MOVW(gd, u8&0x1f);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
u8 = F8;
ed = x1;
MOVW(gd, u8&0x1f);
@@ -829,7 +852,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
ed = xEAX+(nextop&7);
wback = 0;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MOV_REG_ASR_IMM5(x1, gd, 5); // r1 = (gd>>5);
ADD_REG_LSL_IMM5(x3, wback, x1, 2); //(&ed)+=r1*4;
MARKLOCK;
@@ -864,7 +887,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
wb1 = 0;
ed = x2;
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, LOCK_LOCK);
MARKLOCK;
LDREXB(x2, wback);
wb1 = 1;
@@ -896,7 +919,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
}
emit_add32(dyn, ninst, ed, gd, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(wback, 3);
B_MARK(cNE); // unaligned
@@ -936,48 +959,54 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 0xC7:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
nextop = F8;
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDREX_COND(cNE, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
} else {
LDREXD(x2, wback);
switch((nextop>>3)&7) {
case 1:
INST_NAME("LOCK CMPXCHG8B Gq, Eq");
SETFLAGS(X_ZF, SF_SUBSET);
DMB_ISH();
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
LDREXD_COND(cEQ, x2, wback);
LDR_IMM9_COND(cNE, x3, wback, 4);
LDREX_COND(cNE, x2, wback);
} else {
LDREXD(x2, wback);
}
CMPS_REG_LSL_IMM5(xEAX, x2, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x3, 0);
B_MARK(cNE); // EDX != Ed[1]
MOV_REG(x2, xEBX);
MOV_REG(x3, xECX);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x14, x2, wback);
STREX_COND(cNE, x14, x2, wback);
} else {
STREXD(x14, x2, wback);
}
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STR_IMM9_COND(cNE, x3, wback, 4);
}
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x2);
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
DMB_ISH();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
DEFAULT;
}
CMPS_REG_LSL_IMM5(xEAX, x2, 0);
B_MARK(cNE); // EAX != Ed[0]
CMPS_REG_LSL_IMM5(xEDX, x3, 0);
B_MARK(cNE); // EDX != Ed[1]
MOV_REG(x2, xEBX);
MOV_REG(x3, xECX);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STREXD_COND(cEQ, x14, x2, wback);
STREX_COND(cNE, x14, x2, wback);
} else {
STREXD(x14, x2, wback);
}
CMPS_IMM8(x14, 0);
B_MARKLOCK(cNE);
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
STR_IMM9_COND(cNE, x3, wback, 4);
}
MOVW(x1, 1);
B_MARK3(c__);
MARK;
MOV_REG(xEAX, x2);
MOV_REG(xEDX, x3);
MOVW(x1, 0);
MARK3;
DMB_ISH();
BFI(xFlags, x1, F_ZF, 1);
break;
default:
@@ -993,12 +1022,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
{
case 0: // INC Ed
INST_NAME("INC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_inc32(dyn, ninst, ed, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(wback, 3);
B_MARK(cNE); // unaligned
@@ -1030,12 +1059,12 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 1: //DEC Ed
INST_NAME("DEC Ed");
SETFLAGS(X_ALL&~X_CF, SF_SUBSET);
SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
if((nextop&0xC0)==0xC0) {
ed = xEAX+(nextop&7);
emit_dec32(dyn, ninst, ed, x3, x14);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1);
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 1, LOCK_LOCK);
if(!fixedaddress) {
TSTS_IMM8(wback, 3);
B_MARK(cNE); // unaligned
+100 -10
View File
@@ -30,16 +30,20 @@
parity = getedparity(dyn, ninst, addr, nextop, 3); \
a = fpu_get_scratch_double(dyn); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL); \
VLDR_64(a, ed, fixedaddress); \
} else { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);\
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);\
LDR_IMM9(x2, ed, fixedaddress+0); \
LDR_IMM9(x3, ed, fixedaddress+4); \
VMOVtoV_D(a, x2, x3); \
} \
}
#define GETGM(a) \
gd = (nextop&0x38)>>3; \
a = mmx_get_reg(dyn, ninst, x1, x2, x3, gd)
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
uint8_t nextop = F8;
@@ -69,7 +73,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -86,7 +90,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(d0, v0);
} else {
VMOVfrV_D(x2, x3, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
}
@@ -101,7 +105,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(v0, d0);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-4, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -128,7 +132,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
@@ -144,7 +148,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
d0 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
d0 = fpu_get_scratch_double(dyn);
VLDR_64(d0, ed, fixedaddress);
}
@@ -159,7 +163,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSQRT_F64(v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
VMSR(x14); // restore FPSCR
}
break;
case 0x58:
@@ -168,7 +184,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
VMSR(x14); // restore FPSCR
}
break;
case 0x59:
INST_NAME("MULSD Gx, Ex");
@@ -176,7 +204,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
VMSR(x14); // restore FPSCR
}
break;
case 0x5A:
INST_NAME("CVTSD2SS Gx, Ex");
@@ -200,7 +240,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
VMSR(x14); // restore FPSCR
}
break;
case 0x5D:
INST_NAME("MINSD Gx, Ex");
@@ -219,7 +271,19 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
gd = (nextop&0x38)>>3;
v0 = sse_get_reg(dyn, ninst, x1, gd, 1);
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(v0, v0, d0);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
TSTS_IMM8_ROR(x3, 0b00000001, 0);
VNEG_F64_cond(cNE, v0, v0);
VMSR(x14); // restore FPSCR
}
break;
case 0x5F:
INST_NAME("MAXSD Gx, Ex");
@@ -241,7 +305,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -276,7 +340,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -288,6 +352,24 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
break;
case 0x80:
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8A:
case 0x8B:
case 0x8C:
case 0x8D:
case 0x8E:
case 0x8F:
return dynarec0F(dyn, addr-1, ip, ninst, ok, need_epilog);
case 0xC2:
INST_NAME("CMPSD Gx, Ex");
nextop = F8;
@@ -311,6 +393,14 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoV_D(v0, x2, x2);
break;
case 0xD6:
INST_NAME("MOVDQ2Q Gm, Ex");
nextop = F8;
GETGM(v0);
GETEX(v1, 0);
VMOV_64(v0, v1);
break;
case 0xF0:
INST_NAME("LDDQ Gx,Ex");
nextop = F8;
@@ -321,7 +411,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
+59 -21
View File
@@ -38,7 +38,7 @@
a = b*2; \
parity = getedparity(dyn, ninst, addr, nextop, 2); \
if(parity) { \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL); \
VLDR_32(a, ed, fixedaddress); \
} else { \
GETED; \
@@ -50,6 +50,9 @@
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETGX_empty(a) gd = ((nextop&0x38)>>3); \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
@@ -98,10 +101,17 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
}
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
VEORQ(v0, v0, v0);
VMOVtoDx_32(v0, 0, x2);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity && (v0<16)) {
VEORQ(v0, v0, v0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
VLDR_32(v0*2, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress); // to avoid bus errors
VEORQ(v0, v0, v0);
VMOVtoDx_32(v0, 0, x2);
}
}
break;
case 0x11:
@@ -128,9 +138,15 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(q0, d1);
}
} else {
VMOVfrDx_32(x2, v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
STR_IMM9(x2, ed, fixedaddress);
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity && (v0<16)) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 0, 0, NULL);
VSTR_32(v0*2, ed, fixedaddress);
} else {
VMOVfrDx_32(x2, v0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
STR_IMM9(x2, ed, fixedaddress);
}
}
break;
case 0x12:
@@ -140,7 +156,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
@@ -156,7 +172,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
q1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
q1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(q1, ed);
}
@@ -214,10 +230,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
@@ -243,10 +259,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_32(s0, ed, fixedaddress);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
VMOVtoV(s0, x2);
}
@@ -380,7 +396,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -485,7 +501,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVQ(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress+0);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
@@ -502,7 +518,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
if((nextop&0xC0)==0xC0) {
v1 = sse_get_reg(dyn, ninst, x1, nextop&7, 0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
v1 = fpu_get_scratch_quad(dyn);
VLD1Q_64(v1, ed);
}
@@ -539,7 +555,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVD(v0, v1);
} else {
v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
VLD1_64(v0, ed);
}
VEOR(v0+1, v0+1, v0+1);
@@ -553,7 +569,7 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v1 = sse_get_reg_empty(dyn, ninst, x1, nextop&7);
VMOVQ(v1, v0);
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-12, 0, 0, NULL);
VMOVfrV_D(x2, x3, v0);
STR_IMM9(x2, ed, fixedaddress+0);
STR_IMM9(x3, ed, fixedaddress+4);
@@ -614,6 +630,28 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VMOVtoDx_32(v0, 0, x2);
break;
case 0xD6:
INST_NAME("MOVQ2DQ Gx, Em");
nextop = F8;
GETGX_empty(v0);
if((nextop&0xC0)==0xC0) {
v1 = mmx_get_reg(dyn, ninst, x1, x2, x3, (nextop&7));
VEORQ(v0, v0, v0); // usefull?
VMOV_64(v0, v1);
} else {
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
}
}
break;
case 0xE6:
INST_NAME("CVTDQ2PD Gx, Ex");
nextop = F8;
@@ -629,10 +667,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
v0 = fpu_get_scratch_double(dyn);
parity = getedparity(dyn, ninst, addr, nextop, 3);
if(parity) {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 1023, 3, 0, NULL);
VLDR_64(v0, ed, fixedaddress); // vfpu opcode here
} else {
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 4095-8, 0, 0, NULL);
LDR_IMM9(x2, ed, fixedaddress);
LDR_IMM9(x3, ed, fixedaddress+4);
VMOVtoV_D(v0, x2, x3);
+393 -93
View File
@@ -8,6 +8,7 @@
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include "debug.h"
#include "box86context.h"
@@ -66,12 +67,12 @@ void arm_fxtract(x86emu_t* emu)
}
void arm_fprem(x86emu_t* emu)
{
int32_t tmp32s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp32s;
int64_t tmp64s = ST0.d / ST1.d;
ST0.d -= ST1.d * tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
}
void arm_frndint(x86emu_t* emu)
{
@@ -116,6 +117,43 @@ void arm_fistp64(x86emu_t* emu, int64_t* ed)
}
}
int64_t arm_fist64_0(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = nearbyint(d);
return tmp;
}
int64_t arm_fist64_1(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = floor(d);
return tmp;
}
int64_t arm_fist64_2(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = ceil(d);
return tmp;
}
int64_t arm_fist64_3(double d)
{
int64_t tmp;
if(isgreater(d, (double)(int64_t)0x7fffffffffffffffLL) || isless(d, (double)(int64_t)0x8000000000000000LL) || !isfinite(d))
tmp = 0x8000000000000000LL;
else
tmp = trunc(d);
return tmp;
}
void arm_fistt64(x86emu_t* emu, int64_t* ed)
{
// used of memcpy to avoid aligments issues
@@ -126,7 +164,7 @@ void arm_fistt64(x86emu_t* emu, int64_t* ed)
void arm_fld(x86emu_t* emu, uint8_t* ed)
{
memcpy(&STld(0).ld, ed, 10);
LD2D(&STld(0), &ST(0).d);
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
}
@@ -142,7 +180,7 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
LD2D(p, &ST(i).d);
D2LD(&ST(i).d, p);
p+=10;
}
}
@@ -153,7 +191,7 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
uint8_t* p = ed;
p += 28;
for (int i=0; i<8; ++i) {
D2LD(&ST(i).d, p);
LD2D(p, &ST(i).d);
p+=10;
}
@@ -162,48 +200,48 @@ void arm_frstor(x86emu_t* emu, uint8_t* ed)
void arm_fprem1(x86emu_t* emu)
{
// simplified version
int32_t tmp32s = round(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp32s;
int64_t tmp64s = lrint(ST0.d / ST1.d);
ST0.d -= ST1.d*tmp64s;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C0 = (tmp32s&1);
emu->sw.f.F87_C3 = ((tmp32s>>1)&1);
emu->sw.f.F87_C1 = ((tmp32s>>2)&1);
emu->sw.f.F87_C1 = (tmp64s&1);
emu->sw.f.F87_C3 = ((tmp64s>>1)&1);
emu->sw.f.F87_C0 = ((tmp64s>>2)&1);
}
// Get a FPU single scratch reg
int fpu_get_scratch_single(dynarec_arm_t* dyn)
{
return dyn->fpu_scratch++; // return an Sx
return dyn->n.fpu_scratch++; // return an Sx
}
// Get a FPU double scratch reg
int fpu_get_scratch_double(dynarec_arm_t* dyn)
{
int i = (dyn->fpu_scratch+1)&(~1);
dyn->fpu_scratch = i+2;
int i = (dyn->n.fpu_scratch+1)&(~1);
dyn->n.fpu_scratch = i+2;
return i/2; // return a Dx
}
// Get a FPU quad scratch reg
int fpu_get_scratch_quad(dynarec_arm_t* dyn)
{
if(dyn->fpu_scratch>4) {
if(dyn->fpu_extra_qscratch) {
if(dyn->n.fpu_scratch>4) {
if(dyn->n.fpu_extra_qscratch) {
dynarec_log(LOG_NONE, "Warning, Extra QScratch slot taken and need another one!\n");
} else
dyn->fpu_extra_qscratch = fpu_get_reg_quad(dyn, NEON_CACHE_SCR, 0);
return dyn->fpu_extra_qscratch;
dyn->n.fpu_extra_qscratch = fpu_get_reg_quad(dyn, NEON_CACHE_SCR, 0);
return dyn->n.fpu_extra_qscratch;
}
int i = (dyn->fpu_scratch+3)&(~3);
dyn->fpu_scratch = i+4;
int i = (dyn->n.fpu_scratch+3)&(~3);
dyn->n.fpu_scratch = i+4;
return i/2; // Return a Dx, not a Qx
}
// Reset scratch regs counter
void fpu_reset_scratch(dynarec_arm_t* dyn)
{
dyn->fpu_scratch = 0;
if(dyn->fpu_extra_qscratch) {
fpu_free_reg_quad(dyn, dyn->fpu_extra_qscratch);
dyn->fpu_extra_qscratch = 0;
dyn->n.fpu_scratch = 0;
if(dyn->n.fpu_extra_qscratch) {
fpu_free_reg_quad(dyn, dyn->n.fpu_extra_qscratch);
dyn->n.fpu_extra_qscratch = 0;
}
}
// Get a FPU double reg
@@ -211,10 +249,13 @@ int fpu_get_reg_double(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
{
// TODO: check upper limit?
int i=0;
while (dyn->fpuused[i]) ++i;
dyn->fpuused[i] = 1;
while (dyn->n.fpuused[i] && (i<24)) ++i;
assert(i<24);
dyn->n.fpuused[i] = 1;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i].t = t;
dyn->n.news |= (1<<i);
return i+FPUFIRST; // return a Dx
}
// Free a FPU double reg
@@ -222,7 +263,7 @@ void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
{
// TODO: check upper limit?
int i=reg-FPUFIRST;
dyn->fpuused[i] = 0;
dyn->n.fpuused[i] = 0;
if(dyn->n.neoncache[i].t!=NEON_CACHE_ST_F && dyn->n.neoncache[i].t!=NEON_CACHE_ST_D)
dyn->n.neoncache[i].v = 0;
}
@@ -230,36 +271,42 @@ void fpu_free_reg_double(dynarec_arm_t* dyn, int reg)
int fpu_get_reg_quad(dynarec_arm_t* dyn, unsigned int t, unsigned int n)
{
int i=0;
while (dyn->fpuused[i] || dyn->fpuused[i+1]) i+=2;
dyn->fpuused[i] = dyn->fpuused[i+1] = 1;
while ((dyn->n.fpuused[i] || dyn->n.fpuused[i+1]) && (i<24)) i+=2;
assert(i<24);
dyn->n.fpuused[i] = dyn->n.fpuused[i+1] = 1;
dyn->n.neoncache[i].t = t;
dyn->n.neoncache[i].n = n;
dyn->n.neoncache[i+1].t = t;
dyn->n.neoncache[i+1].n = n;
dyn->n.news |= (3<<i);
return i+FPUFIRST; // Return a Dx, not a Qx
}
// Free a FPU quad reg
void fpu_free_reg_quad(dynarec_arm_t* dyn, int reg)
{
int i=reg-FPUFIRST;
dyn->fpuused[i] = dyn->fpuused[i+1] = 0;
dyn->n.fpuused[i] = dyn->n.fpuused[i+1] = 0;
dyn->n.neoncache[i].v = 0;
dyn->n.neoncache[i+1].v = 0;
}
// Reset fpu regs counter
void fpu_reset_reg(dynarec_arm_t* dyn)
{
dyn->fpu_reg = 0;
dyn->n.fpu_reg = 0;
for (int i=0; i<24; ++i) {
dyn->fpuused[i]=0;
dyn->n.fpuused[i]=0;
dyn->n.neoncache[i].v = 0;
}
}
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a)
{
if(!dyn->insts)
return NEON_CACHE_ST_D;
if (dyn->insts[ninst].n.swapped) {
if(dyn->insts[ninst].n.combined1 == a)
a = dyn->insts[ninst].n.combined2;
else if(dyn->insts[ninst].n.combined2 == a)
a = dyn->insts[ninst].n.combined1;
}
for(int i=0; i<24; ++i)
if((dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
|| dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
@@ -283,114 +330,141 @@ int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a)
return NEON_CACHE_ST_D;
}
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st)
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a)
{
if(a+dyn->insts[ninst].n.stack_next-st<0)
/*if(a+dyn->insts[ninst].n.stack_next-st<0)
// The STx has been pushed at the end of instructon, so stop going back
return -1;
return -1;*/
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a, int st)
int neoncache_get_st_f_noback(dynarec_arm_t* dyn, int ninst, int a)
{
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->insts[ninst].n.neoncache[i].n==a+dyn->insts[ninst].n.stack-st)
&& dyn->insts[ninst].n.neoncache[i].n==a)
return i;
return -1;
}
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a, int st)
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a)
{
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].t==NEON_CACHE_ST_F
&& dyn->n.neoncache[i].n==a+dyn->n.stack-st)
&& dyn->n.neoncache[i].n==a)
return i;
return -1;
}
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st);
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a);
static void neoncache_promote_double_combined(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
if(a == dyn->insts[ninst].n.combined1) {
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined2, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined2 %d i=%d\n", ninst, dyn->insts[ninst].n.combined2 ,i);
if(a == dyn->insts[ninst].n.combined1 || a == dyn->insts[ninst].n.combined2) {
if(a == dyn->insts[ninst].n.combined1) {
a = dyn->insts[ninst].n.combined2;
} else
a = dyn->insts[ninst].n.combined1;
int i = neoncache_get_st_f_noback(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_combined, ninst=%d combined%c %d i=%d (stack:%d/%d)\n", ninst, (a == dyn->insts[ninst].n.combined2)?'2':'1', a ,i, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined2, st);
if(!dyn->insts[ninst].n.barrier)
neoncache_promote_double_internal(dyn, ninst-1, maxinst, a-dyn->insts[ninst].n.stack_push);
// go forward is combined is not pop'd
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined2)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined2, st);
}
} else if(a == dyn->insts[ninst].n.combined2) {
int i = neoncache_get_st_f_noback(dyn, ninst, dyn->insts[ninst].n.combined1, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined1 %d i=%d\n", ninst, dyn->insts[ninst].n.combined1 ,i);
if(i>=0) {
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
neoncache_promote_double_internal(dyn, ninst-1, maxinst, dyn->insts[ninst].n.combined1, st);
// go forward is combined is not pop'd
if(dyn->insts[ninst].n.stack_next-dyn->insts[ninst].n.stack<=dyn->insts[ninst].n.combined1)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, dyn->insts[ninst].n.combined1, st);
if(a-dyn->insts[ninst].n.stack_pop>=0)
if(!dyn->insts[ninst+1].n.barrier)
neoncache_promote_double_forward(dyn, ninst+1, maxinst, a-dyn->insts[ninst].n.stack_pop);
}
}
}
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_internal(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
if(dyn->insts[ninst+1].n.barrier)
return;
while(ninst>=0) {
int i = neoncache_get_st_f(dyn, ninst, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
a+=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: add pop'd ST (going backward)
int i = neoncache_get_st_f(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d, a=%d st=%d:%d, i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->insts[ninst].n.stack-st; // adjust STx
st = dyn->insts[ninst].n.stack; // new stack depth
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
if(dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
} else {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_internal, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
}
a-=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: remove push'd ST (going backward)
--ninst;
if(ninst<0 || a<0 || dyn->insts[ninst].n.barrier)
return;
}
}
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a, int st)
static void neoncache_promote_double_forward(dynarec_arm_t* dyn, int ninst, int maxinst, int a)
{
while(ninst<maxinst) {
int i = neoncache_get_st_f_noback(dyn, ninst, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d/%d, i=%d\n", ninst, a, st, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, i);
while((ninst!=-1) && (ninst<maxinst) && (a>=0)) {
a+=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: add push'd ST (going forward)
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d swapped %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
if (a==dyn->insts[ninst].n.combined1)
a = dyn->insts[ninst].n.combined2;
else if (a==dyn->insts[ninst].n.combined2)
a = dyn->insts[ninst].n.combined1;
}
int i = neoncache_get_st_f_noback(dyn, ninst, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d, a=%d st=%d:%d(%d/%d), i=%d\n", ninst, a, dyn->insts[ninst].n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop, i);
if(i<0) return;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->insts[ninst].n.stack-st; // adjust STx
st = dyn->insts[ninst].n.stack; // new stack depth
// check combined propagation too
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d/%d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, st, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a, st);
if((dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) && !dyn->insts[ninst].n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double_forward, ninst=%d combined %d/%d vs %d with st %d\n", ninst, dyn->insts[ninst].n.combined1 ,dyn->insts[ninst].n.combined2, a, dyn->insts[ninst].n.stack);
neoncache_promote_double_combined(dyn, ninst, maxinst, a);
}
++ninst;
a-=dyn->insts[ninst].n.stack_pop; // adjust Stack depth: remove pop'd ST (going forward)
if(dyn->insts[ninst].x86.has_next && !dyn->insts[ninst].n.barrier)
++ninst;
else
ninst=-1;
}
neoncache_promote_double(dyn, ninst, a, st);
if(ninst==maxinst)
neoncache_promote_double(dyn, ninst, a);
}
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st)
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a)
{
int i = neoncache_get_current_st_f(dyn, a, st);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d/%d i=%d\n", ninst, a, st, dyn->n.stack, i);
int i = neoncache_get_current_st_f(dyn, a);
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d a=%d st=%d i=%d\n", ninst, a, dyn->n.stack, i);
if(i<0) return;
dyn->n.neoncache[i].t = NEON_CACHE_ST_D;
a+=dyn->n.stack-st;
st = dyn->n.stack;
dyn->insts[ninst].n.neoncache[i].t = NEON_CACHE_ST_D;
// check combined propagation too
if(dyn->n.combined1 || dyn->n.combined2) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined2, st);
else if(dyn->n.combined2 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined1, st);
if(dyn->n.swapped) {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d swapped! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
a = dyn->n.combined2;
else if(dyn->n.combined2 == a)
a = dyn->n.combined1;
} else {
//if(box86_dynarec_dump) dynarec_log(LOG_NONE, "neoncache_promote_double, ninst=%d combined! %d/%d vs %d\n", ninst, dyn->n.combined1 ,dyn->n.combined2, a);
if(dyn->n.combined1 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined2);
else if(dyn->n.combined2 == a)
neoncache_promote_double(dyn, ninst, dyn->n.combined1);
}
}
if(!ninst) return;
neoncache_promote_double_internal(dyn, ninst-1, ninst, a, st);
a-=dyn->insts[ninst].n.stack_push; // // adjust Stack depth: remove push'd ST (going backward)
if(!ninst || a<0) return;
neoncache_promote_double_internal(dyn, ninst-1, ninst, a);
}
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
@@ -403,6 +477,158 @@ int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b)
return NEON_CACHE_ST_D;
}
int isPred(dynarec_arm_t* dyn, int ninst, int pred) {
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
if(dyn->insts[ninst].pred[i]==pred)
return pred;
return -1;
}
int getNominalPred(dynarec_arm_t* dyn, int ninst) {
if((ninst<=0) || !dyn->insts[ninst].pred_sz)
return -1;
if(isPred(dyn, ninst, ninst-1)!=-1)
return ninst-1;
return dyn->insts[ninst].pred[0];
}
static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int i2 = dyn->insts[ninst].x86.jmp_insts;
if(i2<0)
return 1;
if((dyn->insts[i2].x86.barrier&BARRIER_FLOAT))
return ((dyn->insts[ninst].x86.barrier&BARRIER_FLOAT))?0:1; // if the barrier as already been apply, no transform needed
int ret = 0;
if(!i2) { // just purge
if(dyn->insts[ninst].n.stack_next) {
return 1;
}
for(int i=0; i<24 && !ret; ++i)
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!(
(dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_F || dyn->insts[ninst].n.neoncache[i].t==NEON_CACHE_ST_D)
&& dyn->insts[ninst].n.neoncache[i].n<dyn->insts[ninst].n.stack_pop))
ret = 1;
}
return ret;
}
// Check if ninst can be compatible to i2
if(dyn->insts[ninst].n.stack_next != dyn->insts[i2].n.stack-dyn->insts[i2].n.stack_push) {
return 1;
}
neoncache_t cache_i2 = dyn->insts[i2].n;
neoncacheUnwind(&cache_i2);
for(int i=0; i<24; ++i) {
if(dyn->insts[ninst].n.neoncache[i].v) { // there is something at ninst for i
if(!cache_i2.neoncache[i].v) { // but there is nothing at i2 for i
ret = 1;
} else if(dyn->insts[ninst].n.neoncache[i].v!=cache_i2.neoncache[i].v) { // there is something different
if(dyn->insts[ninst].n.neoncache[i].n!=cache_i2.neoncache[i].n) { // not the same x86 reg
ret = 1;
}
else if(dyn->insts[ninst].n.neoncache[i].t == NEON_CACHE_XMMR && cache_i2.neoncache[i].t == NEON_CACHE_XMMW)
{/* nothing */ }
else
ret = 1;
}
} else if(cache_i2.neoncache[i].v)
ret = 1;
}
return ret;
}
void neoncacheUnwind(neoncache_t* cache)
{
if(cache->swapped) {
// unswap
int a = -1;
int b = -1;
for(int j=0; j<24 && ((a==-1) || (b==-1)); ++j)
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if(cache->neoncache[j].n == cache->combined1)
a = j;
else if(cache->neoncache[j].n == cache->combined2)
b = j;
}
if(a!=-1 && b!=-1) {
int tmp = cache->neoncache[a].n;
cache->neoncache[a].n = cache->neoncache[b].n;
cache->neoncache[b].n = tmp;
}
cache->swapped = 0;
cache->combined1 = cache->combined2 = 0;
}
if(cache->news) {
// reove the newly created neoncache
for(int i=0; i<24; ++i)
if(cache->news&(1<<i))
cache->neoncache[i].v = 0;
cache->news = 0;
}
if(cache->stack_push) {
// unpush
for(int j=0; j<24; ++j) {
if((cache->neoncache[j].t == NEON_CACHE_ST_D || cache->neoncache[j].t == NEON_CACHE_ST_F)) {
if(cache->neoncache[j].n<cache->stack_push)
cache->neoncache[j].v = 0;
else
cache->neoncache[j].n-=cache->stack_push;
}
}
cache->x87stack-=cache->stack_push;
cache->stack-=cache->stack_push;
cache->stack_push = 0;
}
cache->x87stack+=cache->stack_pop;
cache->stack_next = cache->stack;
cache->stack_pop = 0;
cache->barrier = 0;
// And now, rebuild the x87cache info with neoncache
cache->mmxcount = 0;
cache->fpu_scratch = 0;
cache->fpu_extra_qscratch = 0;
cache->fpu_reg = 0;
for(int i=0; i<8; ++i) {
cache->x87cache[i] = -1;
cache->mmxcache[i] = -1;
cache->ssecache[i].v = -1;
cache->x87reg[i] = 0;
}
int x87reg = 0;
for(int i=0; i<24; ++i) {
if(cache->neoncache[i].v) {
cache->fpuused[i] = 1;
switch (cache->neoncache[i].t) {
case NEON_CACHE_MM:
cache->mmxcache[cache->neoncache[i].n] = i+FPUFIRST;
++cache->mmxcount;
++cache->fpu_reg;
break;
case NEON_CACHE_XMMR:
case NEON_CACHE_XMMW:
cache->ssecache[cache->neoncache[i].n].reg = i+FPUFIRST;
cache->ssecache[cache->neoncache[i].n].write = (cache->neoncache[i].t==NEON_CACHE_XMMW)?1:0;
++cache->fpu_reg;
++i; // next next
break;
case NEON_CACHE_ST_F:
case NEON_CACHE_ST_D:
cache->x87cache[x87reg] = cache->neoncache[i].n;
cache->x87reg[x87reg] = i+FPUFIRST;
++x87reg;
++cache->fpu_reg;
break;
case NEON_CACHE_SCR:
cache->fpuused[i] = 0;
cache->neoncache[i].v = 0;
break;
}
} else {
cache->fpuused[i] = 0;
}
}
}
#define F8 *(uint8_t*)(addr++)
#define F32 *(uint32_t*)(addr+=4, addr-4)
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
@@ -496,3 +722,77 @@ int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int
#undef PK
}
const char* getCacheName(int t, int n)
{
static char buff[20];
switch(t) {
case NEON_CACHE_ST_D: sprintf(buff, "ST%d", n); break;
case NEON_CACHE_ST_F: sprintf(buff, "st%d", n); break;
case NEON_CACHE_MM: sprintf(buff, "MM%d", n); break;
case NEON_CACHE_XMMW: sprintf(buff, "XMM%d", n); break;
case NEON_CACHE_XMMR: sprintf(buff, "xmm%d", n); break;
case NEON_CACHE_SCR: sprintf(buff, "Scratch"); break;
case NEON_CACHE_NONE: buff[0]='\0'; break;
}
return buff;
}
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst)
{
// check flags cache
if(dyn->insts[ninst].f_entry.dfnone || dyn->insts[ninst].f_entry.pending)
return 0;
if(dyn->insts[ninst].x86.state_flags)
return 0;
// check neoncache
neoncache_t* n = &dyn->insts[ninst].n;
if(n->news || n->stack || n->stack_next)
return 0;
for(int i=0; i<24; ++i)
if(n->neoncache[i].v)
return 0;
return 1;
}
static int flagsCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int jmp = dyn->insts[ninst].x86.jmp_insts;
if(jmp<0)
return 0;
if(dyn->insts[ninst].f_exit.dfnone) // flags are fully known, nothing we can do more
return 0;
/* if((dyn->f.pending!=SF_SET)
&& (dyn->f.pending!=SF_SET_PENDING)) {
if(dyn->f.pending!=SF_PENDING) {*/
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: return 0;
case SF_SET:
if(dyn->insts[ninst].f_exit.pending!=SF_SET && dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING)
return 1;
else
return 0;
case SF_SET_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return 0;
case SF_PENDING:
if(dyn->insts[ninst].f_exit.pending!=SF_SET
&& dyn->insts[ninst].f_exit.pending!=SF_SET_PENDING
&& dyn->insts[ninst].f_exit.pending!=SF_PENDING)
return 1;
else
return (dyn->insts[jmp].f_entry.dfnone == dyn->insts[ninst].f_exit.dfnone)?0:1;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->insts[ninst].f_exit.dfnone)
return 1;
return 0;
}
int CacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int ret = 0;
if (fpuCacheNeedsTransform(dyn, ninst)) ret|=1;
if (flagsCacheNeedsTransform(dyn, ninst)) ret|=2;
return ret;
}
+25 -2
View File
@@ -23,6 +23,11 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
int64_t arm_fist64_0(double d);
int64_t arm_fist64_1(double d);
int64_t arm_fist64_2(double d);
int64_t arm_fist64_3(double d);
void arm_ud(x86emu_t* emu);
#define FPUFIRST 8
@@ -50,13 +55,29 @@ void fpu_reset_reg(dynarec_arm_t* dyn);
// Get type for STx
int neoncache_get_st(dynarec_arm_t* dyn, int ninst, int a);
// Get if STx is FLOAT or DOUBLE
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a, int st);
int neoncache_get_st_f(dynarec_arm_t* dyn, int ninst, int a);
// Get actual type for STx
int neoncache_get_current_st(dynarec_arm_t* dyn, int ninst, int a);
// Get actual STx is FLOAT or DOUBLE
int neoncache_get_current_st_f(dynarec_arm_t* dyn, int a);
// Back-propagate a change float->double
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a, int st);
void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
// Combine and propagate if needed (pass 1 only)
int neoncache_combine_st(dynarec_arm_t* dyn, int ninst, int a, int b); // with stack current dyn->n_stack*
// FPU Cache transformation (for loops)
int CacheNeedsTransform(dynarec_arm_t* dyn, int i1);
// Undo the changes of a neoncache to get the status before the instruction
void neoncacheUnwind(neoncache_t* cache);
// is inst clean for a son branch?
int isInstClean(dynarec_arm_t* dyn, int ninst);
// predecessor access
int isPred(dynarec_arm_t* dyn, int ninst, int pred);
int getNominalPred(dynarec_arm_t* dyn, int ninst);
// Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD
int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity);
// Do the GETED, but don't emit anything...
@@ -65,4 +86,6 @@ uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop);
// Is what pointed at addr a native call? And if yes, to what function?
int isNativeCall(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t* calladdress, int* retn);
const char* getCacheName(int t, int n);
#endif //__DYNAREC_ARM_FUNCTIONS_H__
File diff suppressed because it is too large. Load diff
+88 -46
View File
@@ -27,6 +27,9 @@
#define PKip(a) *(uint8_t*)(ip+a)
#define PKa(a) *(uint8_t*)(a)
//LOCK_* define
#define LOCK_LOCK (int*)1
// GETGD get x86 register in gd
#define GETGD gd = xEAX+((nextop&0x38)>>3)
//GETED can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
@@ -34,7 +37,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(x1, wback, fixedaddress); \
ed = x1; \
}
@@ -43,7 +46,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, (hint==x2)?x1:x2, &fixedaddress, 4095, 0, 0, NULL); \
LDR_IMM9(hint, wback, fixedaddress); \
ed = hint; \
}
@@ -53,7 +56,7 @@
MOV_REG(ret, ed); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, hint, &fixedaddress, 4095, 0, 0, NULL); \
ed = ret; \
LDR_IMM9(ed, wback, fixedaddress); \
}
@@ -66,7 +69,7 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
LDR_REG_LSL_IMM5(x1, wback, O, 0); \
ed = x1; \
}
@@ -75,8 +78,9 @@
ed = xEAX+(nextop&7); \
wback = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, O, 0);\
addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, 0, 0, 0, NULL); \
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
ed = x1; \
}
@@ -94,7 +98,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, w, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -106,7 +110,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRH_IMM8(i, wback, fixedaddress); \
ed = i; \
wb1 = 1; \
@@ -118,7 +122,7 @@
ed = i; \
wb1 = 0; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSH_IMM8(i, wback, fixedaddress);\
ed = i; \
wb1 = 1; \
@@ -138,7 +142,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 4095, 0, 0, NULL); \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
@@ -152,9 +156,10 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0); \
ADD_REG_LSL_IMM5(wback, wback, i, 0); \
LDRB_IMM9(i, wback, fixedaddress); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0, 0, 0, NULL); \
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
if(wback!=x3) wback = x3; \
LDRB_IMM9(i, wback, fixedaddress); \
wb1 = 1; \
ed = i; \
}
@@ -167,7 +172,7 @@
wb1 = 0; \
ed = i; \
} else { \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0); \
addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 255, 0, 0, NULL); \
LDRSB_IMM8(i, wback, fixedaddress);\
wb1 = 1; \
ed = i; \
@@ -211,6 +216,12 @@
#define CALL_2D(F, M) call_d(dyn, ninst, F, NULL, 2, x3, -1, M, 0)
// CALL_1DD will use x3 for the call address. Return value in D0, 1 ARG in D0, cals 2 functions in a row
#define CALL_1DD(F, F2, M) call_d(dyn, ninst, F, F2, 1, x3, -1, M, 0)
// CALL_1D_U64 will use S as scratch. Return value in ret/ret2, 1 ARG in D0
#define CALL_1DR_U64(R, ret, ret2, S, M) call_dr(dyn, ninst, R, 1, S, ret, ret2, M, 1)
// CALL_1D will use S as scratch. Return value in D0, 1 ARG in D0
#define CALL_1DR(R, S, M) call_dr(dyn, ninst, R, 1, S, -1, -1, M, 0)
// CALL_1RD will use S as scratch. Return value in D0, 1 ARG in R
#define CALL_1RD(F, R, S, M) call_rd(dyn, ninst, F, R, S, M, 0);
#define MARK if(dyn->insts) {dyn->insts[ninst].mark = (uintptr_t)dyn->arm_size;}
#define GETMARK ((dyn->insts)?dyn->insts[ninst].mark:(dyn->arm_size+4))
@@ -239,7 +250,7 @@
Bcond(cond, j32)
// Branch to next instruction if cond (use j32)
#define B_NEXT(cond) \
j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size+8)):0; \
j32 = dyn->insts[ninst].epilog-(dyn->arm_size+8); \
Bcond(cond, j32)
// Branch to MARKSEG if cond (use j32)
#define B_MARKSEG(cond) \
@@ -250,11 +261,11 @@
j32 = GETMARKLOCK-(dyn->arm_size+8); \
Bcond(cond, j32)
#define IFX(A) if((dyn->insts[ninst].x86.need_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.need_flags&(X_PEND) || !dyn->insts[ninst].x86.need_flags))
#define IFXX(A) if((dyn->insts[ninst].x86.need_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x86.need_flags==(A) || dyn->insts[ninst].x86.need_flags==(B) || dyn->insts[ninst].x86.need_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x86.need_flags&(A) && !(dyn->insts[ninst].x86.need_flags&(B))))
#define IFX(A) if((dyn->insts[ninst].x86.gen_flags&(A)))
#define IFX_PENDOR0 if((dyn->insts[ninst].x86.gen_flags&(X_PEND) || !dyn->insts[ninst].x86.gen_flags))
#define IFXX(A) if((dyn->insts[ninst].x86.gen_flags==(A)))
#define IFX2X(A, B) if((dyn->insts[ninst].x86.gen_flags==(A) || dyn->insts[ninst].x86.gen_flags==(B) || dyn->insts[ninst].x86.gen_flags==((A)|(B))))
#define IFXN(A, B) if((dyn->insts[ninst].x86.gen_flags&(A) && !(dyn->insts[ninst].x86.gen_flags&(B))))
// Generate FCOM with s1 and s2 scratch regs (the VCMP is already done)
#define FCOM(s1, s2) \
@@ -284,15 +295,20 @@
} \
#define SET_DFNONE(S) if(!dyn->dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->dfnone = 0
#define SET_DFOK() dyn->dfnone = 1
#define SET_DFNONE(S) if(!dyn->f.dfnone) {MOVW(S, d_none); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=1;}
#define SET_DF(S, N) if(N) {MOVW(S, N); STR_IMM9(S, xEmu, offsetof(x86emu_t, df)); dyn->f.dfnone=0;} else SET_DFNONE(S)
#define SET_NODF() dyn->f.dfnone = 0
#define SET_DFOK() dyn->f.dfnone = 1
#ifndef MAYSETFLAGS
#define MAYSETFLAGS()
#endif
#ifndef READFLAGS
#define READFLAGS(A) \
if(((A)!=X_PEND) && dyn->state_flags!=SF_SET && dyn->state_flags!=SF_SET_PENDING) { \
if(dyn->state_flags!=SF_PENDING) { \
if((dyn->f.pending!=SF_SET) \
&& (dyn->f.pending!=SF_SET_PENDING)) { \
if(dyn->f.pending!=SF_PENDING) { \
LDR_IMM9(x3, xEmu, offsetof(x86emu_t, df)); \
TSTS_REG_LSL_IMM5(x3, x3, 0); \
j32 = (GETMARKF)-(dyn->arm_size+8); \
@@ -300,16 +316,26 @@
} \
CALL_(UpdateFlags, -1, 0); \
MARKF; \
dyn->state_flags = SF_SET; \
dyn->f.pending = SF_SET; \
SET_DFOK(); \
}
#endif
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->state_flags!=SF_SET && B==SF_SUBSET && (dyn->insts[ninst].x86.need_flags&(~((A)/*|X_PEND*/)))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
dyn->state_flags = (B==SF_SUBSET)?SF_SET: \
((B==SF_SET_PENDING && !(dyn->insts[ninst].x86.need_flags&X_PEND)?SF_SET:B))
#define SETFLAGS(A, B) \
if(dyn->f.pending!=SF_SET \
&& ((B)&SF_SUB) \
&& (dyn->insts[ninst].x86.gen_flags&(~(A)))) \
READFLAGS(((dyn->insts[ninst].x86.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x86.gen_flags)&(~(A)));\
if(dyn->insts[ninst].x86.gen_flags) switch(B) { \
case SF_SUBSET: \
case SF_SET: dyn->f.pending = SF_SET; break; \
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
case SF_SUBSET_PENDING: \
case SF_SET_PENDING: \
dyn->f.pending = (dyn->insts[ninst].x86.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
break; \
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
#define JUMP(A, C)
@@ -320,17 +346,14 @@
#ifndef BARRIER_NEXT
#define BARRIER_NEXT(A)
#endif
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.need_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.need_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x86.need_flags)
#define UFLAG_OP1(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op1));}
#define UFLAG_OP2(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, op2));}
#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A1, xEmu, offsetof(x86emu_t, op1));STR_IMM9(A2, 0, offsetof(x86emu_t, op2));}
#define UFLAG_RES(A) if(dyn->insts[ninst].x86.gen_flags) {STR_IMM9(A, xEmu, offsetof(x86emu_t, res));}
#define UFLAG_DF(r, A) if(dyn->insts[ninst].x86.gen_flags) {SET_DF(r, A)}
#define UFLAG_IF if(dyn->insts[ninst].x86.gen_flags)
#ifndef DEFAULT
#define DEFAULT *ok = -1; BARRIER(2)
#endif
#ifndef NEW_BARRIER_INST
#define NEW_BARRIER_INST
#define DEFAULT *ok = -1; BARRIER(BARRIER_NOFLAGS)
#endif
#if STEP < 2
@@ -368,6 +391,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define dynarecDF STEPNAME(dynarecDF)
#define dynarecF0 STEPNAME(dynarecF0)
#define dynarec660F STEPNAME(dynarec660F)
#define dynarec66F0 STEPNAME(dynarec66F0)
#define dynarecF20F STEPNAME(dynarecF20F)
#define dynarecF30F STEPNAME(dynarecF30F)
@@ -380,6 +404,8 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define iret_to_epilog STEPNAME(iret_to_epilog_)
#define call_c STEPNAME(call_c_)
#define call_d STEPNAME(call_d_)
#define call_dr STEPNAME(call_dr_)
#define call_rd STEPNAME(call_rd_)
#define grab_fsdata STEPNAME(grab_fsdata_)
#define grab_tlsdata STEPNAME(grab_tlsdata_)
#define emit_cmp8 STEPNAME(emit_cmp8)
@@ -454,6 +480,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define emit_shrd32c STEPNAME(emit_shrd32c)
#define emit_shld32c STEPNAME(emit_shld32c)
#define emit_shrd32 STEPNAME(emit_shrd32)
#define emit_shld32 STEPNAME(emit_shld32)
#define emit_pf STEPNAME(emit_pf)
@@ -471,6 +498,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define x87_stackcount STEPNAME(x87_stackcount)
#define x87_setround STEPNAME(x87_setround)
#define x87_restoreround STEPNAME(x87_restoreround)
#define x87_swapreg STEPNAME(x87_swapreg)
#define sse_setround STEPNAME(sse_setround)
#define mmx_get_reg STEPNAME(mmx_get_reg)
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
@@ -492,8 +520,10 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
// put back (if needed) the single reg in place
#define fpu_putback_single_reg STEPNAME(fpu_putback_single_reg)
#define CacheTransform STEPNAME(CacheTransform)
/* setup r2 to address pointed by */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly);
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask, int getfixonly, int* l);
/* setup r2 to address pointed by */
uintptr_t geted16(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixedaddress, uint32_t absmax, uint32_t mask);
@@ -507,10 +537,10 @@ void retn_to_epilog(dynarec_arm_t* dyn, int ninst, int n);
void iret_to_epilog(dynarec_arm_t* dyn, int ninst);
void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, uint32_t mask, int saveflags);
void call_d(dynarec_arm_t* dyn, int ninst, void* fnc, void* fnc2, int n, int reg, int ret, uint32_t mask, int saveflags);
void call_dr(dynarec_arm_t* dyn, int ninst, int reg, int n, int s1, int ret, int ret2, uint32_t mask, int saveflags);
void call_rd(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int s1, uint32_t mask, int saveflags);
void grab_fsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void grab_tlsdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg);
void emit_lock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_unlock(dynarec_arm_t* dyn, uintptr_t addr, int ninst);
void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_cmp32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
@@ -583,6 +613,7 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, int32_t c, int s3, int s4
void emit_shrd32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shld32c(dynarec_arm_t* dyn, int ninst, int s1, int s2, int32_t c, int s3, int s4);
void emit_shrd32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_shld32(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4);
void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4);
@@ -615,9 +646,19 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st);
int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3);
// Restore round flag
void x87_restoreround(dynarec_arm_t* dyn, int ninst, int s1);
// swap 2 x87 regs
void x87_swapreg(dynarec_arm_t* dyn, int ninst, int s1, int s2, int a, int b);
// 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);
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3);
#if STEP < 2
#define CHECK_CACHE() 0
#else
#define CHECK_CACHE() (cacheupd = CacheNeedsTransform(dyn, ninst))
#endif
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
int neoncache_st_coherency(dynarec_arm_t* dyn, int ninst, int a, int b);
@@ -656,7 +697,7 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// common coproc helpers
// reset the cache
void fpu_reset(dynarec_arm_t* dyn, int ninst);
void fpu_reset(dynarec_arm_t* dyn);
// purge the FPU cache (needs 3 scratch registers) next=1 if for a conditionnal branch jumping out of block (no tracking updated)
void fpu_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
void x87_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1, int s2, int s3);
@@ -688,6 +729,7 @@ uintptr_t dynarecDE(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog);
+122 -21
View File
@@ -30,21 +30,77 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
{
int ok = 1;
int ninst = 0;
int j32;
uintptr_t ip = addr;
uintptr_t init_addr = addr;
MAYUSE(init_addr);
int need_epilog = 1;
dyn->sons_size = 0;
// Clean up (because there are multiple passes)
dyn->state_flags = 0;
dyn->dfnone = 0;
fpu_reset(dyn, ninst);
dyn->f.pending = 0;
dyn->f.dfnone = 0;
fpu_reset(dyn);
int reset_n = -1;
// ok, go now
INIT;
while(ok) {
ip = addr;
if((dyn->insts[ninst].x86.barrier==1)) {
NEW_BARRIER_INST;
if (reset_n!=-1) {
if(reset_n==-2) {
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
dyn->f.dfnone = 0;
dyn->f.pending = 0;
fpu_reset(dyn);
} else {
MESSAGE(LOG_DEBUG, "Reset Caches with %d\n",reset_n);
#if STEP > 1
// for STEP 2 & 3, just need to refrest with current, and undo the changes (push & swap)
dyn->n = dyn->insts[ninst].n;
neoncacheUnwind(&dyn->n);
#ifdef HAVE_TRACE
if(box86_dynarec_dump)
if(memcmp(&dyn->n, &dyn->insts[reset_n].n, sizeof(neon_cache_t))) {
MESSAGE(LOG_DEBUG, "Warning, difference in neoncache: reset=");
for(int i=0; i<24; ++i)
if(dyn->insts[reset_n].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[reset_n].n.neoncache[i].t, dyn->insts[reset_n].n.neoncache[i].n));
if(dyn->insts[reset_n].n.combined1 || dyn->insts[reset_n].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[reset_n].n.swapped?"SWP":"CMB", dyn->insts[reset_n].n.combined1, dyn->insts[reset_n].n.combined2);
if(dyn->insts[reset_n].n.stack_push || dyn->insts[reset_n].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[reset_n].n.stack_push, -dyn->insts[reset_n].n.stack_pop);
MESSAGE(LOG_DEBUG, " ==> ");
for(int i=0; i<24; ++i)
if(dyn->insts[ninst].n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->insts[ninst].n.neoncache[i].t, dyn->insts[ninst].n.neoncache[i].n));
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2);
if(dyn->insts[ninst].n.stack_push || dyn->insts[ninst].n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->insts[ninst].n.stack_push, -dyn->insts[ninst].n.stack_pop);
MESSAGE(LOG_DEBUG, " -> ");
for(int i=0; i<24; ++i)
if(dyn->n.neoncache[i].v)
MESSAGE(LOG_DEBUG, " %02d:%s", i, getCacheName(dyn->n.neoncache[i].t, dyn->n.neoncache[i].n));
if(dyn->n.combined1 || dyn->n.combined2)
MESSAGE(LOG_DEBUG, " %s:%02d/%02d", dyn->n.swapped?"SWP":"CMB", dyn->n.combined1, dyn->n.combined2);
if(dyn->n.stack_push || dyn->n.stack_pop)
MESSAGE(LOG_DEBUG, " (%d:%d)", dyn->n.stack_push, -dyn->n.stack_pop);
MESSAGE(LOG_DEBUG, "\n");
}
#endif //HAVE_TRACE
#else
dyn->n = dyn->insts[reset_n].n;
#endif
dyn->f = dyn->insts[reset_n].f_exit;
if(dyn->insts[ninst].x86.barrier&BARRIER_FLOAT) {
MESSAGE(LOG_DEBUG, "Apply Barrier Float\n");
fpu_reset(dyn);
}
if(dyn->insts[ninst].x86.barrier&BARRIER_FLAGS) {
MESSAGE(LOG_DEBUG, "Apply Barrier Flags\n");
dyn->f.dfnone = 0;
dyn->f.pending = 0;
}
}
reset_n = -1;
}
// propagate ST stack state, especial stack pop that are defered
if(dyn->n.stack_pop) {
@@ -58,8 +114,14 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
dyn->n.stack_pop = 0;
}
dyn->n.stack = dyn->n.stack_next;
dyn->n.news = 0;
dyn->n.stack_push = 0;
dyn->n.swapped = 0;
NEW_INST;
fpu_reset_scratch(dyn);
if((dyn->insts[ninst].x86.need_before&~X_PEND) && !dyn->insts[ninst].pred_sz) {
READFLAGS(dyn->insts[ninst].x86.need_before&~X_PEND);
}
#ifdef HAVE_TRACE
if(my_context->dec && box86_dynarec_trace) {
if((trace_end == 0)
@@ -80,43 +142,82 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
INST_EPILOG;
if(dyn->insts[ninst+1].x86.barrier) {
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if(dyn->insts[ninst+1].x86.barrier!=2) {
dyn->state_flags = 0;
dyn->dfnone = 0;
int next = ninst+1;
#if STEP > 0
if(!dyn->insts[ninst].x86.has_next && dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts!=-1)
next = dyn->insts[ninst].x86.jmp_insts;
#endif
if(dyn->insts[ninst].x86.has_next && dyn->insts[next].x86.barrier) {
if(dyn->insts[next].x86.barrier&BARRIER_FLOAT)
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
if(dyn->insts[next].x86.barrier&BARRIER_FLAGS) {
dyn->f.pending = 0;
dyn->f.dfnone = 0;
}
}
#if STEP != 0
if(!ok && !need_epilog && (addr < (dyn->start+dyn->isize))) {
ok = 1;
// we use the 1st predecessor here
int ii = ninst+1;
while(ii<dyn->size && !dyn->insts[ii].pred_sz)
++ii;
if((dyn->insts[ii].x86.barrier&BARRIER_FULL)==BARRIER_FULL)
reset_n = -2; // hack to say Barrier!
else {
reset_n = getNominalPred(dyn, ii); // may get -1 if no predecessor are availble
if(reset_n==-1) {
reset_n = -2;
MESSAGE(LOG_DEBUG, "Warning, Reset Caches mark not found\n");
}
}
}
#if STEP == 0
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3))
#else
#ifndef PROT_READ
#define PROT_READ 1
#endif
if(!ok && !need_epilog && box86_dynarec_bigblock && (getProtection(addr+3)&PROT_READ))
if(*(uint32_t*)addr!=0) { // check if need to continue (but is next 4 bytes are 0, stop)
uintptr_t next = get_closest_next(dyn, addr);
if(next && (
(((next-addr)<15) && is_nops(dyn, addr, next-addr))
||(((next-addr)<30) && is_instructions(dyn, addr, next-addr)) ))
&& (((box86_dynarec_bigblock<2) && isJumpTableDefault((void*)next)) || (box86_dynarec_bigblock>1))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
dynarec_log(LOG_DEBUG, "Extend block %p, %p -> %p (ninst=%d)\n", dyn, (void*)addr, (void*)next, ninst);
ok = 1;
// need to find back that instruction to copy the caches, as previous version cannot be used anymore
reset_n = -2;
for(int ii=0; ii<ninst; ++ii)
if(dyn->insts[ii].x86.jmp == next) {
reset_n = ii;
ii=ninst;
}
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Extend block %p, %p -> %p (ninst=%d, jump from %d)\n", dyn, (void*)addr, (void*)next, ninst, reset_n);
} else if(next && (next-addr)<30) {
dynarec_log(LOG_DEBUG, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
if(box86_dynarec_dump) dynarec_log(LOG_NONE, "Cannot extend block %p -> %p (%02X %02X %02X %02X %02X %02X %02X %02x)\n", (void*)addr, (void*)next, PK(0), PK(1), PK(2), PK(3), PK(4), PK(5), PK(6), PK(7));
}
}
#endif
if(ok<0) {ok = 0; need_epilog=1;}
++ninst;
#if STEP == 0
if(ok && !isJumpTableDefault((void*)addr))
if((ok && !isJumpTableDefault((void*)addr) && (box86_dynarec_bigblock<2)) ||
(ok && dyn->size >= 2000))
#else
if(ok && (ninst==dyn->size))
#endif
{
#if STEP == 3
dynarec_log(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
int j32;
MAYUSE(j32);
MESSAGE(LOG_DEBUG, "Stopping block %p (%d / %d)\n",(void*)init_addr, ninst, dyn->size);
--ninst;
if(!dyn->insts[ninst].x86.barrier) {
BARRIER(BARRIER_FLOAT);
}
#if STEP == 0
dyn->insts[ninst].x86.need_after |= X_PEND;
#endif
BARRIER(2);
++ninst;
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
jump_to_next(dyn, addr, 0, ninst);
ok=0; need_epilog=0;
@@ -127,6 +228,6 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
jump_to_epilog(dyn, ip, 0, ninst); // no linker here, it's an unknow instruction
}
FINI;
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d, %d sons)\n", dyn->size, dyn->sons_size);
MESSAGE(LOG_DUMP, "---- END OF BLOCK ---- (%d)\n", dyn->size);
return addr;
}
+23 -10
View File
@@ -5,30 +5,43 @@
dyn->insts[ninst].x86.addr = addr;\
if(ninst) dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr
#define MESSAGE(A, ...)
#define READFLAGS(A) dyn->insts[ninst].x86.use_flags = A
#define SETFLAGS(A,B) {dyn->insts[ninst].x86.set_flags = A; dyn->insts[ninst].x86.state_flags = B;}
#define MAYSETFLAGS() dyn->insts[ninst].x86.may_set = 1
#define READFLAGS(A) \
dyn->insts[ninst].x86.use_flags = A; dyn->f.dfnone = 1;\
dyn->f.pending=SF_SET
#define SETFLAGS(A,B) \
dyn->insts[ninst].x86.set_flags = A; \
dyn->insts[ninst].x86.state_flags = B; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0;
#define EMIT(A)
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define BARRIER(A) dyn->insts[ninst].x86.barrier = A
#define BARRIER_NEXT(A) if(ninst<dyn->size) dyn->insts[ninst+1].x86.barrier = A
#define JUMP(A, C) if((A)>addr) add_next(dyn, (uintptr_t)(A)); dyn->insts[ninst].x86.jmp = A; dyn->insts[ninst].x86.jmp_cond = C
#define BARRIER(A) if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x86.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
#define BARRIER_NEXT(A) dyn->insts[ninst+1].x86.barrier = A
#define NEW_INST \
++dyn->size; \
if(dyn->size+3>=dyn->cap) { \
dyn->insts = (instruction_arm_t*)realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
dyn->insts = (instruction_arm_t*)box_realloc(dyn->insts, sizeof(instruction_arm_t)*dyn->cap*2); \
memset(&dyn->insts[dyn->cap], 0, sizeof(instruction_arm_t)*dyn->cap); \
dyn->cap *= 2; \
} \
dyn->insts[ninst].x86.addr = ip; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0; \
dyn->insts[ninst].f_entry = dyn->f; \
if(ninst) {dyn->insts[ninst-1].x86.size = dyn->insts[ninst].x86.addr - dyn->insts[ninst-1].x86.addr;}
#define INST_EPILOG
#define INST_EPILOG \
dyn->insts[ninst].f_exit = dyn->f; \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].x86.has_next = ok;
#define INST_NAME(name)
#define DEFAULT \
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, PKip(0), \
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
dynarec_log(LOG_NONE, "%p: Dynarec stopped @ %s (%s:%u) because of Opcode %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", \
(void*)ip, __FUNCTION__, __FILE__, __LINE__, PKip(0), \
PKip(1), PKip(2), PKip(3), \
PKip(4), PKip(5), PKip(6), \
PKip(7), PKip(8), PKip(9), \
+7 -4
View File
@@ -2,11 +2,14 @@
#define FINI
#define MESSAGE(A, ...)
#define EMIT(A)
#define READFLAGS(A)
#define SETFLAGS(A,B)
#define NEW_INST dyn->n.combined1 = dyn->n.combined2 = 0
#define NEW_INST \
dyn->insts[ninst].f_entry = dyn->f; \
dyn->n.combined1 = dyn->n.combined2 = 0;\
dyn->n.swapped = 0; dyn->n.barrier = 0
#define INST_EPILOG dyn->insts[ninst].n = dyn->n
#define INST_EPILOG \
dyn->insts[ninst].n = dyn->n; \
dyn->insts[ninst].f_exit = dyn->f
#define INST_NAME(name)
+4 -2
View File
@@ -3,7 +3,9 @@
#define MESSAGE(A, ...)
#define EMIT(A) dyn->insts[ninst].size+=4; dyn->arm_size+=4
#define NEW_INST if(ninst) {dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size);}
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
#define NEW_BARRIER_INST if(ninst) ++dyn->sons_size
+29 -23
View File
@@ -7,46 +7,52 @@
dyn->insts[ninst].size2 += 4
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST
#define NEW_INST \
#define INST_EPILOG
#define INST_NAME(name) \
if(box86_dynarec_dump) {\
printf_x86_instruction(my_context->dec, &dyn->insts[ninst].x86, name); \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d, set=%X, use=%X, need=%X", \
dynarec_log(LOG_NONE, "%s%p: %d emited opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X", \
(box86_dynarec_dump>1)?"\e[32m":"", \
(void*)(dyn->arm_start+dyn->insts[ninst].address), \
dyn->insts[ninst].size/4, \
ninst, \
dyn->insts[ninst].x86.barrier, \
dyn->insts[ninst].x86.state_flags, \
dyn->state_flags, \
dyn->f.pending, \
dyn->f.dfnone, \
dyn->insts[ninst].x86.may_set?"may":"set", \
dyn->insts[ninst].x86.set_flags, \
dyn->insts[ninst].x86.gen_flags, \
dyn->insts[ninst].x86.use_flags, \
dyn->insts[ninst].x86.need_flags); \
dyn->insts[ninst].x86.need_before, \
dyn->insts[ninst].x86.need_after); \
if(dyn->insts[ninst].pred_sz) { \
dynarec_log(LOG_NONE, ", pred="); \
for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)\
dynarec_log(LOG_NONE, "%s%d", ii?"/":"", dyn->insts[ninst].pred[ii]);\
} \
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts>=0)\
dynarec_log(LOG_NONE, ", jmp=%d", dyn->insts[ninst].x86.jmp_insts);\
if(dyn->insts[ninst].x86.jmp && dyn->insts[ninst].x86.jmp_insts==-1)\
dynarec_log(LOG_NONE, ", jmp=out");\
for(int ii=0; ii<24; ++ii) { \
switch(dyn->insts[ninst].n.neoncache[ii].t) { \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:ST%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:st%d", (ii+8)*2, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:MM%d", ii+8, dyn->insts[ninst].n.neoncache[ii].n); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:XMM%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:xmm%d", (ii+8)/2, dyn->insts[ninst].n.neoncache[ii].n); ++ii; break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:Scratch", ii+8); break; \
case NEON_CACHE_ST_D: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_ST_F: dynarec_log(LOG_NONE, " S%d:%s", (ii+8)*2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_MM: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_XMMW: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_XMMR: dynarec_log(LOG_NONE, " Q%d:%s", (ii+8)/2, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); ++ii; break; \
case NEON_CACHE_SCR: dynarec_log(LOG_NONE, " D%d:%s", ii+8, getCacheName(dyn->insts[ninst].n.neoncache[ii].t, dyn->insts[ninst].n.neoncache[ii].n)); break; \
case NEON_CACHE_NONE: \
default: break; \
} \
} \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next) \
printf_log(LOG_NONE, " X87:%d/%d", dyn->n.stack, dyn->insts[ninst].n.stack_next);\
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
printf_log(LOG_NONE, " CMB:%d/%d", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
}
#define NEW_BARRIER_INST \
if(ninst) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here\n");\
++dyn->sons_size; \
if(dyn->n.stack || dyn->insts[ninst].n.stack_next || dyn->insts[ninst].n.x87stack) \
dynarec_log(LOG_NONE, " X87:%d/%d(+%d/-%d)%d", dyn->n.stack, dyn->insts[ninst].n.stack_next, dyn->insts[ninst].n.stack_push, dyn->insts[ninst].n.stack_pop, dyn->insts[ninst].n.x87stack); \
if(dyn->insts[ninst].n.combined1 || dyn->insts[ninst].n.combined2) \
dynarec_log(LOG_NONE, " %s:%d/%d", dyn->insts[ninst].n.swapped?"SWP":"CMB", dyn->insts[ninst].n.combined1, dyn->insts[ninst].n.combined2); \
dynarec_log(LOG_NONE, "%s\n", (box86_dynarec_dump>1)?"\e[m":""); \
}
+58 -40
View File
@@ -5,6 +5,9 @@
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
#define NEON_CACHE_NONE 0
#define NEON_CACHE_ST_D 1
@@ -20,31 +23,6 @@ typedef union neon_cache_s {
unsigned int n:4; // reg number
};
} neon_cache_t;
typedef struct neoncache_s {
neon_cache_t neoncache[24];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
uint8_t combined1;
uint8_t combined2;
} neoncache_t;
typedef struct instruction_arm_s {
instruction_x86_t x86;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
neoncache_t n;
} instruction_arm_t;
typedef union sse_cache_s {
int v;
struct {
@@ -52,6 +30,57 @@ typedef union sse_cache_s {
uint8_t write;
};
} sse_cache_t;
typedef struct neoncache_s {
// Neon cache
neon_cache_t neoncache[24];
int8_t stack;
int8_t stack_next;
int8_t stack_pop;
int8_t stack_push;
uint8_t combined1;
uint8_t combined2;
uint8_t swapped; // the combined reg were swapped
uint8_t barrier; // is there a barrier at instruction epilog?
uint32_t news; // bitmask, wich neoncache are new for this opcode
// fpu cache
int8_t x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int8_t x87reg[8]; // reg used for x87cache entry
int8_t mmxcache[8];// cache status for the 8 MMX registers
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
int8_t fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
int8_t x87stack; // cache stack counter
int8_t mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
int8_t fpu_scratch;// scratch counter
int8_t fpu_extra_qscratch; // some opcode need an extra quad scratch register
int8_t fpu_reg; // x87/sse/mmx reg counter
} neoncache_t;
typedef struct flagcache_s {
int pending; // is there a pending flags here, or to check?
int dfnone; // if defered flags is already set to df_none
} flagcache_t;
typedef struct instruction_arm_s {
instruction_x86_t x86;
uintptr_t address; // (start) address of the arm emited instruction
uintptr_t epilog; // epilog of current instruction (can be start of next, of barrier stuff)
int size; // size of the arm emited instruction
int size2; // size of the arm emited instrucion after pass2
int pred_sz; // size of predecessor list
int *pred; // predecessor array
uintptr_t mark, mark2, mark3;
uintptr_t markf;
uintptr_t markseg;
uintptr_t marklock;
int pass2choice;// value for choices that are fixed on pass2 for pass3
uintptr_t natcall;
int retn;
int barrier_maybe;
flagcache_t f_exit; // flags status at end of intruction
neoncache_t n; // neoncache at end of intruction (but before poping)
flagcache_t f_entry; // flags status before the instruction begin
} instruction_arm_t;
typedef struct dynarec_arm_s {
instruction_arm_t *insts;
@@ -62,31 +91,20 @@ typedef struct dynarec_arm_s {
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
int state_flags;// actual state for on-demand flags
int x87cache[8];// cache status for the 8 x87 register behind the fpu stack
int x87reg[8]; // reg used for x87cache entry
int mmxcache[8];// cache status for the 8 MMX registers
sse_cache_t ssecache[8];// cache status for the 8 SSE(2) registers
int fpuused[24];// all 8..31 double reg from fpu, used by x87, sse and mmx
flagcache_t f;
neoncache_t n; // cache for the 8..31 double reg from fpu, plus x87 stack delta
int x87stack; // cache stack counter
int mmxcount; // number of mmx register used (not both mmx and x87 at the same time)
int fpu_scratch;// scratch counter
int fpu_extra_qscratch; // some opcode need an extra quad scratch register
int fpu_reg; // x87/sse/mmx reg counter
int dfnone; // if defered flags is already set to df_none
uintptr_t* next; // variable array of "next" jump address
int next_sz;
int next_cap;
uintptr_t* sons_x86; // the x86 address of potential dynablock sons
void** sons_arm; // the arm address of potential dynablock sons
int sons_size; // number of potential dynablock sons
int* predecessor;// single array of all predecessor
dynablock_t* dynablock;
instsize_t* instsize;
} dynarec_arm_t;
void add_next(dynarec_arm_t *dyn, uintptr_t addr);
uintptr_t get_closest_next(dynarec_arm_t *dyn, uintptr_t addr);
int is_nops(dynarec_arm_t *dyn, uintptr_t addr, int n);
int is_instructions(dynarec_arm_t *dyn, uintptr_t addr, int n);
void CreateJmpNextTo(void* addr, void* tonext);
#endif //__DYNAREC_ARM_PRIVATE_H_
+8
View File
@@ -0,0 +1,8 @@
#ifndef __DYNAREC_NEXT_H__
#define __DYNAREC_NEXT_H__
void arm_next(void) EXPORTDYN;
void arm_prolog(x86emu_t* emu, void* addr) EXPORTDYN;
void arm_epilog() EXPORTDYN;
#endif //__DYNAREC_NEXT_H__
+20 -10
View File
@@ -1,6 +1,11 @@
#ifndef __DYNAREC_PRIVATE_H_
#define __DYNAREC_PRIVATE_H_
#define BARRIER_NONE 0
#define BARRIER_FLAGS 1
#define BARRIER_FLOAT 2
#define BARRIER_FULL 3
// all flags for the use_flags field
#define X_CF (1<<0)
#define X_PF (1<<1)
@@ -9,27 +14,32 @@
#define X_SF (1<<4)
#define X_OF (1<<5)
#define X_ALL ((1<<6)-1)
#define X_PEND (0x1000)
#define X_PEND (0x80)
// all state flags
#define SF_UNKNOWN 0
#define SF_SET 1
#define SF_PENDING 2
#define SF_SET_PENDING 3
#define SF_MAYSET 4
#define SF_SUBSET 5
#define SF_SET_PENDING (SF_SET|SF_PENDING)
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
int32_t size; // size of the instruction
int barrier; // next instruction is a jump point, so no optim allowed
uintptr_t jmp; // offset to jump to, even if conditionnal (0 if not), no relative offset here
int jmp_cond; // 1 of conditionnal jump
int jmp_insts; // instuction to jump to (-1 if out of the block)
uint32_t use_flags; // 0 or combination of X_?F
uint32_t set_flags; // 0 or combination of X_?F
uint32_t need_flags; // calculated
int state_flags; // One of SF_XXX state
uint8_t jmp_cond; // 1 of conditionnal jump
uint8_t has_next; // does this opcode can continue to the next?
uint8_t barrier; // next instruction is a jump point, so no optim allowed
uint8_t state_flags;// One of SF_XXX state
uint8_t use_flags; // 0 or combination of X_?F
uint8_t set_flags; // 0 or combination of X_?F
uint8_t may_set; // 1 if the flags may not be set
uint8_t gen_flags; // calculated
uint8_t need_before; // calculated
uint8_t need_after; // calculated
} instruction_x86_t;
void printf_x86_instruction(zydis_dec_t* dec, instruction_x86_t* inst, const char* name);
+1 -1
View File
@@ -83,7 +83,7 @@ INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=10 0 0 <4> 0 0 0 <2>/01 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=01 0 0 <4> 0 0 0 <2>/11 <2> 0 <4>
INVALIDATE 1 1 1 1 0 0 1 1 1 <1> 1 1 <2>/=00 0 0 <4> 0 0 0 <2>/=11 <2> 0 <4>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d16 &l&l param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 0 @<2> Q M 0 Vm VREV\%d64 &g&g param\<c>.\%d8 &l&l size\ <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 0 1 0 U Q M 0 Vm VPADDL<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 0 Q M 0 Vm VCLS<c>.<dt> <Qd>, <Qm>
NEON 1 1 1 1 0 0 1 1 1 D 1 1 size 0 0 Vd 0 1 0 0 1 Q M 0 Vm VCLZ<c>.<dt> <Qd>, <Qm>
+721 -334
View File
File diff suppressed because it is too large. Load diff
+10 -5
View File
@@ -1,14 +1,12 @@
#ifndef __ELFLOADER_PRIVATE_H_
#define __ELFLOADER_PRIVATE_H_
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
#endif
typedef struct library_s library_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
#include <pthread.h>
#include <elf.h>
#include "elfloader.h"
struct elfheader_s {
char* name;
@@ -66,11 +64,14 @@ struct elfheader_s {
uintptr_t plt_end;
uintptr_t text;
int textsz;
uintptr_t bss;
int bsssz;
uintptr_t paddr;
uintptr_t vaddr;
int align;
uint32_t memsz;
uint32_t reserve;
uint32_t stacksz;
int stackalign;
uintptr_t tlsaddr;
@@ -91,6 +92,10 @@ struct elfheader_s {
library_t *lib;
needed_libs_t *neededlibs;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
};
#define R_386_NONE 0
+78 -64
View File
@@ -17,16 +17,16 @@
int LoadSH(FILE *f, Elf32_Shdr *s, void** SH, const char* name, uint32_t type)
{
if(type && (s->sh_type != type)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
printf_dump(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has incorect type (%d != %d)\n", name, s->sh_offset, s->sh_size, s->sh_type, type);
return -1;
}
if (type==SHT_SYMTAB && s->sh_size%sizeof(Elf32_Sym)) {
printf_log(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
printf_dump(LOG_INFO, "Section Header \"%s\" (off=%d, size=%d) has size (not multiple of %d)\n", name, s->sh_offset, s->sh_size, sizeof(Elf32_Sym));
}
*SH = calloc(1, s->sh_size);
*SH = box_calloc(1, s->sh_size);
fseeko64(f, s->sh_offset ,SEEK_SET);
if(fread(*SH, s->sh_size, 1, f)!=1) {
printf_log(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
printf_dump(LOG_INFO, "Cannot read Section Header \"%s\" (off=%d, size=%d)\n", name, s->sh_offset, s->sh_size);
return -1;
}
@@ -46,7 +46,7 @@ int FindSection(Elf32_Shdr *s, int n, char* SHStrTab, const char* name)
void LoadNamedSection(FILE *f, Elf32_Shdr *s, int size, char* SHStrTab, const char* name, const char* clearname, uint32_t type, void** what, int* num)
{
int n = FindSection(s, size, SHStrTab, name);
printf_log(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
printf_dump(LOG_DEBUG, "Loading %s (idx = %d)\n", clearname, n);
if(n)
LoadSH(f, s+n, what, name, type);
if(type==SHT_SYMTAB || type==SHT_DYNSYM) {
@@ -63,59 +63,59 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
Elf32_Ehdr header;
int level = (exec)?LOG_INFO:LOG_DEBUG;
if(fread(&header, sizeof(Elf32_Ehdr), 1, f)!=1) {
printf_log(level, "Cannot read ELF Header\n");
printf_dump(level, "Cannot read ELF Header\n");
return NULL;
}
if(memcmp(header.e_ident, ELFMAG, SELFMAG)!=0) {
printf_log(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
printf_dump(LOG_INFO, "Not an ELF file (sign=%c%c%c%c)\n", header.e_ident[0], header.e_ident[1], header.e_ident[2], header.e_ident[3]);
return NULL;
}
if(header.e_ident[EI_CLASS]!=ELFCLASS32) {
if(header.e_ident[EI_CLASS]==ELFCLASS64) {
printf_log(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
printf_dump(LOG_INFO, "This is a 64bits ELF! box86 can only run 32bits ELF!\n");
} else {
printf_log(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
printf_dump(LOG_INFO, "Not a 32bits ELF (%d)\n", header.e_ident[EI_CLASS]);
}
return NULL;
}
if(header.e_ident[EI_DATA]!=ELFDATA2LSB) {
printf_log(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
printf_dump(LOG_INFO, "Not a LittleEndian ELF (%d)\n", header.e_ident[EI_DATA]);
return NULL;
}
if(header.e_ident[EI_VERSION]!=EV_CURRENT) {
printf_log(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
printf_dump(LOG_INFO, "Incorrect ELF version (%d)\n", header.e_ident[EI_VERSION]);
return NULL;
}
if(header.e_ident[EI_OSABI]!=ELFOSABI_LINUX && header.e_ident[EI_OSABI]!=ELFOSABI_NONE && header.e_ident[EI_OSABI]!=ELFOSABI_SYSV) {
printf_log(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
printf_dump(LOG_INFO, "Not a Linux ELF (%d)\n",header.e_ident[EI_OSABI]);
return NULL;
}
if(header.e_type != ET_EXEC && header.e_type != ET_DYN) {
printf_log(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
printf_dump(LOG_INFO, "Not an Executable (%d)\n", header.e_type);
return NULL;
}
if(header.e_machine != EM_386) {
printf_log(level, "Not an i386 ELF (%d)\n", header.e_machine);
printf_dump(level, "Not an i386 ELF (%d)\n", header.e_machine);
return NULL;
}
if(header.e_entry == 0 && exec) {
printf_log(LOG_INFO, "No entry point in ELF\n");
printf_dump(LOG_INFO, "No entry point in ELF\n");
return NULL;
}
if(header.e_phentsize != sizeof(Elf32_Phdr)) {
printf_log(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
printf_dump(LOG_INFO, "Program Header Entry size incorrect (%d != %d)\n", header.e_phentsize, sizeof(Elf32_Phdr));
return NULL;
}
if(header.e_shentsize != sizeof(Elf32_Shdr) && header.e_shentsize != 0) {
printf_log(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
printf_dump(LOG_INFO, "Section Header Entry size incorrect (%d != %d)\n", header.e_shentsize, sizeof(Elf32_Shdr));
return NULL;
}
elfheader_t *h = calloc(1, sizeof(elfheader_t));
h->name = strdup(name);
elfheader_t *h = box_calloc(1, sizeof(elfheader_t));
h->name = box_strdup(name);
h->entrypoint = header.e_entry;
h->numPHEntries = header.e_phnum;
h->numSHEntries = header.e_shnum;
@@ -124,55 +124,55 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(header.e_shentsize && header.e_shnum) {
// special cases for nums
if(h->numSHEntries == 0) {
printf_log(LOG_DEBUG, "Read number of Sections in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of Sections in 1st Section\n");
// read 1st section header and grab actual number from here
fseeko64(f, header.e_shoff, SEEK_SET);
Elf32_Shdr section;
if(fread(&section, sizeof(Elf32_Shdr), 1, f)!=1) {
free(h);
printf_log(LOG_INFO, "Cannot read Initial Section Header\n");
box_free(h);
printf_dump(LOG_INFO, "Cannot read Initial Section Header\n");
return NULL;
}
h->numSHEntries = section.sh_size;
}
// now read all section headers
printf_log(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)calloc(h->numSHEntries, sizeof(Elf32_Shdr));
printf_dump(LOG_DEBUG, "Read %d Section header\n", h->numSHEntries);
h->SHEntries = (Elf32_Shdr*)box_calloc(h->numSHEntries, sizeof(Elf32_Shdr));
fseeko64(f, header.e_shoff ,SEEK_SET);
if(fread(h->SHEntries, sizeof(Elf32_Shdr), h->numSHEntries, f)!=h->numSHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Section Header\n");
printf_dump(LOG_INFO, "Cannot read all Section Header\n");
return NULL;
}
if(h->numPHEntries == PN_XNUM) {
printf_log(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of Program Header in 1st Section\n");
// read 1st section header and grab actual number from here
h->numPHEntries = h->SHEntries[0].sh_info;
}
}
printf_log(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
h->PHEntries = (Elf32_Phdr*)calloc(h->numPHEntries, sizeof(Elf32_Phdr));
printf_dump(LOG_DEBUG, "Read %d Program header\n", h->numPHEntries);
h->PHEntries = (Elf32_Phdr*)box_calloc(h->numPHEntries, sizeof(Elf32_Phdr));
fseeko64(f, header.e_phoff ,SEEK_SET);
if(fread(h->PHEntries, sizeof(Elf32_Phdr), h->numPHEntries, f)!=h->numPHEntries) {
FreeElfHeader(&h);
printf_log(LOG_INFO, "Cannot read all Program Header\n");
printf_dump(LOG_INFO, "Cannot read all Program Header\n");
return NULL;
}
if(header.e_shentsize && header.e_shnum) {
if(h->SHIdx == SHN_XINDEX) {
printf_log(LOG_DEBUG, "Read number of String Table in 1st Section\n");
printf_dump(LOG_DEBUG, "Read number of String Table in 1st Section\n");
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_dump(LOG_INFO, "Incoherent Section String Table Index : %d / %d\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_dump(LOG_DEBUG, "Loading Sections Table String (idx = %d)\n", h->SHIdx);
if(LoadSH(f, h->SHEntries+h->SHIdx, (void*)&h->SHStrTab, ".shstrtab", SHT_STRTAB)) {
FreeElfHeader(&h);
return NULL;
@@ -231,61 +231,65 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
break;
case DT_INIT: // Entry point
h->initentry = ptr;
printf_log(LOG_DEBUG, "The DT_INIT is at address %p\n", (void*)h->initentry);
printf_dump(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);
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAY is at address %p\n", (void*)h->initarray);
break;
case DT_INIT_ARRAYSZ:
h->initarray_sz = val / sizeof(Elf32_Addr);
printf_log(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
printf_dump(LOG_DEBUG, "The DT_INIT_ARRAYSZ is %d\n", h->initarray_sz);
break;
case DT_PREINIT_ARRAYSZ:
if(val)
printf_dump(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", val);
break;
case DT_FINI: // Exit hook
h->finientry = ptr;
printf_log(LOG_DEBUG, "The DT_FINI is at address %p\n", (void*)h->finientry);
printf_dump(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);
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAY is at address %p\n", (void*)h->finiarray);
break;
case DT_FINI_ARRAYSZ:
h->finiarray_sz = val / sizeof(Elf32_Addr);
printf_log(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
printf_dump(LOG_DEBUG, "The DT_FINI_ARRAYSZ is %d\n", h->finiarray_sz);
break;
case DT_VERNEEDNUM:
h->szVerNeed = val;
printf_log(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
printf_dump(LOG_DEBUG, "The DT_VERNEEDNUM is %d\n", h->szVerNeed);
break;
case DT_VERNEED:
h->VerNeed = (Elf32_Verneed*)ptr;
printf_log(LOG_DEBUG, "The DT_VERNEED is at address %p\n", h->VerNeed);
printf_dump(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);
printf_dump(LOG_DEBUG, "The DT_VERDEFNUM is %d\n", h->szVerDef);
break;
case DT_VERDEF:
h->VerDef = (Elf32_Verdef*)ptr;
printf_log(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
printf_dump(LOG_DEBUG, "The DT_VERDEF is at address %p\n", h->VerDef);
break;
}
}
if(h->rel) {
if(h->relent != sizeof(Elf32_Rel)) {
printf_log(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_Rel));
printf_dump(LOG_NONE, "Rel Table Entry size invalid (0x%x should be 0x%x)\n", h->relent, sizeof(Elf32_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_dump(LOG_DEBUG, "Rel Table @%p (0x%x/0x%x)\n", (void*)h->rel, h->relsz, h->relent);
}
if(h->rela) {
if(h->relaent != sizeof(Elf32_Rela)) {
printf_log(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_Rela));
printf_dump(LOG_NONE, "RelA Table Entry size invalid (0x%x should be 0x%x)\n", h->relaent, sizeof(Elf32_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_dump(LOG_DEBUG, "RelA Table @%p (0x%x/0x%x)\n", (void*)h->rela, h->relasz, h->relaent);
}
if(h->jmprel) {
if(h->pltrel == DT_REL) {
@@ -293,16 +297,16 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
} else if(h->pltrel == DT_RELA) {
h->pltent = sizeof(Elf32_Rela);
} else {
printf_log(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\n", h->pltsz, h->pltrel);
printf_dump(LOG_NONE, "PLT Table type is unknown (size = 0x%x, type=%d)\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=%d)\n", h->pltsz, h->pltent, h->pltrel);
printf_dump(LOG_NONE, "PLT Table Entry size invalid (0x%x, ent=0x%x, type=%d)\n", h->pltsz, h->pltent, h->pltrel);
FreeElfHeader(&h);
return NULL;
}
printf_log(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/0x%0x)\n", (void*)h->jmprel, h->pltrel, h->pltsz, h->pltent);
printf_dump(LOG_DEBUG, "PLT Table @%p (type=%d 0x%x/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
@@ -313,32 +317,39 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
if(ii) {
h->gotplt = h->SHEntries[ii].sh_addr;
h->gotplt_end = h->gotplt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
printf_dump(LOG_DEBUG, "The GOT.PLT Table is at address %p\n", (void*)h->gotplt);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".got");
if(ii) {
h->got = h->SHEntries[ii].sh_addr;
h->got_end = h->got + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
printf_dump(LOG_DEBUG, "The GOT Table is at address %p..%p\n", (void*)h->got, (void*)h->got_end);
}
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".plt");
if(ii) {
h->plt = h->SHEntries[ii].sh_addr;
h->plt_end = h->plt + h->SHEntries[ii].sh_size;
printf_log(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
printf_dump(LOG_DEBUG, "The PLT Table is at address %p..%p\n", (void*)h->plt, (void*)h->plt_end);
}
// grab version of symbols
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".gnu.version");
if(ii) {
h->VerSym = (Elf32_Half*)(h->SHEntries[ii].sh_addr);
printf_log(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
printf_dump(LOG_DEBUG, "The .gnu.version is at address %p\n", h->VerSym);
}
// grab .text for main code
// grab .bss 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_dump(LOG_DEBUG, "The .text is at address %p, and is %d big\n", (void*)h->text, h->textsz);
}
// grab .bss to find brk
ii = FindSection(h->SHEntries, h->numSHEntries, h->SHStrTab, ".bss");
if(ii) {
h->bss = (uintptr_t)(h->SHEntries[ii].sh_addr);
h->bsssz = h->SHEntries[ii].sh_size;
printf_dump(LOG_DEBUG, "The .bss is at address %p, and is %d big\n", (void*)h->bss, h->bsssz);
}
LoadNamedSection(f, h->SHEntries, h->numSHEntries, h->SHStrTab, ".dynstr", "DynSym Strings", SHT_STRTAB, (void**)&h->DynStr, NULL);
@@ -350,19 +361,22 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
const char* GetSymbolVersion(elfheader_t* h, int version)
{
if(!h->VerNeed || (version<2))
version&=0x7fff; // remove bit15 that switch between hidden/public
if(version<2)
return NULL;
/*if(version==1)
return "*";*/
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf32_Vernaux *aux = (Elf32_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 = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
if(h->VerNeed) {
Elf32_Verneed *ver = (Elf32_Verneed*)((uintptr_t)h->VerNeed + h->delta);
while(ver) {
Elf32_Vernaux *aux = (Elf32_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 = (Elf32_Vernaux*)((uintptr_t)aux + aux->vna_next);
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
ver = ver->vn_next?((Elf32_Verneed*)((uintptr_t)ver + ver->vn_next)):NULL;
}
return GetParentSymbolVersion(h, version); // if symbol is "internal", use Def table instead
}
+66 -17
View File
@@ -60,6 +60,26 @@
if(emu->quit) goto fini;
STEP;
NEXT;
_0f_0x0D: /* PREFETCH group */
nextop = F8;
switch((nextop>>3)&7) {
case 1: /* PREFETCHW */
GET_ED; //nothing for now. Could maybe use some builtin prefetch instruction
break;
default:
goto _default;
}
NEXT;
_0f_0x0E: /* FEMMS */
emu->old_ip = R_EIP;
R_EIP = ip-2;
emit_signal(emu, SIGILL, (void*)R_EIP, 0);
ip = R_EIP;
if(emu->quit) goto fini;
STEP;
NEXT;
_0f_0x10: /* MOVUPS Gx,Ex */
nextop = F8;
GET_EX;
@@ -227,7 +247,7 @@
if(EM->ub[i]&128)
GM.ub[i] = 0;
else
GM.ub[i] = eax1.ub[EM->ub[i]&7];
GM.ub[i] = eam1.ub[EM->ub[i]&7];
}
break;
case 0x04: /* PMADDUBSW Gm,Em */
@@ -280,6 +300,17 @@
}
break;
case 0xF0: /* MOVBE Gd, Ed*/
nextop = F8;
GET_ED;
GD.dword[0] = __builtin_bswap32(ED->dword[0]);
break;
case 0xF1: /* MOVBE Ed, Gd*/
nextop = F8;
GET_ED;
ED->dword[0] = __builtin_bswap32(GD.dword[0]);
break;
default:
goto _default;
}
@@ -288,7 +319,7 @@
_0f_0x3A:
opcode = F8;
switch(opcode) {
case 0xF: /* palignr */
case 0x0F: /* palignr */
nextop = F8;
GET_EM;
tmp8u = F8;
@@ -297,8 +328,10 @@
} else if (tmp8u > 8) {
tmp8u -= 8;
GM.q >>= tmp8u*8;
} else if (tmp8u == 8 || tmp8u == 0) {
} else if (tmp8u == 8) {
// nothing
} else if (tmp8u == 0) {
GM.q = EM->q;
} else {
GM.q <<= (8-tmp8u)*8;
GM.q |= (EM->q >> tmp8u*8);
@@ -435,8 +468,18 @@
_0f_0x52: /* RSQRTPS Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
GX.f[i] = 1.0f/sqrtf(EX->f[i]);
for(int i=0; i<4; ++i) {
if(EX->f[i]==0)
GX.f[i] = 1.0f/EX->f[i];
else if (EX->f[i]<0)
GX.f[i] = NAN;
else if (isnan(EX->f[i]))
GX.f[i] = EX->f[i];
else if (isinf(EX->f[i]))
GX.f[i] = 0.0;
else
GX.f[i] = 1.0f/sqrtf(EX->f[i]);
}
NEXT;
_0f_0x53: /* RCPPS Gx, Ex */
nextop = F8;
@@ -1093,19 +1136,25 @@
GX.q[1] = eax1.q[1];
NEXT;
_0f_0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
switch((nextop>>3)&7) {
case 1:
CHECK_FLAGS(emu);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
break;
default:
goto _default;
}
NEXT;
_0f_0xC8:
+12
View File
@@ -55,6 +55,9 @@
STEP
NEXT;
_66_0x1E: /* PUSH DS */
Push16(emu, emu->segs[_DS]);
NEXT;
_66_0x1F: /* POP DS */
emu->segs[_DS] = Pop16(emu); // no check, no use....
emu->segs_serial[_DS] = 0;
@@ -86,6 +89,10 @@
_66_0x3D:
cmp16(emu, R_AX, F16);
NEXT;
_66_0x3E: /* DS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x40:
_66_0x41:
@@ -482,6 +489,11 @@
R_ECX = tmp32u;
NEXT;
_66_0xF5: /* CMC */
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!ACCESS_FLAG(F_CF), F_CF);
NEXT;
_66_0xF7: /* GRP3 Ew(,Iw) */
nextop = F8;
GET_EW;
+17 -3
View File
@@ -23,6 +23,7 @@
ll = ST(nextop&7).sq;
ST(nextop&7).sq = ST0.sq;
ST0.sq = ll;
emu->sw.f.F87_C1 = 0;
break;
case 0xD0: /* FNOP */
@@ -30,9 +31,11 @@
case 0xE0: /* FCHS */
ST0.d = -ST0.d;
emu->sw.f.F87_C1 = 0;
break;
case 0xE1: /* FABS */
ST0.d = fabs(ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xE4: /* FTST */
@@ -73,25 +76,30 @@
case 0xF0: /* F2XM1 */
ST0.d = exp2(ST0.d) - 1.0;
emu->sw.f.F87_C1 = 0;
break;
case 0xF1: /* FYL2X */
ST(1).d *= log2(ST0.d);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xF2: /* FPTAN */
ST0.d = tan(ST0.d);
fpu_do_push(emu);
ST0.d = 1.0;
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xF3: /* FPATAN */
ST1.d = atan2(ST1.d, ST0.d);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xF4: /* FXTRACT */
ST0.d = frexp(ST0.d, &tmp32s);
fpu_do_push(emu);
ST0.d = tmp32s;
// C1 set only if stack under/overflow occurs
break;
case 0xF8: /* FPREM */
@@ -146,30 +154,37 @@
case 0xF9: /* FYL2XP1 */
ST(1).d *= log2(ST0.d + 1.0);
fpu_do_pop(emu);
emu->sw.f.F87_C1 = 0;
break;
case 0xFA: /* FSQRT */
ST0.d = sqrt(ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xFB: /* FSINCOS */
fpu_do_push(emu);
sincos(ST1.d, &ST1.d, &ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xFC: /* FRNDINT */
ST0.d = fpu_round(emu, ST0.d);
emu->sw.f.F87_C1 = 0;
break;
case 0xFD: /* FSCALE */
// this could probably be done by just altering the exponant part of the float...
if(ST0.d!=0.0)
ST0.d *= exp2(trunc(ST1.d));
emu->sw.f.F87_C1 = 0;
break;
case 0xFE: /* FSIN */
ST0.d = sin(ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
case 0xFF: /* FCOS */
ST0.d = cos(ST0.d);
emu->sw.f.F87_C2 = 0;
emu->sw.f.F87_C1 = 0;
break;
@@ -230,9 +245,8 @@
break;
case 5: /* FLDCW Ew */
GET_EW;
emu->cw = EW->word[0];
emu->cw.x16 = EW->word[0];
// do something with cw?
emu->round = (fpu_round_t)((emu->cw >> 10) & 3);
break;
case 6: /* FNSTENV m */
// warning, incomplete
@@ -244,7 +258,7 @@
break;
case 7: /* FNSTCW Ew */
GET_EW;
EW->word[0] = emu->cw;
EW->word[0] = emu->cw.x16;
break;
default:
goto _default;
+1 -1
View File
@@ -132,7 +132,7 @@
GET_ED;
fpu_do_push(emu);
memcpy(&STld(0).ld, ED, 10);
LD2D(&STld(0), &ST(0).d);
LD2D(&STld(0).ld, &ST(0).d);
STld(0).uref = ST0.q;
break;
case 7: /* FSTP tbyte */
+30 -2
View File
@@ -53,17 +53,32 @@
case 0x51: /* SQRTSD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] = sqrt(EX->d[0]);
if(EX->d[0]<0.0 )
GX.d[0] = -NAN;
else
GX.d[0] = sqrt(EX->d[0]);
break;
case 0x58: /* ADDSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// add generate a -NAN only if doing inf + -inf
if((isinf(GX.d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)!=(GX.q[0]&0x8000000000000000LL)))
GX.d[0] = -NAN;
else
#endif
GX.d[0] += EX->d[0];
break;
case 0x59: /* MULSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
if((isinf(GX.d[0]) && EX->d[0]==0.0) || (isinf(EX->d[0]) && GX.d[0]==0.0))
GX.d[0] = -NAN;
else
#endif
GX.d[0] *= EX->d[0];
break;
case 0x5A: /* CVTSD2SS Gx, Ex */
@@ -75,18 +90,31 @@
case 0x5C: /* SUBSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
// sub generate a -NAN only if doing inf - inf
if((isinf(GX.d[0]) && isinf(EX->d[0]) && (EX->q[0]&0x8000000000000000LL)==(GX.q[0]&0x8000000000000000LL)))
GX.d[0] = -NAN;
else
#endif
GX.d[0] -= EX->d[0];
break;
case 0x5D: /* MINSD Gx, Ex */
nextop = F8;
GET_EX;
if (isnan(GX.d[0]) || isnan(EX->d[0]) || isless(EX->d[0], GX.d[0]))
if (isnan(GX.d[0]) || isnan(EX->d[0]) || (EX->d[0]<=GX.d[0]))
GX.d[0] = EX->d[0];
break;
case 0x5E: /* DIVSD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
is_nan = isnan(GX.d[0]) || isnan(EX->d[0]);
#endif
GX.d[0] /= EX->d[0];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[0]))
GX.d[0] = -NAN;
#endif
break;
case 0x5F: /* MAXSD Gx, Ex */
nextop = F8;
+8 -9
View File
@@ -89,7 +89,7 @@ x86emu_t *NewX86Emu(box86context_t *context, uintptr_t start, uintptr_t stack, i
{
printf_log(LOG_DEBUG, "Allocate a new X86 Emu, with EIP=%p and Stack=%p/0x%X\n", (void*)start, (void*)stack, stacksize);
x86emu_t *emu = (x86emu_t*)calloc(1, sizeof(x86emu_t));
x86emu_t *emu = (x86emu_t*)box_calloc(1, sizeof(x86emu_t));
internalX86Setup(emu, context, start, stack, stacksize, ownstack);
@@ -130,7 +130,7 @@ void AddCleanup(x86emu_t *emu, void *p)
{
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);
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 0;
my_context->cleanups[my_context->clean_sz].a = NULL;
@@ -141,7 +141,7 @@ void AddCleanup1Arg(x86emu_t *emu, void *p, void* a)
{
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);
my_context->cleanups = (cleanup_t*)box_realloc(my_context->cleanups, sizeof(cleanup_t)*my_context->clean_cap);
}
my_context->cleanups[my_context->clean_sz].arg = 1;
my_context->cleanups[my_context->clean_sz].a = a;
@@ -171,7 +171,7 @@ void CallAllCleanup(x86emu_t *emu)
RunFunctionWithEmu(emu, 0, (uintptr_t)(my_context->cleanups[i].f), my_context->cleanups[i].arg, my_context->cleanups[i].a );
}
my_context->clean_sz = 0;
free(my_context->cleanups);
box_free(my_context->cleanups);
my_context->cleanups = NULL;
}
@@ -190,7 +190,7 @@ void FreeX86Emu(x86emu_t **emu)
internalFreeX86(*emu);
free(*emu);
box_free(*emu);
*emu = NULL;
}
@@ -217,10 +217,9 @@ void CloneEmu(x86emu_t *newemu, const x86emu_t* emu)
memcpy(newemu->fpu_ll, emu->fpu_ll, sizeof(emu->fpu_ll));
memcpy(newemu->p_regs, emu->p_regs, sizeof(emu->p_regs));
newemu->cw = emu->cw;
memcpy(&newemu->sw, &emu->sw, sizeof(emu->sw));
newemu->sw = emu->sw;
newemu->top = emu->top;
newemu->fpu_stack = emu->fpu_stack;
memcpy(&newemu->round, &emu->round, sizeof(emu->round));
memcpy(newemu->xmm, emu->xmm, sizeof(emu->xmm));
newemu->mxcsr = emu->mxcsr;
newemu->quit = emu->quit;
@@ -323,14 +322,14 @@ const char* DumpCPURegs(x86emu_t* emu, uintptr_t ip)
}
// start with FPU regs...
if(emu->fpu_stack) {
if(emu->fpu_stack<8)
if(emu->fpu_stack<9)
for (int i=0; i<emu->fpu_stack; i++) {
//if(i==4) strcat(buff, "\n");
sprintf(tmp, "ST%d=%f", i, emu->x87[(emu->top+i)&7].d);
strcat(buff, tmp);
int c = 10-strlen(tmp);
if(c<1) c=1;
while(c--) strcat(buff, " ");
if(i==3) strcat(buff, "\n");
}
else {
sprintf(tmp, "Warning, incoherent fpu_stack=%d", emu->fpu_stack);
+2 -3
View File
@@ -29,13 +29,12 @@ typedef struct x86emu_s {
x86flags_t eflags;
reg32_t ip;
// fpu / mmx
x87control_t cw;
x87flags_t sw;
mmx87_regs_t x87[8];
mmx87_regs_t mmx[8];
uint16_t cw;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
fpu_round_t round;
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
+50 -29
View File
@@ -85,11 +85,16 @@ void x86Int3(x86emu_t* emu)
elfheader_t *h = FindElfAddress(my_context, *(uintptr_t*)(R_ESP));
int have_trace = 0;
if(h && strstr(ElfName(h), "libMiles")) have_trace = 1;*/
if(box86_log>=LOG_DEBUG /*|| have_trace*/) {
if(box86_log>=LOG_DEBUG || cycle_log) {
int tid = GetTID();
char buff[256] = "\0";
char t_buff[256] = "\0";
char buff2[64] = "\0";
char buff3[64] = "\0";
char* buff = cycle_log?my_context->log_call[my_context->current_line]:t_buff;
char* buffret = cycle_log?my_context->log_ret[my_context->current_line]:NULL;
if(buffret) buffret[0] = '\0';
if(cycle_log)
my_context->current_line = (my_context->current_line+1)&(CYCLE_LOG-1);
char *tmp;
int post = 0;
int perr = 0;
@@ -97,7 +102,7 @@ void x86Int3(x86emu_t* emu)
const char *s = NULL;
s = GetNativeName((void*)addr);
if(addr==(uintptr_t)PltResolver) {
snprintf(buff, 256, "%s", " ... ");
snprintf(buff, 256, "%s", cycle_log?"PltResolver ":" ... ");
} else
if(strstr(s, "SDL_RWFromFile")==s || strstr(s, "SDL_RWFromFile")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%s, %s)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
@@ -119,16 +124,20 @@ void x86Int3(x86emu_t* emu)
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d (,%d))", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "shm_open")) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d, %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8), *(int*)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "mkdir")==0) {
tmp = *(char**)(R_ESP+4);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %d)", tid, *(void**)(R_ESP), s, (tmp)?tmp:"(nil)", *(int*)(R_ESP+8));
perr = 1;
} else if(!strcmp(s, "fopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 1;
perr = 2;
} else if(!strcmp(s, "freopen")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", %p)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
perr = 2;
} else if(!strcmp(s, "fopen64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
perr = 2;
@@ -138,9 +147,14 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "getenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
post = 2;
} else if(strstr(s, "putenv")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "pread")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u, %d)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12), *(int32_t*)(R_ESP+16));
perr = 1;
} else if(!strcmp(s, "read")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %u)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(uint32_t*)(R_ESP+12));
perr = 1;
} else if(strstr(s, "ioctl")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, 0x%x, %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(int32_t*)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
@@ -150,13 +164,13 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "rindex")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"), %i(%c))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+4), *(int32_t*)(R_ESP+8), *(int32_t*)(R_ESP+8));
} else if(strstr(s, "my___xstat64")==s) {
} else if(strstr(s, "__xstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strcmp(s, "my___xstat")==0) {
} else if(strcmp(s, "__xstat")==0) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "my___lxstat64")==s) {
} else if(strstr(s, "__lxstat64")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p(\"%s\"), %p)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(char**)(R_ESP+8), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
perr = 1;
} else if(strstr(s, "sem_timedwait")==s) {
@@ -174,10 +188,10 @@ void x86Int3(x86emu_t* emu)
int16_t* p16 = *(int16_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p[%u/%d/0x%x], %d)", tid, *(void**)(R_ESP), s, *(int*)(R_ESP+4), p16, p16[0], p16[1], p16[2], *(int*)(R_ESP+12));
perr = 1;
} else if(!strcmp(s, "my_mmap64")) {
} else if(!strcmp(s, "mmap64")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %lld)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int64_t*)(R_ESP+24));
perr = 3;
} else if(!strcmp(s, "my_mmap")) {
} else if(!strcmp(s, "mmap")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, 0x%x, %d, 0x%x, %d, %d)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(int*)(R_ESP+20), *(int*)(R_ESP+24));
perr = 3;
} else if(strstr(s, "strcasecmp")==s || strstr(s, "__strcasecmp")==s) {
@@ -190,54 +204,58 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(\"%.127s\", \"%.127s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "strlen")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p(\"%s\"))", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), ((R_ESP+4))?(*(char**)(R_ESP+4)):"nil");
} else if(strstr(s, "my_vsnprintf")==s) {
} else if(strstr(s, "vsnprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %u, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_vsprintf")==s) {
} else if(strstr(s, "vsprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8), *(void**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my___vsprintf_chk")==s) {
} else if(strstr(s, "__vsprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %d, %zu, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(int*)(R_ESP+8), *(size_t*)(R_ESP+12), *(char**)(R_ESP+16), *(void**)(R_ESP+20));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my___snprintf_chk")==s) {
} else if(strstr(s, "__snprintf_chk")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %d, %d, \"%s\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(int*)(R_ESP+12), *(int*)(R_ESP+16), *(char**)(R_ESP+20), *(void**)(R_ESP+24));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_snprintf")==s) {
} else if(strstr(s, "snprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(char**)(R_ESP+12));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_sprintf")==s) {
} else if(strstr(s, "sprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8));
pu32 = *(uint32_t**)(R_ESP+4);
post = 3;
} else if(strstr(s, "my_printf")==s) {
} else if(strstr(s, "printf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "my_wprintf")==s) {
} else if(strstr(s, "wprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+4);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+8);
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
} else if(strstr(s, "my___vswprintf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
} else if(strstr(s, "__vswprintf")==s) {
if(*(size_t*)(R_ESP+12)<2) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, %p, %p, %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16), *(void**)(R_ESP+20));
} else {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, %zu, \"%S\", %p)", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(size_t*)(R_ESP+8), *(wchar_t**)(R_ESP+12), *(void**)(R_ESP+16));
pu32 = *(uint32_t**)(R_ESP+4);
post = 6;
}
} else if(strstr(s, "puts")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\"...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "fputs")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", %p...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(void**)(R_ESP+8));
} else if(strstr(s, "my_fprintf")==s) {
} else if(strstr(s, "fprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a __fprint_chk
pu32 = *(uint32_t**)(R_ESP+12);
snprintf(buff, 255, "%04d|%p: Calling %s(%08X, \"%s\", ...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), pu32?((char*)(pu32)):"nil");
} else if(strstr(s, "my_vfprintf")==s) {
} else if(strstr(s, "vfprintf")==s) {
pu32 = *(uint32_t**)(R_ESP+8);
if(((uintptr_t)pu32)<0x5) // probably a _chk function
pu32 = *(uint32_t**)(R_ESP+12);
@@ -246,9 +264,9 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "vkGetDeviceProcAddr")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(strstr(s, "my_glXGetProcAddress")==s) {
} else if(strstr(s, "glXGetProcAddress")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\")", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4));
} else if(strstr(s, "my_sscanf")==s) {
} else if(strstr(s, "sscanf")==s) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "vsscanf")) {
snprintf(buff, 255, "%04d|%p: Calling %s(\"%s\", \"%s\", ...)", tid, *(void**)(R_ESP), s, *(char**)(R_ESP+4), *(char**)(R_ESP+8));
@@ -270,14 +288,14 @@ void x86Int3(x86emu_t* emu)
} else if(strstr(s, "udev_monitor_new_from_netlink")==s) {
post = 5;
snprintf(buff, 255, "%04d|%p: Calling %s(%p, \"%s\")", tid, *(void**)(R_ESP), s, *(void**)(R_ESP+4), *(char**)(R_ESP+8));
} else if(!strcmp(s, "my_syscall")) {
} else if(!strcmp(s, "syscall")) {
snprintf(buff, 255, "%04d|%p: Calling %s(%d, %p, %p, %p...)", tid, *(void**)(R_ESP), s, *(int32_t*)(R_ESP+4), *(void**)(R_ESP+8), *(void**)(R_ESP+12), *(void**)(R_ESP+16));
perr = 1;
} else {
snprintf(buff, 255, "%04d|%p: Calling %s (%08X, %08X, %08X...)", tid, *(void**)(R_ESP), s, *(uint32_t*)(R_ESP+4), *(uint32_t*)(R_ESP+8), *(uint32_t*)(R_ESP+12));
}
pthread_mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, "%s =>", buff);
if(!cycle_log) printf_log(LOG_NONE, "%s =>", buff);
pthread_mutex_unlock(&emu->context->mutex_trace);
w(emu, addr); // some function never come back, so unlock the mutex first!
if(post)
@@ -308,7 +326,10 @@ void x86Int3(x86emu_t* emu)
else if(perr==3 && ((int)R_EAX)==-1)
snprintf(buff3, 63, " (errno=%d:\"%s\")", errno, strerror(errno));
pthread_mutex_lock(&emu->context->mutex_trace);
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
if(cycle_log)
snprintf(buffret, 127, "0x%X%s%s", R_EAX, buff2, buff3);
else
printf_log(LOG_NONE, " return 0x%08X%s%s\n", R_EAX, buff2, buff3);
pthread_mutex_unlock(&emu->context->mutex_trace);
} else
w(emu, addr);
-8
View File
@@ -165,14 +165,6 @@ Implements the INC instruction and side effects.
static inline uint32_t inc32(x86emu_t *emu, uint32_t d)
{
CHECK_FLAGS(emu);
if(emu->df == d_shr32) {
// workaround for some wine trickery
uint32_t cnt = emu->op2;
if (cnt > 0) {
uint32_t cc = emu->op1 & (1 << (cnt - 1));
CONDITIONAL_SET_FLAG(cc, F_CF);
}
}
emu->res = d + 1;
emu->op1 = d;
emu->df = d_inc32;
+7 -4
View File
@@ -46,6 +46,9 @@ int Run(x86emu_t *emu, int step)
int64_t ll;
sse_regs_t *opex, eax1;
mmx87_regs_t *opem, eam1;
#ifndef NOALIGN
int is_nan;
#endif
if(emu->quit)
return 0;
@@ -101,7 +104,7 @@ int Run(x86emu_t *emu, int step)
static const void* opcodes0f[256] = {
&&_0f_0x00, &&_0f_0x01, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x00-0x07
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_default, &&_default, &&_default, //0x08-0x0F
&&_default, &&_default, &&_default, &&_0f_0x0B, &&_default ,&&_0f_0x0D, &&_0f_0x0E, &&_default, //0x08-0x0F
&&_0f_0x10, &&_0f_0x11, &&_0f_0x12, &&_0f_0x13, &&_0f_0x14, &&_0f_0x15, &&_0f_0x16, &&_0f_0x17, //0x10-0x17
&&_0f_0x18, &&_default, &&_0f_0x1A, &&_0f_0x1B, &&_default ,&&_default, &&_default, &&_0f_0x1F, //0x18-0x1F
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0x20-0x27
@@ -138,11 +141,11 @@ int Run(x86emu_t *emu, int step)
&&_66_0x00_0, &&_66_0x00_1, &&_66_0x00_2, &&_66_0x00_3, &&_66_0x00_4 ,&&_66_0x00_5, &&_66_0x06, &&_66_0x07, //0x00-0x07
&&_66_0x08_0, &&_66_0x08_1, &&_66_0x08_2, &&_66_0x08_3, &&_66_0x08_4 ,&&_66_0x08_5, &&_default, &&_66_0x0F, //0x08-0x0F
&&_66_0x10_0, &&_66_0x10_1, &&_66_0x10_2, &&_66_0x10_3, &&_66_0x10_4 ,&&_66_0x10_5, &&_default, &&_default, //0x10-0x17
&&_66_0x18_0, &&_66_0x18_1, &&_66_0x18_2, &&_66_0x18_3, &&_66_0x18_4 ,&&_66_0x18_5, &&_default, &&_66_0x1F, //0x18-0x1F
&&_66_0x18_0, &&_66_0x18_1, &&_66_0x18_2, &&_66_0x18_3, &&_66_0x18_4 ,&&_66_0x18_5, &&_66_0x1E, &&_66_0x1F, //0x18-0x1F
&&_66_0x20_0, &&_66_0x20_1, &&_66_0x20_2, &&_66_0x20_3, &&_66_0x20_4 ,&&_66_0x20_5, &&_66_0x26, &&_default, //0x20-0x27
&&_66_0x28_0, &&_66_0x28_1, &&_66_0x28_2, &&_66_0x28_3, &&_66_0x28_4 ,&&_66_0x28_5, &&_66_0x2E, &&_default, //0x28-0x2F
&&_66_0x30_0, &&_66_0x30_1, &&_66_0x30_2, &&_66_0x30_3, &&_66_0x30_4 ,&&_66_0x30_5, &&_66_0x36, &&_default, //0x30-0x37
&&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_default, &&_default, //0x38-0x3F
&&_default, &&_66_0x39, &&_default, &&_66_0x3B, &&_default, &&_66_0x3D, &&_66_0x3E, &&_default, //0x38-0x3F
&&_66_0x40, &&_66_0x41, &&_66_0x42, &&_66_0x43, &&_66_0x44, &&_66_0x45, &&_66_0x46, &&_66_0x47,
&&_66_0x48, &&_66_0x49, &&_66_0x4A, &&_66_0x4B, &&_66_0x4C, &&_66_0x4D, &&_66_0x4E, &&_66_0x4F,
&&_66_0x50, &&_66_0x51, &&_66_0x52, &&_66_0x53, &&_66_0x54, &&_66_0x55, &&_66_0x56, &&_66_0x57, //0x50-0x57
@@ -165,7 +168,7 @@ int Run(x86emu_t *emu, int step)
&&_default, &&_66_0xD9, &&_default, &&_default, &&_default ,&&_66_0xDD, &&_default, &&_default, //0xD8-0xDF
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE0-0xE7
&&_default, &&_default, &&_default, &&_default, &&_default ,&&_default, &&_default, &&_default, //0xE8-0xEF
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_default, &&_default, &&_66_0xF7,
&&_66_0xF0, &&_default, &&_66_0xF2, &&_66_0xF3, &&_default, &&_66_0xF5, &&_default, &&_66_0xF7,
&&_66_0xF8, &&_66_0xF9, &&_default, &&_default, &&_default, &&_default, &&_default, &&_66_0xFF
};
+216 -49
View File
@@ -536,63 +536,73 @@ void RunLock(x86emu_t *emu)
#endif
break;
case 0xC7: /* CMPXCHG8B Gq */
CHECK_FLAGS(emu);
nextop = F8;
GET_ED;
switch((nextop>>3)&7) {
case 1:
CHECK_FLAGS(emu);
#ifdef DYNAREC
if(((uintptr_t)ED)&7) {
// unaligned!!!
uint64_t ref = R_EDX;
ref = ref<<32 | R_EAX;
void* p = (void*)(((uintptr_t)ED + 3)&~3);
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
do {
uint64_t m = *(uint64_t*)ED;
m&=~((0xffffffffLL)<<d);
tmp32u = arm_lock_read_d(p);
m|=((uint64_t)tmp32u)<<d;
if(ref == m) {
if(((uintptr_t)ED)&7) {
// unaligned!!!
uint64_t ref = R_EDX;
ref = ref<<32 | R_EAX;
void* p = (void*)(((uintptr_t)ED + 3)&~3);
int d = (((uintptr_t)p - (uintptr_t)ED))*8;
do {
uint64_t m = *(uint64_t*)ED;
m&=~((0xffffffffLL)<<d);
tmp32u = arm_lock_read_d(p);
m|=((uint64_t)tmp32u)<<d;
if(ref == m) {
SET_FLAG(F_ZF);
m = ((uint64_t)R_ECX)<<32 | R_EBX;
tmp32u2 = m>>d;
tmp32s = arm_lock_write_d(p, tmp32u2);
if(!tmp32s)
*(uint64_t*)ED = m;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = m&0xffffffff;
R_EDX = m>>32;
tmp32s = 0;
}
} while(tmp32s);
} else
do {
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
m = ((uint64_t)R_ECX)<<32 | R_EBX;
tmp32u2 = m>>d;
tmp32s = arm_lock_write_d(p, tmp32u2);
if(!tmp32s)
*(uint64_t*)ED = m;
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = m&0xffffffff;
R_EDX = m>>32;
tmp32s = 0;
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
} while(tmp32s);
} else
do {
arm_lock_read_dd(&tmp32u, &tmp32u2, ED);
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
tmp32s = arm_lock_write_dd(R_EBX, R_ECX, ED);
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
tmp32s = 0;
}
} while(tmp32s);
#else
pthread_mutex_lock(&emu->context->mutex_lock);
tmp32u = ED->dword[0];
tmp32u2= ED->dword[1];
if(R_EAX == tmp32u && R_EDX == tmp32u2) {
SET_FLAG(F_ZF);
ED->dword[0] = R_EBX;
ED->dword[1] = R_ECX;
} else {
CLEAR_FLAG(F_ZF);
R_EAX = tmp32u;
R_EDX = tmp32u2;
}
pthread_mutex_unlock(&emu->context->mutex_lock);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
ip = R_EIP;
printf_log(LOG_NONE, "Illegal Opcode 0xF0 0xC7 0x%02X 0x%02X\n", nextop, PK(0));
emu->quit=1;
emu->error |= ERR_ILLEGAL;
break;
}
break;
default:
// trigger invalid lock?
@@ -798,6 +808,59 @@ void RunLock66(x86emu_t *emu)
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 0xFF:
nextop = F8;
GET_EW;
switch((nextop>>3)&7) {
case 0: /* INC Ed */
#ifdef DYNAREC
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = inc16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, inc16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = inc32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
case 1: /* DEC Ed */
#ifdef DYNAREC
if((uintptr_t)ED&1) {
//meh.
do {
tmp16u = ED->dword[0];
tmp16u &=~0xff;
tmp16u |= arm_lock_read_b(ED);
tmp16u = dec16(emu, tmp16u);
} while(arm_lock_write_b(ED, tmp16u&0xff));
ED->dword[0] = tmp16u;
} else
do {
tmp16u = arm_lock_read_h(ED);
} while(arm_lock_write_h(ED, dec16(emu, tmp16u)));
#else
pthread_mutex_lock(&emu->context->mutex_lock);
ED->dword[0] = dec32(emu, ED->dword[0]);
pthread_mutex_unlock(&emu->context->mutex_lock);
#endif
break;
default:
ip=R_EIP;
UnimpOpcode(emu);
break;
}
break;
default:
ip-=3; // unfetch nextop, F0 & 66
UnimpOpcode(emu);
@@ -889,6 +952,18 @@ void RunGS(x86emu_t *emu)
GET_ED_OFFS(tlsdata);
GD.dword[0] = xor32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x39: /* CMP Ed,Gd */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, ED->dword[0], GD.dword[0]);
break;
case 0x3B: /* CMP Gd,Ed */
nextop = F8;
GET_ED_OFFS(tlsdata);
cmp32(emu, GD.dword[0], ED->dword[0]);
break;
case 0x40:
case 0x41:
@@ -1134,6 +1209,7 @@ void RunFS(x86emu_t *emu)
{
uintptr_t ip = R_EIP+1;
uint8_t opcode = F8;
int8_t tmp8s;
uint8_t nextop;
reg32_t *oped;
uint8_t tmp8u;
@@ -1263,6 +1339,93 @@ void RunFS(x86emu_t *emu)
tmp32u = F32;
GD.dword[0] = imul32(emu, ED->dword[0], tmp32u);
break;
#define GOCOND(BASE, PREFIX, CONDITIONAL) \
case BASE+0x0: \
PREFIX \
if(ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0x1: \
PREFIX \
if(!ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0x2: \
PREFIX \
if(ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+0x3: \
PREFIX \
if(!ACCESS_FLAG(F_CF)) \
CONDITIONAL \
break; \
case BASE+0x4: \
PREFIX \
if(ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+0x5: \
PREFIX \
if(!ACCESS_FLAG(F_ZF)) \
CONDITIONAL \
break; \
case BASE+0x6: \
PREFIX \
if((ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+0x7: \
PREFIX \
if(!(ACCESS_FLAG(F_ZF) || ACCESS_FLAG(F_CF))) \
CONDITIONAL \
break; \
case BASE+0x8: \
PREFIX \
if(ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+0x9: \
PREFIX \
if(!ACCESS_FLAG(F_SF)) \
CONDITIONAL \
break; \
case BASE+0xA: \
PREFIX \
if(ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xB: \
PREFIX \
if(!ACCESS_FLAG(F_PF)) \
CONDITIONAL \
break; \
case BASE+0xC: \
PREFIX \
if(ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xD: \
PREFIX \
if(ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF)) \
CONDITIONAL \
break; \
case BASE+0xE: \
PREFIX \
if(ACCESS_FLAG(F_ZF) || (ACCESS_FLAG(F_SF) != ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break; \
case BASE+0xF: \
PREFIX \
if(!ACCESS_FLAG(F_ZF) && (ACCESS_FLAG(F_SF) == ACCESS_FLAG(F_OF))) \
CONDITIONAL \
break;
GOCOND(0x70
, tmp8s = F8S; CHECK_FLAGS(emu);
, ip += tmp8s;
) /* Jxx Ib */
#undef GOCOND
case 0x80: /* GRP Eb,Ib */
case 0x82: // 0x82 and 0x80 are the same opcodes it seems?
nextop = F8;
@@ -1349,6 +1512,10 @@ void RunFS(x86emu_t *emu)
*(uint32_t*)((tlsdata) + tmp32s) = R_EAX;
break;
case 0xA8: /* TEST AL, Ib */
test8(emu, R_AL, F8);
break;
case 0xC0: /* GRP2 Eb,Ib */
nextop = F8;
GET_EB_OFFS(tlsdata);
+345 -11
View File
@@ -38,6 +38,9 @@ void Run660F(x86emu_t *emu)
int32_t tmp32s;
sse_regs_t *opex, eax1, *opx2;
mmx87_regs_t *opem;
#ifndef NOALIGN
int is_nan;
#endif
opcode = F8;
@@ -366,6 +369,23 @@ void Run660F(x86emu_t *emu)
}
break;
case 0x14: /* BLENDVPS Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
if(emu->xmm[0].ud[i]&0x80000000)
GX.ud[i] = EX->ud[i];
}
break;
case 0x17: // PTEST GX, EX
nextop = F8;
GET_EX;
CHECK_FLAGS(emu);
CONDITIONAL_SET_FLAG(!((GX.q[0]&EX->q[0])|(GX.q[1]&EX->q[1])), F_ZF);
CONDITIONAL_SET_FLAG(!(((~GX.q[0])&EX->q[0])|((~GX.q[1])&EX->q[1])), F_CF);
break;
case 0x1C: /* PABSB Gx, Ex */
nextop = F8;
GET_EX;
@@ -388,6 +408,104 @@ void Run660F(x86emu_t *emu)
}
break;
case 0x20: /* PMOVSXBW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=7; i>=0; --i)
GX.sw[i] = EX->sb[i];
break;
case 0x21: /* PMOVSXBD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.sd[i] = EX->sb[i];
break;
case 0x22: /* PMOVSXBQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sb[i];
break;
case 0x23: /* PMOVSXWD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.sd[i] = EX->sw[i];
break;
case 0x24: /* PMOVSXWQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sw[i];
break;
case 0x25: /* PMOVSXDQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.sq[i] = EX->sd[i];
break;
case 0x30: /* PMOVZXBW Gx, Ex */
nextop = F8;
GET_EX;
for(int i=7; i>=0; --i)
GX.uw[i] = EX->ub[i];
break;
case 0x31: /* PMOVZXBD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.ud[i] = EX->ub[i];
break;
case 0x32: /* PMOVZXBQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->ub[i];
break;
case 0x33: /* PMOVZXWD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=3; i>=0; --i)
GX.ud[i] = EX->uw[i];
break;
case 0x34: /* PMOVZXWQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->uw[i];
break;
case 0x35: /* PMOVZXDQ Gx, Ex */
nextop = F8;
GET_EX;
for(int i=1; i>=0; --i)
GX.q[i] = EX->ud[i];
break;
case 0x39: /* PMINSD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.sd[i]>EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
case 0x3D: /* PMAXSD Gx, Ex */
nextop = F8;
GET_EX;
for(int i=0; i<4; ++i)
if(GX.sd[i]<EX->sd[i])
GX.sd[i] = EX->sd[i];
break;
case 0x40: /* PMULLD Gx, Ex */
nextop = F8;
GET_EX;
for (int i=0; i<4; ++i) {
GX.sd[i] *= EX->sd[i];
}
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
@@ -397,6 +515,112 @@ void Run660F(x86emu_t *emu)
case 0x3A: // these are some SSE3 opcodes
opcode = F8;
switch(opcode) {
case 0x08: // roundps GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
GX.f[1] = nearbyint(EX->f[1]);
GX.f[2] = nearbyint(EX->f[2]);
GX.f[3] = nearbyint(EX->f[3]);
break;
case ROUND_Down:
GX.f[0] = floor(EX->f[0]);
GX.f[1] = floor(EX->f[1]);
GX.f[2] = floor(EX->f[2]);
GX.f[3] = floor(EX->f[3]);
break;
case ROUND_Up:
GX.f[0] = ceil(EX->f[0]);
GX.f[1] = ceil(EX->f[1]);
GX.f[2] = ceil(EX->f[2]);
GX.f[3] = ceil(EX->f[3]);
break;
case ROUND_Chop:
GX.f[0] = trunc(EX->f[0]);
GX.f[1] = trunc(EX->f[1]);
GX.f[2] = trunc(EX->f[2]);
GX.f[3] = trunc(EX->f[3]);
break;
}
break;
case 0x09: // roundpd GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
GX.d[1] = nearbyint(EX->d[1]);
break;
case ROUND_Down:
GX.d[0] = floor(EX->d[0]);
GX.d[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GX.d[0] = ceil(EX->d[0]);
GX.d[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GX.d[0] = trunc(EX->d[0]);
GX.d[1] = trunc(EX->d[1]);
break;
}
break;
case 0x0A: // roundss GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.f[0] = nearbyint(EX->f[0]);
break;
case ROUND_Down:
GX.f[0] = floor(EX->f[0]);
break;
case ROUND_Up:
GX.f[0] = ceil(EX->f[0]);
break;
case ROUND_Chop:
GX.f[0] = trunc(EX->f[0]);
break;
}
break;
case 0x0B: // roundsd GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
switch((tmp8u & 4) ? ((emu->mxcsr >> 13) & 3) : (tmp8u & 3))
{
case ROUND_Nearest:
GX.d[0] = nearbyint(EX->d[0]);
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] = trunc(EX->d[0]);
break;
}
break;
case 0x0E: /* PBLENDW Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
for (int i=0; i<8; ++i) {
if(tmp8u&(1<<i))
GX.uw[i] = EX->uw[i];
}
break;
case 0x0F: // PALIGNR GX, EX, u8
nextop = F8;
GET_EX;
@@ -434,6 +658,37 @@ void Run660F(x86emu_t *emu)
}
#endif
break;
case 0x16: // PEXTRD ED, GX, u8
nextop = F8;
GET_ED;
tmp8u = F8;
ED->dword[0] = GX.ud[tmp8u&3];
break;
case 0x20: // PINSRB GX, Ed, Ib
nextop = F8;
GET_ED;
tmp8u = F8;
GX.ub[tmp8u&0xF] = ED->byte[0]; // only low 8bits
break;
case 0x21: // INSERTPS GX, EX, u8
nextop = F8;
GET_EX;
tmp8u = F8;
if((nextop&0xC0)==0xC0) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
GX.ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
for(int i=0; i<4; ++i)
if(tmp8u&(1<<i))
GX.ud[i] = 0;
break;
case 0x22: // PINSRD GX, ED, u8
nextop = F8;
GET_ED;
tmp8u = F8;
GX.ud[tmp8u&0x3] = ED->dword[0];
break;
default:
ip = R_EIP;
UnimpOpcode(emu);
@@ -450,8 +705,14 @@ void Run660F(x86emu_t *emu)
case 0x51: /* SQRTPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] = sqrt(EX->d[0]);
GX.d[1] = sqrt(EX->d[1]);
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
if(EX->d[i]<0.0) // on x86, default nan are negative
GX.d[i] = -NAN; // but input NAN are not touched (so sqrt(+nan) -> +nan)
else
#endif
GX.d[i] = sqrt(EX->d[i]);
}
break;
case 0x54: /* ANDPD Gx, Ex */
@@ -481,14 +742,28 @@ void Run660F(x86emu_t *emu)
case 0x58: /* ADDPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] += EX->d[0];
GX.d[1] += EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// add generate a -NAN only if doing inf + -inf
if((isinf(GX.d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)!=(GX.q[i]&0x8000000000000000LL)))
GX.d[i] = -NAN;
else
#endif
GX.d[i] += EX->d[i];
}
break;
case 0x59: /* MULPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] *= EX->d[0];
GX.d[1] *= EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// mul generate a -NAN only if doing (+/-)inf * (+/-)0
if((isinf(GX.d[i]) && EX->d[i]==0.0) || (isinf(EX->d[i]) && GX.d[i]==0.0))
GX.d[i] = -NAN;
else
#endif
GX.d[i] *= EX->d[i];
}
break;
case 0x5A: /* CVTPD2PS Gx, Ex */
nextop = F8;
@@ -530,8 +805,15 @@ void Run660F(x86emu_t *emu)
case 0x5C: /* SUBPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] -= EX->d[0];
GX.d[1] -= EX->d[1];
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
// sub generate a -NAN only if doing inf - inf
if((isinf(GX.d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)==(GX.q[i]&0x8000000000000000LL)))
GX.d[i] = -NAN;
else
#endif
GX.d[i] -= EX->d[i];
}
break;
case 0x5D: /* MINPD Gx, Ex */
nextop = F8;
@@ -544,8 +826,16 @@ void Run660F(x86emu_t *emu)
case 0x5E: /* DIVPD Gx, Ex */
nextop = F8;
GET_EX;
GX.d[0] /= EX->d[0];
GX.d[1] /= EX->d[1];
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
is_nan = isnan(GX.d[i]) || isnan(EX->d[i]);
#endif
GX.d[i] /= EX->d[i];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[i]))
GX.d[i] = -NAN;
#endif
}
break;
case 0x5F: /* MAXPD Gx, Ex */
nextop = F8;
@@ -834,11 +1124,50 @@ void Run660F(x86emu_t *emu)
case 0x7C: /* HADDPD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
is_nan = isnan(GX.d[0]) || isnan(GX.d[1]);
#endif
GX.d[0] += GX.d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[0]))
GX.d[0] = -NAN;
#endif
if(EX==&GX) {
GX.d[1] = GX.d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX.d[1] = EX->d[0] + EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[1]))
GX.d[1] = -NAN;
#endif
}
break;
case 0x7D: /* HSUBPD Gx, Ex */
nextop = F8;
GET_EX;
#ifndef NOALIGN
is_nan = isnan(GX.d[0]) || isnan(GX.d[1]);
#endif
GX.d[0] -= GX.d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[0]))
GX.d[0] = -NAN;
#endif
if(EX==&GX) {
GX.d[1] = GX.d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX.d[1] = EX->d[0] - EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX.d[1]))
GX.d[1] = -NAN;
#endif
}
break;
@@ -1059,6 +1388,11 @@ void Run660F(x86emu_t *emu)
GET_EB;
GW.sword[0] = EB->sbyte[0];
break;
case 0xBF: /* MOVSX Gw,Ew */
nextop = F8;
GET_EW;
GW.sword[0] = EW->sword[0];
break;
case 0xC1: /* XADD Gw,Ew */ // Xchange and Add
nextop = F8;
@@ -1467,4 +1801,4 @@ void Run660F(x86emu_t *emu)
R_EIP = ip;
return;
}
}
+107 -16
View File
@@ -19,6 +19,7 @@
#include "x86run.h"
#include "librarian.h"
#include "elfloader.h"
#include "bridge.h"
#ifdef HAVE_TRACE
#include "x86trace.h"
#endif
@@ -62,6 +63,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
return 0;
emu->quit = 0;
}
MarkElfInitDone(my_context->elfs[0]);
printf_log(LOG_DEBUG, "Transfert to main(%d, %p, %p)=>%p from __libc_start_main\n", my_context->argc, my_context->argv, my_context->envv, main);
// call main and finish
PushExit(emu);
@@ -70,7 +72,7 @@ int32_t EXPORT my___libc_start_main(x86emu_t* emu, int *(main) (int, char * *, c
DynaRun(emu);
emu->quit = 1; // finished!
return 0;
return (int)R_EAX;
}
#endif
@@ -339,6 +341,51 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
break;
case d_rcl8:
cc = (emu->op1 >> (8 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 6) & 0x2)), F_OF);
break;
case d_rcl16:
cc = (emu->op1 >> (16 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 14) & 0x2)), F_OF);
break;
case d_rcl32:
cc = (emu->op1 >> (32 - emu->op2)) & 0x1;
CONDITIONAL_SET_FLAG(cc, F_CF);
CONDITIONAL_SET_FLAG(emu->op2 == 1 && XOR2(cc + ((emu->res >> 30) & 0x2)), F_OF);
break;
case d_rcr8:
cnt = emu->op2 % 9;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 6) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_rcr16:
cnt = emu->op2 % 17;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 14) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_rcr32:
cnt = emu->op2 % 33;
if (cnt == 1) {
CONDITIONAL_SET_FLAG(emu->op1 & 0x1, F_CF);
cc = ACCESS_FLAG(F_CF) != 0;
CONDITIONAL_SET_FLAG(XOR2(cc + ((emu->op1 >> 30) & 0x2)), F_OF);
} else {
CONDITIONAL_SET_FLAG((emu->op1 >> (cnt - 1)) & 0x1, F_CF);
}
break;
case d_shl8:
if (emu->op2 < 8) {
cnt = emu->op2 % 8;
@@ -512,7 +559,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x80, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -521,7 +568,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x8000, F_SF);
CONDITIONAL_SET_FLAG((emu->res & 0xffff) == 0, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -530,7 +577,7 @@ void UpdateFlags(x86emu_t *emu)
CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
bc = (emu->res & ((~emu->op1) | emu->op2)) | ((~emu->op1) & emu->op2);
CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
@@ -727,14 +774,21 @@ const char* getAddrFunctionName(uintptr_t addr)
static char ret[1000];
uint32_t sz = 0;
uintptr_t start = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, addr), (void*)addr, &start, &sz);
elfheader_t* elf = FindElfAddress(my_context, addr);
const char* symbname = FindNearestSymbolName(elf, (void*)addr, &start, &sz);
if(symbname && addr>=start && (addr<(start+sz) || !sz)) {
if(addr==start)
sprintf(ret, "%s/%s", ElfName(FindElfAddress(my_context, addr)), symbname);
if(symbname[0]=='\0')
sprintf(ret, "%s + 0x%x", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));
else if(addr==start)
sprintf(ret, "%s/%s", ElfName(elf), symbname);
else
sprintf(ret, "%s/%s + %d", ElfName(FindElfAddress(my_context, addr)), symbname, addr - start);
} else
sprintf(ret, "???");
sprintf(ret, "%s/%s + %d", ElfName(elf), symbname, addr - start);
} else {
if(elf) {
sprintf(ret, "%s + 0x%x", ElfName(elf), addr - (uintptr_t)GetBaseAddress(elf));
} else
sprintf(ret, "???");
}
return ret;
}
@@ -751,11 +805,46 @@ void printFunctionAddr(uintptr_t nextaddr, const char* text)
}
}
#ifdef HAVE_TRACE
extern uint64_t start_cnt;
#define PK(a) (*(uint8_t*)(ip+a))
#define PK32(a) (*(int32_t*)((uint8_t*)(ip+a)))
uintptr_t evalED(x86emu_t* emu, uintptr_t ip) {
uint8_t nextop = PK(0);
if((nextop&0xC0)==0xC0)
return emu->regs[(nextop&7)].dword[0];
else {
++ip;
if(!(nextop&0xC0)) {
if((nextop&7)==4) {
uint8_t sib = PK(0);
++ip;
uintptr_t base = ((sib&0x7)==5)?(PK32(0)):(emu->regs[(sib&0x7)].dword[0]);
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); \
return *(uintptr_t*)base;
} else if((nextop&7)==5) {
return *(uintptr_t*)PK32(0);
} else {
return *(uintptr_t*)emu->regs[nextop&7].dword[0];
}
} else {
uintptr_t base;
if((nextop&7)==4) {
uint8_t sib = PK(0);
++ip;
base = emu->regs[(sib&0x7)].dword[0];
base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6));
} else {
base = emu->regs[(nextop&0x7)].dword[0];
} \
base+=(nextop&0x80)?(*(int32_t*)ip):(*(int8_t*)ip);
return *(uintptr_t*)base;
}
}
}
#ifdef HAVE_TRACE
extern uint64_t start_cnt;
void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
{
if(start_cnt) --start_cnt;
@@ -786,7 +875,7 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
}
} else {
printf_log(LOG_NONE, "%s", DecodeX86Trace(my_context->dec, ip));
uint8_t peek = PK(0);
const uint8_t peek = PK(0);
if(peek==0xC3 || peek==0xC2) {
printf_log(LOG_NONE, " => %p", *(void**)(R_ESP));
printFunctionAddr(*(uintptr_t*)(R_ESP), "=> ");
@@ -797,9 +886,11 @@ void PrintTrace(x86emu_t* emu, uintptr_t ip, int dynarec)
uintptr_t nextaddr = ip + 5 + PK32(1);
printFunctionAddr(nextaddr, "=> ");
} else if(peek==0xFF) {
if(PK(1)==0x25) {
uintptr_t nextaddr = ip + 6 + PK32(2);
printFunctionAddr(nextaddr, "=> ");
const uint8_t pk1 = PK(1);
if(((pk1>>3)&7)==2 || ((pk1>>3)&7)==4) { // jmp/call near
uintptr_t nextaddr = (uintptr_t)getAlternate((void*)evalED(emu, ip+1));
printf_log(LOG_NONE, " => %p", nextaddr);
printFunctionAddr(nextaddr, " / ");
}
}
printf_log(LOG_NONE, "\n");
+141 -46
View File
@@ -72,13 +72,13 @@ void* my_mmap(x86emu_t* emu, void *addr, unsigned long length, int prot, int fla
void* my_mmap64(x86emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, int64_t offset);
int my_munmap(x86emu_t* emu, void* addr, unsigned long length);
int my_mprotect(x86emu_t* emu, void *addr, unsigned long len, int prot);
void* ElfSetBrk(void* newbrk);
// cannot include <fcntl.h>, it conflict with some asm includes...
#ifndef O_NONBLOCK
#define O_NONBLOCK 04000
#endif
#undef fcntl
int fcntl(int fd, int cmd, ... /* arg */ );
int my_fcntl(int fd, int cmd, ... /* arg */ );
// Syscall table for x86 can be found here: http://shell-storm.org/shellcode/files/syscalls.html
typedef struct scwrap_s {
@@ -112,7 +112,7 @@ scwrap_t syscallwrap[] = {
{ 40, __NR_rmdir, 1 },
{ 41, __NR_dup, 1 },
{ 42, __NR_pipe, 1 },
{ 45, __NR_brk, 1 },
//{ 45, __NR_brk, 1 },
{ 47, __NR_getgid, 0 },
{ 49, __NR_geteuid, 0 },
{ 50, __NR_getegid, 0 },
@@ -192,6 +192,8 @@ scwrap_t syscallwrap[] = {
{ 175, __NR_rt_sigprocmask, 4 },
{ 179, __NR_rt_sigsuspend, 2 },
{ 183, __NR_getcwd, 2 },
{ 184, __NR_capget, 2},
{ 185, __NR_capset, 2},
{ 186, __NR_sigaltstack, 2 }, // neeed wrap or something?
{ 191, __NR_ugetrlimit, 2 },
// { 192, __NR_mmap2, 6},
@@ -204,6 +206,9 @@ scwrap_t syscallwrap[] = {
{ 201, __NR_geteuid32, 0 },
{ 202, __NR_getegid32, 0 },
{ 208, __NR_setresuid32, 3 },
{ 209, __NR_getresuid32, 3 },
{ 210, __NR_setresgid32, 3 },
{ 211, __NR_getresgid32, 3 },
#else
// PowerPC uses the same syscalls for 32/64 bit processes.
{ 199, __NR_getuid, 0 },
@@ -211,6 +216,9 @@ scwrap_t syscallwrap[] = {
{ 201, __NR_geteuid, 0 },
{ 202, __NR_getegid, 0 },
{ 208, __NR_setresuid, 3 },
{ 209, __NR_getresuid, 3 },
{ 210, __NR_setresgid, 3 },
{ 211, __NR_getresgid, 3 },
#endif
{ 220, __NR_getdents64, 3 },
//{ 221, __NR_fcntl64, 3 },
@@ -246,6 +254,9 @@ scwrap_t syscallwrap[] = {
#ifdef __NR_memfd_create
{ 356, __NR_memfd_create, 2},
#endif
#ifdef __NR_futex_waitv
{ 449, __NR_futex_waitv, 5},
#endif
};
struct mmap_arg_struct {
@@ -317,9 +328,42 @@ int clone_fn(void* arg)
DynaRun(emu);
int ret = R_EAX;
FreeX86Emu(&emu);
my_context->stack_clone_used = 0;
return ret;
}
#ifndef __NR_ipc
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
static int my_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
#define IPC_SEMOP 1
#define IPC_SEMGET 2
#define IPC_SEMCTL 3
#define IPC_SEMTIMEDOP 4
#define IPC_MSGSND 11
#define IPC_MSGRCV 12
#define IPC_MSGGET 13
#define IPC_MSGCTL 14
#define IPC_SHMAT 21
#define IPC_SHMDT 22
#define IPC_SHMGET 23
#define IPC_SHMCTL 24
int version;
version = call>>16;
call &= 0xffff;
switch (call) {
case IPC_SHMGET:
return semget(first, second, third);
default:
printf_log(LOG_INFO, "Unsuported IPC call %d (version %d)\n", call, version);
return -ENOSYS;
}
}
#endif
void EXPORT x86Syscall(x86emu_t *emu)
{
RESET_FLAGS(emu);
@@ -387,21 +431,14 @@ void EXPORT x86Syscall(x86emu_t *emu)
R_EAX = time(NULL);
break;
#endif
case 45: // sys_brk
R_EAX = (uintptr_t)ElfSetBrk((void*)R_EBX);
break;
case 54: // sys_ioctl
R_EAX = (uint32_t)ioctl((int)R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
break;
case 55: // sys_fcntl
if(R_ECX==4) {
// filter out O_NONBLOCK so old stacally linked games that access X11 don't get EAGAIN error sometimes
int tmp = of_convert((int)R_EDX)&(~O_NONBLOCK);
if(R_EDX==0xFFFFF7FF) {
// special case for ~O_NONBLOCK...
int flags = fcntl(R_EBX, 3);
tmp = flags&~O_NONBLOCK;
}
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, tmp);
} else
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
R_EAX = (uint32_t)my_fcntl((int)R_EBX, (int)R_ECX, R_EDX);
break;
#ifndef __NR_getrlimit
case 76: // sys_getrlimit... this is the old version, using the new one. Maybe some tranform is needed?
@@ -476,47 +513,56 @@ void EXPORT x86Syscall(x86emu_t *emu)
case 110: // iopl
R_EAX = 0; // only on x86, so return 0...
break;
#endif
#ifndef __NR_ipc
case 117: // ipc
R_EAX = (uint32_t)my_ipc(R_EBX, (int)R_ECX, (int)R_EDX, (int)R_ESI, (void*)R_EDI, (long)R_EBP);
break;
#endif
case 119: // sys_sigreturn
emu->quit = 1; // we should be inside a DynaCall in a sigaction callback....
break;
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
// so flags=R_EBX, stack=R_ECX, parent_tid=R_EDX, tls=R_ESI, child_tid=R_EDI
if(R_ECX)
{
// should wrap that using a thread...
//struct x86_pt_regs *regs = (struct x86_pt_regs *)R_EDI;
// lets duplicate the emu
void* stack_base = (void*)R_ECX;
int stack_size = 0;
if(!R_ECX) {
// allocate a new stack...
stack_size = 1024*1024;
//stack_base = malloc(stack_size); // why not 1M... (normal operation do copy on write, simpler to just copy)
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base-size_to_copy, (void*)R_ESP, size_to_copy);
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (R_ECX)?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
SetESP(newemu, (uintptr_t)stack_base);
// setup registers
/*if(regs) {
SetEAX(newemu, regs->eax);
SetEBX(newemu, regs->ebx);
SetECX(newemu, regs->ecx);
SetEDX(newemu, regs->edx);
SetEDI(newemu, regs->edi);
SetESI(newemu, regs->esi);
SetEBP(newemu, regs->ebp);
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
SetESP(newemu, (uintptr_t)stack_base - size_to_copy);*/
void* mystack = (R_EBX&CLONE_VM)?malloc(1024*1024):NULL; // stack for own process... memory leak, but no practical way to remove it
int ret = clone(clone_fn, (void*)((R_EBX&CLONE_VM)?((uintptr_t)mystack+1024*1024):0), R_EBX, newemu, R_ESI, R_EDI, R_EBP);
//int r = syscall(__NR_clone, R_EBX, (R_EBX&CLONE_VM)?((uintptr_t)mystack):0, R_EDX, R_ESI, NULL); // cannot use that syscall in C: how to setup the stack?!
R_EAX = ret;
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), R_EBX, newemu, R_EDX, R_ESI, R_EDI);
R_EAX = (uint32_t)ret;
}
else
R_EAX = (uint32_t)syscall(__NR_clone, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI);
break;
case 122: // uname
{
@@ -585,11 +631,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
}
break;
case 221: // sys_fcntl64
if(R_ECX==4) {
int tmp = of_convert((int)R_EDX);
R_EAX = (uint32_t)fcntl((int)R_EBX, R_ECX, tmp);
} else
R_EAX = (uint32_t)fcntl((int)R_EBX, (int)R_ECX, R_EDX);
R_EAX = (uint32_t)my_fcntl((int)R_EBX, (int)R_ECX, R_EDX);
break;
case 243: // set_thread_area
R_EAX = my_set_thread_area((thread_area_t*)R_EBX);
@@ -639,6 +681,7 @@ void EXPORT x86Syscall(x86emu_t *emu)
uint32_t EXPORT my_syscall(x86emu_t *emu)
{
static uint32_t warned = 0;
uint32_t s = u32(0);
printf_log(LOG_DEBUG, "%p: Calling libc syscall 0x%02X (%d) %p %p %p %p %p\n", (void*)R_EIP, s, s, (void*)u32(4), (void*)u32(8), (void*)u32(12), (void*)u32(16), (void*)u32(20));
// check wrapper first
@@ -675,14 +718,63 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return (uint32_t)close(i32(4));
case 11: // execve
return (uint32_t)my_execve(emu, p(4), p(8), p(12));
case 45: // brk
return (uintptr_t)ElfSetBrk(p(4));
case 91: // munmap
return (uint32_t)my_munmap(emu, p(4), u32(8));
#ifndef __NR_ipc
case 117: // ipc
return (uint32_t)my_ipc(u32(4), i32(8), i32(12), i32(16), p(20), i32(24));
#endif
case 120: // clone
// x86 raw syscall is long clone(unsigned long flags, void *stack, int *parent_tid, unsigned long tls, int *child_tid);
// so flags=u(4), stack=p(8), parent_tid=p(12), tls=p(16), child_tid=p(20)
if(p(8))
{
void* stack_base = p(8);
int stack_size = 0;
if(!stack_base) {
// allocate a new stack...
int currstack = 0;
if((R_ESP>=(uintptr_t)emu->init_stack) && (R_ESP<=((uintptr_t)emu->init_stack+emu->size_stack)))
currstack = 1;
stack_size = (currstack)?emu->size_stack:(1024*1024);
stack_base = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
// copy value from old stack to new stack
if(currstack)
memcpy(stack_base, emu->init_stack, stack_size);
else {
int size_to_copy = (uintptr_t)emu->init_stack + emu->size_stack - (R_ESP);
memcpy(stack_base+stack_size-size_to_copy, (void*)R_ESP, size_to_copy);
}
}
x86emu_t * newemu = NewX86Emu(emu->context, R_EIP, (uintptr_t)stack_base, stack_size, (p(8))?0:1);
SetupX86Emu(newemu);
CloneEmu(newemu, emu);
Push32(newemu, 0);
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = box_malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
} else {
if(!my_context->stack_clone)
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
// x86_64 raw clone is long clone(unsigned long flags, void *stack, int *parent_tid, int *child_tid, unsigned long tls);
long ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), u32(4), newemu, p(12), p(16), p(20));
return (uint32_t)ret;
}
else
return (uint32_t)syscall(__NR_clone, u32(4), p(8), p(12), p(16), p(20));
break;
case 123: // SYS_modify_ldt
return my_modify_ldt(emu, i32(4), (thread_area_t*)p(8), i32(12));
case 125: // mprotect
return (uint32_t)my_mprotect(emu, p(4), u32(8), i32(12));
case 174: // sys_rt_sigaction
return (uint32_t)my_sigaction(emu, i32(4), (x86_sigaction_t*)p(8), (x86_sigaction_t*)p(12));
return (uint32_t)my_syscall_sigaction(emu, i32(4), p(8), p(12), i32(16));
case 192: // mmap2
return (uint32_t)my_mmap64(emu, p(4), u32(8), i32(12), i32(16), i32(20), u32(24));
case 243: // set_thread_area
@@ -718,9 +810,12 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
return (uint32_t)my_memfd_create(emu, (void*)R_EBX, R_ECX);
#endif
default:
printf_log(LOG_INFO, "Error: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
emu->quit = 1;
emu->error |= ERR_UNIMPL;
if(!(warned&(1<<s))) {
printf_log(LOG_INFO, "Warning: Unsupported libc Syscall 0x%02X (%d)\n", s, s);
warned|=(1<<s);
}
errno = ENOSYS;
return -1;
}
return 0;
}
+61 -23
View File
@@ -130,32 +130,46 @@ EXPORT uint32_t my_modify_ldt(x86emu_t* emu, int op, thread_area_t* td, int size
#define POS_TLS 0x50
static int sizeDTS(box86context_t* context)
{
return ((context->elfsize+0xff)&~0xff)*8;
}
static int sizeTLSData(int s)
{
uint32_t mask = box86_nogtk?0xffff:0x1fff;
return (s+mask)&~mask;
}
static tlsdatasize_t* setupTLSData(box86context_t* context)
{
// Setup the GS segment:
int dtsize = context->elfsize*8;
void *ptr = (char*)malloc(context->tlssize+4+POS_TLS+dtsize);
memcpy(ptr, context->tlsdata, context->tlssize);
tlsdatasize_t *data = (tlsdatasize_t*)calloc(1, sizeof(tlsdatasize_t));
data->tlsdata = ptr;
int dtssize = sizeDTS(context);
int datasize = sizeTLSData(context->tlssize);
void *ptr_oversized = (char*)box_malloc(dtssize+POS_TLS+datasize);
void *ptr = (void*)((uintptr_t)ptr_oversized + datasize);
memcpy((void*)((uintptr_t)ptr-context->tlssize), context->tlsdata, context->tlssize);
tlsdatasize_t *data = (tlsdatasize_t*)box_calloc(1, sizeof(tlsdatasize_t));
data->data = ptr;
data->tlssize = context->tlssize;
data->ptr = ptr_oversized;
data->n_elfs = context->elfsize;
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, 4); // put canary in place
uintptr_t tlsptr = (uintptr_t)ptr+context->tlssize;
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x0), &tlsptr, 4);
uintptr_t dtp = (uintptr_t)ptr+context->tlssize+POS_TLS;
memset((void*)((uintptr_t)ptr), 0, POS_TLS+dtssize); // set to 0 remining bytes
memcpy((void*)((uintptr_t)ptr+0x14), context->canary, 4); // put canary in place
uintptr_t tlsptr = (uintptr_t)ptr;
memcpy((void*)((uintptr_t)ptr+0x0), &tlsptr, 4);
uintptr_t dtp = (uintptr_t)ptr+POS_TLS;
memcpy((void*)(tlsptr+0x4), &dtp, 4);
if(dtsize) {
if(dtssize) {
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*8), &dtp, 4);
memcpy((void*)((uintptr_t)ptr+context->tlssize+POS_TLS+i*8+4), &i, 4); // index
dtp = (uintptr_t)ptr + GetTLSBase(context->elfs[i]);
memcpy((void*)((uintptr_t)ptr+POS_TLS+i*8), &dtp, 4);
memcpy((void*)((uintptr_t)ptr+POS_TLS+i*8+4), &i, 4); // index
}
}
memcpy((void*)((uintptr_t)ptr+context->tlssize+0x10), &context->vsyscall, 4); // address of vsyscall
memcpy((void*)((uintptr_t)ptr+0x10), &context->vsyscall, 4); // address of vsyscall
return data;
}
@@ -171,13 +185,37 @@ void* resizeTLSData(box86context_t *context, void* oldptr)
{
pthread_mutex_lock(&context->mutex_tls);
tlsdatasize_t* oldata = (tlsdatasize_t*)oldptr;
tlsdatasize_t *data = setupTLSData(context);
// copy the relevent old part, in case something changed
memcpy((void*)((uintptr_t)data->tlsdata+(context->tlssize-oldata->tlssize)), oldata->tlsdata, oldata->tlssize);
// all done, update new size, free old pointer and exit
pthread_mutex_unlock(&context->mutex_tls);
free_tlsdatasize(oldptr);
return data;
if(sizeTLSData(oldata->tlssize)!=sizeTLSData(context->tlssize) || (oldata->n_elfs/0xff)!=(context->elfsize/0xff)) {
printf_log(LOG_INFO, "Warning, resizing of TLS occured! size: %d->%d / n_elfs: %d->%d\n", sizeTLSData(oldata->tlssize), sizeTLSData(context->tlssize), 1+(oldata->n_elfs/0xff), 1+(context->elfsize/0xff));
tlsdatasize_t *data = setupTLSData(context);
// copy the relevent old part, in case something changed
memcpy((void*)((uintptr_t)data->data-oldata->tlssize), (void*)((uintptr_t)oldata->data-oldata->tlssize), oldata->tlssize);
// all done, update new size, free old pointer and exit
pthread_mutex_unlock(&context->mutex_tls);
free_tlsdatasize(oldptr);
return data;
} else {
// keep the same tlsdata, but fill in the blanks
// adjust tlsdata
void *ptr = oldata->data;
if(context->tlssize!=oldata->tlssize) {
memcpy((void*)((uintptr_t)ptr-context->tlssize), context->tlsdata, context->tlssize-oldata->tlssize);
oldata->tlssize = context->tlssize;
}
// adjust DTS
if(oldata->n_elfs!=context->elfsize) {
uintptr_t dtp = (uintptr_t)ptr+POS_TLS;
for (int i=oldata->n_elfs; i<context->elfsize; ++i) {
// set pointer
dtp = (uintptr_t)ptr + GetTLSBase(context->elfs[i]);
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8) = dtp;
*(uint64_t*)((uintptr_t)ptr+POS_TLS+i*8+4) = i; // index
}
oldata->n_elfs = context->elfsize;
}
pthread_mutex_unlock(&context->mutex_tls);
return oldata;
}
}
static void* GetSeg33Base()
@@ -189,7 +227,7 @@ static void* GetSeg33Base()
if(ptr->tlssize != my_context->tlssize) {
ptr = (tlsdatasize_t*)resizeTLSData(my_context, ptr);
}
return ptr->tlsdata+ptr->tlssize;
return ptr->data;
}
void* GetSegmentBase(uint32_t desc)
Loaded 100 of 481 files, more files were not shown because too many files have changed in this diff. Show more