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
Radical 25e4072fef Update COMPILE.md
Refined version (Still needs a few changes)
2022-04-08 15:18:51 +02:00
309 changed files with 10628 additions and 8780 deletions

No files matched your search

+16 -1
View File
@@ -29,8 +29,23 @@ jobs:
matrix:
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
+24 -3
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.4)
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})
@@ -10,19 +10,22 @@ option(GOA_CLONE "Set to ON if targeting GO Advance clones, like RG351p/v, Gamef
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 ODROIDN2 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 "")
@@ -58,7 +61,7 @@ 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 RPI4ARM64 OR PHYTIUM OR SD845 OR A64))
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)
@@ -134,10 +137,22 @@ 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)
@@ -237,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"
@@ -395,6 +411,7 @@ set(WRAPPEDS
"${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"
@@ -442,6 +459,9 @@ set(WRAPPEDS
"${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
@@ -496,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"
+66 -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`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
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`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
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`. Also, on armbian, you may need to also use `sudo apt install libc6-dev-armhf-cross` or you may have an issue with `crt1.o` and a few other similar file not found at link.
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,45 +104,60 @@ 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.
----
+5 -4
View File
@@ -1,6 +1,6 @@
![Official logo](img/Box86Logo.png "Official Logo")
Linux Userspace x86_64 Emulator with a twist
Linux Userspace x86 Emulator with a twist
[View changelog](https://github.com/ptitSeb/box86/blob/master/docs/CHANGELOG.md) | [中文](https://github.com/ptitSeb/box86/blob/master/docs/README_CN.md) | [Report an error](https://github.com/ptitSeb/box86/issues/new)
@@ -92,9 +92,10 @@ 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 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 aforementioned 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.
@@ -121,7 +122,7 @@ 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 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)
+1 -1
View File
@@ -126,7 +126,7 @@ Box86已经封装了Vulkan。如果设备的系统有32位的Vulkan驱动程序
贡献方式有很多种:代码贡献、财务帮助、捐赠捐赠和广告合作!
以下感谢不分先后:
* 代码贡献:rajdakin, icecream95, M-HT
* 财务帮助:FlyingFathead, stormchaser3000
* 财务帮助: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)
+40 -2
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.)
@@ -129,14 +134,20 @@ Enable/Disable simulation of 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)
* 1 : Only use Double for x87 emulation (slower, may be needed for some specific games, like Crysis)
* 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
@@ -186,11 +197,38 @@ 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 (for x64, use [box64](https://github.com/ptitSeb/box64) & wine-amd64 with an `aarch64` processor).
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
+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."
+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)
+16 -14
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):
@@ -751,9 +750,12 @@ def readFiles(files: Iterable[str]) -> Tuple[JumbledFunctions, JumbledFunctions,
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", "tbbmallocproxy") \
or match("tcmallocminimal","tbbmallocproxy") \
:
# libc and ldlinux have some "__libc_" data symbols in common... TODO check if ok
continue
@@ -1056,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
@@ -1257,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)]
@@ -1265,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)]
+35 -21
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,7 +181,8 @@ box86context_t *NewBox86Context(int argc)
context->local_maplib = NewLibrarian(context, 1);
context->versym = NewDictionnary();
context->system = NewBridge();
context->defver = NewDefaultVersion();
context->globaldefver = NewDefaultVersion();
context->weakdefver = NewDefaultVersion();
// create vsyscall
context->vsyscall = AddBridge(context->system, iFEv, x86Syscall, 0, NULL);
addAlternate((void*)0xffffe400, (void*)context->vsyscall);
@@ -188,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);
@@ -230,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);
@@ -244,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;
}
@@ -274,10 +280,11 @@ 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);
@@ -285,7 +292,7 @@ void FreeBox86Context(box86context_t** context)
freeALProcWrapper(ctx);
if(ctx->stack_clone)
free(ctx->stack_clone);
box_free(ctx->stack_clone);
void* ptr;
if ((ptr = pthread_getspecific(ctx->tlskey)) != NULL) {
@@ -295,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) {
@@ -308,7 +315,8 @@ void FreeBox86Context(box86context_t** context)
if(ctx->emu_sig)
FreeX86Emu(&ctx->emu_sig);
FreeDefaultVersion(&ctx->defver);
FreeDefaultVersion(&ctx->globaldefver);
FreeDefaultVersion(&ctx->weakdefver);
finiAllHelpers(ctx);
@@ -324,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) {
@@ -332,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++;
@@ -343,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 6
#define BOX86_REVISION 7
#endif //__BOX86_VERSION_H_
+321 -125
View File
@@ -25,23 +25,32 @@
#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 {
@@ -55,13 +64,15 @@ 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 {
@@ -105,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
@@ -235,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;
}
@@ -255,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;
@@ -284,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;
@@ -293,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) {
@@ -300,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;
}
@@ -326,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;
@@ -353,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;
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);
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);
}
}
}
@@ -394,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;
@@ -414,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;
@@ -439,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;
}
@@ -450,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;
@@ -460,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;
}
}
@@ -538,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
@@ -553,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
@@ -563,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)
{
@@ -616,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);
@@ -634,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)
@@ -652,40 +757,80 @@ 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_INFO, " %p-%p\n", (void*)m->begin, (void*)m->end);
printf_log(LOG_NONE, " %p-%p\n", (void*)m->begin, (void*)m->end);
m = m->next;
}
}
@@ -711,7 +856,7 @@ void addMapMem(uintptr_t begin, uintptr_t end)
newm = m;
} else {
// create a new block
newm = (mapmem_t*)calloc(1, sizeof(mapmem_t));
newm = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
newm->next = m->next;
newm->begin = begin;
newm->end = end;
@@ -723,7 +868,7 @@ void addMapMem(uintptr_t begin, uintptr_t end)
newm->end = newm->next->end;
mapmem_t* tmp = newm->next;
newm->next = tmp->next;
free(tmp);
box_free(tmp);
}
// all done!
}
@@ -751,9 +896,9 @@ void removeMapMem(uintptr_t begin, uintptr_t end)
m = mapmem;
prev = NULL;
}
free(tmp);
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*)calloc(1, sizeof(mapmem_t)); // create a new "next"
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;
@@ -773,35 +918,56 @@ void removeMapMem(uintptr_t begin, uintptr_t end)
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
}
}
@@ -811,14 +977,15 @@ void freeProtection(uintptr_t addr, uintptr_t size)
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] = 0;
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;
}
@@ -828,8 +995,8 @@ void allocProtection(uintptr_t addr, uintptr_t size, uint32_t prot)
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])
memprot[i] = prot;
if(!memprot[i].prot)
memprot[i].prot = prot;
}
}
@@ -840,6 +1007,7 @@ void loadProtectionFromMap()
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)) {
@@ -847,6 +1015,7 @@ void loadProtectionFromMap()
(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);
@@ -857,11 +1026,16 @@ void loadProtectionFromMap()
}
}
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
void* findBlockNearHint(void* hint, size_t size)
#define MEDIAN (void*)0x40000000
static void* findBlockHinted(void* hint, size_t size)
{
mapmem_t* m = mapmem;
uintptr_t h = (uintptr_t)hint;
@@ -874,13 +1048,21 @@ void* findBlockNearHint(void* hint, size_t size)
return hint;
if(addr>=h && end-addr+1>=size)
return (void*)addr;
if(end>=0xc0000000 & h<0xc0000000)
return NULL;
m = m->next;
}
return hint;
return NULL;
}
void* findBlockNearHint(void* hint, size_t size)
{ void* ret = findBlockHinted(hint, size);
return ret?ret:hint;
}
void* find32bitBlock(size_t size)
{
return findBlockNearHint(LOWEST, size);
void* ret = findBlockHinted(MEDIAN, size);
if(!ret) ret = findBlockHinted(LOWEST, size);
return ret;
}
int unlockCustommemMutex()
@@ -938,10 +1120,11 @@ 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*)calloc(1, sizeof(mapmem_t));
mapmem = (mapmem_t*)box_calloc(1, sizeof(mapmem_t));
mapmem->begin = 0x0;
mapmem->end = (uintptr_t)LOWEST - 1;
loadProtectionFromMap();
@@ -960,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;
}
}
@@ -977,29 +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;
free(tmp);
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
+4 -1
View File
@@ -391,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]
@@ -464,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))
@@ -793,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) )
+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__
+1 -1
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>
+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 && current->done) {
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_
+12 -18
View File
@@ -20,12 +20,7 @@
#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
@@ -44,9 +39,8 @@ void* LinkNext(x86emu_t* emu, uintptr_t addr, void* x2)
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)) {
@@ -54,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
@@ -114,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
@@ -168,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
@@ -199,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);
@@ -229,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
+141 -195
View File
@@ -23,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]);
}
@@ -74,7 +75,7 @@ void add_next(dynarec_arm_t *dyn, uintptr_t addr) {
// 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;
}
@@ -100,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);
@@ -249,7 +252,7 @@ static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86
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)
@@ -270,7 +273,7 @@ static instsize_t* addInst(instsize_t* insts, size_t* size, size_t* cap, int x86
static void fillPredecessors(dynarec_arm_t* dyn)
{
int pred_sz = 0;
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) {
@@ -280,13 +283,13 @@ static void fillPredecessors(dynarec_arm_t* dyn)
}
}
// second the "has_next"
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)) {
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*)malloc(pred_sz*sizeof(int));
dyn->predecessor = (int*)box_malloc(pred_sz*sizeof(int));
// fill pred pointer
int* p = dyn->predecessor;
for(int i=0; i<dyn->size; ++i) {
@@ -294,7 +297,6 @@ static void fillPredecessors(dynarec_arm_t* dyn)
p += dyn->insts[i].pred_sz;
dyn->insts[i].pred_sz=0; // reset size, it's reused to actually fill pred[]
}
assert(p==dyn->predecessor+pred_sz);
// 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))
@@ -305,59 +307,51 @@ static void fillPredecessors(dynarec_arm_t* dyn)
}
static void updateNeed(dynarec_arm_t* dyn, int ninst, uint32_t need) {
uint32_t old_need = dyn->insts[ninst].x86.need_flags;
uint32_t new_need = old_need | need;
uint32_t new_use = dyn->insts[ninst].x86.use_flags;
uint32_t old_use = dyn->insts[ninst].x86.old_use;
if((new_need&X_PEND) && dyn->insts[ninst].x86.state_flags==SF_SUBSET) {
new_need &=~X_PEND;
new_need |= X_ALL;
}
uint32_t new_set = 0;
if(dyn->insts[ninst].x86.state_flags & SF_SET)
new_set = dyn->insts[ninst].x86.set_flags;
if(dyn->insts[ninst].x86.state_flags & SF_PENDING)
new_set |= X_PEND;
if((new_need&X_PEND) && (
dyn->insts[ninst].x86.state_flags==SF_SET || dyn->insts[ninst].x86.state_flags==SF_SUBSET)) {
new_need &=~X_PEND;
new_need |=X_ALL;
}
dyn->insts[ninst].x86.need_flags = new_need;
dyn->insts[ninst].x86.old_use = new_use;
if(dyn->insts[ninst].x86.jmp_insts==-1)
new_need |= X_PEND;
// a Flag Barrier will change all need to "Pending", as it clear all flags optimisation
if(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)
new_need = X_PEND;
if((new_need == old_need) && (new_use == old_use)) // no changes, bye
return;
if(!(new_need && dyn->insts[ninst].x86.barrier&BARRIER_FLAGS)) {
new_need &=~new_set; // clean needed flag that were suplied
new_need |= new_use; // new need
}
if((new_need == (X_ALL|X_PEND)) && (dyn->insts[ninst].x86.state_flags & SF_SET))
new_need = X_ALL;
//update need to new need on predecessor
for(int i=0; i<dyn->insts[ninst].pred_sz; ++i)
updateNeed(dyn, dyn->insts[ninst].pred[i], new_need);
}
static void resetNeed(dynarec_arm_t* dyn) {
for(int i = dyn->size; i-- > 0;) {
dyn->insts[i].x86.old_use = 0;
dyn->insts[i].x86.need_flags = dyn->insts[i].x86.default_need;
// 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);
@@ -373,21 +367,49 @@ void CancelBlock()
current_helper = NULL;
if(!helper)
return;
free(helper->next);
free(helper->insts);
free(helper->predecessor);
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;
@@ -399,33 +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 with current barriers
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
// 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.use_flags |= X_PEND;
helper.insts[i].x86.need_after |= X_PEND;
} else {
// find jump address instruction
int k=-1;
@@ -440,94 +458,54 @@ dynarec_log(LOG_DEBUG, "Asked to Fill block %p with %p\n", block, (void*)addr);
}
// fill predecessors with the jump address
fillPredecessors(&helper);
// check for the optionnal barriers now
for(int i=helper.size-1; i>=0; --i) {
if(helper.insts[i].barrier_maybe) {
// out-of-block jump
if(helper.insts[i].x86.jmp_insts == -1) {
// nothing for now
} else {
// inside block jump
int k = helper.insts[i].x86.jmp_insts;
if(k>i) {
// jump in the future
if(helper.insts[k].pred_sz>1) {
// with multiple flow, put a barrier
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
} else {
// jump back
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
}
}
}
}
// check to remove useless barrier, in case of jump when destination doesn't needs flags
/*for(int i=helper.size-1; i>=0; --i) {
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
&& helper.insts[k].x86.barrier&BARRIER_FLAGS) {
//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 &= ~BARRIER_FLAGS; // remove flag barrier
}
}
}*/
// reset need_flags and compute again, now taking barrier into account (because barrier change use_flags)
for(int i = helper.size; i-- > 0;) {
int k;
if(helper.insts[i].x86.jmp
&& ((k=helper.insts[i].x86.jmp_insts)>=0)
) {
if(helper.insts[k].x86.barrier&BARRIER_FLAGS)
// jumpto barrier
helper.insts[i].x86.use_flags |= X_PEND;
if(helper.insts[i].x86.barrier&BARRIER_FLAGS && (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags))
helper.insts[k].x86.barrier|=BARRIER_FLAGS;
else
helper.insts[i].x86.use_flags |= (helper.insts[k].x86.need_flags | helper.insts[k].x86.use_flags);
}
if(helper.insts[i].x86.barrier&BARRIER_FLAGS)
// immediate barrier
helper.insts[i].x86.use_flags |= X_PEND;
}
resetNeed(&helper);
for(int i = helper.size; i-- > 0;)
updateNeed(&helper, i, 0);
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);
@@ -539,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) {
@@ -572,38 +550,6 @@ 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.predecessor);
helper.predecessor = NULL;
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;
+80 -38
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:
@@ -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");
@@ -702,11 +726,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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) \
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 { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
@@ -992,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);
@@ -1018,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);
@@ -1063,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:
@@ -1074,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:
@@ -1099,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;
}
@@ -1112,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;
@@ -1127,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);
}
@@ -1139,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);
}
@@ -1151,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;
}
@@ -1172,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 {
@@ -1495,7 +1522,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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");
@@ -1526,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 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:
@@ -1569,7 +1596,9 @@ 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
if(box86_dynarec_safeflags) {
READFLAGS(X_PEND); // lets play safe here too
}
BARRIER(BARRIER_FLOAT);
i32 = F16;
retn_to_epilog(dyn, ninst, i32);
@@ -1580,7 +1609,9 @@ 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
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;
@@ -1598,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:
@@ -1612,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;
@@ -1644,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;
@@ -1851,7 +1884,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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");
@@ -1961,7 +1994,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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");
@@ -1971,7 +2004,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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:
@@ -2068,11 +2101,11 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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) \
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 { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
@@ -2125,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;*/
@@ -2158,7 +2191,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
@@ -2190,7 +2223,7 @@ 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
@@ -2228,7 +2261,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
jump_to_next(dyn, addr+i32, 0, ninst);
} else {
// inside the block
fpuCacheTransform(dyn, ninst, x1, x2, x3);
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;
@@ -2284,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);
@@ -2343,7 +2377,11 @@ 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
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;
@@ -2375,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);
@@ -2399,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);
@@ -2464,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);
@@ -2488,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);
@@ -2783,7 +2825,7 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
break;
case 2: // CALL Ed
INST_NAME("CALL Ed");
PASS2IF(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
+82 -54
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
@@ -93,7 +95,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
switch((nextop>>3)&7) {
case 1:
INST_NAME("PREFETCHW");
//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);
addr = fakeed(dyn,addr, ninst, nextop);
// should use PLDW, but it's not available on cortex-a8 for example
break;
@@ -111,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);
@@ -130,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);
@@ -150,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);
@@ -166,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);
}
@@ -210,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;
@@ -224,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);
}
@@ -246,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);
@@ -276,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;
@@ -289,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;
@@ -301,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);
}
@@ -316,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;
@@ -328,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);
}
@@ -342,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);
}
@@ -384,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;
@@ -442,6 +444,32 @@ 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;
}
@@ -480,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); \
}
@@ -592,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);
@@ -843,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);
@@ -919,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;
@@ -953,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) {
@@ -977,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);
}
@@ -998,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);
}
@@ -1015,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);
}
@@ -1141,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;
@@ -1155,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);
}
@@ -1178,11 +1206,11 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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) \
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 { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
@@ -1291,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); \
}
@@ -1415,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);
@@ -1471,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);
@@ -1535,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);
}
@@ -1547,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);
}
@@ -1563,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);
}
@@ -1646,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;
@@ -1678,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;
@@ -1690,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;
@@ -1706,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;
}
@@ -1726,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;
}
@@ -1756,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;
}
@@ -1786,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;
}
@@ -1824,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);
@@ -1896,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;
@@ -1908,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;
@@ -1975,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;
@@ -1988,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);
}
@@ -2002,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);
}
@@ -2016,7 +2044,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
v2 = fpu_get_scratch_double(dyn);
if((nextop&0xC0)!=0xC0) {
// from memory
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);
u8 = F8;
q0 = v0;
// Low part
@@ -2166,7 +2194,7 @@ uintptr_t dynarec0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
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);
@@ -2404,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;
+16 -7
View File
@@ -29,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);
@@ -185,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;
@@ -198,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;
@@ -210,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);
}
@@ -261,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);
@@ -270,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);
@@ -297,7 +306,7 @@ 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(BARRIER_FULL);
@@ -312,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);
}
+6 -6
View File
@@ -372,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;
@@ -385,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;
@@ -397,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);
}
@@ -437,7 +437,7 @@ uintptr_t dynarecGS(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, 0, 0, 0);
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);
@@ -452,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);
@@ -640,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);
}
+15 -9
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:
@@ -516,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
@@ -543,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:
@@ -557,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);
}
@@ -571,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;
@@ -584,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);
@@ -798,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);
@@ -939,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);
@@ -975,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);
+69 -66
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; \
} \
@@ -622,24 +622,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
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 FPCSR reg and test FPU execption (invalid operation only)
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);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VADD_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
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:
@@ -649,24 +649,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
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 FPCSR reg and test FPU execption (invalid operation only)
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);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VMUL_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
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:
@@ -697,24 +697,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
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 FPCSR reg and test FPU execption (invalid operation only)
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);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VSUB_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
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:
@@ -737,24 +737,24 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETGX(q1, 1);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
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 FPCSR reg and test FPU execption (invalid operation only)
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);
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
VDIV_F64(q1+1, q1+1, q0+1);
if(!box86_dynarec_fastnan) {
VMRS(x3); // get the FPCSR reg and test FPU execption (invalid operation only)
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:
@@ -893,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;
@@ -906,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;
@@ -929,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;
@@ -952,6 +952,9 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
@@ -1041,7 +1044,7 @@ uintptr_t dynarec660F(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, 0, 0, 0);
addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, 0, NULL);
u8 = F8;
if ((u8==0) || (u8==0b01010101) || (u8==0b10101010) || (u8==0b11111111)) {
if(u8&3) {
@@ -1068,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);
}
@@ -1089,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);
}
@@ -1106,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);
}
@@ -1135,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);
}
@@ -1156,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);
}
@@ -1173,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);
}
@@ -1201,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);
}
@@ -1222,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);
}
@@ -1245,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);
}
@@ -1266,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);
}
@@ -1320,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;
@@ -1332,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;
@@ -1346,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);
@@ -1388,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);
@@ -1436,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;
}
@@ -1456,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);
@@ -1485,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);
@@ -1498,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);
@@ -1514,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;
}
@@ -1534,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;
}
@@ -1563,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;
}
@@ -1592,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;
}
@@ -1626,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);
@@ -1685,7 +1688,7 @@ 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);
@@ -1756,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);
}
@@ -1770,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);
}
@@ -1883,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);
@@ -2072,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;
+58 -3
View File
@@ -30,6 +30,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
uint8_t ed, gd, u8;
int fixedaddress;
int32_t i32, j32;
int16_t i16;
MAYUSE(i32);
MAYUSE(j32);
MAYUSE(gb1);
@@ -37,7 +38,61 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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();
@@ -51,7 +106,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
emit_inc16(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} 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, 1);
B_MARK(cNE); // unaligned
@@ -89,7 +144,7 @@ uintptr_t dynarec66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
emit_dec32(dyn, ninst, ed, x3, x14);
EWBACK(x1);
} 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, 1);
B_MARK(cNE); // unaligned
+4 -2
View File
@@ -30,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;
@@ -142,11 +144,11 @@ uintptr_t dynarec67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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) \
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 { \
fpuCacheTransform(dyn, ninst, x1, x2, x3); \
CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \
i32 = dyn->insts[dyn->insts[ninst].x86.jmp_insts].address-(dyn->arm_size+8);\
Bcond(c__, i32); \
} \
+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;
+9 -11
View File
@@ -575,10 +575,10 @@ uintptr_t dynarecD9(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 {
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);
}
@@ -598,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);
}
@@ -617,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);
}
@@ -630,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);
}
@@ -641,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);
}
@@ -657,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));
+11 -11
View File
@@ -187,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;
@@ -202,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);
@@ -228,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);
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);
@@ -253,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);
@@ -273,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);
@@ -283,7 +283,7 @@ 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);
@@ -333,7 +333,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#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);
}
@@ -341,7 +341,7 @@ uintptr_t dynarecDB(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
#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);
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;
+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);
+10 -10
View File
@@ -156,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);
@@ -168,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);
@@ -178,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);
@@ -192,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);
@@ -205,20 +205,20 @@ 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->n.x87stack) {
+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;
+13 -13
View File
@@ -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 {
@@ -320,7 +320,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
@@ -328,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,7 +343,7 @@ uintptr_t dynarecDF(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
} else {
#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);
//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
@@ -413,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
+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) {
+92 -74
View File
@@ -51,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);
@@ -71,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);
@@ -95,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);
@@ -116,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);
@@ -141,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);
@@ -162,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);
@@ -187,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);
@@ -208,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);
@@ -232,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);
@@ -253,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);
@@ -277,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);
@@ -297,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);
@@ -321,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);
@@ -342,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);
@@ -374,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);
@@ -415,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);
@@ -436,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);
@@ -457,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);
@@ -477,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);
@@ -497,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);
@@ -538,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);
@@ -613,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;
@@ -652,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);
}
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x1, x14);}
} else {
UFLAG_IF {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
UFLAG_IF {emit_cmp32(dyn, ninst, xEAX, ed, x3, x14);}
MOV_REG(xEAX, ed);
MARK3
DMB_ISH();
break;
case 0xB3:
INST_NAME("LOCK BTR Ed, Gd");
@@ -708,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;
@@ -744,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;
}
@@ -767,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);
@@ -798,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);
@@ -834,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;
@@ -869,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;
@@ -901,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
@@ -947,7 +965,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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);
addr = geted(dyn, addr, ninst, nextop, &wback, x1, &fixedaddress, 0, 0, 1, LOCK_LOCK);
MARKLOCK;
if(!fixedaddress || (fixedaddress && (fixedaddress&7))) {
TSTS_IMM8(wback, 7);
@@ -1009,7 +1027,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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
@@ -1046,7 +1064,7 @@ uintptr_t dynarecF0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
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
+38 -15
View File
@@ -30,10 +30,10 @@
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); \
@@ -73,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);
@@ -90,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);
}
@@ -105,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);
@@ -132,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);
}
@@ -148,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);
}
@@ -165,7 +165,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
@@ -174,6 +174,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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;
@@ -185,7 +186,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
@@ -194,6 +195,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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:
@@ -204,7 +206,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
@@ -213,6 +215,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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:
@@ -239,7 +242,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
@@ -248,6 +251,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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:
@@ -269,7 +273,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
GETEX(d0, 0);
if(!box86_dynarec_fastnan) {
VMRS(x14); // get fpscr
ORR_IMM8(x3, x14, 0b001, 6); // enable exceptions
ORR_IMM8(x3, x14, 0b010, 9); // enable exceptions
BIC_IMM8(x3, x3, 0b10011111, 0);
VMSR(x3);
}
@@ -278,6 +282,7 @@ uintptr_t dynarecF20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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:
@@ -300,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);
}
@@ -335,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);
}
@@ -347,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;
@@ -388,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);
+20 -20
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; \
@@ -104,10 +104,10 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
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);
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);
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);
@@ -140,11 +140,11 @@ uintptr_t dynarecF30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
} else {
parity = getedparity(dyn, ninst, addr, nextop, 2);
if(parity && (v0<16)) {
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);
VSTR_32(v0*2, ed, fixedaddress);
} else {
VMOVfrDx_32(x2, v0, 0);
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);
}
}
@@ -156,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);
}
@@ -172,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);
}
@@ -230,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);
}
@@ -259,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);
}
@@ -396,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);
}
@@ -501,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);
@@ -518,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);
}
@@ -555,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);
@@ -569,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);
@@ -641,10 +641,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_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);
@@ -667,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);
+43 -1
View File
@@ -491,7 +491,7 @@ int getNominalPred(dynarec_arm_t* dyn, int ninst) {
return dyn->insts[ninst].pred[0];
}
int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
static int fpuCacheNeedsTransform(dynarec_arm_t* dyn, int ninst) {
int i2 = dyn->insts[ninst].x86.jmp_insts;
if(i2<0)
return 1;
@@ -754,3 +754,45 @@ int isInstClean(dynarec_arm_t* dyn, int ninst)
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;
}
+1 -1
View File
@@ -66,7 +66,7 @@ void neoncache_promote_double(dynarec_arm_t* dyn, int ninst, int a);
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 fpuCacheNeedsTransform(dynarec_arm_t* dyn, int i1);
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);
+63 -3
View File
@@ -27,8 +27,11 @@
#include "dynarec_arm_helper.h"
/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */
uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int* fixaddress, 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* fixaddress, uint32_t absmax, uint32_t mask, int getfixonly, int* l)
{
int lock = l?((l==LOCK_LOCK)?1:2):0;
if(lock==2)
*l = (box86_dynarec_strongmem==2)?1:0;
uint8_t ret = 2;
uint8_t scratch = 2;
*fixaddress = 0;
@@ -51,6 +54,10 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
*fixaddress = tmp;
}
} else {
switch(lock) {
case 1: addLockAddress(tmp); break;
case 2: if(isLockAddress(tmp)) *l=1; break;
}
MOV32(ret, tmp);
}
} else {
@@ -1098,7 +1105,7 @@ 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)
{
LDRH_IMM8(s1, xEmu, offsetof(x86emu_t, mxcsr));
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, mxcsr));
UBFX(s2, s1, 13, 2); // extract round...
MOV32(s1, round_map);
LDR_REG_LSL_IMM5(s2, s1, s2, 2);
@@ -1589,7 +1596,7 @@ static void unloadCache(dynarec_arm_t* dyn, int ninst, int stack_cnt, int s1, in
cache->neoncache[i].v = 0;
}
void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
static void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
{
#if STEP > 1
int i2 = dyn->insts[ninst].x86.jmp_insts;
@@ -1747,6 +1754,59 @@ void fpuCacheTransform(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
MESSAGE(LOG_DUMP, "\t---- Cache Transform\n");
#endif
}
static void flagsCacheTransform(dynarec_arm_t* dyn, int ninst, int s1)
{
#if STEP > 1
int j32;
int jmp = dyn->insts[ninst].x86.jmp_insts;
if(jmp<0)
return;
if(dyn->f.dfnone) // flags are fully known, nothing we can do more
return;
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
int go = 0;
switch (dyn->insts[jmp].f_entry.pending) {
case SF_UNKNOWN: break;
case SF_SET:
if(dyn->f.pending!=SF_SET && dyn->f.pending!=SF_SET_PENDING)
go = 1;
break;
case SF_SET_PENDING:
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
break;
case SF_PENDING:
if(dyn->f.pending!=SF_SET
&& dyn->f.pending!=SF_SET_PENDING
&& dyn->f.pending!=SF_PENDING)
go = 1;
else
go = (dyn->insts[jmp].f_entry.dfnone == dyn->f.dfnone)?0:1;
break;
}
if(dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone)
go = 1;
if(go) {
if(dyn->f.pending!=SF_PENDING) {
LDR_IMM9(s1, xEmu, offsetof(x86emu_t, df));
TSTS_REG_LSL_IMM5(s1, s1, 0);
j32 = (GETMARK3)-(dyn->arm_size+8);
Bcond(cEQ, j32);
}
CALL_(UpdateFlags, -1, 0);
MARK3;
}
#endif
}
void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3) {
if(cacheupd&1)
fpuCacheTransform(dyn, ninst, s1, s2, s3);
if(cacheupd&2)
flagsCacheTransform(dyn, ninst, s1);
}
#ifdef HAVE_TRACE
void fpu_reflectcache(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3)
+39 -34
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,7 +78,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); \
ADD_REG_LSL_IMM5(x2, wback, O, 0); \
if(wback != x2) wback = x2; \
LDR_IMM9(x1, wback, 0); \
@@ -95,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; \
@@ -107,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; \
@@ -119,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; \
@@ -139,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; \
@@ -153,7 +156,7 @@
wb1 = 0; \
ed = i; \
} 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); \
ADD_REG_LSL_IMM5(x3, wback, i, 0); \
if(wback!=x3) wback = x3; \
LDRB_IMM9(i, wback, fixedaddress); \
@@ -169,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; \
@@ -258,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) \
@@ -297,6 +300,10 @@
#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((dyn->f.pending!=SF_SET) \
@@ -313,23 +320,21 @@
SET_DFOK(); \
}
#endif
// SF_MAYSET doesn't change the flags status cache
// it also doesn't consume any needed flags
#ifndef SETFLAGS
#define SETFLAGS(A, B) \
if(dyn->f.pending!=SF_SET \
&& (B==SF_SUBSET || B==SF_SUBSET_PENDING) \
&& (dyn->insts[ninst].x86.need_flags&(~((A)|((B==SF_SUBSET_PENDING)?X_PEND:0))))) \
READFLAGS(dyn->insts[ninst].x86.need_flags&(~(A)|X_PEND)); \
if(dyn->insts[ninst].x86.need_flags) switch(B) { \
&& ((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.need_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
dyn->f.pending = (dyn->insts[ninst].x86.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \
break; \
case SF_MAYSET: break; \
} else dyn->f.pending = SF_SET
#endif
#ifndef JUMP
@@ -341,12 +346,12 @@
#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(BARRIER_NOFLAGS)
#endif
@@ -515,10 +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 fpuCacheTransform STEPNAME(fpuCacheTransform)
#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);
@@ -646,12 +651,12 @@ 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 fpuCacheTransform(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() fpuCacheNeedsTransform(dyn, ninst)
#define CHECK_CACHE() (cacheupd = CacheNeedsTransform(dyn, ninst))
#endif
#define neoncache_st_coherency STEPNAME(neoncache_st_coherency)
+11 -7
View File
@@ -30,11 +30,11 @@ 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->f.pending = 0;
dyn->f.dfnone = 0;
@@ -119,6 +119,9 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
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)
@@ -170,11 +173,15 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
}
}
#else
if(!ok && !need_epilog && box86_dynarec_bigblock && getProtection(addr+3)&~PROT_CUSTOM)
#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))
&& (((box86_dynarec_bigblock<2) && isJumpTableDefault((void*)next)) || (box86_dynarec_bigblock>1))
/*||(((next-addr)<30) && is_instructions(dyn, addr, next-addr))*/ ))
{
ok = 1;
@@ -208,10 +215,7 @@ uintptr_t arm_pass(dynarec_arm_t* dyn, uintptr_t addr)
BARRIER(BARRIER_FLOAT);
}
#if STEP == 0
if(dyn->insts[ninst].x86.set_flags)
dyn->insts[ninst].x86.default_need |= X_PEND;
else
dyn->insts[ninst].x86.use_flags |= X_PEND;
dyn->insts[ninst].x86.need_after |= X_PEND;
#endif
++ninst;
fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
@@ -224,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;
}
+8 -9
View File
@@ -5,16 +5,15 @@
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 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; \
if(B!=SF_MAYSET) { \
dyn->insts[ninst].x86.state_flags = B; \
dyn->f.pending=(B)&SF_SET_PENDING; \
dyn->f.dfnone=((B)&SF_SET)?1:0; \
}
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) 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
@@ -22,7 +21,7 @@
#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; \
} \
@@ -41,8 +40,8 @@
--dyn->size; \
*ok = -1; \
if(box86_dynarec_log>=LOG_INFO || box86_dynarec_dump) {\
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), \
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), \
-2
View File
@@ -6,8 +6,6 @@
#define NEW_INST \
if(ninst) { \
dyn->insts[ninst].address = (dyn->insts[ninst-1].address+dyn->insts[ninst-1].size); \
if(ninst && isInstClean(dyn, ninst)) \
++dyn->sons_size; \
}
#define INST_EPILOG dyn->insts[ninst].epilog = dyn->arm_size;
#define INST_NAME(name)
+5 -8
View File
@@ -8,18 +8,12 @@
#define MESSAGE(A, ...) if(box86_dynarec_dump) dynarec_log(LOG_NONE, __VA_ARGS__)
#define NEW_INST \
if(ninst && isInstClean(dyn, ninst)) { \
dyn->sons_x86[dyn->sons_size] = (uintptr_t)ip; \
dyn->sons_arm[dyn->sons_size] = dyn->block; \
MESSAGE(LOG_DUMP, "----> potential Son here %p/%p\n", (void*)ip, dyn->block); \
++dyn->sons_size; \
}
#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(%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, \
@@ -28,9 +22,12 @@
dyn->insts[ninst].x86.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)\
+3 -3
View File
@@ -5,6 +5,7 @@
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct instsize_s instsize_t;
#define BARRIER_MAYBE 8
@@ -95,16 +96,15 @@ typedef struct dynarec_arm_s {
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__
+4 -4
View File
@@ -24,7 +24,6 @@
#define SF_SUB 4
#define SF_SUBSET (SF_SUB|SF_SET)
#define SF_SUBSET_PENDING (SF_SUBSET|SF_PENDING)
#define SF_MAYSET 8
typedef struct instruction_x86_s {
uintptr_t addr; //address of the instruction
@@ -37,9 +36,10 @@ typedef struct instruction_x86_s {
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 default_need;// 0 or X_PEND basically
uint8_t need_flags; // calculated
uint8_t old_use; // calculated
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);
+207 -146
View File
@@ -12,6 +12,7 @@
#include <errno.h>
#include <dlfcn.h>
#include "custommem.h"
#include "box86version.h"
#include "elfloader.h"
#include "debug.h"
@@ -28,7 +29,6 @@
#include "callback.h"
#include "dynarec.h"
#include "box86stack.h"
#include "custommem.h"
#include "wine_tools.h"
#include "dictionnary.h"
#include "symbols.h"
@@ -56,10 +56,15 @@ elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec)
if(!h)
return NULL;
if ((h->path = realpath(name, NULL)) == NULL) {
h->path = (char*)malloc(1);
if ((h->path = box_realpath(name, NULL)) == NULL) {
h->path = (char*)box_malloc(1);
h->path[0] = '\0';
}
h->mapsymbols = NewMapSymbols();
h->weaksymbols = NewMapSymbols();
h->localsymbols = NewMapSymbols();
return h;
}
@@ -74,19 +79,23 @@ void FreeElfHeader(elfheader_t** head)
cleanDBFromAddressRange(my_context, h->text, h->textsz, 1);
}*/ // will be free at the end, no need to free it now
#endif
free(h->name);
free(h->path);
free(h->PHEntries);
free(h->SHEntries);
free(h->SHStrTab);
free(h->StrTab);
free(h->Dynamic);
free(h->DynStr);
free(h->SymTab);
free(h->DynSym);
box_free(h->name);
box_free(h->path);
box_free(h->PHEntries);
box_free(h->SHEntries);
box_free(h->SHStrTab);
box_free(h->StrTab);
box_free(h->Dynamic);
box_free(h->DynStr);
box_free(h->SymTab);
box_free(h->DynSym);
FreeMapSymbols(&h->mapsymbols);
FreeMapSymbols(&h->weaksymbols);
FreeMapSymbols(&h->localsymbols);
FreeElfMemory(h);
free(h);
box_free(h);
*head = NULL;
}
@@ -153,12 +162,12 @@ const char* ElfName(elfheader_t* head)
int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
{
uintptr_t offs = 0;
if(mainbin && head->vaddr==0) {
char* load_addr = getenv("BOX86_LOAD_ADDR");
if(load_addr)
if(sscanf(load_addr, "0x%zx", &offs)!=1)
offs = 0;
if(!head->vaddr && box86_load_addr) {
offs = box86_load_addr;
box86_load_addr += head->memsz*(1+mainbin);
box86_load_addr = (box86_load_addr+0xffffffLL)&~0xffffffLL;
}
int log_level = box86_load_addr?LOG_INFO:LOG_NEVER;
if(!offs)
offs = head->vaddr;
if(head->vaddr) {
@@ -166,9 +175,9 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
for (int i=0; i<head->numPHEntries; ++i)
if(head->PHEntries[i].p_type == PT_LOAD && head->PHEntries[i].p_flags)
++head->multiblock_n;
head->multiblock_size = (uint32_t*)calloc(head->multiblock_n, sizeof(uint32_t));
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size = (uint32_t*)box_calloc(head->multiblock_n, sizeof(uint32_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
// and now, create all individual blocks
head->memory = (char*)0xffffffff;
int n = 0;
@@ -206,9 +215,15 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
}
head->multiblock_n = n; // might be less in fact
for (int i=0; i<head->multiblock_n; ++i) {
printf_dump(LOG_NEVER, "Allocating 0x%x memory %p for Elf \"%s\"\n", head->multiblock_size[i], (void*)head->multiblock_offs[i], head->name);
void* p = mmap((void*)head->multiblock_offs[i], head->multiblock_size[i]
uintptr_t sz = head->multiblock_size[i];
if(my_context->elfsize==1) {
if(head->multiblock_n==1)
head->reserve = 2*1024*1024; // reserve 2Mb after bss
sz+=head->reserve;
}
printf_dump(log_level, "Allocating 0x%x memory %p for Elf \"%s\"\n", sz, (void*)head->multiblock_offs[i], head->name);
void* p = mmap((void*)head->multiblock_offs[i], sz
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| ((wine_preloaded)?MAP_FIXED:0)*/
, -1, 0);
@@ -240,7 +255,7 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
}
} else {
// vaddr is 0, load everything has a One block
printf_dump(LOG_NEVER, "Allocating 0x%zx memory %p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
printf_dump(log_level, "Allocating 0x%zx memory %p for Elf \"%s\"\n", head->memsz, (void*)offs, head->name);
void* p = mmap((void*)offs, head->memsz
, PROT_READ | PROT_WRITE | PROT_EXEC
, MAP_PRIVATE | MAP_ANONYMOUS /*| (((offs&&wine_preloaded)?MAP_FIXED:0))*/
@@ -257,12 +272,12 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
head->memory = p;
memset(p, 0, head->memsz);
head->delta = (intptr_t)p - (intptr_t)head->vaddr;
printf_dump(LOG_NEVER, "Got %p (delta=%p)\n", p, (void*)head->delta);
printf_dump(log_level, "Got %p (delta=%p)\n", p, (void*)head->delta);
head->multiblock_n = 1;
head->multiblock_size = (uint32_t*)calloc(head->multiblock_n, sizeof(uint32_t));
head->multiblock_offs = (uintptr_t*)calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size = (uint32_t*)box_calloc(head->multiblock_n, sizeof(uint32_t));
head->multiblock_offs = (uintptr_t*)box_calloc(head->multiblock_n, sizeof(uintptr_t));
head->multiblock = (void**)box_calloc(head->multiblock_n, sizeof(void*));
head->multiblock_size[0] = head->memsz;
head->multiblock_offs[0] = (uintptr_t)p;
head->multiblock[0] = p;
@@ -276,11 +291,14 @@ int AllocElfMemory(box86context_t* context, elfheader_t* head, int mainbin)
void FreeElfMemory(elfheader_t* head)
{
if(head->multiblock_n) {
for(int i=0; i<head->multiblock_n; ++i)
munmap(head->multiblock[i], head->multiblock_size[i]);
free(head->multiblock);
free(head->multiblock_size);
free(head->multiblock_offs);
if(head->multiblock_n==1)
munmap(head->multiblock[0], head->multiblock_size[0]+head->reserve);
else
for(int i=0; i<head->multiblock_n; ++i)
munmap(head->multiblock[i], head->multiblock_size[i]);
box_free(head->multiblock);
box_free(head->multiblock_size);
box_free(head->multiblock_offs);
}
}
@@ -347,8 +365,9 @@ int ReloadElfMemory(FILE* f, box86context_t* context, elfheader_t* head)
#ifdef DYNAREC
cleanDBFromAddressRange((uintptr_t)dest, e->p_memsz, 0);
#endif
mprotect(dest, e->p_memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
setProtection((uintptr_t)dest, e->p_memsz, PROT_READ | PROT_WRITE | PROT_EXEC);
uint32_t page_offset = (uintptr_t)dest & (box86_pagesize - 1);
mprotect(dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
setProtection((uintptr_t)dest - page_offset, e->p_memsz + page_offset, PROT_READ | PROT_WRITE | PROT_EXEC);
if(e->p_filesz) {
ssize_t r = -1;
if((r=fread(dest, e->p_filesz, 1, f))!=1) {
@@ -429,6 +448,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rel[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -441,13 +461,6 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}*/
// so weak symbol are the one left
if(!offs && !end) {
if(!offs && !end && (version>1)) {
const char* defver = GetDefaultVersion(my_context->defver, symname);
if(defver && !strcmp(defver, vername)) {
printf_dump(LOG_NEVER, "Try global first, as a global unversionned symbol %s might exist\n", symname);
GetGlobalSymbolStartEnd(maplib, symname, &offs, &end, head, -2, vername);
}
}
if(!offs && !end && local_maplib)
GetGlobalSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs && !end)
@@ -469,19 +482,19 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
ret_ok = 1;
}
if(offs)
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+(offs-(uintptr_t)p)), (void*)offs);
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (ver=%d/%s), (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(*(uintptr_t*)p+(offs-(uintptr_t)p)), (void*)offs);
offs = (offs - (uintptr_t)p);
*p += offs;
break;
case R_386_RELATIVE:
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *(void**)p, (void*)((*p)+head->delta));
*p += head->delta;
break;
case R_386_COPY:
globoffs = offs;
globend = end;
offs = end = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1, defver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs)
@@ -503,13 +516,13 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
end = offs + sym->st_size;
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (ver=%d/%s) \n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)");
}
*p = globoffs;
@@ -523,7 +536,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
*p = offs/* + rela[i].r_addend*/; // not addend it seems
}
}
@@ -548,14 +561,14 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
} else {
if(p) {
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, symname, vername?"@":"", vername?vername:"", *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, symname, vername?"@":"", vername?vername:"", *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
*p += head->delta;
*need_resolv = 1;
}
@@ -565,7 +578,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
printf_log(LOG_NONE, "Error: Symbol sym=%s(%s%s%s/version %d) not found, cannot apply R_386_32 %p (%p) in %s\n", symname, symname, vername?"@":"", vername?vername:"", version, p, *(void**)p, head->name);
ret_ok = 1;
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
*p += offs;
}
break;
@@ -584,10 +597,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
if(h_tls) {
delta = *(int32_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int32_t)offs, end-offs);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int32_t)offs, end-offs);
*p = (uintptr_t)((int32_t)offs + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
}
}
break;
@@ -606,10 +619,10 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
}
if(h_tls) {
delta = *(int32_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
*p = (uintptr_t)(-(int32_t)offs + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
}
}
break;
@@ -627,7 +640,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
offs = getElfIndex(my_context, h_tls);
}
if(p) {
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
@@ -646,7 +659,7 @@ int RelocateElfREL(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t*
offs = sym->st_value;
if(p) {
int tlsoffset = offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
@@ -676,6 +689,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
int version = head->VerSym?((Elf32_Half*)((uintptr_t)head->VerSym+head->delta))[ELF32_R_SYM(rela[i].r_info)]:-1;
if(version!=-1) version &=0x7fff;
const char* vername = GetSymbolVersion(head, version);
const char* defver = GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname);
if(bind==STB_LOCAL) {
offs = sym->st_value + head->delta;
end = offs + sym->st_size;
@@ -708,19 +722,19 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_PC32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
}
if(offs)
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)(*(uintptr_t*)p+(offs-(uintptr_t)p)), (void*)offs);
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_PC32 %p with sym=%s (%p -> %p/%p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, *(void**)p, (void*)(*(uintptr_t*)p+(offs-(uintptr_t)p)), (void*)offs);
offs = (offs - (uintptr_t)p);
*p += offs;
break;
case R_386_RELATIVE:
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":"Global", p, *(void**)p, (void*)((*p)+head->delta));
printf_dump(LOG_NEVER, "Apply [%d] %s R_386_RELATIVE %p (%p -> %p)\n", i, (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *(void**)p, (void*)((*p)+head->delta));
*p = head->delta+ rela[i].r_addend;
break;
case R_386_COPY:
globoffs = offs;
globend = end;
offs = end = 0;
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1); // try globaldata symbols first
GetSymbolStartEnd(GetGlobalData(maplib), symname, &offs, &end, version, vername, 1, defver); // try globaldata symbols first
if(!offs && local_maplib)
GetNoSelfSymbolStartEnd(local_maplib, symname, &offs, &end, head, version, vername);
if(!offs)
@@ -742,13 +756,13 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
end = offs + sym->st_size;
if(sym->st_size && offs) {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) size=%zd on sym=%s (ver=%d/%s) \n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, sym->st_size, symname, version, vername?vername:"(none)");
//memmove((void*)globoffs, (void*)offs, sym->st_size); // preapply to copy part from lib to main elf
AddWeakSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
AddUniqueSymbol(GetGlobalData(maplib), symname, offs, sym->st_size, version, vername);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT with R_386_COPY @%p/%p (%p/%p -> %p/%p) null sized on sym=%s (ver=%d/%s)\n",
(bind==STB_LOCAL)?"Local":"Global", p, globp, (void*)(p?(*p):0),
(bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, globp, (void*)(p?(*p):0),
(void*)(globp?(*globp):0), (void*)offs, (void*)globoffs, symname, version, vername?vername:"(none)");
}
*p = globoffs;
@@ -762,7 +776,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
if(strcmp(symname, "__gmon_start__") && strcmp(symname, "data_start") && strcmp(symname, "__data_start"))
printf_log(LOG_NONE, "Error: Global Symbol %s not found, cannot apply R_386_GLOB_DAT @%p (%p) in %s\n", symname, p, *(void**)p, head->name);
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":"Global", p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
printf_dump(LOG_NEVER, "Apply %s R_386_GLOB_DAT @%p (%p -> %p) on sym=%s (ver=%d/%s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, (void*)(p?(*p):0), (void*)offs, symname, version, vername?vername:"(none)");
*p = offs/* + rela[i].r_addend*/; // not addend it seems
}
}
@@ -787,14 +801,14 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
} else {
if(p) {
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, symname, vername?"@":"", vername?vername:"", *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s R_386_JMP_SLOT %p with sym=%s(%s%s%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, symname, vername?"@":"", vername?vername:"", *(void**)p, (void*)offs);
*p = offs + rela[i].r_addend;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but Jump Slot Offset is NULL \n", symname);
}
}
} else {
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":"Global", p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
printf_dump(LOG_NEVER, "Preparing (if needed) %s R_386_JMP_SLOT %p (0x%x->0x%0x) with sym=%s(%s%s%s/version %d) to be apply later\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, *p, *p+head->delta, symname, symname, vername?"@":"", vername?vername:"", version);
*p += head->delta;
*need_resolv = 1;
}
@@ -804,7 +818,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
printf_log(LOG_NONE, "Error: Symbol %s not found, cannot apply R_386_32 %p (%p) in %s\n", symname, p, *(void**)p, head->name);
ret_ok = 1;
} else {
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
printf_dump(LOG_NEVER, "Apply %s R_386_32 %p with sym=%s (ver=%d/%s) (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, vername?vername:"(none)", *(void**)p, (void*)(offs+*(uint32_t*)p));
*p /*+*/= offs+rela[i].r_addend;
}
break;
@@ -823,10 +837,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
if(h_tls) {
delta = *(int32_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int32_t)offs, end-offs);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, h_tls->tlsbase, (int32_t)offs, end-offs);
*p = (uintptr_t)((int32_t)offs + rela[i].r_addend + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
}
}
break;
@@ -845,10 +859,10 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
if(h_tls) {
delta = *(int32_t*)p;
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
printf_dump(LOG_NEVER, "Applying %s %s on %s @%p (%d -> %d+%d, size=%d)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, delta, -h_tls->tlsbase, -(int32_t)offs, end-offs);
*p = (uintptr_t)(-(int32_t)offs + rela[i].r_addend + h_tls->tlsbase);
} else {
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":"Global", DumpRelType(t), symname, p, (int32_t)offs);
printf_log(LOG_INFO, "Warning, cannot apply %s %s on %s @%p (%d), no elf_header found\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), DumpRelType(t), symname, p, (int32_t)offs);
}
}
break;
@@ -866,7 +880,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
offs = getElfIndex(my_context, h_tls);
}
if(p) {
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":"Global", p, symname, *(void**)p, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s %s %p with sym=%s (%p -> %p)\n", "R_386_TLS_DTPMOD32", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, *(void**)p, (void*)offs);
*p = offs;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s or Elf not found, but R_386_TLS_DTPMOD32 Slot Offset is NULL \n", symname);
@@ -885,7 +899,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
offs = sym->st_value;
if(p) {
int tlsoffset = offs; // it's not an offset in elf memory
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, (void*)tlsoffset, (void*)offs);
printf_dump(LOG_NEVER, "Apply %s R_386_TLS_DTPOFF32 %p with sym=%s (%p -> %p)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, (void*)tlsoffset, (void*)offs);
*p = tlsoffset;
} else {
printf_log(LOG_NONE, "Warning, Symbol %s found, but R_386_TLS_DTPOFF32 Slot Offset is NULL \n", symname);
@@ -898,6 +912,7 @@ int RelocateElfRELA(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t
}
return bindnow?ret_ok:0;
}
void checkHookedSymbols(lib_t *maplib, elfheader_t* h); // in mallochook.c
int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* head)
{
if(head->rel) {
@@ -914,7 +929,7 @@ int RelocateElf(lib_t *maplib, lib_t *local_maplib, int bindnow, elfheader_t* he
if(RelocateElfRELA(maplib, local_maplib, bindnow, head, cnt, (Elf32_Rela *)(head->rela + head->delta), NULL))
return -1;
}
checkHookedSymbols(maplib, head);
return 0;
}
@@ -1025,22 +1040,6 @@ uintptr_t GetLastByte(elfheader_t* h)
void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* weaksymbols, kh_mapsymbols_t* localsymbols, elfheader_t* h)
{
if(box86_dump && h->DynSym) DumpDynSym(h);
int libcef = (strstr(h->name, "libcef.so") || strstr(h->name, "libnode.so"))?1:0;
//libcef.so is linked with tcmalloc staticaly, but this cannot be easily supported in box86, so hacking some "unlink" here
const char* avoid_libcef[] = {"malloc", "realloc", "free", "calloc", "cfree",
"__libc_calloc", "__libc_cfree", "__libc_memallign", "__liv_pvalloc",
"__libcrealloc", "__libc_valloc", "__posix_memalign",
"valloc", "pvalloc", "posix_memalign", "malloc_stats", "malloc_usable_size",
/*"mallopt",*/ "localtime_r",
//c++ symbol from libstdc++ too
//"_ZnwmRKSt9nothrow_t", "_ZdaPv", // operator new(unsigned long, std::nothrow_t const&), operator delete[](void*)
//"_Znwm", "_ZdlPv", "_Znam", // operator new(unsigned long), operator delete(void*), operator new[](unsigned long)
//"_ZnwmSt11align_val_t", "_ZnwmSt11align_val_tRKSt9nothrow_t", // operator new(unsigned long, std::align_val_t)
//"_ZnamSt11align_val_t", "_ZnamSt11align_val_tRKSt9nothrow_t", // operator new[](unsigned long, std::align_val_t)
//"_ZdlPvRKSt9nothrow_t", "_ZdaPvSt11align_val_tRKSt9nothrow_t", // more delete operators
//"_ZdlPvmSt11align_val_t", "_ZdaPvRKSt9nothrow_t",
//"_ZdaPvSt11align_val_t", "_ZdlPvSt11align_val_t",
};
printf_dump(LOG_NEVER, "Will look for Symbol to add in SymTable(%zu)\n", h->numSymTab);
for (size_t i=0; i<h->numSymTab; ++i) {
const char * symname = h->StrTab+h->SymTab[i].st_name;
@@ -1058,8 +1057,8 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
p+=2;
symname = AddDictionnary(my_context->versym, symnameversionned);
const char* vername = AddDictionnary(my_context->versym, p);
AddDefaultVersion(my_context->defver, symname, vername);
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
printf_dump(LOG_NEVER, "Adding %s Default Version \"%s\" for Symbol\"%s\"\n", (bind==STB_WEAK)?"Weak":"Global", vername, symname);
}
if((type==STT_OBJECT || type==STT_FUNC || type==STT_COMMON || type==STT_TLS || type==STT_NOTYPE)
&& (vis==STV_DEFAULT || vis==STV_PROTECTED) && (h->SymTab[i].st_shndx!=0)) {
@@ -1086,13 +1085,6 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
}
} else {
int to_add = 1;
if(libcef) {
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
to_add = 0;
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
if(!strcmp(symname, avoid_libcef[j]))
to_add = 0;
}
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, -1, NULL)))
continue;
uintptr_t offs = (type==STT_TLS)?h->SymTab[i].st_value:(h->SymTab[i].st_value + h->delta);
@@ -1120,21 +1112,14 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
uintptr_t offs = (type==STT_TLS)?h->DynSym[i].st_value:(h->DynSym[i].st_value + h->delta);
size_t sz = h->DynSym[i].st_size;
int version = h->VerSym?((Elf32_Half*)((uintptr_t)h->VerSym+h->delta))[i]:-1;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetDefaultVersion(my_context->defver, symname))?1:0;
int add_default = (version!=-1 && (version&0x7fff)>1 && !(version&0x8000) && !GetDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname))?1:0;
if(version!=-1) version &= 0x7fff;
const char* vername = GetSymbolVersion(h, version);
if(add_default) {
AddDefaultVersion(my_context->defver, symname, vername);
AddDefaultVersion((bind==STB_WEAK)?my_context->weakdefver:my_context->globaldefver, symname, vername);
printf_dump(LOG_NEVER, "Adding Default Version \"%s\" for Symbol\"%s\"\n", vername, symname);
}
int to_add = 1;
if(libcef) {
if(strstr(symname, "_Zn")==symname || strstr(symname, "_Zd")==symname)
to_add = 0;
for(int j=0; j<sizeof(avoid_libcef)/sizeof(avoid_libcef[0]) && to_add; ++j)
if(!strcmp(symname, avoid_libcef[j]))
to_add = 0;
}
if(!to_add || (bind==STB_GNU_UNIQUE && FindGlobalSymbol(maplib, symname, version, vername)))
continue;
printf_dump(LOG_NEVER, "Adding Versionned Symbol(bind=%s) \"%s\" (ver=%d/%s) with offset=%p sz=%zu\n", (bind==STB_LOCAL)?"LOCAL":((bind==STB_WEAK)?"WEAK":"GLOBAL"), symname, version, vername?vername:"(none)", (void*)offs, sz);
@@ -1144,8 +1129,7 @@ void AddSymbols(lib_t *maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
if(bind==STB_WEAK) {
AddSymbol(weaksymbols, symname, offs, sz, version, vername);
} else {
// Binding is Global, the symbol "local" vsibility is ignored (fixes Unreal)
AddWeakSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
AddSymbol(mapsymbols, symname, offs, sz, version?version:1, vername);
}
}
}
@@ -1176,33 +1160,33 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
char* rpath = rpathref;
int is_origin = 0;
while(strstr(rpath, "$ORIGIN")) {
char* origin = strdup(h->path);
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("$ORIGIN")+strlen(origin)+1);
p = strstr(rpath, "$ORIGIN");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("$ORIGIN"));
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
rpath = tmp;
free(origin);
box_free(origin);
is_origin = 1;
}
while(strstr(rpath, "${ORIGIN}")) {
char* origin = strdup(h->path);
char* origin = box_strdup(h->path);
char* p = strrchr(origin, '/');
if(p) *p = '\0'; // remove file name to have only full path, without last '/'
char* tmp = (char*)calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
char* tmp = (char*)box_calloc(1, strlen(rpath)-strlen("${ORIGIN}")+strlen(origin)+1);
p = strstr(rpath, "${ORIGIN}");
memcpy(tmp, rpath, p-rpath);
strcat(tmp, origin);
strcat(tmp, p+strlen("${ORIGIN}"));
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
rpath = tmp;
free(origin);
box_free(origin);
is_origin = 1;
}
if(strchr(rpath, '$')) {
@@ -1219,7 +1203,7 @@ int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, lib
PrependList(&box86->box86_ld_lib, rpath, 1);
}
if(rpath!=rpathref)
free(rpath);
box_free(rpath);
}
if(!h->neededlibs && neededlibs)
@@ -1262,6 +1246,28 @@ int ElfCheckIfUseTCMallocMinimal(elfheader_t* h)
return 0;
}
void RefreshElfTLS(elfheader_t* h)
{
if(h->tlsfilesize) {
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
tlsdatasize_t* ptr;
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL) {
// refresh in tlsdata too
dest = (char*)(ptr->data+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
}
}
}
void MarkElfInitDone(elfheader_t* h)
{
if(h)
h->init_done = 1;
}
void RunElfInit(elfheader_t* h, x86emu_t *emu)
{
if(!h || h->init_done)
@@ -1270,29 +1276,19 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
memset(emu->segs_serial, 0, sizeof(emu->segs_serial));
uintptr_t p = h->initentry + h->delta;
box86context_t* context = GetEmuContext(emu);
// Refresh no-file part of TLS in case default value changed
RefreshElfTLS(h);
// check if in deferedInit
if(context->deferedInit) {
if(context->deferedInitSz==context->deferedInitCap) {
context->deferedInitCap += 4;
context->deferedInitList = (elfheader_t**)realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
context->deferedInitList = (elfheader_t**)box_realloc(context->deferedInitList, context->deferedInitCap*sizeof(elfheader_t*));
}
context->deferedInitList[context->deferedInitSz++] = h;
return;
}
// Refresh no-file part of TLS in case default value changed
if(h->tlsfilesize) {
char* dest = (char*)(my_context->tlsdata+my_context->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing main TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
tlsdatasize_t* ptr;
if ((ptr = (tlsdatasize_t*)pthread_getspecific(my_context->tlskey)) != NULL)
if(ptr->tlssize==my_context->tlssize) {
// refresh in tlsdata too
dest = (char*)(ptr->tlsdata+ptr->tlssize+h->tlsbase);
printf_dump(LOG_DEBUG, "Refreshing active TLS block @%p from %p:0x%x\n", dest, (void*)h->tlsaddr, h->tlssize-h->tlsfilesize);
memcpy(dest, (void*)(h->tlsaddr+h->delta), h->tlsfilesize);
}
}
printf_log(LOG_DEBUG, "Calling Init for %s %p\n", ElfName(h), (void*)p);
h->init_done = 1;
if(h->initentry)
RunFunctionWithEmu(emu, 0, p, 3, context->argc, context->argv, context->envv);
printf_log(LOG_DEBUG, "Done Init for %s\n", ElfName(h));
@@ -1303,7 +1299,6 @@ void RunElfInit(elfheader_t* h, x86emu_t *emu)
RunFunctionWithEmu(emu, 0, (uintptr_t)addr[i], 3, context->argc, context->argv, context->envv);
}
h->init_done = 1;
h->fini_done = 0; // can be fini'd now (in case it was re-inited)
printf_log(LOG_DEBUG, "All Init Done for %s\n", ElfName(h));
return;
@@ -1324,7 +1319,7 @@ void RunDeferedElfInit(x86emu_t *emu)
context->deferedInitCap = context->deferedInitSz = 0;
for (int i=0; i<Sz; ++i)
RunElfInit(List[i], emu);
free(List);
box_free(List);
}
void RunElfFini(elfheader_t* h, x86emu_t *emu)
@@ -1506,7 +1501,7 @@ void* GetTLSPointer(box86context_t* context, elfheader_t* h)
}
if(ptr->tlssize != context->tlssize)
ptr = (tlsdatasize_t*)resizeTLSData(context, ptr);
return ptr->tlsdata+(ptr->tlssize+h->tlsbase);
return ptr->data+h->tlsbase;
}
void* GetDynamicSection(elfheader_t* h)
@@ -1516,8 +1511,54 @@ void* GetDynamicSection(elfheader_t* h)
return h->Dynamic;
}
void* ElfGetBrk(elfheader_t* h)
{
if(!h)
return NULL;
return (void*)(h->bss+h->delta+h->bsssz);
}
void* ElfSetBrk(void* newbrk)
{
if(!my_context)
return NULL;
if(!my_context->elfsize)
return NULL;
elfheader_t* h = my_context->elfs[0];
void* ret = my_context->brk + my_context->brksz;
if(!newbrk)
return ret;
// compute the added size
intptr_t added = (intptr_t)newbrk - (intptr_t)my_context->brk;
if(added<=0) // cannot remove bss
return ret;
//check if elf is 1 big memory and splitted
if(h->multiblock_n!=1) {
// meh
printf_log(LOG_NONE, "Error, using brk on multi-part memory elf is not allowed for now");
} else {
printf_log(LOG_DEBUG, "brk change, start=%p with reserve=0x%x, was 0x%x long, will be 0x%x now => %p\n", my_context->brk, h->reserve, my_context->brksz, added, my_context->brk+added);
if(added>0 && added<h->reserve) {
my_context->brksz = added;
return newbrk;
}
void* newmem = mremap(h->memory, h->memsz+h->reserve+my_context->brksz, h->memsz+h->reserve+added, 0);
if(newmem!=(void*)-1) {
if(added>my_context->brksz)
setProtection((uintptr_t)my_context->brk + my_context->brksz, added-my_context->brksz, PROT_READ|PROT_WRITE);
else
freeProtection((uintptr_t)my_context->brk + added, my_context->brksz - added);
my_context->brksz = added;
ret = my_context->brk + added;
} else {
printf_log(LOG_DEBUG, "failed to remap\n");
}
}
return ret;
}
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr)
{
// if we are here, the there is not block in standard "space"
/*dynablocklist_t* ret = getDBFromAddress(addr);
@@ -1526,7 +1567,7 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
}*/
if(box86_dynarec_forced) {
addDBFromAddressRange(addr, 1);
return getDB(addr>>DYNAMAP_SHIFT);
return getDB(addr);
}
//check if address is in an elf... if yes, grant a block (should I warn)
Dl_info info;
@@ -1539,6 +1580,26 @@ dynablocklist_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t add
}
#endif
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->mapsymbols;
}
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->weaksymbols;
}
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h)
{
if(!h)
return NULL;
return h->localsymbols;
}
typedef struct my_dl_phdr_info_s {
void* dlpi_addr;
const char* dlpi_name;
@@ -1680,7 +1741,7 @@ void CreateMemorymapFile(box86context_t* context, int fd)
// create stack entry
sprintf(buff, "%08x-%08x %c%c%c%c %08x %02x:%02x %ld %s\n",
(uintptr_t)context->stack, (uintptr_t)context->stack+context->stacksz,
'r','w','-','p', 0, 0, 0, 0, "[stack]");
'r','w','-','p', 0, 0, 0, 0L, "[stack]");
dummy = write(fd, buff, strlen(buff));
}
@@ -1702,8 +1763,8 @@ int dl_iterate_phdr_findsymbol(struct dl_phdr_info* info, size_t size, void* dat
for(int j = 0; j<info->dlpi_phnum; ++j) {
if (info->dlpi_phdr[j].p_type == PT_DYNAMIC) {
ElfW(Sym)* sym = NULL;
ElfW(Word) sym_cnt = 0;
//ElfW(Sym)* sym = NULL;
//ElfW(Word) sym_cnt = 0;
ElfW(Verdef)* verdef = NULL;
ElfW(Word) verdef_cnt = 0;
char *strtab = NULL;
@@ -1795,7 +1856,7 @@ EXPORT void PltResolver(x86emu_t* emu)
return;
} else {
if(p) {
printf_dump(LOG_DEBUG, " Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":"Global", p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
printf_dump(LOG_DEBUG, " Apply %s R_386_JMP_SLOT %p with sym=%s(ver %d: %s%s%s) (%p -> %p / %s)\n", (bind==STB_LOCAL)?"Local":((bind==STB_WEAK)?"Weak":"Global"), p, symname, version, symname, vername?"@":"", vername?vername:"",*(void**)p, (void*)offs, ElfName(FindElfAddress(my_context, offs)));
*p = offs;
} else {
printf_log(LOG_NONE, "PltResolver: Warning, Symbol %s(ver %d: %s%s%s) found, but Jump Slot Offset is NULL \n", symname, version, symname, vername?"@":"", vername?vername:"");
+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
+74 -65
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,65 +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_log(LOG_NONE, "Warning, PreInit Array (size=%d) present and ignored!\n", 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) {
@@ -297,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
@@ -317,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);
@@ -355,19 +362,21 @@ elfheader_t* ParseElfHeader(FILE* f, const char* name, int exec)
const char* GetSymbolVersion(elfheader_t* h, int version)
{
version&=0x7fff; // remove bit15 that switch between hidden/public
if(!h->VerNeed || (version<2))
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
}
+19
View File
@@ -71,6 +71,14 @@
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;
@@ -292,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;
}
+4
View File
@@ -89,6 +89,10 @@
_66_0x3D:
cmp16(emu, R_AX, F16);
NEXT;
_66_0x3E: /* DS: */
// ignored
opcode = F8;
goto *opcodes66[opcode];
_66_0x40:
_66_0x41:
+2 -3
View File
@@ -245,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
@@ -259,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;
+6 -7
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;
+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];
+14 -6
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));
@@ -235,7 +240,7 @@ void x86Int3(x86emu_t* emu)
snprintf(buff, 255, "%04d|%p: Calling %s(\"%S\"...)", tid, *(void**)(R_ESP), s, pu32?((wchar_t*)(pu32)):L"nil");
} 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, %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));
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);
@@ -290,7 +295,7 @@ void x86Int3(x86emu_t* emu)
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)
@@ -321,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;
+2 -2
View File
@@ -104,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 ,&&_0f_0x0D, &&_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
@@ -145,7 +145,7 @@ int Run(x86emu_t *emu, int step)
&&_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
+92
View File
@@ -1209,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;
@@ -1338,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;
@@ -1424,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);
+136
View File
@@ -498,6 +498,14 @@ void Run660F(x86emu_t *emu)
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);
@@ -507,6 +515,103 @@ 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;
@@ -561,6 +666,12 @@ void Run660F(x86emu_t *emu)
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;
@@ -1035,6 +1146,31 @@ void Run660F(x86emu_t *emu)
}
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;
case 0x7E: /* MOVD Ed, Gx */
nextop = F8;
GET_ED;
+45 -7
View File
@@ -63,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);
@@ -71,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
@@ -804,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;
@@ -839,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), "=> ");
@@ -850,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");
+64 -24
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 },
@@ -324,6 +332,38 @@ int clone_fn(void* arg)
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);
@@ -391,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?
@@ -480,6 +513,11 @@ 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....
@@ -513,10 +551,10 @@ void EXPORT x86Syscall(x86emu_t *emu)
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
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 = malloc(1024*1024);
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
@@ -593,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);
@@ -684,8 +718,14 @@ 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)
@@ -715,10 +755,10 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
PushExit(newemu);
void* mystack = NULL;
if(my_context->stack_clone_used) {
mystack = malloc(1024*1024); // stack for own process... memory leak, but no practical way to remove it
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 = malloc(1024*1024);
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
my_context->stack_clone_used = 1;
}
@@ -734,7 +774,7 @@ uint32_t EXPORT my_syscall(x86emu_t *emu)
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
+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)
+4 -4
View File
@@ -41,7 +41,7 @@ int InitX86Trace(box86context_t *context)
{
if(context->zydis)
return 0;
context->zydis = (zydis_t*)calloc(1, sizeof(zydis_t));
context->zydis = (zydis_t*)box_calloc(1, sizeof(zydis_t));
if(!context->zydis)
return 1;
context->zydis->lib = dlopen("libZydis.so", RTLD_LAZY);
@@ -69,7 +69,7 @@ void DeleteX86Trace(box86context_t *context)
return;
if(context->zydis->lib)
dlclose(context->zydis->lib);
free(context->zydis);
box_free(context->zydis);
context->zydis = NULL;
}
@@ -77,7 +77,7 @@ zydis_dec_t* InitX86TraceDecoder(box86context_t *context)
{
if(!context->zydis)
return NULL;
zydis_dec_t *dec = (zydis_dec_t*)calloc(1, sizeof(zydis_dec_t));
zydis_dec_t *dec = (zydis_dec_t*)box_calloc(1, sizeof(zydis_dec_t));
dec->ZydisDecoderDecodeBuffer = context->zydis->ZydisDecoderDecodeBuffer;
dec->ZydisFormatterFormatInstruction = context->zydis->ZydisFormatterFormatInstruction;
context->zydis->ZydisDecoderInit(&dec->decoder, ZYDIS_MACHINE_MODE_LONG_COMPAT_32, ZYDIS_ADDRESS_WIDTH_32);
@@ -87,7 +87,7 @@ zydis_dec_t* InitX86TraceDecoder(box86context_t *context)
}
void DeleteX86TraceDecoder(zydis_dec_t **dec)
{
free(*dec);
box_free(*dec);
*dec = NULL;
}
+5 -5
View File
@@ -13,7 +13,7 @@ void reset_fpu(x86emu_t* emu)
{
memset(emu->x87, 0, sizeof(emu->x87));
memset(emu->fpu_ld, 0, sizeof(emu->fpu_ld));
emu->cw = 0x37F;
emu->cw.x16 = 0x37F;
emu->sw.x16 = 0x0000;
emu->top = 0;
emu->fpu_stack = 0;
@@ -213,7 +213,7 @@ long double LD2localLD(void* ld)
void fpu_loadenv(x86emu_t* emu, char* p, int b16)
{
emu->cw = *(uint16_t*)p;
emu->cw.x16 = *(uint16_t*)p;
p+=(b16)?2:4;
emu->sw.x16 = *(uint16_t*)p;
emu->top = emu->sw.f.F87_TOP;
@@ -231,7 +231,7 @@ void fpu_loadenv(x86emu_t* emu, char* p, int b16)
void fpu_savenv(x86emu_t* emu, char* p, int b16)
{
emu->sw.f.F87_TOP = emu->top&7;
*(uint16_t*)p = emu->cw;
*(uint16_t*)p = emu->cw.x16;
p+=2;
if(!b16) {*(uint16_t*)p = 0; p+=2;}
*(uint16_t*)p = emu->sw.x16;
@@ -274,7 +274,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
emu->sw.f.F87_TOP = top;
p->ControlWord = emu->cw;
p->ControlWord = emu->cw.x16;
p->StatusWord = emu->sw.x16;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
@@ -297,7 +297,7 @@ void fpu_fxsave(x86emu_t* emu, void* ed)
void fpu_fxrstor(x86emu_t* emu, void* ed)
{
xsave_t *p = (xsave_t*)ed;
emu->cw = p->ControlWord;
emu->cw.x16 = p->ControlWord;
emu->sw.x16 = p->StatusWord;
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = p->TagWord;
+1 -1
View File
@@ -124,7 +124,7 @@ static inline void fpu_fcomi(x86emu_t* emu, double b)
static inline double fpu_round(x86emu_t* emu, double d) {
if (!isfinite(d))
return d;
switch(emu->round) {
switch(emu->cw.f.C87_RD) {
case ROUND_Nearest:
return nearbyint(d);
case ROUND_Down:
+23 -24
View File
@@ -27,7 +27,6 @@ typedef struct atfork_fnc_s {
} atfork_fnc_t;
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct mmaplist_s mmaplist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
#endif
@@ -40,10 +39,13 @@ typedef void* (*procaddess_t)(const char* name);
typedef void* (*vkprocaddess_t)(void* instance, const char* name);
#define MAX_SIGNAL 64
#define CYCLE_LOG 16
typedef struct tlsdatasize_s {
int32_t tlssize;
void* tlsdata;
int tlssize;
int n_elfs;
void* data;
void* ptr;
} tlsdatasize_t;
void free_tlsdatasize(void* p);
@@ -85,6 +87,7 @@ typedef struct box86context_s {
char* fullpath;
char* box86path; // path of current box86 executable
char* box64path; // path of box64 executable (beside box86, if it exists)
char* bashpath; // path of x86 bash (defined with BOX86_BASH or by running bash directly)
uint32_t stacksz;
int stackalign;
@@ -98,6 +101,9 @@ typedef struct box86context_s {
uintptr_t ep; // entry point
void* brk; // current brk (should be the end of bss segment of main elf)
int brksz; // current added sz for brk
lib_t *maplib; // lib and symbols handling
lib_t *local_maplib; // libs and symbols openned has local (only collection of libs, no symbols)
dic_t *versym; // dictionnary of versionned symbols
@@ -113,7 +119,8 @@ typedef struct box86context_s {
kh_symbolmap_t *almymap; // link to the mysymbolmap if libOpenAL
kh_symbolmap_t *vkwrappers; // the map of wrapper for VulkanProcs (TODO: check SDL2)
kh_symbolmap_t *vkmymap; // link to the mysymbolmap of libGL
kh_defaultversion_t *defver; // the default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *globaldefver; // the global default version for symbols (the XXX@@vvvv of symbols)
kh_defaultversion_t *weakdefver; // the weak default version for symbols (the XXX@@vvvv of symbols)
vkprocaddess_t vkprocaddress;
pthread_mutex_t mutex_once;
@@ -123,6 +130,7 @@ typedef struct box86context_s {
pthread_mutex_t mutex_lock; // dynarec build will use their own mecanism
#else
pthread_mutex_t mutex_dyndump;
uintptr_t max_db_size; // the biggest (in x86_64 instructions bytes) built dynablock
int trace_dynarec;
#endif
pthread_mutex_t mutex_tls;
@@ -130,31 +138,17 @@ typedef struct box86context_s {
pthread_mutex_t mutex_bridge;
library_t *libclib; // shortcut to libc library (if loaded, so probably yes)
library_t *sdl1lib; // shortcut to SDL1 library (if loaded)
void* sdl1allocrw;
void* sdl1freerw;
library_t *sdl1mixerlib;
library_t *sdl2lib; // shortcut to SDL2 library (if loaded)
void* sdl2allocrw;
void* sdl2freerw;
library_t *sdl2mixerlib;
library_t *x11lib;
library_t *libxcb;
library_t *libxcbxfixes;
library_t *libxcbshape;
library_t *libxcbshm;
library_t *libxcbrandr;
library_t *libxcbimage;
library_t *libxcbkeysyms;
library_t *libxcbxtest;
library_t *zlib;
library_t *vorbisfile;
library_t *vorbis;
library_t *asound;
library_t *pulse;
library_t *d3dadapter9;
linkmap_t *linkmap;
void* sdl1allocrw; // AllocRW/FreeRW functions from SDL1
void* sdl1freerw;
void* sdl2allocrw; // AllocRW/FreeRW functions from SDL2
void* sdl2freerw;
int deferedInit;
elfheader_t **deferedInitList;
int deferedInitSz;
@@ -192,6 +186,11 @@ typedef struct box86context_s {
int no_sigill;
void* stack_clone;
int stack_clone_used;
// rolling logs
char* log_call[CYCLE_LOG];
char* log_ret[CYCLE_LOG];
int current_line;
} box86context_t;
extern box86context_t *my_context; // global context
+18 -6
View File
@@ -18,7 +18,6 @@ void customFree(void* p);
#ifdef DYNAREC
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
// custom protection flag to mark Page that are Write protected for Dynarec purpose
uintptr_t AllocDynarecMap(dynablock_t* db, int size);
void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
@@ -26,16 +25,20 @@ void FreeDynarecMap(dynablock_t* db, uintptr_t addr, uint32_t size);
void addDBFromAddressRange(uintptr_t addr, uintptr_t size);
void cleanDBFromAddressRange(uintptr_t addr, uintptr_t size, int destroy);
dynablocklist_t* getDB(uintptr_t idx);
void addJumpTableIfDefault(void* addr, void* jmp);
dynablock_t* getDB(uintptr_t addr);
int addJumpTableIfDefault(void* addr, void* jmp); // return 1 if write was succesfull
void setJumpTableIfRef(void* addr, void* jmp, void* ref); // return 1 if write was succesfull
void setJumpTableDefault(void* addr);
void setJumpTableDefaultRef(void* addr, void* jmp);
int isJumpTableDefault(void* addr);
uintptr_t getJumpTable();
uintptr_t getJumpTableAddress(uintptr_t addr);
uintptr_t getJumpAddress(uintptr_t addr);
#endif
#define PROT_DYNAREC 0x80
#define PROT_CUSTOM (PROT_DYNAREC)
#define PROT_DYNAREC 0x80
#define PROT_DYNAREC_R 0x40
#define PROT_CUSTOM (PROT_DYNAREC | PROT_DYNAREC_R)
void updateProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
void setProtection(uintptr_t addr, uintptr_t size, uint32_t prot);
@@ -45,7 +48,10 @@ void freeProtection(uintptr_t addr, uintptr_t size);
void loadProtectionFromMap();
#ifdef DYNAREC
void protectDB(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size);
void unprotectDB(uintptr_t addr, uintptr_t size, int mark); // if mark==0, the blocks are not marked as potentially dirty
int IsInHotPage(uintptr_t addr);
int AreaInHotPage(uintptr_t start, uintptr_t end);
void AddHotPage(uintptr_t addr);
#endif
void* find32bitBlock(size_t size);
void* findBlockNearHint(void* hint, size_t size);
@@ -58,4 +64,10 @@ void relockCustommemMutex(int locks);
void init_custommem_helper(box86context_t* ctx);
void fini_custommem_helper(box86context_t* ctx);
#ifdef DYNAREC
// ---- StrongMemoryModel
void addLockAddress(uintptr_t addr); // add an address to the list of "LOCK"able
int isLockAddress(uintptr_t addr); // return 1 is the address is used as a LOCK, 0 else
#endif
#endif //__CUSTOM_MEM__H_
+32 -3
View File
@@ -8,6 +8,8 @@ extern int box86_dump; // dump elf or not
extern int box86_dynarec_log;
extern int box86_dynarec;
extern int box86_pagesize;
extern uintptr_t box86_load_addr;
extern int box86_backtrace;
#ifdef DYNAREC
extern int box86_dynarec_dump;
extern int box86_dynarec_trace;
@@ -16,6 +18,7 @@ extern int box86_dynarec_largest;
extern int box86_dynarec_bigblock;
extern int box86_dynarec_strongmem;
extern int box86_dynarec_x87double;
extern int box86_dynarec_safeflags;
extern uintptr_t box86_nodynarec_start, box86_nodynarec_end;
extern int box86_dynarec_fastnan;
#ifdef ARM
@@ -25,6 +28,7 @@ extern int arm_div;
#endif
#endif
extern int dlsym_error; // log dlsym error
extern int cycle_log; // if using rolling logs
extern int trace_xmm; // include XMM reg in trace?
extern int trace_emm; // include EMM reg in trace?
extern int allow_missing_libs;
@@ -52,11 +56,13 @@ extern int box86_tcmalloc_minimal; // when using tcmalloc_minimal
extern FILE* ftrace;
#define printf_log(L, ...) do {if(L<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define printf_log(L, ...) do {if((L)<=box86_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define printf_dump(L, ...) do {if(box86_dump || (L<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define printf_dump(L, ...) do {if(box86_dump || ((L)<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if(L<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define printf_dlsym(L, ...) do {if(dlsym_error || ((L)<=box86_log)) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define dynarec_log(L, ...) do {if((L)<=box86_dynarec_log) {fprintf(ftrace, __VA_ARGS__); fflush(ftrace);}} while(0)
#define EXPORT __attribute__((visibility("default")))
#ifdef BUILD_DYNAMIC
@@ -65,4 +71,27 @@ extern FILE* ftrace;
#define EXPORTDYN
#endif
void init_malloc_hook();
#ifdef ANDROID
#define box_malloc malloc
#define box_realloc realloc
#define box_calloc calloc
#define box_free free
#define box_memalign memalign
#else
extern size_t(*box_malloc_usable_size)(void*);
extern void* __libc_malloc(size_t);
extern void* __libc_realloc(void*, size_t);
extern void* __libc_calloc(size_t, size_t);
extern void __libc_free(void*);
extern void* __libc_memalign(size_t, size_t);
#define box_malloc __libc_malloc
#define box_realloc __libc_realloc
#define box_calloc __libc_calloc
#define box_free __libc_free
#define box_memalign __libc_memalign
#endif
extern char* box_strdup(const char* s);
extern char* box_realpath(const char* path, char* ret);
#endif //__DEBUG_H_
+3 -13
View File
@@ -3,31 +3,21 @@
typedef struct x86emu_s x86emu_t;
typedef struct dynablock_s dynablock_t;
typedef struct dynablocklist_s dynablocklist_t;
typedef struct kh_dynablocks_s kh_dynablocks_t;
uint32_t X31_hash_code(void* addr, int len);
dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct);
void FreeDynablockList(dynablocklist_t** dynablocks);
void FreeDynablock(dynablock_t* db, int need_lock);
void MarkDynablock(dynablock_t* db);
void FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
void MarkRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
int FreeRangeDynablock(dynablock_t* db, uintptr_t addr, uintptr_t size);
dynablock_t* FindDynablockFromNativeAddress(void* addr); // defined in box86context.h
dynablock_t* FindDynablockDynablocklist(void* addr, kh_dynablocks_t* dynablocks);
uintptr_t StartDynablockList(dynablocklist_t* db);
uintptr_t EndDynablockList(dynablocklist_t* db);
void MarkDirectDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t size);
// Handling of Dynarec block (i.e. an exectable chunk of x86 translated code)
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create, dynablock_t** current); // return NULL if block is not found / cannot be created. Don't create if create==0
dynablock_t* DBGetBlock(x86emu_t* emu, uintptr_t addr, int create); // return NULL if block is not found / cannot be created. Don't create if create==0
dynablock_t* DBAlternateBlock(x86emu_t* emu, uintptr_t addr, uintptr_t filladdr);
// Create and Add an new dynablock in the list, handling direct/map
dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* created);
// for use in signal handler
void cancelFillBlock();
+9 -3
View File
@@ -10,7 +10,7 @@ typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
typedef struct needed_libs_s needed_libs_t;
#ifdef DYNAREC
typedef struct dynablocklist_s dynablocklist_t;
typedef struct dynablock_s dynablock_t;
#endif
elfheader_t* LoadAndCheckElfHeader(FILE* f, const char* name, int exec); // exec : 0 = lib, 1 = exec
@@ -33,9 +33,11 @@ void AddSymbols(lib_t* maplib, kh_mapsymbols_t* mapsymbols, kh_mapsymbols_t* wea
int LoadNeededLibs(elfheader_t* h, lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, box86context_t* box86, x86emu_t* emu);
uintptr_t GetElfInit(elfheader_t* h);
uintptr_t GetElfFini(elfheader_t* h);
void RefreshElfTLS(elfheader_t* h);
void RunElfInit(elfheader_t* h, x86emu_t* emu);
void RunElfFini(elfheader_t* h, x86emu_t* emu);
void RunDeferedElfInit(x86emu_t* emu);
void MarkElfInitDone(elfheader_t* h);
void* GetBaseAddress(elfheader_t* h);
void* GetElfDelta(elfheader_t* h);
uint32_t GetBaseSize(elfheader_t* h);
@@ -47,12 +49,12 @@ uint32_t GetTLSSize(elfheader_t* h);
void* GetTLSPointer(box86context_t* context, elfheader_t* h);
void* GetDTatOffset(box86context_t* context, int index, int offset);
#ifdef DYNAREC
dynablocklist_t* GetDynablocksFromAddress(box86context_t* context, uintptr_t addr);
dynablocklist_t* GetDynablocksFromElf(elfheader_t* h);
dynablock_t* GetDynablocksFromAddress(box86context_t *context, uintptr_t addr);
#endif
void ResetSpecialCaseMainElf(elfheader_t* h);
void CreateMemorymapFile(box86context_t* context, int fd);
void* GetDynamicSection(elfheader_t* h);
void* ElfGetBrk(elfheader_t* h);
int ElfCheckIfUseTCMallocMinimal(elfheader_t* h); // return 1 if tcmalloc is used
@@ -61,6 +63,10 @@ const char* GetParentSymbolVersion(elfheader_t* h, int index);
const char* VersionnedName(const char* name, int ver, const char* vername);
int SameVersionnedSymbol(const char* name1, int ver1, const char* vername1, const char* name2, int ver2, const char* vername2);
kh_mapsymbols_t* GetMapSymbols(elfheader_t* h);
kh_mapsymbols_t* GetWeakSymbols(elfheader_t* h);
kh_mapsymbols_t* GetLocalSymbols(elfheader_t* h);
void* GetNativeSymbolUnversionned(void* lib, const char* name);
void AddMainElfToLinkmap(elfheader_t* lib);
+4
View File
@@ -16,6 +16,10 @@ char* ResolveFile(const char* filename, path_collection_t* paths);
// 1: if file is an x86 elf, 0: if not (or not found)
int FileIsX86ELF(const char* filename);
int FileIsX64ELF(const char* filename);
int FileIsShell(const char* filename);
// return temp folder (will return /tmp if nothing is correct)
const char* GetTmpDir();
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
void sanitize_mojosetup_gtk_background();
+195 -87
View File
@@ -25,6 +25,21 @@ typedef struct my_GObjectClass_s
void* pdummy[6];
} my_GObjectClass_t;
typedef struct my_GInitiallyUnownedClass_s
{
int g_type_class;
void* construct_properties;
void* (*constructor) (int type, uint32_t n_construct_properties, void* construct_properties);
void (*set_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*get_property) (void* object, uint32_t property_id, void* value, void* pspec);
void (*dispose) (void* object);
void (*finalize) (void* object);
void (*dispatch_properties_changed) (void* object, uint32_t n_pspecs, void* pspecs);
void (*notify) (void* object, void* pspec);
void (*constructed) (void* object);
uint32_t flags;
void* pdummy[6];
} my_GInitiallyUnownedClass_t;
typedef struct my_GtkObjectClass_s
{
@@ -34,7 +49,7 @@ typedef struct my_GtkObjectClass_s
void (*destroy) (void* object);
} my_GtkObjectClass_t;
typedef struct my_GtkWidgetClass_s
typedef struct my_GtkWidget2Class_s
{
my_GtkObjectClass_t parent_class;
uint32_t activate_signal;
@@ -108,11 +123,102 @@ typedef struct my_GtkWidgetClass_s
void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void);
} my_GtkWidgetClass_t;
} my_GtkWidget2Class_t;
typedef struct my_GtkContainerClass_s
typedef struct my_GtkWidget3Class_s
{
my_GtkWidgetClass_t parent_class;
my_GInitiallyUnownedClass_t parent_class;
uint32_t activate_signal;
void (*dispatch_child_properties_changed) (void* widget, uint32_t n_pspecs, void* pspecs);
void (* destroy) (void* widget);
void (* show) (void* widget);
void (* show_all) (void* widget);
void (* hide) (void* widget);
void (* map) (void* widget);
void (* unmap) (void* widget);
void (* realize) (void* widget);
void (* unrealize) (void* widget);
void (* size_allocate) (void* widget, void* allocation);
void (* state_changed) (void* widget, int previous_state);
void (* state_flags_changed) (void* widget, int previous_state_flags);
void (* parent_set) (void* widget, void* previous_parent);
void (* hierarchy_changed) (void* widget, void* previous_toplevel);
void (* style_set) (void* widget, void* previous_style);
void (* direction_changed) (void* widget, int previous_direction);
void (* grab_notify) (void* widget, int was_grabbed);
void (* child_notify) (void* widget, void* child_property);
int (* draw) (void* widget, void* cr);
int (* get_request_mode) (void* widget);
void (* get_preferred_height) (void* widget, void* minimum_height, void* natural_height);
void (* get_preferred_width_for_height) (void* widget, int height, void* minimum_width, void* natural_width);
void (* get_preferred_width) (void* widget, void* minimum_width, void* natural_width);
void (* get_preferred_height_for_width) (void* widget, int width, void* minimum_height, void* natural_height);
int (* mnemonic_activate) (void* widget, int group_cycling);
void (* grab_focus) (void* widget);
int (* focus) (void* widget, int direction);
void (* move_focus) (void* widget, int direction);
int (* keynav_failed) (void* widget, int direction);
int (* event) (void* widget, void* event);
int (* button_press_event) (void* widget, void* event);
int (* button_release_event) (void* widget, void* event);
int (* scroll_event) (void* widget, void* event);
int (* motion_notify_event) (void* widget, void* event);
int (* delete_event) (void* widget, void* event);
int (* destroy_event) (void* widget, void* event);
int (* key_press_event) (void* widget, void* event);
int (* key_release_event) (void* widget, void* event);
int (* enter_notify_event) (void* widget, void* event);
int (* leave_notify_event) (void* widget, void* event);
int (* configure_event) (void* widget, void* event);
int (* focus_in_event) (void* widget, void* event);
int (* focus_out_event) (void* widget, void* event);
int (* map_event) (void* widget, void* event);
int (* unmap_event) (void* widget, void* event);
int (* property_notify_event) (void* widget, void* event);
int (* selection_clear_event) (void* widget, void* event);
int (* selection_request_event) (void* widget, void* event);
int (* selection_notify_event) (void* widget, void* event);
int (* proximity_in_event) (void* widget, void* event);
int (* proximity_out_event) (void* widget, void* event);
int (* visibility_notify_event) (void* widget, void* event);
int (* window_state_event) (void* widget, void* event);
int (* damage_event) (void* widget, void* event);
int (* grab_broken_event) (void* widget, void* event);
void (* selection_get) (void* widget, void* selection_data, uint32_t info, uint32_t time_);
void (* selection_received) (void* widget, void* selection_data, uint32_t time_);
void (* drag_begin) (void* widget, void* context);
void (* drag_end) (void* widget, void* context);
void (* drag_data_get) (void* widget, void* context, void* selection_data, uint32_t info, uint32_t time_);
void (* drag_data_delete) (void* widget, void* context);
void (* drag_leave) (void* widget, void* context, uint32_t time_);
int (* drag_motion) (void* widget, void* context, int x, int y, uint32_t time_);
int (* drag_drop) (void* widget, void* context, int x, int y, uint32_t time_);
void (* drag_data_received) (void* widget, void* context, int x, int y, void* selection_data, uint32_t info, uint32_t time_);
int (* drag_failed) (void* widget, void* context, int result);
int (* popup_menu) (void* widget);
int (* show_help) (void* widget, int help_type);
void* (* get_accessible) (void *widget);
void (* screen_changed) (void* widget, void* previous_screen);
int (* can_activate_accel) (void* widget, uint32_t signal_id);
void (* composited_changed) (void* widget);
int (* query_tooltip) (void* widget, int x, int y, int keyboard_tooltip, void* tooltip);
void (* compute_expand) (void* widget, void*hexpand_p, void* vexpand_p);
void (* adjust_size_request) (void* widget, int orientation, void* minimum_size, void* natural_size);
void (* adjust_size_allocation) (void*widget, int orientation, void* minimum_size, void* natural_size, void* allocated_pos, void* allocated_size);
void (* style_updated) (void* widget);
int (* touch_event) (void* widget, void* event);
void (* get_preferred_height_and_baseline_for_width) (void* widget, int width, void* minimum_height, void* natural_height, void* minimum_baseline, void* natural_baseline);
void (* adjust_baseline_request) (void* widget, void* minimum_baseline, void* natural_baseline);
void (* adjust_baseline_allocation) (void* widget, void* baseline);
void (*queue_draw_region) (void* widget, void* region);
void* priv;
void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void);
} my_GtkWidget3Class_t;
typedef struct my_GtkContainer2Class_s
{
my_GtkWidget2Class_t parent_class;
void (*add) (void* container, void* widget);
void (*remove) (void* container, void* widget);
void (*check_resize) (void* container);
@@ -126,7 +232,7 @@ typedef struct my_GtkContainerClass_s
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkContainerClass_t;
} my_GtkContainer2Class_t;
typedef struct my_GtkActionClass_s
{
@@ -144,14 +250,14 @@ typedef struct my_GtkActionClass_s
void (*_gtk_reserved4) (void);
} my_GtkActionClass_t;
typedef struct my_GtkMiscClass_s
typedef struct my_GtkMisc2Class_s
{
my_GtkWidgetClass_t parent_class;
} my_GtkMiscClass_t;
my_GtkWidget2Class_t parent_class;
} my_GtkMisc2Class_t;
typedef struct my_GtkLabelClass_s
typedef struct my_GtkLabel2Class_s
{
my_GtkMiscClass_t parent_class;
my_GtkMisc2Class_t parent_class;
void (* move_cursor) (void* label, int step, int count, int extend_selection);
void (* copy_clipboard) (void* label);
void (* populate_popup) (void* label, void* menu);
@@ -159,11 +265,11 @@ typedef struct my_GtkLabelClass_s
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkLabelClass_t;
} my_GtkLabel2Class_t;
typedef struct my_GtkTreeViewClass_s
typedef struct my_GtkTreeView2Class_s
{
my_GtkContainerClass_t parent_class;
my_GtkContainer2Class_t parent_class;
void (* set_scroll_adjustments) (void* tree_view, void* hadjustment, void* vadjustment);
void (* row_activated) (void* tree_view, void* path, void* column);
int (* test_expand_row) (void* tree_view, void* iter, void* path);
@@ -185,19 +291,19 @@ typedef struct my_GtkTreeViewClass_s
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkTreeViewClass_t;
} my_GtkTreeView2Class_t;
typedef struct my_GtkBinClass_s
typedef struct my_GtkBin2Class_s
{
my_GtkContainerClass_t parent_class;
my_GtkContainer2Class_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkBinClass_t;
} my_GtkBin2Class_t;
typedef struct my_GtkWindowClass_s {
my_GtkBinClass_t parent_class;
typedef struct my_GtkWindow2Class_s {
my_GtkBin2Class_t parent_class;
void (* set_focus) (void* window, void* focus);
int (* frame_event) (void* window, void* event);
void (* activate_focus) (void* window);
@@ -208,10 +314,10 @@ typedef struct my_GtkWindowClass_s {
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkWindowClass_t;
} my_GtkWindow2Class_t;
typedef struct my_GtkButtonClass_s {
my_GtkBinClass_t parent_class;
typedef struct my_GtkButton2Class_s {
my_GtkBin2Class_t parent_class;
void (* pressed) (void *button);
void (* released) (void *button);
void (* clicked) (void *button);
@@ -222,37 +328,37 @@ typedef struct my_GtkButtonClass_s {
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkButtonClass_t;
} my_GtkButton2Class_t;
typedef struct my_GtkToggleButtonClass_s {
my_GtkButtonClass_t parent_class;
typedef struct my_GtkToggleButton2Class_s {
my_GtkButton2Class_t parent_class;
void (* toggled) (void* toggle_button);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkToggleButtonClass_t;
} my_GtkToggleButton2Class_t;
typedef struct my_GtkCheckButtonClass_s {
my_GtkToggleButtonClass_t parent_class;
typedef struct my_GtkCheckButton2Class_s {
my_GtkToggleButton2Class_t parent_class;
void (* draw_indicator) (void* check_button, void* area);
void (*_gtk_reserved0) (void);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkCheckButtonClass_t;
} my_GtkCheckButton2Class_t;
typedef struct my_GtkComboBoxClass_s {
my_GtkBinClass_t parent_class;
typedef struct my_GtkComboBox2Class_s {
my_GtkBin2Class_t parent_class;
void (* changed) (void* combo_box);
void*(* get_active_text)(void* combo_box);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkComboBoxClass_t;
} my_GtkComboBox2Class_t;
typedef struct my_GtkEntryClass_s {
my_GtkWidgetClass_t parent_class;
typedef struct my_GtkEntry2Class_s {
my_GtkWidget2Class_t parent_class;
void (* populate_popup) (void* entry, void* menu);
void (* activate) (void* entry);
void (* move_cursor) (void* entry, int step, int count, int extend_selection);
@@ -266,10 +372,10 @@ typedef struct my_GtkEntryClass_s {
void (* get_text_area_size) (void* entry, void* x, void* y, void* width, void* height);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkEntryClass_t;
} my_GtkEntry2Class_t;
typedef struct my_GtkSpinButtonClass_s {
my_GtkEntryClass_t parent_class;
typedef struct my_GtkSpinButton2Class_s {
my_GtkEntry2Class_t parent_class;
int (*input) (void* spin_button, void* new_value);
int (*output) (void* spin_button);
void (*value_changed) (void* spin_button);
@@ -278,10 +384,10 @@ typedef struct my_GtkSpinButtonClass_s {
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
} my_GtkSpinButtonClass_t;
} my_GtkSpinButton2Class_t;
typedef struct my_GtkProgressClass_s {
my_GtkWidgetClass_t parent_class;
typedef struct my_GtkProgress2Class_s {
my_GtkWidget2Class_t parent_class;
void (* paint) (void* progress);
void (* update) (void* progress);
void (* act_mode_enter) (void* progress);
@@ -289,23 +395,23 @@ typedef struct my_GtkProgressClass_s {
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkProgressClass_t;
} my_GtkProgress2Class_t;
typedef struct my_GtkProgressBarClass_s {
my_GtkProgressClass_t parent_class;
typedef struct my_GtkProgressBar2Class_s {
my_GtkProgress2Class_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkProgressBarClass_t;
} my_GtkProgressBar2Class_t;
typedef struct my_GtkFrameClass_s {
my_GtkBinClass_t parent_class;
typedef struct my_GtkFrame2Class_s {
my_GtkBin2Class_t parent_class;
void (*compute_child_allocation) (void* frame, void* allocation);
} my_GtkFrameClass_t;
} my_GtkFrame2Class_t;
typedef struct my_GtkMenuShellClass_s {
my_GtkContainerClass_t parent_class;
typedef struct my_GtkMenuShell2Class_s {
my_GtkContainer2Class_t parent_class;
void (*deactivate) (void* menu_shell);
void (*selection_done) (void* menu_shell);
void (*move_current) (void* menu_shell, int direction);
@@ -317,31 +423,31 @@ typedef struct my_GtkMenuShellClass_s {
int (*move_selected) (void* menu_shell, int distance);
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
} my_GtkMenuShellClass_t;
} my_GtkMenuShell2Class_t;
typedef struct my_GtkMenuBarClass_s {
my_GtkMenuShellClass_t parent_class;
typedef struct my_GtkMenuBar2Class_s {
my_GtkMenuShell2Class_t parent_class;
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
} my_GtkMenuBarClass_t;
} my_GtkMenuBar2Class_t;
typedef struct my_MetaFramesClass_s
typedef struct my_MetaFrames2Class_s
{
my_GtkWindowClass_t parent_class;
my_GtkWindow2Class_t parent_class;
} my_MetaFramesClass_t;
} my_MetaFrames2Class_t;
typedef struct my_GtkTableClass_s
typedef struct my_GtkTable2Class_s
{
my_GtkContainerClass_t parent_class;
} my_GtkTableClass_t;
my_GtkContainer2Class_t parent_class;
} my_GtkTable2Class_t;
typedef struct my_GtkFixedClass_s
typedef struct my_GtkFixed2Class_s
{
my_GtkContainerClass_t parent_class;
} my_GtkFixedClass_t;
my_GtkContainer2Class_t parent_class;
} my_GtkFixed2Class_t;
typedef struct my_GDBusObjectManagerClientClass_s
{
@@ -406,31 +512,33 @@ my_GtkTypeInfo_t* findFreeGtkTypeInfo(my_GtkTypeInfo_t* fcts, int parent);
void InitGTKClass(bridge_t *bridge);
void FiniGTKClass();
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget) \
GTKCLASS(GtkContainer) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel) \
GTKCLASS(GtkMisc) \
GTKCLASS(GtkTreeView) \
GTKCLASS(GtkBin) \
GTKCLASS(GtkWindow) \
GTKCLASS(GtkTable) \
GTKCLASS(GtkFixed) \
GTKCLASS(GtkButton) \
GTKCLASS(GtkComboBox) \
GTKCLASS(GtkToggleButton)\
GTKCLASS(GtkCheckButton)\
GTKCLASS(GtkEntry) \
GTKCLASS(GtkSpinButton) \
GTKCLASS(GtkProgress) \
GTKCLASS(GtkProgressBar)\
GTKCLASS(GtkFrame) \
GTKCLASS(GtkMenuShell) \
GTKCLASS(GtkMenuBar) \
GTKCLASS(MetaFrames) \
#define GTKCLASSES() \
GTKCLASS(GObject) \
GTKCLASS(GInitiallyUnowned) \
GTKCLASS(GtkObject) \
GTKCLASS(GtkWidget2) \
GTKCLASS(GtkWidget3) \
GTKCLASS(GtkContainer2) \
GTKCLASS(GtkAction) \
GTKCLASS(GtkLabel2) \
GTKCLASS(GtkMisc2) \
GTKCLASS(GtkTreeView2) \
GTKCLASS(GtkBin2) \
GTKCLASS(GtkWindow2) \
GTKCLASS(GtkTable2) \
GTKCLASS(GtkFixed2) \
GTKCLASS(GtkButton2) \
GTKCLASS(GtkComboBox2) \
GTKCLASS(GtkToggleButton2) \
GTKCLASS(GtkCheckButton2) \
GTKCLASS(GtkEntry2) \
GTKCLASS(GtkSpinButton2) \
GTKCLASS(GtkProgress2) \
GTKCLASS(GtkProgressBar2) \
GTKCLASS(GtkFrame2) \
GTKCLASS(GtkMenuShell2) \
GTKCLASS(GtkMenuBar2) \
GTKCLASS(MetaFrames2) \
GTKCLASS(GDBusObjectManagerClient) \
#define GTKCLASS(A) void Set##A##ID(int id);
-3
View File
@@ -21,9 +21,6 @@ dlprivate_t *NewDLPrivate();
void FreeDLPrivate(dlprivate_t **lib);
box86context_t* GetLibrarianContext(lib_t* maplib);
kh_mapsymbols_t* GetMapSymbol(lib_t* maplib);
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib);
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib);
kh_mapsymbols_t* GetGlobalData(lib_t* maplib);
int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, int local, int bindnow, const char** paths, int npath, box86context_t* box86, x86emu_t* emu); // 0=success, 1=error
library_t* GetLibMapLib(lib_t* maplib, const char* name);
+11 -5
View File
@@ -9,6 +9,11 @@ typedef struct kh_symbolmap_s kh_symbolmap_t;
typedef struct box86context_s box86context_t;
typedef struct x86emu_s x86emu_t;
typedef struct needed_libs_s needed_libs_t;
typedef struct elfheader_s elfheader_t;
#define LIB_WRAPPED 0
#define LIB_EMULATED 1
#define LIB_UNNKNOW -1
library_t *NewLibrary(const char* path, box86context_t* box86);
int AddSymbolsLibrary(lib_t* maplib, library_t* lib, x86emu_t* emu);
@@ -19,9 +24,9 @@ void Free1Library(library_t **lib, x86emu_t* emu);
char* GetNameLib(library_t *lib);
int IsSameLib(library_t* lib, const char* path); // check if lib is same (path -> name)
int GetLibSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
int GetLibNoWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername, int local);
int GetLibGlobalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int *weak, int version, const char* vername, int local);
int GetLibWeakSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int* weak, int version, const char* vername, int local);
int GetLibLocalSymbolStartEnd(library_t* lib, const char* name, uintptr_t* start, uintptr_t* end, int* weak, int version, const char* vername, int local);
void fillGLProcWrapper(box86context_t* context);
void freeGLProcWrapper(box86context_t* context);
void fillALProcWrapper(box86context_t* context);
@@ -31,7 +36,8 @@ int GetNeededLibN(library_t* lib);
library_t* GetNeededLib(library_t* lib, int idx);
lib_t* GetMaplib(library_t* lib);
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. native)
void* GetHandle(library_t* lib); // NULL if not native
int GetElfIndex(library_t* lib); // -1 if no elf (i.e. wrapped)
elfheader_t* GetElf(library_t* lib); // NULL if no elf (i.e. wrapped)
void* GetHandle(library_t* lib); // NULL if not wrapped
#endif //__LIBRARY_H_
+17
View File
@@ -196,6 +196,23 @@ typedef union {
uint16_t x16;
} x87flags_t;
typedef union {
struct __attribute__ ((__packed__)) {
unsigned int C87_IM:1; // interupt masks
unsigned int C87_DM:1;
unsigned int C87_ZM:1;
unsigned int C87_OM:1;
unsigned int C87_UM:1;
unsigned int C87_PM:1;
unsigned int C87_R1:2; // reserved
unsigned int C87_PC:2; // precision control (24bits, reserved, 53bits, 64bits)
unsigned int C87_RD:2; // Rounds
unsigned int C87_IC:1;
unsigned int C87_R2:3; // reserved
} f;
uint16_t x16;
} x87control_t;
typedef union {
uint64_t q;
int64_t sq;
+3 -3
View File
@@ -14,10 +14,10 @@ void FreeMapSymbols(kh_mapsymbols_t** map);
// replace if already there
void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local);
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver);
// don't add if already there
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local);
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername);
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver);
const char* GetSymbolName(kh_mapsymbols_t* mapsymbols, void* p, uintptr_t* offs, uint32_t* sz, const char** vername);
// default version handling
+5 -4
View File
@@ -7,15 +7,16 @@ typedef struct box86context_s box86context_t;
typedef int (*wrappedlib_init_t)(library_t * lib, box86context_t* box86); // 0 = success
typedef void (*wrappedlib_fini_t)(library_t * lib);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int version, const char* vername, int local);
typedef int (*wrappedlib_get_t)(library_t* lib, const char* name, uintptr_t *offs, uint32_t *sz, int* weak, int version, const char* vername, int local);
void setNeededLibs(library_t* lib, int n, ...);
#define SETALT(A) lib->w.altmy = box_strdup(#A)
#define SETALTPREFIX(A) lib->w.altprefix = box_strdup(A)
typedef struct wrappedlib_s {
const char* name;
wrappedlib_init_t init;
wrappedlib_fini_t fini;
wrappedlib_get_t get;
wrappedlib_get_t getnoweak;
wrappedlib_get_t getlocal;
} wrappedlib_t;
#endif //__WRAPPEDLIBS_H__
+2 -2
View File
@@ -20,7 +20,7 @@ void FreeDictionnary(dic_t **d)
return;
kh_dic_t* dic = (kh_dic_t*)*d;
const char* k;
kh_foreach_key(dic, k, free((void*)k));
kh_foreach_key(dic, k, box_free((void*)k));
kh_destroy(dic, dic);
*d = NULL;
}
@@ -31,7 +31,7 @@ const char* AddDictionnary(dic_t* d, const char* s)
khint_t k = kh_get(dic, dic, s);
if(k!=kh_end(dic))
return kh_key(dic, k);
char* n = strdup(s);
char* n = box_strdup(s);
int ret;
k = kh_put(dic, dic, n, &ret);
return n;
+113 -102
View File
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "debug.h"
#include "librarian.h"
@@ -19,17 +20,12 @@ KHASH_MAP_IMPL_INT(mapoffsets, cstr_t);
lib_t *NewLibrarian(box86context_t* context, int ownlibs)
{
lib_t *maplib = (lib_t*)calloc(1, sizeof(lib_t));
lib_t *maplib = (lib_t*)box_calloc(1, sizeof(lib_t));
maplib->mapsymbols = NewMapSymbols();
maplib->weaksymbols = NewMapSymbols();
maplib->localsymbols = NewMapSymbols();
maplib->mapoffsets = kh_init(mapoffsets);
maplib->globaldata = NewMapSymbols();
maplib->bridge = NewBridge();
maplib->context = context;
maplib->ownlibs = ownlibs;
return maplib;
@@ -78,7 +74,7 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
if((*maplib)->ownlibs && (*maplib)->libsz) {
printf_log(LOG_DEBUG, "Closing %d libs from maplib %p\n", (*maplib)->libsz, *maplib);
char *freed = (char*)calloc((*maplib)->libsz, sizeof(char));
char *freed = (char*)box_calloc((*maplib)->libsz, sizeof(char));
if (!freed) {
printf_log(LOG_INFO, "Failed to malloc freed table, using old algorithm (a crash is likely)\n");
for (int i=(*maplib)->libsz-1; i>=0; --i)
@@ -92,15 +88,12 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
}
memset((*maplib)->libraries, 0, (*maplib)->libsz*sizeof(library_t*)); // NULL = 0 anyway
(*maplib)->libsz = 0;
free(freed);
box_free(freed);
}
}
free((*maplib)->libraries);
box_free((*maplib)->libraries);
(*maplib)->libraries = NULL;
FreeMapSymbols(&(*maplib)->mapsymbols);
FreeMapSymbols(&(*maplib)->weaksymbols);
FreeMapSymbols(&(*maplib)->localsymbols);
if((*maplib)->mapoffsets) {
kh_destroy(mapoffsets, (*maplib)->mapoffsets);
}
@@ -110,29 +103,14 @@ void FreeLibrarian(lib_t **maplib, x86emu_t *emu)
if((*maplib)->bridge)
FreeBridge(&(*maplib)->bridge);
free(*maplib);
box_free(*maplib);
*maplib = NULL;
}
box86context_t* GetLibrarianContext(lib_t* maplib)
{
return maplib->context;
}
kh_mapsymbols_t* GetMapSymbol(lib_t* maplib)
{
return maplib->mapsymbols;
}
kh_mapsymbols_t* GetWeakSymbol(lib_t* maplib)
{
return maplib->weaksymbols;
}
kh_mapsymbols_t* GetLocalSymbol(lib_t* maplib)
{
return maplib->localsymbols;
return my_context;
}
kh_mapsymbols_t* GetGlobalData(lib_t* maplib)
@@ -167,7 +145,7 @@ void MapLibAddLib(lib_t* maplib, library_t* lib)
return;
if (maplib->libsz == maplib->libcap) {
maplib->libcap += 8;
maplib->libraries = (library_t**)realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
maplib->libraries = (library_t**)box_realloc(maplib->libraries, maplib->libcap*sizeof(library_t*));
}
maplib->libraries[maplib->libsz] = lib;
++maplib->libsz;
@@ -299,7 +277,7 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
return 1;
}
if (lib->type == 1) {
if (lib->type == LIB_EMULATED) {
// Need to add library to the linkmap (put here so the link is ordered)
linkmap_t *lm = addLinkMapLib(lib);
if(!lm) {
@@ -307,9 +285,9 @@ int AddNeededLib_add(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib
printf_log(LOG_DEBUG, "Failure to add lib linkmap\n");
return 1;
}
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->priv.n.elf_index]);
lm->l_addr = (Elf32_Addr)GetElfDelta(my_context->elfs[lib->e.elf_index]);
lm->l_name = lib->name;
lm->l_ld = GetDynamicSection(my_context->elfs[lib->priv.n.elf_index]);
lm->l_ld = GetDynamicSection(my_context->elfs[lib->e.elf_index]);
}
return 0;
}
@@ -357,14 +335,13 @@ int AddNeededLib(lib_t* maplib, needed_libs_t* neededlibs, library_t* deplib, in
{
box86_mapclean = 0;
if(!neededlibs) {
neededlibs = alloca(sizeof(needed_libs_t));
memset(neededlibs, 0, sizeof(needed_libs_t));
neededlibs = box_calloc(1, sizeof(needed_libs_t));
}
int idx = neededlibs->size;
// Add libs and symbol
for(int i=0; i<npath; ++i) {
if(AddNeededLib_add(maplib, neededlibs, deplib, local, paths[i], box86, emu)) {
printf_log(LOG_INFO, "Error loading needed lib %s\n", paths[i]);
printf_log(strchr(paths[i],'/')?LOG_DEBUG:LOG_INFO, "Error loading needed lib %s\n", paths[i]);
return 1;
}
}
@@ -403,79 +380,100 @@ uintptr_t FindGlobalSymbol(lib_t *maplib, const char* name, int version, const c
static int isLocal(elfheader_t* self, library_t* l)
{
if(GetElfIndex(l)==-1)
return 1;
if(my_context->elfs[GetElfIndex(l)]==self)
if(GetElf(l)==self)
return 1;
return 0;
}
int GetNoSelfSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
//excude self if defined
if(maplib->context->elfs[0]!=self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 0))
if(*start)
return 1;
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 0))
if(*start)
return 1;
assert(self); // need self for this one
//search for the self, to start "next"
int go = -1;
int weak = 0;
for(int i=0; i<maplib->libsz && (go==-1); ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (GetElf(maplib->libraries[i])==self))
go = i+1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 0))
if(go<0)
go = 0; // not found...
for(int i=go; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 0))
if(*start)
return 1;
}
for(int i=go; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 0);
// loop done, weak symbol found
if(weak && *start)
return 1;
// if self defined, give it another chance with self...
if(self) {
if(maplib->context->elfs[0]==self) {
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
if(my_context->elfs[0]!=self) {
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start)
return 1;
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, 1))
defver = GetDefaultVersion(my_context->weakdefver, name);
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start)
return 1;
weak = 1;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self))
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 1))
if(*start)
return 1;
}
for(int i=0; i<go; ++i) {
if(GetElfIndex(maplib->libraries[i])==-1 || (my_context->elfs[GetElfIndex(maplib->libraries[i])]!=self))
GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 1);
}
if(weak && *start)
return 1;
}
// nope, not found
return 0;
}
static int GetGlobalSymbolStartEnd_internal(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t* self, int version, const char* vername)
{
int weak = 0;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
// search non-weak symbol, from older to newer (first GLOBAL object wins)
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
if(*start)
return 1;
// TODO: create a temporary map to search lib only 1 time, and in order of needed...
// search in needed libs from neededlibs first, in order
for(int i=0; i<my_context->neededlibs.size; ++i)
if(GetLibNoWeakSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
if(GetLibGlobalSymbolStartEnd(my_context->neededlibs.libs[i], name, start, end, &weak, version, vername, isLocal(self, my_context->neededlibs.libs[i])))
if(*start)
return 1;
// search in global symbols
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i])))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
return 1;
}
if(GetSymbolStartEnd(maplib->weaksymbols, name, start, end, version, vername, (maplib->context->elfs[0]==self || !self)?1:0))
// check with default version...
defver = GetDefaultVersion(my_context->weakdefver, name);
int ok = 0;
// GetSymbolStartEnd should not change start/end if symbol is not found
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, start, end, version, vername, (my_context->elfs[0]==self || !self)?1:0, defver))
if(*start)
return 1;
ok = 1;
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, isLocal(self, maplib->libraries[i]))) // only weak symbol haven't been found yet
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, isLocal(self, maplib->libraries[i])))
if(*start)
return 1;
ok = 1;
}
// nope, not found
return 0;
return (ok && *start)?1:0;
}
void** my_GetGTKDisplay();
void** my_GetGthreadsGotInitialized();
@@ -484,14 +482,14 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
if(GetGlobalSymbolStartEnd_internal(maplib, name, start, end, self, version, vername)) {
if(start && end && *end==*start) { // object is of 0 sized, try to see an "_END" object of null size
uintptr_t start2, end2;
char* buff = (char*)malloc(strlen(name) + strlen("_END") + 1);
char* buff = (char*)box_malloc(strlen(name) + strlen("_END") + 1);
strcpy(buff, name);
strcat(buff, "_END");
if(GetGlobalSymbolStartEnd_internal(maplib, buff, &start2, &end2, self, version, vername)) {
if(end2>*end && start2==end2)
*end = end2;
}
free(buff);
box_free(buff);
}
return 1;
}
@@ -508,10 +506,6 @@ int GetGlobalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, u
printf_log(LOG_INFO, "Using global g_threads_got_initialized for gthread2 (%p:%p)\n", start, *(void**)start);
return 1;
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
// not found...
return 0;
}
@@ -520,41 +514,60 @@ elfheader_t* GetGlobalSymbolElf(lib_t *maplib, const char* name, int version, co
{
uintptr_t start = 0;
uintptr_t end = 0;
if(GetSymbolStartEnd(maplib->mapsymbols, name, &start, &end, version, vername, 1))
return maplib->context->elfs[0];
if(GetSymbolStartEnd(maplib->weaksymbols, name, &start, &end, version, vername, 1))
return maplib->context->elfs[0];
int weak = 0;
elfheader_t* ret = NULL;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
return my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1)) {
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, &weak, version, vername, 1)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
return maplib->context->elfs[idx];
if(weak)
ret = my_context->elfs[idx];
else
return my_context->elfs[idx];
}
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalSymbolElf(maplib, name, 2, defver);
// nope, not found
return NULL;
defver = GetDefaultVersion(my_context->weakdefver, name);
if(GetSymbolStartEnd(GetWeakSymbols(my_context->elfs[0]), name, &start, &end, version, vername, 1, defver))
ret = my_context->elfs[0];
for(int i=0; i<maplib->libsz; ++i) {
if(GetLibWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, &weak, version, vername, 1)) {
int idx = GetElfIndex(maplib->libraries[i]);
if(idx==-1) {
printf_log(LOG_NONE, "Warning, getting Elf info for a native symbol \"%s\" from lib \"%s\"\n", name, GetNameLib(maplib->libraries[i]));
return NULL;
}
if(weak)
ret = my_context->elfs[idx];
else
return my_context->elfs[idx];
}
}
// return what has been found (maybe nothing)
return ret;
}
int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, int version, const char* vername)
{
if(GetSymbolStartEnd(maplib->mapsymbols, name, start, end, version, vername, 1))
int weak = 0;
// check with default version...
const char* defver = GetDefaultVersion(my_context->globaldefver, name);
if(GetSymbolStartEnd(GetMapSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, defver))
if(*start || *end)
return 1;
for(int i=0; i<maplib->libsz; ++i)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 1))
if(*start || *end)
return 1;
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetGlobalNoWeakSymbolStartEnd(maplib, name, start, end, 2, defver);
// nope, not found
return 0;
}
@@ -562,15 +575,13 @@ int GetGlobalNoWeakSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* st
int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, const char* vername)
{
uintptr_t start, end;
int weak;
// check with default version...
for(int i=0; i<maplib->libsz; ++i)
if(GetElfIndex(maplib->libraries[i])==-1)
if(GetLibNoWeakSymbolStartEnd(maplib->libraries[i], name, &start, &end, version, vername, 1))
if(GetLibGlobalSymbolStartEnd(maplib->libraries[i], name, &start, &end, &weak, version, vername, 1))
if(start || end)
return 1;
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return IsGlobalNoWeakSymbolInNative(maplib, name, 2, defver);
// nope, not found
return 0;
@@ -578,26 +589,26 @@ int IsGlobalNoWeakSymbolInNative(lib_t *maplib, const char* name, int version, c
int GetLocalSymbolStartEnd(lib_t *maplib, const char* name, uintptr_t* start, uintptr_t* end, elfheader_t *self, int version, const char* vername)
{
if(maplib->context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(maplib->localsymbols, name, start, end, version, vername, 1))
// check with default version...
int weak;
if(my_context->elfs[0]==self || !self) {
if(GetSymbolStartEnd(GetLocalSymbols(my_context->elfs[0]), name, start, end, version, vername, 1, NULL))
if(*start || *end)
return 1;
if(self)
return 0;
}
for(int i=0; i<maplib->libsz; ++i) {
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || maplib->context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, version, vername, 1))
if(GetElfIndex(maplib->libraries[i])!=-1 && (!self || my_context->elfs[GetElfIndex(maplib->libraries[i])]==self)) {
if(GetLibLocalSymbolStartEnd(maplib->libraries[i], name, start, end, &weak, version, vername, 1))
if(*start)
return 1;
if(self)
return 0;
}
}
// check with default version...
const char* defver;
if(version==0 && (defver=GetDefaultVersion(my_context->defver, name)))
return GetLocalSymbolStartEnd(maplib, name, start, end, self, 2, defver);
return 0;
}
-3
View File
@@ -13,9 +13,6 @@ typedef char* cstr_t;
KHASH_MAP_DECLARE_INT(mapoffsets, cstr_t);
typedef struct lib_s {
khash_t(mapsymbols) *mapsymbols;
khash_t(mapsymbols) *weaksymbols;
khash_t(mapsymbols) *localsymbols;
khash_t(mapoffsets) *mapoffsets;
khash_t(mapsymbols) *globaldata;
library_t **libraries;
+360 -277
View File
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
#ifndef __LIBRARY_INNER_H__
#define __LIBRARY_INNER_H__
void WrappedLib_CommonInit(library_t* lib);
void WrappedLib_FinishFini(library_t* lib);
#endif
+30 -31
View File
@@ -8,10 +8,11 @@
#include "wrappedlibs.h"
#include "box86context.h"
typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct kh_bridgemap_s kh_bridgemap_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct lib_s lib_t;
typedef struct bridge_s bridge_t;
typedef struct elfheader_s elfheader_t;
typedef struct kh_bridgemap_s kh_bridgemap_t;
typedef struct kh_mapsymbols_s kh_mapsymbols_t;
typedef struct x86emu_s x86emu_t;
typedef void (*wrapper_t)(x86emu_t* emu, uintptr_t fnc);
@@ -35,20 +36,27 @@ typedef struct wlib_s {
bridge_t *bridge;
void* lib; // dlopen result
void* priv; // actual private
void* p2; // second private
void* box86lib; // ref to the dlopen on box86 itself from context
char* altprefix; // if function names are mangled..
int needed;
char** neededlibs;
kh_symbolmap_t *symbolmap;
kh_symbolmap_t *wsymbolmap;
kh_symbolmap_t *mysymbolmap;
kh_symbolmap_t *wmysymbolmap;
kh_symbolmap_t *stsymbolmap;
kh_symbolmap_t *wstsymbolmap;
kh_symbol2map_t *symbol2map;
kh_datamap_t *datamap;
kh_datamap_t *wdatamap;
kh_datamap_t *mydatamap;
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
} wlib_t;
typedef struct nlib_s {
typedef struct elib_s {
int elf_index;
int finalized;
kh_mapsymbols_t *mapsymbols;
kh_mapsymbols_t *weaksymbols;
kh_mapsymbols_t *localsymbols;
} nlib_t;
elfheader_t *elf;
} elib_t;
typedef struct library_s {
char* name; // <> path
@@ -57,29 +65,20 @@ typedef struct library_s {
int type; // 0: native(wrapped) 1: emulated(elf) -1: undetermined
int active;
wrappedlib_fini_t fini;
wrappedlib_get_t get; // get weak and no weak
wrappedlib_get_t getnoweak; // get only non weak symbol
wrappedlib_get_t getlocal;
wrappedlib_get_t getglobal; // get global symbol (not weak)
wrappedlib_get_t getweak; // get weak symbol
wrappedlib_get_t getlocal; // get local symbol
union {
wlib_t w;
nlib_t n;
} priv; // private lib data
box86context_t *context; // parent context
kh_bridgemap_t *bridgemap;
kh_symbolmap_t *symbolmap;
kh_symbolmap_t *wsymbolmap;
kh_symbolmap_t *mysymbolmap;
kh_symbolmap_t *wmysymbolmap;
kh_symbolmap_t *stsymbolmap;
kh_symbolmap_t *wstsymbolmap;
kh_symbol2map_t *symbol2map;
kh_datamap_t *datamap;
kh_datamap_t *wdatamap;
kh_datamap_t *mydatamap;
char *altmy; // to avoid duplicate symbol, like with SDL1/SDL2
elib_t e;
}; // private lib data
needed_libs_t needed;
needed_libs_t dependedby;
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
int refcnt; // refcounting the lib
lib_t *maplib; // local maplib, for dlopen'd library with LOCAL binding (most of the dlopen)
kh_bridgemap_t *gbridgemap; // global symbol bridgemap
kh_bridgemap_t *wbridgemap; // weak symbol bridgemap
kh_bridgemap_t *lbridgemap; // local symbol bridgemap
} library_t;
void add_neededlib(needed_libs_t* needed, library_t* lib);
void free_neededlib(needed_libs_t* needed);
@@ -104,7 +103,7 @@ typedef struct map_onedata_s {
int weak;
} map_onedata_t;
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int version, const char* vername, int local); // Add bridges to functions
int getSymbolInMaps(library_t*lib, const char* name, int noweak, uintptr_t *addr, uint32_t *size, int* weak, int version, const char* vername, int local); // Add bridges to functions
typedef struct linkmap_s {
// actual struct link_map
+19 -15
View File
@@ -41,7 +41,7 @@ void FreeMapSymbols(kh_mapsymbols_t** map)
if(!map || !(*map))
return;
versymbols_t *v;
kh_foreach_value_ref(*map, v, free(v->syms););
kh_foreach_value_ref(*map, v, box_free(v->syms););
kh_destroy(mapsymbols, *map);
*map = NULL;
@@ -105,7 +105,7 @@ static versymbol_t* FindFirstVersion(versymbols_t* s)
}
// Match version (so ver=0:0, ver=1:-1/1/X, ver=-1:any, ver=X:1/"name")
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, int local)
static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername, int local, const char* defver)
{
if(!s || !s->sz)
return NULL;
@@ -114,13 +114,15 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret && defver) ret = FindVersion(s, defver);
return ret;
}
if(ver==-1) {
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret) ret = FindFirstVersion(s);
if(!ret && defver) ret = FindVersion(s, defver);
//if(!ret) ret = FindFirstVersion(s);
return ret;
}
if(ver==-2) {
@@ -132,12 +134,14 @@ static versymbol_t* MatchVersion(versymbols_t* s, int ver, const char* vername,
if(local) ret = FindVersionLocal(s);
if(!ret) ret = FindVersionGlobal(s);
if(!ret) ret = FindNoVersion(s);
if(!ret) ret = FindFirstVersion(s);
if(!ret && defver) ret = FindVersion(s, defver);
//if(!ret) ret = FindFirstVersion(s);
return ret;
}
ret = FindVersion(s, vername);
if(local && !ret) FindVersionLocal(s);
if(!ret) return FindVersionGlobal(s);
if(local && !ret) ret = FindVersionLocal(s);
if(!ret && defver && vername && !strcmp(defver, vername)) ret = FindVersionGlobal(s);
//if(!ret) return FindVersionGlobal(s);
return ret;
}
@@ -157,7 +161,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
// add a new record
if(v->sz == v->cap) {
v->cap+=4;
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
v->syms = (versymbol_t*)box_realloc(v->syms, v->cap*sizeof(versymbol_t));
}
int idx = v->sz++;
v->syms[idx].version = ver;
@@ -166,7 +170,7 @@ void AddSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, ui
v->syms[idx].sym.sz = sz;
}
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local)
uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, const char* vername, int local, const char* defver)
{
if(!mapsymbols)
return 0;
@@ -174,13 +178,13 @@ uintptr_t FindSymbol(kh_mapsymbols_t *mapsymbols, const char* name, int ver, con
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t * s = MatchVersion(v, ver, vername, local);
versymbol_t * s = MatchVersion(v, ver, vername, local, defver);
if(s)
return s->sym.offs;
return 0;
}
void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
void AddUniqueSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr, uint32_t sz, int ver, const char* vername)
{
int ret;
khint_t k = kh_put(mapsymbols, mapsymbols, name, &ret);
@@ -194,7 +198,7 @@ void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr
// add a new record
if(v->sz == v->cap) {
v->cap+=4;
v->syms = (versymbol_t*)realloc(v->syms, v->cap*sizeof(versymbol_t));
v->syms = (versymbol_t*)box_realloc(v->syms, v->cap*sizeof(versymbol_t));
}
int idx = v->sz++;
v->syms[idx].version = ver;
@@ -203,7 +207,7 @@ void AddWeakSymbol(kh_mapsymbols_t *mapsymbols, const char* name, uintptr_t addr
v->syms[idx].sym.sz = sz;
}
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local)
int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t* start, uintptr_t* end, int ver, const char* vername, int local, const char* defver)
{
if(!mapsymbols)
return 0;
@@ -211,7 +215,7 @@ int GetSymbolStartEnd(kh_mapsymbols_t* mapsymbols, const char* name, uintptr_t*
if(k==kh_end(mapsymbols))
return 0;
versymbols_t * v = &kh_val(mapsymbols, k);
versymbol_t* s = MatchVersion(v, ver, vername, local);
versymbol_t* s = MatchVersion(v, ver, vername, local, defver);
if(s) {
*start = s->sym.offs;
*end = *start + s->sym.sz;
@@ -250,7 +254,7 @@ void FreeDefaultVersion(kh_defaultversion_t** def)
if(!def || !*def)
return;
const char* v;
kh_foreach_value(*def, v, free((char*)v););
kh_foreach_value(*def, v, box_free((char*)v););
kh_destroy(defaultversion, *def);
*def = NULL;
@@ -261,7 +265,7 @@ void AddDefaultVersion(kh_defaultversion_t* def, const char* symname, const char
int ret;
khint_t k = kh_put(defaultversion, def, symname, &ret);
if(!ret) return; // already set!
kh_value(def, k) = strdup(vername);
kh_value(def, k) = box_strdup(vername);
}
const char* GetDefaultVersion(kh_defaultversion_t* def, const char* symname)
{
+4
View File
@@ -105,6 +105,7 @@ GO("libdbusmenu-glib.so.4", dbusmenuglib)
GO("libdbus-glib-1.so.2", dbusglib1)
GO("libgudev-1.0.so.0", gudev1)
GO("libappindicator.so.1", appindicator)
GO("libappindicator3.so.1", appindicator3)
GO("libatk-1.0.so.0", atk)
GO("libatk-bridge-2.0.so.0", atkbridge)
GO("libpangoft2-1.0.so", pangoft2)
@@ -164,6 +165,9 @@ GO("libgsttag-1.0.so.0", gsttag)
GO("libgstvideo-1.0.so.0", gstvideo)
GO("libgomp.so.1", gomp)
GO("libcap.so.2", cap)
GO("libpcap.so.0", pcap)
GO("libFAudio.so.0", faudio)
GO("libtbbmalloc_proxy.so.2", tbbmallocproxy)
#ifdef ANDROID
GO("libc.so", libc)
+3 -2
View File
@@ -11,6 +11,7 @@
#include "x86emu.h"
#include "emu/x86emu_private.h"
#include "myalign.h"
#include "debug.h"
void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack)
{
@@ -894,7 +895,7 @@ void alignNGValue(my_GValue_t* v, void* value, int n)
v->g_type = *(int*)value;
memcpy(v->data, value+4, 2*sizeof(double));
++v;
value+=4*2*sizeof(double);
value+=4+2*sizeof(double);
--n;
}
}
@@ -904,7 +905,7 @@ void unalignNGValue(void* value, my_GValue_t* v, int n)
*(int*)value = v->g_type;
memcpy(value+4, v->data, 2*sizeof(double));
++v;
value+=4*2*sizeof(double);
value+=4+2*sizeof(double);
--n;
}
}
+2 -2
View File
@@ -111,7 +111,7 @@ x86_ftsent_t* getFtsent(kh_ftsent_t* ftsentMap, FTSENT* ftsent, int dolink)
return kh_value(ftsentMap, k);
// new value... so need convertion & alignment
k = kh_put(ftsent, ftsentMap, (uintptr_t)ftsent, &ret);
x86_ftsent_t *x86ftsent = kh_value(ftsentMap, k) = (x86_ftsent_t*)malloc(sizeof(x86_ftsent_t));
x86_ftsent_t *x86ftsent = kh_value(ftsentMap, k) = (x86_ftsent_t*)box_malloc(sizeof(x86_ftsent_t));
UnalignFTSENT(x86ftsent, ftsent); // unalign
// handle the 3 embedded ftsent...
if(ftsent->fts_info<=14 && ftsent->fts_info!=7) { //14 is max value, 7 is err
@@ -138,7 +138,7 @@ void freeFts(box86context_t* context, void* ftsp)
kh_ftsent_t *ftsentMap = kh_value(ftsmap, k);
x86_ftsent_t* x86ftsent;
kh_foreach_value(ftsentMap, x86ftsent, free(x86ftsent));
kh_foreach_value(ftsentMap, x86ftsent, box_free(x86ftsent));
kh_destroy(ftsent, ftsentMap);
kh_del(fts, ftsmap, k);
}
+6 -6
View File
@@ -65,12 +65,12 @@ static void* findchunkfunFct(void* fct)
static void* reverse_chunkfunFct(library_t* lib, void* fct)
{
if(!fct) return fct;
if(CheckBridged(lib->priv.w.bridge, fct))
return (void*)CheckBridged(lib->priv.w.bridge, fct);
if(CheckBridged(lib->w.bridge, fct))
return (void*)CheckBridged(lib->w.bridge, fct);
#define GO(A) if(my_chunkfun_##A == fct) return (void*)my_chunkfun_fct_##A;
SUPER()
#undef GO
return (void*)AddBridge(lib->priv.w.bridge, pFL, fct, 0, NULL);
return (void*)AddBridge(lib->w.bridge, pFL, fct, 0, NULL);
}
// freefun
#define GO(A) \
@@ -98,12 +98,12 @@ static void* findfreefunFct(void* fct)
static void* reverse_freefunFct(library_t* lib, void* fct)
{
if(!fct) return fct;
if(CheckBridged(lib->priv.w.bridge, fct))
return (void*)CheckBridged(lib->priv.w.bridge, fct);
if(CheckBridged(lib->w.bridge, fct))
return (void*)CheckBridged(lib->w.bridge, fct);
#define GO(A) if(my_freefun_##A == fct) return (void*)my_freefun_fct_##A;
SUPER()
#undef GO
return (void*)AddBridge(lib->priv.w.bridge, vFp, fct, 0, NULL);
return (void*)AddBridge(lib->w.bridge, vFp, fct, 0, NULL);
}
#undef SUPER
+137 -28
View File
@@ -11,6 +11,9 @@
#include <ucontext.h>
#include <setjmp.h>
#include <sys/mman.h>
#ifndef ANDROID
#include <execinfo.h>
#endif
#include "box86context.h"
#include "debug.h"
@@ -108,14 +111,57 @@ struct i386_fpstate
unsigned short status;
unsigned short magic;
/* FXSR FPU environment. */
uint32_t _fxsr_env[6];
uint32_t mxcsr;
uint32_t reserved;
struct i386_fpxreg _fxsr_st[8];
struct i386_xmmreg _xmm[8];
uint32_t padding[56];
uint16_t ControlWord; /* 000 */
uint16_t StatusWord; /* 002 */
uint8_t TagWord; /* 004 */
uint8_t Reserved1; /* 005 */
uint16_t ErrorOpcode; /* 006 */
uint32_t ErrorOffset; /* 008 */
uint16_t ErrorSelector; /* 00c */
uint16_t Reserved2; /* 00e */
uint32_t DataOffset; /* 010 */
uint16_t DataSelector; /* 014 */
uint16_t Reserved3; /* 016 */
uint32_t MxCsr; /* 018 */
uint32_t MxCsr_Mask; /* 01c */
sse_regs_t FloatRegisters[8];/* 020 */ // fpu/mmx are store in 128bits here
sse_regs_t XmmRegisters[16]; /* 0a0 */
uint8_t Reserved4[96]; /* 1a0 */
}__attribute__((packed));
static void save_fpreg(x86emu_t* emu, struct i386_fpstate* state)
{
state->cw = emu->cw.x16;
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
emu->sw.f.F87_TOP = top;
state->sw = emu->sw.x16;
uint8_t tags = 0;
for (int i=0; i<8; ++i)
tags |= ((emu->p_regs[i].tag)<<(i*2)==0b11)?0:1;
fpu_fxsave(emu, &state->ControlWord);
}
static void load_fpreg(x86emu_t* emu, struct i386_fpstate* state)
{
emu->cw.x16 = state->cw;
emu->sw.x16 = state->sw;
emu->top = emu->sw.f.F87_TOP;
uint8_t tags = state->tag;
for(int i=0; i<8; ++i)
emu->p_regs[i].tag = (tags>>(i*2))?0:0b11;
// copy back MMX regs...
int top = emu->top&7;
int stack = 8-top;
if(top==0) // check if stack is full or empty, based on tag[0]
stack = (emu->p_regs[0].tag)?8:0;
for(int i=0; i<8; ++i)
memcpy((i<stack)?&ST(i):&emu->mmx[i], &state->_st[i], sizeof(mmx87_regs_t));
// copy SSE regs
fpu_fxrstor(emu, &state->ControlWord);
}
typedef struct i386_fpstate *i386_fpregset_t;
typedef struct
@@ -224,7 +270,7 @@ struct kernel_sigaction {
static void sigstack_destroy(void* p)
{
i386_stack_t *ss = (i386_stack_t*)p;
free(ss);
box_free(ss);
}
static pthread_key_t sigstack_key;
@@ -276,6 +322,7 @@ uint32_t RunFunctionHandler(int* exit, i386_ucontext_t* sigcontext, uintptr_t fn
// longjmp inside signal handler, lets grab all relevent value and do the actual longjmp in the signal handler
emu->longjmp = 0;
if(sigcontext) {
printf_log(LOG_DEBUG, "Longjmp in signal\n");
#define GO(R) sigcontext->uc_mcontext.gregs[REG_E##R] = emu->regs[_##R].dword[0]
GO(AX);
GO(CX);
@@ -339,7 +386,7 @@ EXPORT int my_sigaltstack(x86emu_t* emu, const i386_stack_t* ss, i386_stack_t* o
if(ss->ss_flags==SS_DISABLE) {
if(new_ss)
free(new_ss);
box_free(new_ss);
pthread_setspecific(sigstack_key, NULL);
return 0;
@@ -356,7 +403,7 @@ EXPORT int my_sigaltstack(x86emu_t* emu, const i386_stack_t* ss, i386_stack_t* o
}
}
if(!new_ss)
new_ss = (i386_stack_t*)calloc(1, sizeof(i386_stack_t));
new_ss = (i386_stack_t*)box_calloc(1, sizeof(i386_stack_t));
new_ss->ss_sp = ss->ss_sp;
new_ss->ss_size = ss->ss_size;
@@ -378,8 +425,9 @@ uintptr_t getX86Address(dynablock_t* db, uintptr_t arm_addr)
do {
x86sz+=db->instsize[i].x86;
armsz+=db->instsize[i].nat*4;
++i;
}
while(!db->instsize[++i].x86);
while(db->instsize[i-1].x86==15 || db->instsize[i-1].nat==15);
if(arm_addr>=armaddr && arm_addr<(armaddr+armsz))
return x86addr;
armaddr+=armsz;
@@ -401,8 +449,9 @@ static int getDBX86N(dynablock_t* db, uintptr_t arm_addr)
do {
x86sz+=db->instsize[i].x86;
armsz+=db->instsize[i].nat*4;
++i;
}
while(!db->instsize[++i].x86);
while(db->instsize[i-1].x86==15 || db->instsize[i-1].nat==15);
if(arm_addr>=armaddr && arm_addr<(armaddr+armsz))
return (arm_addr-armaddr)>>2;
armaddr+=armsz;
@@ -460,10 +509,15 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
used_stack = 1;
new_ss->ss_flags = SS_ONSTACK;
}
} else {
frame -= 0x200/sizeof(uintptr_t); // redzone
}
// TODO: do I need to really setup 2 stack frame? That doesn't seems right!
// setup stack frame
frame -= sizeof(siginfo_t)/sizeof(uintptr_t);
siginfo_t* info2 = (siginfo_t*)frame;
memcpy(info2, info, sizeof(siginfo_t));
// try to fill some sigcontext....
frame -= sizeof(i386_ucontext_t)/sizeof(uintptr_t);
i386_ucontext_t *sigcontext = (i386_ucontext_t*)frame;
@@ -508,7 +562,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
#endif
// get FloatPoint status
sigcontext->uc_mcontext.fpregs = (i386_fpregset_t)&sigcontext->xstate;
fpu_fxsave(emu, &sigcontext->xstate);
save_fpreg(emu, sigcontext->uc_mcontext.fpregs);
// add custom SIGN in reserved area
//((unsigned int *)(&sigcontext.xstate.fpstate.padding))[8*4+12] = 0x46505853; // not yet, when XSAVE / XRSTR will be ready
// get signal mask
@@ -547,7 +601,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
if((uintptr_t)info->si_addr == sigcontext->uc_mcontext.gregs[REG_EIP]) {
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0010; // execution flag issue (probably)
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = (info->si_code == SEGV_ACCERR)?13:14;
} else if(info->si_code==SEGV_ACCERR && !(prot&PROT_WRITE)) {
} else if((info->si_code==SEGV_ACCERR) && !(prot&PROT_WRITE)) {
sigcontext->uc_mcontext.gregs[REG_ERR] = 0x0002; // write flag issue
/*if(abs((intptr_t)info->si_addr-(intptr_t)sigcontext->uc_mcontext.gregs[REG_ESP])<16)
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 12; // stack overflow probably
@@ -565,7 +619,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
else if(sig==SIGILL)
sigcontext->uc_mcontext.gregs[REG_TRAPNO] = 6;
// call the signal handler
i386_ucontext_t sigcontext_copy = *sigcontext;
i386_mcontext_t sigmcontext_copy = sigcontext->uc_mcontext;
// save old value from emu
#define GO(R) uint32_t old_##R = R_##R
GO(EAX);
@@ -582,7 +636,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
if(simple)
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 1, sig);
else
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info, sigcontext);
ret = RunFunctionHandler(&exits, sigcontext, my_context->signals[sig], 3, sig, info2, sigcontext);
// restore old value from emu
#define GO(R) R_##R = old_##R
GO(EAX);
@@ -590,7 +644,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
GO(EDX);
#undef GO
if(memcmp(sigcontext, &sigcontext_copy, sizeof(i386_ucontext_t))) {
if(memcmp(&sigcontext->uc_mcontext, &sigmcontext_copy, sizeof(i386_mcontext_t))) {
emu_jmpbuf_t* ejb = GetJmpBuf();
if(ejb->jmpbuf_ok) {
#define GO(R) ejb->emu->regs[_##R].dword[0]=sigcontext->uc_mcontext.gregs[REG_E##R]
@@ -616,6 +670,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
GO(CS);
GO(SS);
#undef GO
load_fpreg(ejb->emu, &sigcontext->xstate.fpstate);
printf_log(LOG_DEBUG, "Context has been changed in Sigactionhanlder, doing siglongjmp to resume emu\n");
if(old_code)
*old_code = -1; // re-init the value to allow another segfault at the same place
@@ -624,7 +679,7 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, int Locks, siginfo_t*
//relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled
siglongjmp(ejb->jmpbuf, 1);
}
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[REG_EIP]!=sigcontext_copy.uc_mcontext.gregs[REG_EIP])?" (EIP changed)":"");
printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[REG_EIP]!=sigmcontext_copy.gregs[REG_EIP])?" (EIP changed)":"");
}
// restore regs...
#define GO(R) emu->regs[_##R].dword[0] = sigcontext->uc_mcontext.gregs[REG_E##R]
@@ -688,13 +743,23 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
}
dynablock_t* db = NULL;
int db_searched = 0;
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_DYNAREC)) {
// access error, unprotect the block (and mark them dirty)
unprotectDB((uintptr_t)addr, 1); // unprotect 1 byte... But then, the whole page will be unprotected
if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) {
// check if SMC inside block
db = FindDynablockFromNativeAddress(pc);
db_searched = 1;
dynarec_log(LOG_INFO/*LOG_DEBUG*/, "SIGSEGV with Access error on %p for %p , db=%p(%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL);
static uintptr_t repeated_page = 0;
dynarec_log(LOG_DEBUG, "SIGSEGV with Access error on %p for %p , db=%p(%p), prot=0x%x (old page=%p)\n", pc, addr, db, db?((void*)db->x86_addr):NULL, prot, (void*)repeated_page);
static int repeated_count = 0;
if(repeated_page == ((uintptr_t)addr&~0xfff)) {
++repeated_count; // Access eoor multiple time on same page, disable dynarec on this page a few time...
dynarec_log(LOG_DEBUG, "Detecting a Hotpage at %p (%d)\n", (void*)repeated_page, repeated_count);
AddHotPage(repeated_page);
} else {
repeated_page = (uintptr_t)addr&~0xfff;
repeated_count = 0;
}
// access error, unprotect the block (and mark them dirty)
unprotectDB((uintptr_t)addr, 1, 1); // unprotect 1 byte... But then, the whole page will be unprotected
if(db && ((addr>=db->x86_addr && addr<(db->x86_addr+db->x86_size)) || db->need_test)) {
// dynablock got auto-dirty! need to get out of it!!!
emu_jmpbuf_t* ejb = GetJmpBuf();
@@ -755,7 +820,7 @@ void my_box86signalhandler(int32_t sig, siginfo_t* info, void * ucntx)
glitch_addr = NULL;
glitch_prot = 0;
}
if(addr && pc && (prot&(PROT_READ|PROT_WRITE)==(PROT_READ|PROT_WRITE))) {
if(addr && pc && ((prot&(PROT_READ|PROT_WRITE))==(PROT_READ|PROT_WRITE))) {
static void* glitch_pc = NULL;
static void* glitch_addr = NULL;
static int glitch_prot = 0;
@@ -831,6 +896,15 @@ exit(-1);
exit(-1);
}
}
if(cycle_log) {
int j = (my_context->current_line+1)&(CYCLE_LOG-1);
for (int i=0; i<CYCLE_LOG; ++i) {
int k = (i+j)&(CYCLE_LOG-1);
if(my_context->log_call[k][0]) {
printf_log(log_minimum, "%s => return %s\n", my_context->log_call[k], my_context->log_ret[k]);
}
}
}
#ifdef DYNAREC
uint32_t hash = 0;
if(db && ((addr<db->x86_addr || addr>(db->x86_addr+db->x86_size)) || (prot&PROT_READ)))
@@ -841,6 +915,20 @@ exit(-1);
addr, info->si_code, prot, db, db?db->block:0, db?(db->block+db->size):0,
db?db->x86_addr:0, db?(db->x86_addr+db->x86_size):0,
getAddrFunctionName((uintptr_t)(db?db->x86_addr:0)), (db?db->need_test:0)?"need_stest":"clean", db?db->hash:0, hash);
#if defined(ARM)
static const char* reg_name[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI"};
if(db)
for (int i=0; i<8; ++i) {
if(!(i%4)) printf_log(log_minimum, "\n");
printf_log(log_minimum, "%s:0x%08x ", reg_name[i], ((uint32_t*)&p->uc_mcontext.arm_r4)[i]);
}
if(esp!=addr)
for (int i=-4; i<4; ++i) {
printf_log(log_minimum, "%sESP%c0x%02x:0x%08x", (i%4)?" ":"\n", i<0?'-':'+', abs(i)*4, *(uintptr_t*)(esp+i*4));
}
#else
#warning TODO
#endif
#else
printf_log(log_minimum, "%04d|%s @%p (%s) (x86pc=%p/%s:\"%s\", esp=%p), for accessing %p (code=%d)", GetTID(), signame, pc, name, (void*)x86pc, elfname?elfname:"???", x86name?x86name:"???", esp, addr, info->si_code);
#endif
@@ -854,9 +942,24 @@ exit(-1);
printf_log(log_minimum, " x86opcode=%02X %02X %02X %02X %02X %02X %02X %02X\n", ((uint8_t*)x86pc)[0], ((uint8_t*)x86pc)[1], ((uint8_t*)x86pc)[2], ((uint8_t*)x86pc)[3], ((uint8_t*)x86pc)[4], ((uint8_t*)x86pc)[5], ((uint8_t*)x86pc)[6], ((uint8_t*)x86pc)[7]);
else
printf_log(log_minimum, "\n");
#ifndef ANDROID
if(box86_backtrace && (log_minimum<=box86_log)) {
int nptrs;
void *buffer[200];
char **strings;
printf_log(LOG_NONE, "Native bactrace:\n");
nptrs = backtrace(buffer, 200);
strings = backtrace_symbols(buffer, nptrs);
for(int j=0; j<nptrs; j++)
printf_log(LOG_NONE, "\t%s\n", strings[j]);
box_free(strings);
}
#endif
}
#if 1
if(sig==SIGSEGV && (info->si_code==2 && ((prot&~PROT_DYNAREC)==7 || (prot&~PROT_DYNAREC)==5))) {
#if 0
if(sig==SIGSEGV && (info->si_code==2 && ((prot&~PROT_CUSTOM)==7 || (prot&~PROT_CUSTOM)==5))) {
/* there are some strange things happening with Terraria, where a segfault auccurs but the memory is perfectly accessible
(probably some timing issue) */
//box86_log=2;
@@ -904,8 +1007,10 @@ void emit_signal(x86emu_t* emu, int sig, void* addr, int code)
EXPORT sighandler_t my_signal(x86emu_t* emu, int signum, sighandler_t handler)
{
if(signum<0 || signum>=MAX_SIGNAL)
if(signum<0 || signum>=MAX_SIGNAL) {
errno = EINVAL;
return SIG_ERR;
}
if(signum==SIGSEGV && emu->context->no_sigsegv)
return 0;
@@ -932,8 +1037,10 @@ EXPORT sighandler_t my_sysv_signal(x86emu_t* emu, int signum, sighandler_t handl
int EXPORT my_sigaction(x86emu_t* emu, int signum, const x86_sigaction_t *act, x86_sigaction_t *oldact)
{
if(signum<0 || signum>=MAX_SIGNAL)
if(signum<0 || signum>=MAX_SIGNAL) {
errno = EINVAL;
return -1;
}
if(signum==SIGSEGV && emu->context->no_sigsegv)
return 0;
@@ -984,8 +1091,10 @@ __attribute__((alias("my_sigaction")));
int EXPORT my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_restorer_t *act, x86_sigaction_restorer_t *oldact, int sigsetsize)
{
printf_log(LOG_DEBUG, "Syscall/Sigaction(signum=%d, act=%p, old=%p, size=%d)\n", signum, act, oldact, sigsetsize);
if(signum<0 || signum>=MAX_SIGNAL)
if(signum<0 || signum>=MAX_SIGNAL) {
errno = EINVAL;
return -1;
}
if(signum==SIGSEGV && emu->context->no_sigsegv)
return 0;
@@ -1072,7 +1181,7 @@ int EXPORT my_syscall_sigaction(x86emu_t* emu, int signum, const x86_sigaction_r
ret = sigaction(signum, act?&newact:NULL, oldact?&old:NULL);
if(oldact && ret==0) {
oldact->sa_flags = old.sa_flags;
oldact->sa_mask = old.sa_mask;
memcpy(&oldact->sa_mask, &old.sa_mask, (sigsetsize>8)?8:sigsetsize);
if(old.sa_flags & 0x04)
oldact->_u._sa_sigaction = old.sa_sigaction; //TODO should wrap...
else
+80 -46
View File
@@ -27,14 +27,19 @@
#include "bridge.h"
#ifdef DYNAREC
#include "dynablock.h"
#include "dynarec/arm_lock_helper.h"
#endif
typedef void (*vFppp_t)(void*, void*, void*);
typedef void (*vFpi_t)(void*, int);
typedef int (*iFli_t)(long unsigned int, int);
//starting with glibc 2.34+, those 2 functions are in libc.so as versionned symbol only
// So use dlsym to get the symbol unversionned, as simple link will not work.
static vFppp_t real_pthread_cleanup_push_defer = NULL;
static vFpi_t real_pthread_cleanup_pop_restore = NULL;
// with glibc 2.34+, pthread_kill changed behaviour and might break some program, so using old version if possible
// it will be pthread_kill@GLIBC_2.4 on arm, but it's GLIBC_2.0 on i386
static iFli_t real_phtread_kill_old = NULL;
// those function can be used simply
void _pthread_cleanup_push(void* buffer, void* routine, void* arg); // declare hidden functions
void _pthread_cleanup_pop(void* buffer, int exec);
@@ -81,7 +86,7 @@ void CleanStackSize(box86context_t* context)
if(!context || !context->stacksizes)
return;
pthread_mutex_lock(&context->mutex_thread);
kh_foreach_value(context->stacksizes, ts, free(ts));
kh_foreach_value(context->stacksizes, ts, box_free(ts));
kh_destroy(threadstack, context->stacksizes);
context->stacksizes = NULL;
pthread_mutex_unlock(&context->mutex_thread);
@@ -92,7 +97,7 @@ void FreeStackSize(kh_threadstack_t* map, uintptr_t attr)
pthread_mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(threadstack, map, attr);
if(k!=kh_end(map)) {
free(kh_value(map, k));
box_free(kh_value(map, k));
kh_del(threadstack, map, k);
}
pthread_mutex_unlock(&my_context->mutex_thread);
@@ -104,7 +109,7 @@ void AddStackSize(kh_threadstack_t* map, uintptr_t attr, void* stack, size_t sta
int ret;
pthread_mutex_lock(&my_context->mutex_thread);
k = kh_put(threadstack, map, attr, &ret);
threadstack_t* ts = kh_value(map, k) = (threadstack_t*)calloc(1, sizeof(threadstack_t));
threadstack_t* ts = kh_value(map, k) = (threadstack_t*)box_calloc(1, sizeof(threadstack_t));
ts->stack = stack;
ts->stacksize = stacksize;
pthread_mutex_unlock(&my_context->mutex_thread);
@@ -144,7 +149,7 @@ static void FreeCancelThread(box86context_t* context)
#ifndef ANDROID
static __pthread_unwind_buf_t* AddCancelThread(x86_unwind_buff_t* buff)
{
__pthread_unwind_buf_t* r = (__pthread_unwind_buf_t*)calloc(1, sizeof(__pthread_unwind_buf_t));
__pthread_unwind_buf_t* r = (__pthread_unwind_buf_t*)box_calloc(1, sizeof(__pthread_unwind_buf_t));
buff->__pad[3] = r;
return r;
}
@@ -157,7 +162,7 @@ static __pthread_unwind_buf_t* GetCancelThread(x86_unwind_buff_t* buff)
static void DelCancelThread(x86_unwind_buff_t* buff)
{
__pthread_unwind_buf_t* r = (__pthread_unwind_buf_t*)buff->__pad[3];
free(r);
box_free(r);
buff->__pad[3] = NULL;
}
#endif
@@ -173,7 +178,7 @@ static void emuthread_destroy(void* p)
emuthread_t *et = (emuthread_t*)p;
if(et) {
FreeX86Emu(&et->emu);
free(et);
box_free(et);
}
}
@@ -190,7 +195,7 @@ void thread_set_emu(x86emu_t* emu)
pthread_once(&thread_key_once, thread_key_alloc);
emuthread_t *et = (emuthread_t*)pthread_getspecific(thread_key);
if(!et) {
et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t));
} else {
if(et->emu != emu)
FreeX86Emu(&et->emu);
@@ -216,7 +221,7 @@ x86emu_t* thread_get_emu()
stacksize = stack_size;
pthread_attr_destroy(&attr);
}
//void* stack = calloc(1, stacksize);
//void* stack = box_calloc(1, stacksize);
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
x86emu_t *emu = NewX86Emu(my_context, 0, (uintptr_t)stack, stacksize, 1);
SetupX86Emu(emu);
@@ -302,12 +307,12 @@ EXPORT int my_pthread_create(x86emu_t *emu, void* t, void* attr, void* start_rou
stacksize = attr_stacksize;
own = 0;
} else {
//stack = malloc(stacksize);
//stack = box_malloc(stacksize);
stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
own = 1;
}
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t));
x86emu_t *emuthread = NewX86Emu(my_context, (uintptr_t)start_routine, (uintptr_t)stack, stacksize, own);
SetupX86Emu(emuthread);
SetFS(emuthread, GetFS(emu));
@@ -317,8 +322,7 @@ EXPORT int my_pthread_create(x86emu_t *emu, void* t, void* attr, void* start_rou
#ifdef DYNAREC
if(box86_dynarec) {
// pre-creation of the JIT code for the entry point of the thread
dynablock_t *current = NULL;
DBGetBlock(emu, (uintptr_t)start_routine, 1, &current);
DBGetBlock(emu, (uintptr_t)start_routine, 1);
}
#endif
// create thread
@@ -329,9 +333,9 @@ EXPORT int my_pthread_create(x86emu_t *emu, void* t, void* attr, void* start_rou
void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet)
{
int stacksize = (ssize)?ssize:(2*1024*1024); //default stack size is 2Mo
//void* stack = malloc(stacksize);
//void* stack = box_malloc(stacksize);
void* stack = mmap(NULL, stacksize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0);
emuthread_t *et = (emuthread_t*)calloc(1, sizeof(emuthread_t));
emuthread_t *et = (emuthread_t*)box_calloc(1, sizeof(emuthread_t));
x86emu_t *emuthread = NewX86Emu(emu->context, (uintptr_t)f, (uintptr_t)stack, stacksize, 1);
SetupX86Emu(emuthread);
SetFS(emuthread, GetFS(emu));
@@ -341,8 +345,7 @@ void* my_prepare_thread(x86emu_t *emu, void* f, void* arg, int ssize, void** pet
#ifdef DYNAREC
if(box86_dynarec) {
// pre-creation of the JIT code for the entry point of the thread
dynablock_t *current = NULL;
DBGetBlock(emu, (uintptr_t)f, 1, &current);
DBGetBlock(emu, (uintptr_t)f, 1);
}
#endif
*pet = et;
@@ -490,25 +493,27 @@ static void* findcleanup_routineFct(void* fct)
#undef SUPER
// once_callback
// Don't use a "GO" scheme, once callback are only called once by definition
// custom implementation of pthread_once...
static __thread uintptr_t my_once_callback_fct = 0;
static void my_once_callback()
int EXPORT my_pthread_once(x86emu_t* emu, int* once, void* cb)
{
if(my_once_callback_fct) {
if(GetNativeFnc((uintptr_t)my_once_callback_fct)) {
vFv_t f = (vFv_t)GetNativeFnc((uintptr_t)my_once_callback_fct);
f();
return;
}
RunFunction(my_context, my_once_callback_fct, 0, 0);
}
}
int EXPORT my_pthread_once(x86emu_t* emu, void* once, void* cb)
{
my_once_callback_fct = (uintptr_t)cb;
return pthread_once(once, my_once_callback);
#ifdef DYNAREC
#ifdef ARM
int old = arm_lock_xchg(once, 1);
#else
#error Not implemented
#endif
#else
int old = *once; // outside of the mutex in case once is badly formed
pthread_mutex_lock(&my_context->mutex_lock);
old = *once;
*once = 1;
pthread_mutex_unlock(&my_context->mutex_lock);
#endif
if(old)
return 0;
EmuCall(emu, (uintptr_t)cb); // avoid DynaCall for now, functions are only used once after all
return 0;
}
EXPORT int my___pthread_once(x86emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));
@@ -538,7 +543,7 @@ static pthread_cond_t* add_cond(void* cond)
if(!ret)
c = kh_value(mapcond, k); // already there... reinit an existing one?
else
c = kh_value(mapcond, k) = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
c = kh_value(mapcond, k) = (pthread_cond_t*)box_calloc(1, sizeof(pthread_cond_t));
*(void**)cond = cond;
pthread_mutex_unlock(&my_context->mutex_thread);
return c;
@@ -553,7 +558,7 @@ static pthread_cond_t* get_cond(void* cond)
khint_t k = kh_get(mapcond, mapcond, (uintptr_t)cond);
if(k==kh_end(mapcond)) {
printf_log(LOG_DEBUG, "BOX86: Note: phtread_cond not found, create a new empty one\n");
ret = (pthread_cond_t*)calloc(1, sizeof(pthread_cond_t));
ret = (pthread_cond_t*)box_calloc(1, sizeof(pthread_cond_t));
k = kh_put(mapcond, mapcond, (uintptr_t)cond, &r);
kh_value(mapcond, k) = ret;
*(void**)cond = cond;
@@ -572,7 +577,7 @@ static void del_cond(void* cond)
pthread_mutex_lock(&my_context->mutex_thread);
khint_t k = kh_get(mapcond, mapcond, *(uintptr_t*)cond);
if(k!=kh_end(mapcond)) {
free(kh_value(mapcond, k));
box_free(kh_value(mapcond, k));
kh_del(mapcond, mapcond, k);
}
pthread_mutex_unlock(&my_context->mutex_thread);
@@ -708,12 +713,28 @@ EXPORT int my_pthread_attr_setaffinity_np(x86emu_t* emu, void* attr, uint32_t cp
EXPORT int my_pthread_kill(x86emu_t* emu, void* thread, int sig)
{
// should ESCHR result be filtered, as this is expected to be the 2.34 behaviour?
// check for old "is everything ok?"
if((thread==NULL) && (sig==0))
return pthread_kill(pthread_self(), 0);
return pthread_kill((pthread_t)thread, sig);
}
EXPORT int my_pthread_kill_old(x86emu_t* emu, void* thread, int sig)
{
// check for old "is everything ok?"
if(!thread)
thread = (void*)pthread_self();
return real_phtread_kill_old((pthread_t)thread, sig);
}
EXPORT int my_pthread_join(x86emu_t* emu, void* thread, void** ret)
{
if(!thread)
return ESRCH;
return pthread_join((pthread_t)thread, ret);
}
//EXPORT void my_pthread_exit(x86emu_t* emu, void* retval)
//{
// emu->quit = 1; // to be safe
@@ -738,7 +759,7 @@ pthread_mutex_t* getAlignedMutex(pthread_mutex_t* m)
return kh_value(unaligned_mutex, k);
int r;
k = kh_put(mutex, unaligned_mutex, (uintptr_t)m, &r);
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_t* ret = kh_value(unaligned_mutex, k) = (pthread_mutex_t*)box_malloc(sizeof(pthread_mutex_t));
memcpy(ret, m, sizeof(pthread_mutex_t));
return ret;
}
@@ -751,7 +772,7 @@ EXPORT int my_pthread_mutex_destroy(pthread_mutex_t *m)
pthread_mutex_t *n = kh_value(unaligned_mutex, k);
kh_del(mutex, unaligned_mutex, k);
int ret = pthread_mutex_destroy(n);
free(n);
box_free(n);
return ret;
}
return pthread_mutex_destroy(m);
@@ -771,7 +792,7 @@ static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER;
static mutexes_block_t* NewMutexesBlock()
{
mutexes_block_t* ret = (mutexes_block_t*)calloc(1, sizeof(mutexes_block_t));
mutexes_block_t* ret = (mutexes_block_t*)box_calloc(1, sizeof(mutexes_block_t));
ret->n_free = MUTEXES_SIZE;
return ret;
}
@@ -821,7 +842,7 @@ void FreeAllMutexes(mutexes_block_t* m)
return;
FreeAllMutexes(m->next);
// should destroy all mutexes also?
free(m);
box_free(m);
}
pthread_mutex_t* GetMutex(int k)
@@ -934,8 +955,8 @@ static void emujmpbuf_destroy(void* p)
{
emu_jmpbuf_t *ej = (emu_jmpbuf_t*)p;
if(ej) {
free(ej->jmpbuf);
free(ej);
box_free(ej->jmpbuf);
box_free(ej);
}
}
@@ -945,8 +966,8 @@ emu_jmpbuf_t* GetJmpBuf()
{
emu_jmpbuf_t *ejb = (emu_jmpbuf_t*)pthread_getspecific(jmpbuf_key);
if(!ejb) {
ejb = (emu_jmpbuf_t*)calloc(1, sizeof(emu_jmpbuf_t));
ejb->jmpbuf = calloc(1, sizeof(jmp_buf));
ejb = (emu_jmpbuf_t*)box_calloc(1, sizeof(emu_jmpbuf_t));
ejb->jmpbuf = box_calloc(1, sizeof(jmp_buf));
pthread_setspecific(jmpbuf_key, ejb);
}
return ejb;
@@ -957,6 +978,19 @@ void init_pthread_helper()
real_pthread_cleanup_push_defer = (vFppp_t)dlsym(NULL, "_pthread_cleanup_push_defer");
real_pthread_cleanup_pop_restore = (vFpi_t)dlsym(NULL, "_pthread_cleanup_pop_restore");
// search for older symbol for pthread_kill
{
char buff[50];
for(int i=0; i<34 && !real_phtread_kill_old; ++i) {
snprintf(buff, 50, "GLIBC_2.%d", i);
real_phtread_kill_old = (iFli_t)dlvsym(NULL, "pthread_kill", buff);
}
}
if(!real_phtread_kill_old) {
printf_log(LOG_INFO, "Warning, older than 2.34 pthread_kill not found, using current one\n");
real_phtread_kill_old = (iFli_t)pthread_kill;
}
InitCancelThread();
mapcond = kh_init(mapcond);
pthread_key_create(&jmpbuf_key, emujmpbuf_destroy);
@@ -972,7 +1006,7 @@ void fini_pthread_helper(box86context_t* context)
pthread_cond_t *cond;
kh_foreach_value(mapcond, cond,
pthread_cond_destroy(cond);
free(cond);
box_free(cond);
);
kh_destroy(mapcond, mapcond);
mapcond = NULL;
@@ -981,7 +1015,7 @@ void fini_pthread_helper(box86context_t* context)
pthread_mutex_t *m;
kh_foreach_value(unaligned_mutex, m,
pthread_mutex_destroy(m);
free(m);
box_free(m);
);
kh_destroy(mutex, unaligned_mutex);
#else
+792 -222
View File
File diff suppressed because it is too large. Load diff
+5 -4
View File
@@ -1,9 +1,10 @@
#include <stdint.h>
void* VulkanFromx86(void* src, void** save);
void VulkanTox86(void* src, void* save);
void* VulkanFromx86(void* src);
void* VulkanTox86(void* src);
int vkalignSize(const char* desc);
void* vkalignStruct(void* src, const char* desc, int cnt);
void vkunalignStruct(void* dst, void* src, const char* desc, int cnt);
void* vkStructUnalign(void* src, const char* desc, int cnt);
void* vkunalignStruct(void* src, const char* desc, int cnt);
void* vkStructUnalign(void* src, const char* desc, int cnt);
void* vkunalignNewStruct(void* dst, void* src, const char* desc, int cnt);
+279 -81
View File
@@ -20,6 +20,7 @@
#include <dirent.h>
#include <signal.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#ifdef DYNAREC
#ifdef ARM
#include <linux/auxvec.h>
@@ -47,6 +48,8 @@ int box86_dump = 0;
int box86_nobanner = 0;
int box86_dynarec_log = LOG_NONE;
int box86_pagesize;
uintptr_t box86_load_addr = 0;
int box86_backtrace = 0;
#ifdef DYNAREC
int box86_dynarec = 1;
int box86_dynarec_dump = 0;
@@ -56,6 +59,7 @@ int box86_dynarec_bigblock = 1;
int box86_dynarec_strongmem = 0;
int box86_dynarec_x87double = 0;
int box86_dynarec_fastnan = 1;
int box86_dynarec_safeflags = 1;
uintptr_t box86_nodynarec_start = 0;
uintptr_t box86_nodynarec_end = 0;
#ifdef ARM
@@ -68,6 +72,7 @@ int arm_v8 = 0;
int box86_dynarec = 0;
#endif
int dlsym_error = 0;
int cycle_log = 0;
int trace_xmm = 0;
int trace_emm = 0;
#ifdef HAVE_TRACE
@@ -82,6 +87,7 @@ int x11color16 = 0;
#if defined(RPI) || defined(RK3399) || defined(RK3288) || defined(GOA_CLONE) || defined(PYRA) || defined(PANDORA)
int box86_tokitori2 = 0;
#endif
int box86_sc3u = 0;
int box86_mapclean = 0;
int box86_zoom = 0;
int x11threads = 0;
@@ -157,6 +163,7 @@ void my_child_fork()
}
#ifdef DYNAREC
int getNCpu();
void GatherDynarecExtensions()
{
if(box86_dynarec==0) // no need to check if no dynarec
@@ -215,7 +222,9 @@ void GatherDynarecExtensions()
if(arm_div)
printf_log(LOG_INFO, " IDIVA");
printf_log(LOG_INFO, " PageSize:%d\n", box86_pagesize);
printf_log(LOG_INFO, " PageSize:%d", box86_pagesize);
int ncpu = getNCpu();
printf_log(LOG_INFO, " Cores:%d\n", ncpu);
#endif
}
#endif
@@ -260,6 +269,19 @@ void LoadLogEnv()
if(!box86_nobanner)
printf_log(LOG_INFO, "Debug level is %d\n", box86_log);
}
p = getenv("BOX86_ROLLING_LOG");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='1')
cycle_log = p[0]-'0';
}
if(cycle_log && box86_log>LOG_INFO) {
cycle_log = 0;
printf_log(LOG_NONE, "Incompatible Rolling log and Debug Log, disabling Rolling log\n");
}
}
if(!box86_nobanner && cycle_log)
printf_log(LOG_INFO, "Rolling log, showing last %d function call on signals\n", CYCLE_LOG);
p = getenv("BOX86_DUMP");
if(p) {
if(strlen(p)==1) {
@@ -350,6 +372,17 @@ void LoadLogEnv()
if(!box86_dynarec_fastnan)
printf_log(LOG_INFO, "Dynarec will try to normalize generated NAN\n");
}
p = getenv("BOX86_DYNAREC_SAFEFLAGS");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='2')
box86_dynarec_safeflags = p[0]-'0';
}
if(!box86_dynarec_safeflags)
printf_log(LOG_INFO, "Dynarec will not play it safe with x86 flags\n");
else
printf_log(LOG_INFO, "Dynarec will play %s safe with x86 flags\n", (box86_dynarec_safeflags==1)?"moderatly":"it");
}
p = getenv("BOX86_NODYNAREC");
if(p) {
if (strchr(p,'-')) {
@@ -396,12 +429,20 @@ void LoadLogEnv()
#endif
#endif
// Other BOX86 env. var.
p = getenv("BOX86_LOAD_ADDR");
if(p) {
if(sscanf(p, "0x%zx", &box86_load_addr)!=1)
box86_load_addr = 0;
if(box86_load_addr)
printf_log(LOG_INFO, "Use a starting load address of %p\n", (void*)box86_load_addr);
}
p = getenv("BOX86_DLSYM_ERROR");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
dlsym_error = p[0]-'0';
}
printf_log(LOG_INFO, "Shows details of dlopen / dlsym /dlclose : %s\n", dlsym_error?"Yes":"No");
}
#ifdef PANDORA
p = getenv("BOX86_X11COLOR16");
@@ -435,11 +476,11 @@ void LoadLogEnv()
}
p = getenv("BOX86_LIBGL");
if(p)
libGL = strdup(p);
libGL = box_strdup(p);
if(!libGL) {
p = getenv("SDL_VIDEO_GL_DRIVER");
if(p)
libGL = strdup(p);
libGL = box_strdup(p);
}
if(libGL) {
printf_log(LOG_INFO, "BOX86 using \"%s\" as libGL.so.1\n", p);
@@ -518,6 +559,15 @@ void LoadLogEnv()
if(box86_showsegv)
printf_log(LOG_INFO, "Show Segfault signal even if a signal handler is present\n");
}
p = getenv("BOX86_BACKTRACE");
if(p) {
if(strlen(p)==1) {
if(p[0]>='0' && p[0]<='0'+1)
box86_backtrace = p[0]-'0';
}
if(box86_backtrace)
printf_log(LOG_INFO, "Show Backtrace for signals\n");
}
box86_pagesize = sysconf(_SC_PAGESIZE);
if(!box86_pagesize)
box86_pagesize = 4096;
@@ -572,19 +622,19 @@ int GatherEnv(char*** dest, char** env, const char* prog)
char* ld_path = NULL;
while(*p) {
if(strncmp(*p, "BOX86_PATH=", 11)==0) {
(*dest)[idx++] = strdup(*p);
(*dest)[idx++] = box_strdup(*p);
box86_path = 1;
} else if(strncmp(*p, "BOX86_LD_LIBRARY_PATH=", 22)==0) {
(*dest)[idx++] = strdup(*p);
(*dest)[idx++] = box_strdup(*p);
box86_ld_path = 1;
} else if(strncmp(*p, "_=", 2)==0) {
/*int l = strlen(prog);
char tmp[l+3];
strcpy(tmp, "_=");
strcat(tmp, prog);
(*dest)[idx++] = strdup(tmp);*/
(*dest)[idx++] = box_strdup(tmp);*/
} else if(strncmp(*p, "BOX86_", 6)!=0) {
(*dest)[idx++] = strdup(*p);
(*dest)[idx++] = box_strdup(*p);
/*if(!(strncmp(*p, "PATH=", 5)==0 || strncmp(*p, "LD_LIBRARY_PATH=", 16)==0)) {
}*/
}
@@ -592,10 +642,10 @@ int GatherEnv(char*** dest, char** env, const char* prog)
}
// update the calloc of envv when adding new variables here
if(!box86_path) {
(*dest)[idx++] = strdup("BOX86_PATH=.:bin");
(*dest)[idx++] = box_strdup("BOX86_PATH=.:bin");
}
if(!box86_ld_path) {
(*dest)[idx++] = strdup("BOX86_LD_LIBRARY_PATH=.:lib");
(*dest)[idx++] = box_strdup("BOX86_LD_LIBRARY_PATH=.:lib");
}
// add "_=prog" at the end...
if(prog) {
@@ -603,7 +653,7 @@ int GatherEnv(char*** dest, char** env, const char* prog)
char tmp[l+3];
strcpy(tmp, "_=");
strcat(tmp, prog);
(*dest)[idx++] = strdup(tmp);
(*dest)[idx++] = box_strdup(tmp);
}
// and a final NULL
(*dest)[idx++] = 0;
@@ -622,15 +672,18 @@ void PrintHelp() {
printf(" BOX86_PATH is the box86 version of PATH (default is '.:bin')\n");
printf(" BOX86_LD_LIBRARY_PATH is the box86 version LD_LIBRARY_PATH (default is '.:lib')\n");
printf(" BOX86_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed debug info (level 3 is level 2 + BOX86_DUMP)\n");
printf(" BOX86_ROLLING_LOG 0/1 use a rolling level 2 log of 16 entries\n");
printf(" BOX86_DUMP with 0/1 to dump elf infos\n");
printf(" BOX86_NOBANNER with 0/1 to enable/disable the printing of box86 version and build at start\n");
#ifdef DYNAREC
printf(" BOX86_DYNAREC_LOG with 0/1/2/3 or NONE/INFO/DEBUG/DUMP to set the printed dynarec info\n");
printf(" BOX86_DYNAREC with 0/1 to disable or enable Dynarec (On by default)\n");
printf(" BOX86_NODYNAREC with address interval (0x1234-0x4567) to forbid dynablock creation in the interval specified\n");
printf(" BOX86_DYNAREC_BIGBLOCK 0/1/2 to control Dynarec building BigBlock or not\n");
printf(" BOX86_DYNAREC_STRONGMEM 0/1/2 to control Dynarec emulation attempt of Stong memory model\n");
printf(" BOX86_DYNAREC_X87DOUBLE 0/1 to force Dynarec to use Double for x87 emulation\n");
printf(" BOX86_DYNAREC_BIGBLOCK 0/1/2 to control Dynarec building BigBlock or not (default: 1)\n");
printf(" BOX86_DYNAREC_STRONGMEM 0/1/2 to control Dynarec emulation attempt of Stong memory model (default: 0)\n");
printf(" BOX86_DYNAREC_X87DOUBLE 0/1 to force Dynarec to use Double for x87 emulation (default: 0)\n");
printf(" BOX86_DYNAREC_FASTNAN 0/1 to control if NaN are x86 accurate or not (default: 1)\n");
printf(" BOX86_DYNAREC_SAFEFLAGS 0/1/2 to control flags generation on RET/CALL opcodes (default: 1)\n");
#endif
#ifdef HAVE_TRACE
printf(" BOX86_TRACE with 1 to enable x86 execution trace\n");
@@ -661,12 +714,47 @@ void PrintHelp() {
printf(" BOX86_NOPULSE=1 to disable the loading of pulseaudio libs\n");
printf(" BOX86_NOGTK=1 to disable the loading of wrapped gtk libs\n");
printf(" BOX86_NOVULKAN=1 to disable the loading of wrapped vulkan libs\n");
printf(" BOX86_ENV='XXX=yyyy' will add XXX=yyyy env. var.\n");
printf(" BOX86_ENV1='XXX=yyyy' will add XXX=yyyy env. var. and continue with BOX86_ENV2 ... until var doesn't exist\n");
printf(" BOX86_JITGDB with 1 to launch \"gdb\" when a segfault is trapped, attached to the offending process\n");
}
void addNewEnvVar(const char* s)
{
if(!s)
return;
char* p = box_strdup(s);
char* e = strchr(p, '=');
if(!e) {
printf_log(LOG_INFO, "Invalid speicifc env. var. '%s'\n", s);
box_free(p);
return;
}
*e='\0';
++e;
setenv(p, e, 1);
box_free(p);
}
EXPORTDYN
void LoadEnvVars(box86context_t *context)
{
// Check custom env. var. and add them if needed
{
char* p = getenv("BOX86_ENV");
if(p)
addNewEnvVar(p);
int i = 1;
char box86_env[50];
do {
sprintf(box86_env, "BOX86_ENV%d", i);
p = getenv(box86_env);
if(p) {
addNewEnvVar(p);
++i;
}
} while(p);
}
// check BOX86_LD_LIBRARY_PATH and load it
LoadEnvPath(&context->box86_ld_lib, ".:lib:lib32:x86:i686", "BOX86_LD_LIBRARY_PATH");
#ifdef PANDORA
@@ -757,8 +845,8 @@ void LoadEnvVars(box86context_t *context)
#endif
#ifdef BUILD_LIB
context->argc = 1; // need 1
context->argv = (char**)malloc(sizeof(char*));
context->argv[0] = strdup("dummy");
context->argv = (char**)box_malloc(sizeof(char*));
context->argv[0] = box_strdup("dummy");
#endif
}
@@ -780,7 +868,7 @@ void setupTraceInit(box86context_t* context)
if(trace_start || trace_end)
SetTraceEmu(trace_start, trace_end);
} else {
if (GetSymbolStartEnd(GetMapSymbol(my_context->maplib), p, &trace_start, &trace_end, -1, NULL, -1)) {
if (GetGlobalSymbolStartEnd(my_context->maplib, p, &trace_start, &trace_end, NULL, -1, NULL)) {
SetTraceEmu(trace_start, trace_end);
printf_log(LOG_INFO, "TRACE on %s only (%p-%p)\n", p, (void*)trace_start, (void*)trace_end);
} else {
@@ -830,7 +918,7 @@ void setupTrace(box86context_t* context)
} else {
printf_log(LOG_NONE, "Warning, symbol to Traced (\"%s\") not found, trying to set trace later\n", p);
SetTraceEmu(0, 1); // disabling trace, mostly
trace_func = strdup(p);
trace_func = box_strdup(p);
}
}
}
@@ -891,7 +979,7 @@ void endBox86()
// all done, free context
FreeBox86Context(&my_context);
if(libGL) {
free(libGL);
box_free(libGL);
libGL = NULL;
}
}
@@ -938,13 +1026,14 @@ void init_library()
static void free_contextargv()
{
for(int i=0; i<my_context->argc; ++i)
free(my_context->argv[i]);
box_free(my_context->argv[i]);
}
extern char **environ;
int main(int argc, const char **argv, char **env) {
int main(int argc, const char **argv, char **env)
{
init_malloc_hook();
init_auxval(argc, argv, environ?environ:env);
// trying to open and load 1st arg
if(argc==1) {
@@ -968,7 +1057,27 @@ int main(int argc, const char **argv, char **env) {
// check BOX86_LOG debug level
LoadLogEnv();
char* bashpath = NULL;
{
char* p = getenv("BOX86_BASH");
if(p) {
if(FileIsX86ELF(p) || FileIsX64ELF(p)) {
bashpath = p;
} else {
printf_log(LOG_INFO, "the x86 bash \"%s\" is not an x86 binary\n", p);
}
}
if(!bashpath && (p=getenv("BOX64_BASH"))) {
if(FileIsX86ELF(p) || FileIsX64ELF(p)) {
bashpath = p;
} else {
printf_log(LOG_INFO, "the x86_64 bash \"%s\" is not an x86_64 binary\n", p);
}
}
}
if(bashpath)
printf_log(LOG_INFO, "Using bash \"%s\"\n", bashpath);
const char* prog = argv[1];
int nextarg = 1;
// check if some options are passed
@@ -1018,12 +1127,6 @@ int main(int argc, const char **argv, char **env) {
printf_log(LOG_NONE, "winedbg detected, not launching it!\n");
exit(0); // exiting, it doesn't work anyway
}
#ifdef DYNAREC
if(argv[nextarg+1] && strstr(argv[nextarg+1], "Crysis")) {
printf_log(LOG_NONE, "Crysis detected, forcing use of Double for x87 emulation\n");
box86_dynarec_x87double = 1;
}
#endif
box86_wine = 1;
}
// check if this is wineserver
@@ -1043,12 +1146,23 @@ int main(int argc, const char **argv, char **env) {
my_context->box86path = ResolveFile(argv[0], &my_context->box86_path);
// check if box64 is present
{
my_context->box64path = strdup(my_context->box86path);
char* p = strrchr(my_context->box64path, '8'); // get the 8 of box86
p[0] = '6'; p[1] = '4'; // change 86 to 64
my_context->box64path = getenv("BOX86_BOX64");
if(!my_context->box64path) {
my_context->box64path = box_strdup(my_context->box86path);
char* p = strrchr(my_context->box64path, '8'); // get the 8 of box86
p[0] = '6'; p[1] = '4'; // change 86 to 64
}
if(!FileExist(my_context->box64path, IS_FILE)) {
free(my_context->box64path);
box_free(my_context->box64path);
my_context->box64path = ResolveFile("box64", &my_context->box86_path);
}
if(!FileExist(my_context->box64path, IS_FILE)) {
box_free(my_context->box64path);
my_context->box64path = NULL;
if(bashpath && FileIsX64ELF(bashpath)) {
printf_log(LOG_INFO, "The bash binary given is an x86_64 version, but box64 is not found\n");
bashpath = NULL;
}
}
}
@@ -1056,7 +1170,7 @@ int main(int argc, const char **argv, char **env) {
my_context->envc = CountEnv(environ?environ:env);
printf_log(LOG_INFO, "Counted %d Env var\n", my_context->envc);
// allocate extra space for new environment variables such as BOX86_PATH
my_context->envv = (char**)calloc(my_context->envc+4, sizeof(char*));
my_context->envv = (char**)box_calloc(my_context->envc+4, sizeof(char*));
GatherEnv(&my_context->envv, environ?environ:env, my_context->box86path);
if(box86_dump) {
for (int i=0; i<my_context->envc; ++i)
@@ -1098,7 +1212,7 @@ int main(int argc, const char **argv, char **env) {
// lets build argc/argv stuff
printf_log(LOG_INFO, "Looking for %s\n", prog);
if(strchr(prog, '/'))
my_context->argv[0] = strdup(prog);
my_context->argv[0] = box_strdup(prog);
else
my_context->argv[0] = ResolveFile(prog, &my_context->box86_path);
@@ -1120,13 +1234,22 @@ int main(int argc, const char **argv, char **env) {
printf_log(LOG_INFO, "Dontstarve* detected, forcing emulated SDL2\n");
AddPath("libSDL2-2.0.so.0", &my_context->box86_emulated_libs, 0);
}
// special case for A Golden Wake / GeminiRue that use an old SDL2 and vorbis libs
if(strstr(prgname, "A_Golden_Wake.bin.x86")==prgname || strstr(prgname, "GeminiRue.bin.x86")==prgname) {
printf_log(LOG_INFO, "A Golden Wake / Gemini Rue detected, prefer emulated libs\n");
box86_prefer_emulated = 1;
}
// special case for steam that somehow seems to alter libudev opaque pointer (udev_monitor)
if(strstr(prgname, "steam")==prgname) {
printf_log(LOG_INFO, "steam detected, forcing emulated libudev and gtk\n");
AddPath("libudev.so.0", &my_context->box86_emulated_libs, 0);
box86_steam = 1;
box86_nogtk = 1;
AddPath("libSDL2-2.0.so.0", &my_context->box86_emulated_libs, 0);
unsetenv("BOX86_NOGTK");
#ifdef PANDORA
x11color16 = 1;
#endif
}
// special case for steam-runtime-check-requirements to fake 64bits suport
if(strstr(prgname, "steam-runtime-check-requirements")==prgname) {
@@ -1141,8 +1264,8 @@ int main(int argc, const char **argv, char **env) {
}
// special case for UnrealLinux.bin, it doesn't like "full path resolution"
if(!strcmp(prog, "UnrealLinux.bin") && my_context->argv[0]) {
free(my_context->argv[0]);
my_context->argv[0] = strdup("./UnrealLinux.bin");
box_free(my_context->argv[0]);
my_context->argv[0] = box_strdup("./UnrealLinux.bin");
}
#if defined(RPI) || defined(RK3399) || defined(RK3288) || defined(GOA_CLONE) || defined(PYRA) || defined(PANDORA)
// special case for TokiTori 2+, that check if texture max size is > = 8192
@@ -1151,6 +1274,15 @@ int main(int argc, const char **argv, char **env) {
box86_tokitori2 = 1;
}
#endif
// special case for SimCity3k Demo, that have a bug were it do feof after fclose on the same fd
if(strstr(prgname, "sc3u_demo.x86")==prgname) {
printf_log(LOG_INFO, "SimCity3000 Demo detected, runtime patch to fix buf feof after fclose\n");
box86_sc3u = 1;
}
if(strstr(prgname, "sc3u")==prgname) {
printf_log(LOG_INFO, "SimCity3000 detected, runtime patch to fix buf feof after fclose\n");
box86_sc3u = 1;
}
// special case for zoom
if(strstr(prgname, "zoom")==prgname) {
printf_log(LOG_INFO, "Zoom detected, trying to use system libturbojpeg if possible\n");
@@ -1161,6 +1293,21 @@ int main(int argc, const char **argv, char **env) {
printf_log(LOG_INFO, "X3Reunion detected, forcing emulated libjpeg\n");
AddPath("libjpeg.so.62", &my_context->box86_emulated_libs, 0);
}
// special case for bash (add BOX86_NOBANNER=1 if not there)
if(!strcmp(prgname, "bash")) {
printf_log(LOG_INFO, "bash detected, disabling banner\n");
if (!box86_nobanner) {
setenv("BOX86_NOBANNER", "1", 0);
setenv("BOX64_NOBANNER", "1", 0);
}
if (!bashpath) {
bashpath = (char*)prog;
setenv("BOX86_BASH", prog, 1);
}
}
if(bashpath)
my_context->bashpath = box_strdup(bashpath);
/*if(strstr(prgname, "awesomium_process")==prgname) {
printf_log(LOG_INFO, "awesomium_process detected, forcing emulated libpng12\n");
AddPath("libpng12.so.0", &my_context->box86_emulated_libs, 0);
@@ -1170,7 +1317,7 @@ int main(int argc, const char **argv, char **env) {
}*/
for(int i=1; i<my_context->argc; ++i) {
my_context->argv[i] = strdup(argv[i+nextarg]);
my_context->argv[i] = box_strdup(argv[i+nextarg]);
printf_log(LOG_INFO, "argv[%i]=\"%s\"\n", i, my_context->argv[i]);
}
@@ -1189,44 +1336,56 @@ int main(int argc, const char **argv, char **env) {
FreeCollection(&ld_preload);
return -1;
}
if(!(my_context->fullpath = realpath(my_context->argv[0], NULL)))
my_context->fullpath = strdup(my_context->argv[0]);
FILE *f = fopen64(my_context->argv[0], "rb");
if(!(my_context->fullpath = box_realpath(my_context->argv[0], NULL)))
my_context->fullpath = box_strdup(my_context->argv[0]);
if(getenv("BOX86_ARG0"))
my_context->argv[0] = box_strdup(getenv("BOX86_ARG0"));
FILE *f = fopen64(my_context->fullpath, "rb");
if(!f) {
printf_log(LOG_NONE, "Error: Cannot open %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: Cannot open %s\n", my_context->fullpath);
free_contextargv();
FreeBox86Context(&my_context);
FreeCollection(&ld_preload);
return -1;
}
elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->argv[0], 1);
elfheader_t *elf_header = LoadAndCheckElfHeader(f, my_context->fullpath, 1);
if(!elf_header) {
int x64 = my_context->box64path?FileIsX64ELF(my_context->argv[0]):0;
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->argv[0], x64?"using box64":"natively");
int x64 = my_context->box64path?FileIsX64ELF(my_context->fullpath):0;
int script = my_context->bashpath?FileIsShell(my_context->fullpath):0;
printf_log(LOG_NONE, "Error: reading elf header of %s, try to launch %s instead\n", my_context->fullpath, x64?"using box64":(script?"using bash":"natively"));
fclose(f);
free_contextargv();
FreeCollection(&ld_preload);
int ret;
if(x64) {
// duplicate the array and insert 1st arg as box86
const char** newargv = (const char**)calloc(my_context->argc+2, sizeof(char*));
const char** newargv = (const char**)box_calloc(my_context->argc+2, sizeof(char*));
newargv[0] = my_context->box64path;
for(int i=0; i<my_context->argc; ++i)
newargv[i+1] = my_context->argv[i];
FreeBox86Context(&my_context);
return execvp(newargv[0], (char * const*)newargv);
ret = execvp(newargv[0], (char * const*)newargv);
} else if (script) {
// duplicate the array and insert 1st arg as box64, 2nd is bash
const char** newargv = (const char**)box_calloc(my_context->argc+3, sizeof(char*));
newargv[0] = my_context->box86path;
newargv[1] = my_context->bashpath;
for(int i=0; i<my_context->argc; ++i)
newargv[i+2] = my_context->argv[i];
ret = execvp(newargv[0], (char * const*)newargv);
} else {
const char** newargv = (const char**)calloc(my_context->argc+1, sizeof(char*));
const char** newargv = (const char**)box_calloc(my_context->argc+1, sizeof(char*));
for(int i=0; i<my_context->argc; ++i)
newargv[i] = my_context->argv[i];
FreeBox86Context(&my_context);
return execvp(newargv[0], (char * const*)newargv);
ret = execvp(newargv[0], (char * const*)newargv);
}
printf_log(LOG_NONE, "Failed to execvp: error is %s\n", strerror(errno));
free_contextargv();
FreeBox86Context(&my_context);
return ret;
}
AddElfHeader(my_context, elf_header);
if(CalcLoadAddr(elf_header)) {
printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: reading elf header of %s\n", my_context->fullpath);
fclose(f);
free_contextargv();
FreeBox86Context(&my_context);
@@ -1235,7 +1394,7 @@ int main(int argc, const char **argv, char **env) {
}
// allocate memory
if(AllocElfMemory(my_context, elf_header, 1)) {
printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: allocating memory for elf %s\n", my_context->fullpath);
fclose(f);
free_contextargv();
FreeBox86Context(&my_context);
@@ -1244,7 +1403,7 @@ int main(int argc, const char **argv, char **env) {
}
// Load elf into memory
if(LoadElfMemory(f, my_context, elf_header)) {
printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: loading in memory elf %s\n", my_context->fullpath);
fclose(f);
free_contextargv();
FreeBox86Context(&my_context);
@@ -1253,6 +1412,7 @@ int main(int argc, const char **argv, char **env) {
}
// can close the file now
fclose(f);
my_context->brk = ElfGetBrk(elf_header);
if(ElfCheckIfUseTCMallocMinimal(elf_header)) {
if(!box86_tcmalloc_minimal) {
// need to reload with tcmalloc_minimal as a LD_PRELOAD!
@@ -1262,10 +1422,10 @@ int main(int argc, const char **argv, char **env) {
int nenv = 0;
while(env[nenv]) nenv++;
// alloc + "LD_PRELOAD" if needd + last NULL ending
char** newenv = (char**)calloc(nenv+1+((preload)?0:1), sizeof(char*));
char** newenv = (char**)box_calloc(nenv+1+((preload)?0:1), sizeof(char*));
// copy strings
for (int i=0; i<nenv; ++i)
newenv[i] = strdup(env[i]);
newenv[i] = box_strdup(env[i]);
// add ld_preload
if(preload) {
// find the line
@@ -1274,24 +1434,24 @@ int main(int argc, const char **argv, char **env) {
if(strstr(newenv[l], "LD_PRELOAD=")==newenv[l]) {
// found it!
char *old = newenv[l];
newenv[l] = (char*)calloc(strlen(old)+strlen("libtcmalloc_minimal.so.4:")+1, sizeof(char));
newenv[l] = (char*)box_calloc(strlen(old)+strlen("libtcmalloc_minimal.so.4:")+1, sizeof(char));
strcpy(newenv[l], "LD_PRELOAD=libtcmalloc_minimal.so.4:");
strcat(newenv[l], old + strlen("LD_PRELOAD="));
free(old);
box_free(old);
// done, end loop
l = nenv;
} else ++l;
}
} else {
//move last one
newenv[nenv] = strdup(newenv[nenv-1]);
free(newenv[nenv-1]);
newenv[nenv-1] = strdup("LD_PRELOAD=libtcmalloc_minimal.so.4");
newenv[nenv] = box_strdup(newenv[nenv-1]);
box_free(newenv[nenv-1]);
newenv[nenv-1] = box_strdup("LD_PRELOAD=libtcmalloc_minimal.so.4");
}
// duplicate argv too
char** newargv = calloc(argc+1, sizeof(char*));
char** newargv = box_calloc(argc+1, sizeof(char*));
int narg = 0;
while(argv[narg]) {newargv[narg] = strdup(argv[narg]); narg++;}
while(argv[narg]) {newargv[narg] = box_strdup(argv[narg]); narg++;}
// launch with new env...
if(execve(newargv[0], newargv, newenv)<0)
printf_log(LOG_NONE, "Failed to relaunch, error is %d/%s\n", errno, strerror(errno));
@@ -1299,6 +1459,35 @@ int main(int argc, const char **argv, char **env) {
printf_log(LOG_INFO, "BOX86: Using tcmalloc_minimal.so.4, and it's in the LD_PRELOAD command\n");
}
}
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
// before launching emulation, let's check if this is a mojosetup from GOG
if (((strstr(prog, "bin/linux/x86/mojosetup") && getenv("MOJOSETUP_BASE")) || strstr(prog, ".mojosetup/mojosetup"))
&& getenv("GTK2_RC_FILES")) {
sanitize_mojosetup_gtk_background();
}
#endif
// change process name
{
char* p = strrchr(my_context->fullpath, '/');
if(p)
++p;
else
p = my_context->fullpath;
if(prctl(PR_SET_NAME, p)==-1)
printf_log(LOG_NONE, "Error setting process name (%s)\n", strerror(errno));
else
printf_log(LOG_INFO, "Rename process to \"%s\"\n", p);
// and now all change the argv (so libs libs mesa find the correct program names)
char* endp = (char*)argv[argc-1];
while(*endp)
++endp; // find last argv[] address
uintptr_t diff = prog - argv[0]; // this is the difference we need to compensate
for(p=(char*)prog; p<=endp; ++p)
*(p - diff) = *p; // copy all element at argv[nextarg] to argv[0]
memset(endp - diff, 0, diff); // fill reminder with NULL
for(int i=nextarg; i<argc; ++i)
argv[i] -= diff; // adjust strings
}
// get and alloc stack size and align
if(CalcStackSize(my_context)) {
printf_log(LOG_NONE, "Error: allocating stack\n");
@@ -1317,6 +1506,19 @@ int main(int argc, const char **argv, char **env) {
printf_log(LOG_NONE, "Cannot patch the game\n");
}
#endif
if(box86_sc3u) {
uint32_t *patch1 = (uint32_t*)0x8400684;
uint32_t *patch2 = (uint32_t*)0x8406644;
if(*patch1==0x57f4c483) {
*patch1=0x57f407eb;
printf_log(LOG_NONE, "Runtime patching the game\n");
} else if(*patch2==0x57f4c483) {
*patch2=0x57f407eb;
printf_log(LOG_NONE, "Runtime patching the game\n");
} else
printf_log(LOG_NONE, "Cannot patch the game\n");
}
// init x86 emu
x86emu_t *emu = NewX86Emu(my_context, my_context->ep, (uintptr_t)my_context->stack, my_context->stacksz, 0);
// stack setup is much more complicated then just that!
@@ -1332,11 +1534,11 @@ int main(int argc, const char **argv, char **env) {
setupTraceInit(my_context);
// export symbols
AddSymbols(my_context->maplib, GetMapSymbol(my_context->maplib), GetWeakSymbol(my_context->maplib), GetLocalSymbol(my_context->maplib), elf_header);
AddSymbols(my_context->maplib, GetMapSymbols(elf_header), GetWeakSymbols(elf_header), GetLocalSymbols(elf_header), elf_header);
if(wine_preloaded) {
uintptr_t wineinfo = FindSymbol(GetMapSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbol(my_context->maplib), "wine_main_preload_info", -1, NULL, 1);
uintptr_t wineinfo = FindSymbol(GetMapSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
if(!wineinfo) wineinfo = FindSymbol(GetWeakSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
if(!wineinfo) wineinfo = FindSymbol(GetLocalSymbols(elf_header), "wine_main_preload_info", -1, NULL, 1, NULL);
if(!wineinfo) {printf_log(LOG_NONE, "Warning, Symbol wine_main_preload_info not found\n");}
else {
*(void**)wineinfo = get_wine_prereserve();
@@ -1349,21 +1551,22 @@ int main(int argc, const char **argv, char **env) {
AddMainElfToLinkmap(elf_header);
// pre-load lib if needed
if(ld_preload.size) {
if(AddNeededLib(NULL, NULL, NULL, 0, 0, (const char**)ld_preload.paths, ld_preload.size, my_context, emu)) {
printf_log(LOG_INFO, "Warning, cannot pre-load a lib\n");
}
for(int i=0; i<ld_preload.size; ++i)
if(AddNeededLib(my_context->maplib, &my_context->neededlibs, NULL, 0, 0, (const char**)&ld_preload.paths[i], 1, my_context, emu)) {
printf_log(LOG_INFO, "Warning, cannot pre-load the lib (%s)\n", ld_preload.paths[i]);
}
}
FreeCollection(&ld_preload);
// Call librarian to load all dependant elf
if(LoadNeededLibs(elf_header, my_context->maplib, &my_context->neededlibs, NULL, 0, 0, my_context, emu)) {
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: loading needed libs in elf %s\n", my_context->fullpath);
FreeBox86Context(&my_context);
return -1;
}
// reloc...
printf_log(LOG_DEBUG, "And now export symbols / relocation for %s...\n", ElfName(elf_header));
if(RelocateElf(my_context->maplib, NULL, 0, elf_header)) {
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", my_context->argv[0]);
printf_log(LOG_NONE, "Error: relocating symbols in elf %s\n", my_context->fullpath);
FreeBox86Context(&my_context);
return -1;
}
@@ -1371,19 +1574,14 @@ int main(int argc, const char **argv, char **env) {
RelocateElfPlt(my_context->maplib, NULL, 0, elf_header);
// defered init
RunDeferedElfInit(emu);
// update TLS of main elf
RefreshElfTLS(elf_header);
// do some special case check, _IO_2_1_stderr_ and friends, that are setup by libc, but it's already done here, so need to do a copy
ResetSpecialCaseMainElf(elf_header);
// init...
setupTrace(my_context);
// get entrypoint
my_context->ep = GetEntryPoint(my_context->maplib, elf_header);
#if defined(RPI) || defined(RK3399) || defined(GOA_CLONE)
// before launching emulation, let's check if this is a mojosetup from GOG
if (((strstr(prog, "bin/linux/x86/mojosetup") && getenv("MOJOSETUP_BASE")) || strstr(prog, ".mojosetup/mojosetup"))
&& getenv("GTK2_RC_FILES")) {
sanitize_mojosetup_gtk_background();
}
#endif
atexit(endBox86);
@@ -1394,13 +1592,13 @@ int main(int argc, const char **argv, char **env) {
ResetFlags(emu);
PushExit(emu); // push to pop it just after
SetEDX(emu, Pop32(emu)); // EDX is exit function
Run(emu, 0);
DynaRun(emu);
// Get EAX
int ret = GetEAX(emu);
printf_log(LOG_DEBUG, "Emulation finished, EAX=%d\n", ret);
if(trace_func) {
free(trace_func);
box_free(trace_func);
trace_func = NULL;
}
Loaded 100 of 309 files, more files were not shown because too many files have changed in this diff. Show more